Merge remote branch 'origin/master' into lp-binning
authorJosé Fonseca <jfonseca@vmware.com>
Fri, 8 Jan 2010 15:42:57 +0000 (15:42 +0000)
committerJosé Fonseca <jfonseca@vmware.com>
Fri, 8 Jan 2010 15:42:57 +0000 (15:42 +0000)
Conflicts:
src/gallium/auxiliary/util/u_surface.c
src/gallium/drivers/llvmpipe/Makefile
src/gallium/drivers/llvmpipe/SConscript
src/gallium/drivers/llvmpipe/lp_bld_arit.c
src/gallium/drivers/llvmpipe/lp_bld_flow.c
src/gallium/drivers/llvmpipe/lp_bld_interp.c
src/gallium/drivers/llvmpipe/lp_clear.c
src/gallium/drivers/llvmpipe/lp_context.c
src/gallium/drivers/llvmpipe/lp_context.h
src/gallium/drivers/llvmpipe/lp_draw_arrays.c
src/gallium/drivers/llvmpipe/lp_jit.c
src/gallium/drivers/llvmpipe/lp_jit.h
src/gallium/drivers/llvmpipe/lp_prim_vbuf.c
src/gallium/drivers/llvmpipe/lp_setup.c
src/gallium/drivers/llvmpipe/lp_setup_point.c
src/gallium/drivers/llvmpipe/lp_state.h
src/gallium/drivers/llvmpipe/lp_state_blend.c
src/gallium/drivers/llvmpipe/lp_state_derived.c
src/gallium/drivers/llvmpipe/lp_state_fs.c
src/gallium/drivers/llvmpipe/lp_state_sampler.c
src/gallium/drivers/llvmpipe/lp_state_surface.c
src/gallium/drivers/llvmpipe/lp_tex_cache.c
src/gallium/drivers/llvmpipe/lp_tex_cache.h
src/gallium/drivers/llvmpipe/lp_tex_sample.h
src/gallium/drivers/llvmpipe/lp_tile_cache.c

33 files changed:
1  2 
Makefile
configs/linux-llvm
progs/demos/gloss.c
progs/trivial/Makefile
progs/trivial/SConscript
progs/trivial/tri-z-eq.c
src/gallium/auxiliary/util/u_surface.c
src/gallium/drivers/llvmpipe/Makefile
src/gallium/drivers/llvmpipe/SConscript
src/gallium/drivers/llvmpipe/lp_bld_arit.c
src/gallium/drivers/llvmpipe/lp_bld_conv.c
src/gallium/drivers/llvmpipe/lp_bld_interp.c
src/gallium/drivers/llvmpipe/lp_bld_logic.h
src/gallium/drivers/llvmpipe/lp_bld_type.c
src/gallium/drivers/llvmpipe/lp_bld_type.h
src/gallium/drivers/llvmpipe/lp_context.c
src/gallium/drivers/llvmpipe/lp_context.h
src/gallium/drivers/llvmpipe/lp_draw_arrays.c
src/gallium/drivers/llvmpipe/lp_fence.c
src/gallium/drivers/llvmpipe/lp_jit.h
src/gallium/drivers/llvmpipe/lp_rast.c
src/gallium/drivers/llvmpipe/lp_screen.c
src/gallium/drivers/llvmpipe/lp_setup.c
src/gallium/drivers/llvmpipe/lp_setup_tri.c
src/gallium/drivers/llvmpipe/lp_state.h
src/gallium/drivers/llvmpipe/lp_state_blend.c
src/gallium/drivers/llvmpipe/lp_state_derived.c
src/gallium/drivers/llvmpipe/lp_state_fs.c
src/gallium/drivers/llvmpipe/lp_state_rasterizer.c
src/gallium/drivers/llvmpipe/lp_state_sampler.c
src/gallium/drivers/llvmpipe/lp_state_surface.c
src/gallium/drivers/llvmpipe/lp_texture.c
src/gallium/drivers/llvmpipe/lp_tile_soa.h

diff --combined Makefile
index 934f85b5ab1c0d17e60c27fb51885294aff2d925,1b46a9193ef0dbf6c2705aa68cbf5cb7ea9fcb18..340747d5609c75f7e8df82873124448e451af67d
+++ b/Makefile
@@@ -105,6 -105,7 +105,7 @@@ irix6-n32-static 
  irix6-o32 \
  irix6-o32-static \
  linux \
+ linux-i965 \
  linux-alpha \
  linux-alpha-static \
  linux-cell \
@@@ -126,7 -127,6 +127,7 @@@ linux-ia64-icc-static 
  linux-icc \
  linux-icc-static \
  linux-llvm \
 +linux-llvm-debug \
  linux-osmesa \
  linux-osmesa-static \
  linux-osmesa16 \
@@@ -183,7 -183,7 +184,7 @@@ ultrix-gcc
  
  # Rules for making release tarballs
  
- VERSION=7.7-devel
+ VERSION=7.7
  DIRECTORY = Mesa-$(VERSION)
  LIB_NAME = MesaLib-$(VERSION)
  DEMO_NAME = MesaDemos-$(VERSION)
@@@ -226,6 -226,11 +227,11 @@@ MAIN_FILES = 
        $(DIRECTORY)/include/GL/vms_x_fix.h                             \
        $(DIRECTORY)/include/GL/wglext.h                                \
        $(DIRECTORY)/include/GL/wmesa.h                                 \
+       $(DIRECTORY)/src/glsl/Makefile                                  \
+       $(DIRECTORY)/src/glsl/Makefile.template                         \
+       $(DIRECTORY)/src/glsl/*/Makefile                                \
+       $(DIRECTORY)/src/glsl/*/SConscript                              \
+       $(DIRECTORY)/src/glsl/*/*.[ch]                                  \
        $(DIRECTORY)/src/Makefile                                       \
        $(DIRECTORY)/src/mesa/Makefile*                                 \
        $(DIRECTORY)/src/mesa/sources.mak                               \
        $(DIRECTORY)/src/mesa/shader/*.[chly]                           \
        $(DIRECTORY)/src/mesa/shader/Makefile                           \
        $(DIRECTORY)/src/mesa/shader/descrip.mms                        \
-       $(DIRECTORY)/src/mesa/shader/grammar/*.[ch]                     \
        $(DIRECTORY)/src/mesa/shader/slang/*.[ch]                       \
        $(DIRECTORY)/src/mesa/shader/slang/descrip.mms                  \
        $(DIRECTORY)/src/mesa/shader/slang/library/*.[ch]               \
@@@ -440,8 -444,7 +445,7 @@@ DEMO_FILES = 
        $(DIRECTORY)/progs/windml/Makefile.ugl          \
        $(DIRECTORY)/progs/windml/*.c                   \
        $(DIRECTORY)/progs/windml/*.bmp                 \
-       $(DIRECTORY)/progs/ggi/*.c                      \
-       $(DIRECTORY)/windows/VC7/progs/progs.sln
+       $(DIRECTORY)/progs/ggi/*.c
  
  GLUT_FILES = \
        $(DIRECTORY)/include/GL/glut.h                  \
        $(DIRECTORY)/src/glut/mini/glut.pc.in           \
        $(DIRECTORY)/src/glut/directfb/Makefile         \
        $(DIRECTORY)/src/glut/directfb/NOTES            \
-       $(DIRECTORY)/src/glut/directfb/*[ch]            \
-       $(DIRECTORY)/windows/VC6/progs/glut/glut.dsp    \
-       $(DIRECTORY)/windows/VC7/progs/glut/glut.vcproj
+       $(DIRECTORY)/src/glut/directfb/*[ch]
  
  DEPEND_FILES = \
        $(TOP)/src/mesa/depend          \
@@@ -506,9 -507,11 +508,11 @@@ rm_depend
                touch $$dep ; \
        done
  
- lib_gz:
-       rm -f configs/current ; \
-       rm -f configs/autoconf ; \
+ rm_config:
+       rm -f configs/current
+       rm -f configs/autoconf
+ lib_gz: rm_config
        cd .. ; \
        tar -cf $(LIB_NAME).tar $(LIB_FILES) ; \
        gzip $(LIB_NAME).tar ; \
@@@ -526,9 -529,7 +530,7 @@@ glut_gz
        gzip $(GLUT_NAME).tar ; \
        mv $(GLUT_NAME).tar.gz $(DIRECTORY)
  
- lib_bz2:
-       rm -f configs/current ; \
-       rm -f configs/autoconf ; \
+ lib_bz2: rm_config
        cd .. ; \
        tar -cf $(LIB_NAME).tar $(LIB_FILES) ; \
        bzip2 $(LIB_NAME).tar ; \
@@@ -546,9 -547,7 +548,7 @@@ glut_bz2
        bzip2 $(GLUT_NAME).tar ; \
        mv $(GLUT_NAME).tar.bz2 $(DIRECTORY)
  
- lib_zip:
-       rm -f configs/current ; \
-       rm -f configs/autoconf ; \
+ lib_zip: rm_config
        rm -f $(LIB_NAME).zip ; \
        cd .. ; \
        zip -qr $(LIB_NAME).zip $(LIB_FILES) ; \
@@@ -577,5 -576,7 +577,7 @@@ md5
        @-md5sum $(GLUT_NAME).tar.bz2
        @-md5sum $(GLUT_NAME).zip
  
- .PHONY: tarballs rm_depend lib_gz demo_gz glut_gz lib_bz2 demo_bz2 \
-       glut_bz2 lib_zip demo_zip glut_zip md5
+ .PHONY: tarballs rm_depend rm_config md5 \
+       lib_gz demo_gz glut_gz \
+       lib_bz2 demo_bz2 glut_bz2 \
+       lib_zip demo_zip glut_zip
diff --combined configs/linux-llvm
index ace4619b36ee2d82d2a5cff3a5eae58e39808e41,dbf7e3ed7a9e85291d424633deed173ac463eacd..988b7057d4efcbf9d48a1e68e35bd38c81ee9d19
@@@ -1,20 -1,16 +1,18 @@@
  # -*-makefile-*-
 -# Configuration for Linux and LLVM with debugging info
 +# Configuration for Linux and LLVM with optimizations
  # Builds the llvmpipe gallium driver
  
  include $(TOP)/configs/linux
  
  CONFIG_NAME = linux-llvm
  
- #GALLIUM_AUXILIARY_DIRS += gallivm
  # Add llvmpipe driver
  GALLIUM_DRIVERS_DIRS += llvmpipe
  
 -OPT_FLAGS = -g -ansi -pedantic
 -DEFINES += -DDEBUG -DDEBUG_MATH -DGALLIUM_LLVMPIPE -DHAVE_UDIS86
 +OPT_FLAGS = -O3 -ansi -pedantic
 +ARCH_FLAGS = -m32 -mmmx -msse -msse2 -mstackrealign
 +
 +DEFINES += -DNDEBUG -DGALLIUM_LLVMPIPE -DHAVE_UDIS86
  
  # override -std=c99
  CFLAGS += -std=gnu99
diff --combined progs/demos/gloss.c
index d32e8f8c68bec9d2132dcc0a50eddb972f047a6c,578736b4e27c0e654ea8f1f13cbd17a8366c3f29..450861e57781934cdcebb9788c4cf391a6d3e249
@@@ -41,7 -41,6 +41,7 @@@
  /* for convolution */
  #define FILTER_SIZE 7
  
 +static GLint Win;
  static GLint WinWidth = 500, WinHeight = 500;
  static GLuint CylinderObj = 0;
  static GLuint TeapotObj = 0;
@@@ -215,11 -214,7 +215,11 @@@ static void Key( unsigned char key, in
        case ' ':
           ToggleAnimate();
           break;
 +      case 'n':
 +         Idle();
 +         break;
        case 27:
 +         glutDestroyWindow(Win);
           exit(0);
           break;
     }
@@@ -441,10 -436,10 +441,10 @@@ static void Init( int argc, char *argv[
  
  int main( int argc, char *argv[] )
  {
-    glutInit( &argc, argv );
     glutInitWindowSize(WinWidth, WinHeight);
+    glutInit( &argc, argv );
     glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
 -   glutCreateWindow(argv[0] );
 +   Win = glutCreateWindow(argv[0] );
     glewInit();
     glutReshapeFunc( Reshape );
     glutKeyboardFunc( Key );
diff --combined progs/trivial/Makefile
index a78837611c19aecd003c9a2718b32a895c4874bc,e15ec33ab5922ef8bda76994f4dce7f99031fdc5..784715db1620b1c2a783dad13699e3a2fb53c962
@@@ -90,8 -90,6 +90,8 @@@ SOURCES = 
        quadstrip-flat.c \
        quadstrip.c \
        readpixels.c \
 +      sub-tex.c \
 +      tex-quads.c \
        tri-alpha.c \
        tri-alpha-tex.c \
        tri-array-interleaved.c \
        tristrip-clip.c \
        tristrip-flat.c \
        tristrip.c \
+       vbo-tri.c \
        vbo-drawarrays.c \
        vbo-noninterleaved.c \
        vbo-drawelements.c \
diff --combined progs/trivial/SConscript
index 37a53293bfc1ccd009937d7ec1b973a83d66e7e1,613383c77b1a374e887a6386e99b9065b7fadc6d..29062564adc6eed3c9585a88070ac557dc0bd73e
@@@ -1,11 -1,4 +1,4 @@@
- Import('env')
- if not env['GLUT']:
-     Return()
- env = env.Clone()
- env.Prepend(LIBS = ['$GLUT_LIB'])
+ Import('*')
  
  progs = [
      'clear-fbo-tex',
@@@ -77,8 -70,6 +70,8 @@@
        'quadstrip-cont',
        'quadstrip-flat',
        'quadstrip',
 +      'sub-tex',
 +      'tex-quads',
        'tri-alpha',
        'tri-blend-color',
        'tri-blend-max',
  ]
  
  for prog in progs:
-     prog = env.Program(
+     prog = progs_env.Program(
          target = prog,
          source = prog + '.c',
      )
diff --combined progs/trivial/tri-z-eq.c
index 195e8a26f6dd200f28569d3ea7b62574eeeaf112,6bdac4741961ab31ef0c6232208163e64cbd6c7b..c04ffae7f1a34b69f1ef251c2bf89ae27908510b
@@@ -61,7 -61,7 +61,7 @@@ static void Key(unsigned char key, int 
        case 27:
        exit(1);
        default:
-       return;
+       break;
      }
  
      glutPostRedisplay();
@@@ -69,8 -69,6 +69,8 @@@
  
  static void Draw(void)
  {
 +   float z = 1.0;
 +
     glClearColor(0.0, 0.0, 1.0, 0.0);
     glClearDepth(1.0);
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
  
     glBegin(GL_TRIANGLES);
     glColor3f(0,0,.7); 
 -   glVertex3f( 0.9, -0.9, 1.0);
 +   glVertex3f( 0.9, -0.9, z);
     glColor3f(.8,0,0); 
 -   glVertex3f( 0.9,  0.9, 1.0);
 +   glVertex3f( 0.9,  0.9, z);
     glColor3f(0,.9,0); 
 -   glVertex3f(-0.9,  0.0, 1.0);
 +   glVertex3f(-0.9,  0.0, z);
     glEnd();
  
     glFlush();
  
 +   {
 +      GLfloat z;
 +      glReadPixels(125, 125, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z);
 +      printf("Z at (125, 125) = %f\n", z);
 +   }
 +
     if (doubleBuffer) {
        glutSwapBuffers();
     }
index cfdf7ab8f8a9fb6ea3213d460bac93fa87ee04bd,35c497820434e5bbb506853101e844c341c8502a..f66376ad7509ff04eda038d0db9e865a0feea22b
@@@ -36,7 -36,7 +36,8 @@@
  #include "pipe/p_state.h"
  #include "pipe/p_defines.h"
  
 +#include "util/u_memory.h"
+ #include "util/u_format.h"
  #include "util/u_surface.h"
  
  
@@@ -80,10 -80,9 +81,9 @@@ util_create_rgba_surface(struct pipe_sc
     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.width0 = width;
+    templ.height0 = height;
+    templ.depth0 = 1;
     templ.tex_usage = usage;
  
     *textureOut = screen->texture_create(screen, &templ);
@@@ -112,73 -111,3 +112,73 @@@ util_destroy_rgba_surface(struct pipe_t
     pipe_texture_reference(&texture, NULL);
  }
  
 +
 +
 +/**
 + * Compare pipe_framebuffer_state objects.
 + * \return TRUE if same, FALSE if different
 + */
 +boolean
 +util_framebuffer_state_equal(const struct pipe_framebuffer_state *dst,
 +                             const struct pipe_framebuffer_state *src)
 +{
 +   unsigned i;
 +
 +   if (dst->width != src->width ||
 +       dst->height != src->height)
 +      return FALSE;
 +
 +   for (i = 0; i < Elements(src->cbufs); i++) {
 +      if (dst->cbufs[i] != src->cbufs[i]) {
 +         return FALSE;
 +      }
 +   }
 +
 +   if (dst->nr_cbufs != src->nr_cbufs) {
 +      return FALSE;
 +   }
 +
 +   if (dst->zsbuf != src->zsbuf) {
 +      return FALSE;
 +   }
 +
 +   return TRUE;
 +}
 +
 +
 +/**
 + * Copy framebuffer state from src to dst, updating refcounts.
 + */
 +void
 +util_copy_framebuffer_state(struct pipe_framebuffer_state *dst,
 +                            const struct pipe_framebuffer_state *src)
 +{
 +   unsigned i;
 +
 +   dst->width = src->width;
 +   dst->height = src->height;
 +
 +   for (i = 0; i < Elements(src->cbufs); i++) {
 +      pipe_surface_reference(&dst->cbufs[i], src->cbufs[i]);
 +   }
 +
 +   dst->nr_cbufs = src->nr_cbufs;
 +
 +   pipe_surface_reference(&dst->zsbuf, src->zsbuf);
 +}
 +
 +
 +void
 +util_unreference_framebuffer_state(struct pipe_framebuffer_state *fb)
 +{
 +   unsigned i;
 +
 +   for (i = 0; i < fb->nr_cbufs; i++) {
 +      pipe_surface_reference(&fb->cbufs[i], NULL);
 +   }
 +
 +   pipe_surface_reference(&fb->zsbuf, NULL);
 +
 +   fb->width = fb->height = 0;
 +   fb->nr_cbufs = 0;
 +}
index 6ec97046e15a4c57930dd789d310c513f5ba8c07,7c6e46006b9569736fc31873684cf179aef481ec..264999a7ceaa301ba335f713864d2da1cfd1670f
@@@ -6,8 -6,6 +6,8 @@@ LIBNAME = llvmpip
  CFLAGS += -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS
  
  C_SOURCES = \
 +      lp_scene.c \
 +      lp_scene_queue.c \
        lp_bld_alpha.c \
        lp_bld_arit.c \
        lp_bld_blend_aos.c \
        lp_bld_depth.c \
        lp_bld_flow.c \
        lp_bld_format_aos.c \
+       lp_bld_format_query.c \
        lp_bld_format_soa.c \
        lp_bld_interp.c \
        lp_bld_intr.c \
        lp_bld_logic.c \
+       lp_bld_pack.c \
+       lp_bld_sample.c \
        lp_bld_sample_soa.c \
        lp_bld_swizzle.c \
        lp_bld_struct.c \
        lp_clear.c \
        lp_context.c \
        lp_draw_arrays.c \
 +      lp_fence.c \
        lp_flush.c \
        lp_jit.c \
 -      lp_prim_vbuf.c \
 +      lp_rast.c \
 +      lp_rast_tri.c \
        lp_setup.c \
 +      lp_setup_line.c \
 +      lp_setup_point.c \
 +      lp_setup_tri.c \
 +      lp_setup_vbuf.c \
        lp_query.c \
        lp_screen.c \
        lp_state_blend.c \
        lp_state_vertex.c \
        lp_state_vs.c \
        lp_surface.c \
 -      lp_tex_cache.c \
        lp_tex_sample_llvm.c \
        lp_texture.c \
 -      lp_tile_cache.c \
        lp_tile_soa.c
  
+ CPP_SOURCES = \
+       lp_bld_misc.cpp
  include ../../Makefile.template
  
  lp_tile_soa.c: lp_tile_soa.py ../../auxiliary/util/u_format_parse.py ../../auxiliary/util/u_format_access.py ../../auxiliary/util/u_format.csv
index ae4303bd24ff6f9f4ba0ba9b1d773475e8d71707,6bb545a501f8f1c11c41ad057e854469f8cb3691..5af77c4a12d68c5eaaef4e8085f18bae238fad01
@@@ -9,6 -9,8 +9,8 @@@ if not env.has_key('LLVM_VERSION')
  
  env.Tool('udis86')
  
+ env.Append(CPPPATH = ['.'])
  env.CodeGenerate(
        target = 'lp_tile_soa.c',
        script = 'lp_tile_soa.py',
@@@ -30,12 -32,16 +32,16 @@@ llvmpipe = env.ConvenienceLibrary
                'lp_bld_depth.c',
                'lp_bld_flow.c',
                'lp_bld_format_aos.c',
+         'lp_bld_format_query.c',
                'lp_bld_format_soa.c',
                'lp_bld_interp.c',
                'lp_bld_intr.c',
 +              'lp_bld_logic.c',
+               'lp_bld_misc.cpp',
+         'lp_bld_pack.c',
+         'lp_bld_sample.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_clear.c',
                'lp_context.c',
                'lp_draw_arrays.c',
 +              'lp_fence.c',
                'lp_flush.c',
                'lp_jit.c',
 -              'lp_prim_vbuf.c',
 -              'lp_setup.c',
                'lp_query.c',
 +              'lp_scene.c',
 +              'lp_scene_queue.c',
                'lp_screen.c',
 +              'lp_setup.c',
 +              'lp_setup_line.c',
 +              'lp_setup_point.c',
 +              'lp_setup_tri.c',
 +              'lp_setup_vbuf.c',
                'lp_state_blend.c',
                'lp_state_clip.c',
                'lp_state_derived.c',
                'lp_state_vertex.c',
                'lp_state_vs.c',
                'lp_surface.c',
 -              'lp_tex_cache.c',
 +              'lp_rast.c',
 +              'lp_rast_tri.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.Prepend(LIBS = [llvmpipe] + gallium)
  
- env.Program(
-     target = 'lp_test_format',
-     source = ['lp_test_format.c'],
- )
+ tests = [
+     'format',
+     'blend',
+     'conv',
+ ]
  
- 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'],
- )
+ for test in tests:
+     target = env.Program(
+         target = 'lp_test_' + test,
+         source = ['lp_test_' + test + '.c', 'lp_test_main.c'],
+     )
+     env.InstallProgram(target)
  
  Export('llvmpipe')
index f8260938f5a337048a6fa1cc4afc94180813895b,eea6b5d6a5c9d2d1002fa9ff5b6edac8dba0c07c..2df86dd32e50e63476af819728907994ea7988a9
@@@ -47,6 -47,7 +47,7 @@@
  
  #include "util/u_memory.h"
  #include "util/u_debug.h"
+ #include "util/u_math.h"
  #include "util/u_string.h"
  #include "util/u_cpu_detect.h"
  
@@@ -54,6 -55,7 +55,7 @@@
  #include "lp_bld_const.h"
  #include "lp_bld_intr.h"
  #include "lp_bld_logic.h"
+ #include "lp_bld_pack.h"
  #include "lp_bld_debug.h"
  #include "lp_bld_arit.h"
  
@@@ -279,45 -281,6 +281,6 @@@ lp_build_sub(struct lp_build_context *b
  }
  
  
- /**
-  * 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.
   *
   */
  static LLVMValueRef
  lp_build_mul_u8n(LLVMBuilderRef builder,
+                  struct lp_type i16_type,
                   LLVMValueRef a, LLVMValueRef b)
  {
-    static LLVMValueRef c01 = NULL;
-    static LLVMValueRef c08 = NULL;
-    static LLVMValueRef c80 = NULL;
+    LLVMValueRef c8;
     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);
+    c8 = lp_build_int_const_scalar(i16_type, 8);
     
  #if 0
     
     /* a*b/255 ~= (a*(b + 1)) >> 256 */
-    b = LLVMBuildAdd(builder, b, c01, "");
+    b = LLVMBuildAdd(builder, b, lp_build_int_const_scalar(i16_type, 1), "");
     ab = LLVMBuildMul(builder, a, b, "");
  
  #else
     
-    /* t/255 ~= (t + (t >> 8) + 0x80) >> 8 */
+    /* ab/255 ~= (ab + (ab >> 8) + 0x80) >> 8 */
     ab = LLVMBuildMul(builder, a, b, "");
-    ab = LLVMBuildAdd(builder, ab, LLVMBuildLShr(builder, ab, c08, ""), "");
-    ab = LLVMBuildAdd(builder, ab, c80, "");
+    ab = LLVMBuildAdd(builder, ab, LLVMBuildLShr(builder, ab, c8, ""), "");
+    ab = LLVMBuildAdd(builder, ab, lp_build_int_const_scalar(i16_type, 0x80), "");
  
  #endif
     
-    ab = LLVMBuildLShr(builder, ab, c08, "");
+    ab = LLVMBuildLShr(builder, ab, c8, "");
  
     return ab;
  }
@@@ -402,6 -362,8 +362,8 @@@ lp_build_mul(struct lp_build_context *b
               LLVMValueRef b)
  {
     const struct lp_type type = bld->type;
+    LLVMValueRef shift;
+    LLVMValueRef res;
  
     if(a == bld->zero)
        return bld->zero;
        return bld->undef;
  
     if(!type.floating && !type.fixed && type.norm) {
-       if(util_cpu_caps.has_sse2 && 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, "");
+       if(type.width == 8) {
+          struct lp_type i16_type = lp_wider_type(type);
+          LLVMValueRef al, ah, bl, bh, abl, abh, ab;
  
-          /* 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, "");
+          lp_build_unpack2(bld->builder, type, i16_type, a, &al, &ah);
+          lp_build_unpack2(bld->builder, type, i16_type, b, &bl, &bh);
  
           /* PMULLW, PSRLW, PADDW */
-          abl = lp_build_mul_u8n(bld->builder, al, bl);
-          abh = lp_build_mul_u8n(bld->builder, ah, bh);
+          abl = lp_build_mul_u8n(bld->builder, i16_type, al, bl);
+          abh = lp_build_mul_u8n(bld->builder, i16_type, 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, "");
+          ab = lp_build_pack2(bld->builder, i16_type, type, abl, abh);
           
           return ab;
        }
        assert(0);
     }
  
-    if(LLVMIsConstant(a) && LLVMIsConstant(b))
-       return LLVMConstMul(a, b);
+    if(type.fixed)
+       shift = lp_build_int_const_scalar(type, type.width/2);
+    else
+       shift = NULL;
+    if(LLVMIsConstant(a) && LLVMIsConstant(b)) {
+       res =  LLVMConstMul(a, b);
+       if(shift) {
+          if(type.sign)
+             res = LLVMConstAShr(res, shift);
+          else
+             res = LLVMConstLShr(res, shift);
+       }
+    }
+    else {
+       res = LLVMBuildMul(bld->builder, a, b, "");
+       if(shift) {
+          if(type.sign)
+             res = LLVMBuildAShr(bld->builder, res, shift, "");
+          else
+             res = LLVMBuildLShr(bld->builder, res, shift, "");
+       }
+    }
+    return res;
+ }
+ /**
+  * Small vector x scale multiplication optimization.
+  */
+ LLVMValueRef
+ lp_build_mul_imm(struct lp_build_context *bld,
+                  LLVMValueRef a,
+                  int b)
+ {
+    LLVMValueRef factor;
+    if(b == 0)
+       return bld->zero;
  
-    return LLVMBuildMul(bld->builder, a, b, "");
+    if(b == 1)
+       return a;
+    if(b == -1)
+       return LLVMBuildNeg(bld->builder, a, "");
+    if(b == 2 && bld->type.floating)
+       return lp_build_add(bld, a, a);
+    if(util_is_pot(b)) {
+       unsigned shift = ffs(b) - 1;
+       if(bld->type.floating) {
+ #if 0
+          /*
+           * Power of two multiplication by directly manipulating the mantissa.
+           *
+           * XXX: This might not be always faster, it will introduce a small error
+           * for multiplication by zero, and it will produce wrong results
+           * for Inf and NaN.
+           */
+          unsigned mantissa = lp_mantissa(bld->type);
+          factor = lp_build_int_const_scalar(bld->type, (unsigned long long)shift << mantissa);
+          a = LLVMBuildBitCast(bld->builder, a, lp_build_int_vec_type(bld->type), "");
+          a = LLVMBuildAdd(bld->builder, a, factor, "");
+          a = LLVMBuildBitCast(bld->builder, a, lp_build_vec_type(bld->type), "");
+          return a;
+ #endif
+       }
+       else {
+          factor = lp_build_const_scalar(bld->type, shift);
+          return LLVMBuildShl(bld->builder, a, factor, "");
+       }
+    }
+    factor = lp_build_const_scalar(bld->type, (double)b);
+    return lp_build_mul(bld, a, factor);
  }
  
  
@@@ -494,13 -509,36 +509,36 @@@ lp_build_div(struct lp_build_context *b
  }
  
  
+ /**
+  * Linear interpolation.
+  *
+  * This also works for integer values with a few caveats.
+  *
+  * @sa http://www.stereopsis.com/doubleblend.html
+  */
  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 delta;
+    LLVMValueRef res;
+    delta = lp_build_sub(bld, v1, v0);
+    res = lp_build_mul(bld, x, delta);
+    res = lp_build_add(bld, v0, res);
+    if(bld->type.fixed)
+       /* XXX: This step is necessary for lerping 8bit colors stored on 16bits,
+        * but it will be wrong for other uses. Basically we need a more
+        * powerful lp_type, capable of further distinguishing the values
+        * interpretation from the value storage. */
+       res = LLVMBuildAnd(bld->builder, res, lp_build_int_const_scalar(bld->type, (1 << bld->type.width/2) - 1), "");
+    return res;
  }
  
  
@@@ -591,7 -629,7 +629,7 @@@ lp_build_abs(struct lp_build_context *b
     if(type.floating) {
        /* Mask out the sign bit */
        LLVMTypeRef int_vec_type = lp_build_int_vec_type(type);
 -      unsigned long absMask = ~(1 << (type.width - 1));
 +      unsigned long long absMask = ~(1ULL << (type.width - 1));
        LLVMValueRef mask = lp_build_int_const_scalar(type, ((unsigned long long) absMask));
        a = LLVMBuildBitCast(bld->builder, a, int_vec_type, "");
        a = LLVMBuildAnd(bld->builder, a, mask, "");
@@@ -1046,7 -1084,7 +1084,7 @@@ lp_build_log(struct lp_build_context *b
               LLVMValueRef x)
  {
     /* log(2) */
-    LLVMValueRef log2 = lp_build_const_scalar(bld->type, 1.4426950408889634);
+    LLVMValueRef log2 = lp_build_const_scalar(bld->type, 0.69314718055994529);
  
     return lp_build_mul(bld, log2, lp_build_exp2(bld, x));
  }
  
  /**
   * Generate polynomial.
-  * Ex:  x^2 * coeffs[0] + x * coeffs[1] + coeffs[2].
+  * Ex:  coeffs[0] + x * coeffs[1] + x^2 * coeffs[2].
   */
  static LLVMValueRef
  lp_build_polynomial(struct lp_build_context *bld,
@@@ -1248,13 -1286,13 +1286,13 @@@ lp_build_log2_approx(struct lp_build_co
        /* mant = (float) mantissa(x) */
        mant = LLVMBuildAnd(bld->builder, i, mantmask, "");
        mant = LLVMBuildOr(bld->builder, mant, one, "");
-       mant = LLVMBuildSIToFP(bld->builder, mant, vec_type, "");
+       mant = LLVMBuildBitCast(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, ""), "");
+       logmant = LLVMBuildMul(bld->builder, logmant, LLVMBuildSub(bld->builder, mant, bld->one, ""), "");
  
        res = LLVMBuildAdd(bld->builder, logmant, logexp, "");
     }
index 1df938529c4f27ae81996c782ffe439406fbab51,99352094379f81e0aca4ab03555082803264907f..9fa8837202207cfd46828d4a5931e5db48c167c2
@@@ -69,6 -69,7 +69,7 @@@
  #include "lp_bld_const.h"
  #include "lp_bld_intr.h"
  #include "lp_bld_arit.h"
+ #include "lp_bld_pack.h"
  #include "lp_bld_conv.h"
  
  
@@@ -124,10 -125,6 +125,10 @@@ lp_build_clamped_float_to_unsigned_norm
        res = LLVMBuildShl(builder, res, lp_build_int_const_scalar(src_type, shift), "");
  
        /* TODO: Fill in the empty lower bits for additional precision? */
 +      /* YES: this fixes progs/trivial/tri-z-eq.c.
 +       * Otherwise vertex Z=1.0 values get converted to something like
 +       * 0xfffffb00 and the test for equality with 0xffffffff fails.
 +       */
  #if 0
        {
           LLVMValueRef msb;
@@@ -202,241 -199,6 +203,6 @@@ lp_build_unsigned_norm_to_float(LLVMBui
  }
  
  
- /**
-  * 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,
-                struct lp_type src_type,
-                struct 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) {
-       struct 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,
-                struct lp_type src_type,
-                struct 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(util_cpu_caps.has_sse2 && 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 || !util_cpu_caps.has_sse4_1)
-             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;
-    }
-    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_pack(LLVMBuilderRef builder,
-               struct lp_type src_type,
-               struct 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) {
-       struct 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.
   *
@@@ -576,7 -338,7 +342,7 @@@ lp_build_conv(LLVMBuilderRef builder
  
     if(tmp_type.width < dst_type.width) {
        assert(num_tmps == 1);
-       lp_build_expand(builder, tmp_type, dst_type, tmp[0], tmp, num_dsts);
+       lp_build_unpack(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;
@@@ -696,7 -458,7 +462,7 @@@ lp_build_conv_mask(LLVMBuilderRef build
     }
     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);
+       lp_build_unpack(builder, src_type, dst_type, src[0], dst, num_dsts);
     }
     else {
        assert(num_srcs == num_dsts);
index affeeca6ff995721a35e7de67c823bb945a00571,49dab8ab61eed907c5d465e1579a29c910fa47a5..daedf40d558b6e95465d79e26d1b6ca9d4e42faa
  #include "lp_bld_interp.h"
  
  
 +/*
 + * The shader JIT function operates on blocks of quads.
 + * Each block has 2x2 quads and each quad has 2x2 pixels.
 + *
 + * We iterate over the quads in order 0, 1, 2, 3:
 + *
 + * #################
 + * #   |   #   |   #
 + * #---0---#---1---#
 + * #   |   #   |   #
 + * #################
 + * #   |   #   |   #
 + * #---2---#---3---#
 + * #   |   #   |   #
 + * #################
 + *
 + * Within each quad, we have four pixels which are represented in SOA
 + * order:
 + *
 + * #########
 + * # 0 | 1 #
 + * #---+---#
 + * # 2 | 3 #
 + * #########
 + *
 + * So the green channel (for example) of the four pixels is stored in
 + * a single vector register: {g0, g1, g2, g3}.
 + */
 +
 +
  static void
  attrib_name(LLVMValueRef val, unsigned attrib, unsigned chan, const char *suffix)
  {
  }
  
  
 +/**
 + * Initialize the bld->a0, dadx, dady fields.  This involves fetching
 + * those values from the arrays which are passed into the JIT function.
 + */
  static void
  coeffs_init(struct lp_build_interp_soa_context *bld,
              LLVMValueRef a0_ptr,
              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");
 +               attrib_name(a0, attrib, chan, ".a0");
                 break;
  
              default:
  }
  
  
- /**
-  * 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.
 + * Emit LLVM code to compute the fragment shader input attribute values.
 + * For example, for a color input, we'll compute red, green, blue and alpha
 + * values for the four pixels in a quad.
 + * Recall that we're operating on 4-element vectors so each arithmetic
 + * operation is operating on the four pixels in a quad.
   */
 -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] = lp_build_mul_imm(&bld->base, bld->dadx[attrib][chan], bld->xstep);
 -               bld->dady[attrib][chan] = lp_build_mul_imm(&bld->base, bld->dady[attrib][chan], bld->ystep);
 -            }
 -         }
 -      }
 -   }
 -}
 -
 -
  static void
  attribs_init(struct lp_build_interp_soa_context *bld)
  {
              res = a0;
  
              if (mode != TGSI_INTERPOLATE_CONSTANT) {
 +               /* res = res + x * dadx */
                 res = lp_build_add(&bld->base, res, lp_build_mul(&bld->base, x, dadx));
 +               /* res = res + y * dady */
                 res = lp_build_add(&bld->base, res, lp_build_mul(&bld->base, y, dady));
              }
  
  }
  
  
 +/**
 + * Increment the shader input attribute values.
 + * This is called when we move from one quad to the next.
 + */
  static void
 -attribs_update(struct lp_build_interp_soa_context *bld)
 +attribs_update(struct lp_build_interp_soa_context *bld, int quad_index)
  {
     LLVMValueRef oow = NULL;
     unsigned attrib;
     unsigned chan;
  
 +   assert(quad_index < 4);
 +
     for(attrib = 0; attrib < bld->num_attribs; ++attrib) {
        unsigned mask = bld->mask[attrib];
        unsigned mode = bld->mode[attrib];
  
                 res = bld->attribs_pre[attrib][chan];
  
 -               if(bld->xstep)
 +               if (quad_index == 1 || quad_index == 3) {
 +                  /* top-right or bottom-right quad */
 +                  /* build res = res + dadx + dadx */
                    res = lp_build_add(&bld->base, res, dadx);
 +                  res = lp_build_add(&bld->base, res, dadx);
 +               }
  
 -               if(bld->ystep)
 +               if (quad_index == 2 || quad_index == 3) {
 +                  /* bottom-left or bottom-right quad */
 +                  /* build res = res + dady + dady */
                    res = lp_build_add(&bld->base, res, dady);
 +                  res = lp_build_add(&bld->base, res, dady);
 +               }
  
 -               bld->attribs_pre[attrib][chan] = res;
 +               //XXX bld->attribs_pre[attrib][chan] = res;
  
                 if (mode == TGSI_INTERPOLATE_PERSPECTIVE) {
                    LLVMValueRef w = bld->pos[3];
@@@ -301,32 -242,17 +275,32 @@@ pos_init(struct lp_build_interp_soa_con
  }
  
  
 +/**
 + * Update quad position values when moving to the next quad.
 + */
  static void
 -pos_update(struct lp_build_interp_soa_context *bld)
 +pos_update(struct lp_build_interp_soa_context *bld, int quad_index)
  {
     LLVMValueRef x = bld->attribs[0][0];
     LLVMValueRef y = bld->attribs[0][1];
 +   const int xstep = 2, ystep = 2;
  
 -   if(bld->xstep)
 -      x = lp_build_add(&bld->base, x, lp_build_const_scalar(bld->base.type, bld->xstep));
 +   if (quad_index == 1 || quad_index == 3) {
 +      /* top-right or bottom-right quad in block */
 +      /* build x += xstep */
 +      x = lp_build_add(&bld->base, x,
 +                       lp_build_const_scalar(bld->base.type, xstep));
 +   }
  
 -   if(bld->ystep)
 -      y = lp_build_add(&bld->base, y, lp_build_const_scalar(bld->base.type, bld->ystep));
 +   if (quad_index == 2) {
 +      /* bottom-left quad in block */
 +      /* build y += ystep */
 +      y = lp_build_add(&bld->base, y,
 +                       lp_build_const_scalar(bld->base.type, ystep));
 +      /* build x -= xstep */
 +      x = lp_build_sub(&bld->base, x,
 +                       lp_build_const_scalar(bld->base.type, xstep));
 +   }
  
     lp_build_name(x, "pos.x");
     lp_build_name(y, "pos.y");
  }
  
  
 +/**
 + * Initialize fragment shader input attribute info.
 + */
  void
  lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld,
                           const struct tgsi_token *tokens,
                           LLVMValueRef dadx_ptr,
                           LLVMValueRef dady_ptr,
                           LLVMValueRef x0,
 -                         LLVMValueRef y0,
 -                         int xstep,
 -                         int ystep)
 +                         LLVMValueRef y0)
  {
     struct tgsi_parse_context parse;
     struct tgsi_full_declaration *decl;
              unsigned first, last, mask;
              unsigned attrib;
  
-             first = decl->DeclarationRange.First;
-             last = decl->DeclarationRange.Last;
+             first = decl->Range.First;
+             last = decl->Range.Last;
              mask = decl->Declaration.UsageMask;
  
              for( attrib = first; attrib <= last; ++attrib ) {
     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.
 + * Advance the position and inputs to the given quad within the block.
   */
  void
 -lp_build_interp_soa_update(struct lp_build_interp_soa_context *bld)
 +lp_build_interp_soa_update(struct lp_build_interp_soa_context *bld,
 +                           int quad_index)
  {
 -   pos_update(bld);
 +   assert(quad_index < 4);
 +
 +   pos_update(bld, quad_index);
  
 -   attribs_update(bld);
 +   attribs_update(bld, quad_index);
  }
index d68763665613e0bd2df6540474add8451a2264ab,d67500ef7074e00930dafc9a6722ea869dbc3188..40d64eb2c1917c2089865224b7105e2f2b2c56f3
  #include "pipe/p_defines.h" /* For PIPE_FUNC_xxx */
  
  
- struct lp_type type;
+ struct lp_type;
  struct lp_build_context;
  
  
 +LLVMValueRef
 +lp_build_compare(LLVMBuilderRef builder,
 +                 const struct lp_type type,
 +                 unsigned func,
 +                 LLVMValueRef a,
 +                 LLVMValueRef b);
 +
 +
  /**
   * @param func is one of PIPE_FUNC_xxx
   */
index e8cf7256c0ebeb32e93efd228dbfe6b56f7d9270,1320a2672142d6ded4f15c2e5deff8f8408ab811..8270cd057f61c114c2f532d09d331f212194bac5
@@@ -157,36 -157,34 +157,55 @@@ lp_build_int_vec_type(struct lp_type ty
  }
  
  
- lp_build_int32_vec4_type()
 +/**
 + * Build int32[4] vector type
 + */
 +LLVMTypeRef
++lp_build_int32_vec4_type(void)
 +{
 +   struct lp_type t;
 +   LLVMTypeRef type;
 +
 +   memset(&t, 0, sizeof(t));
 +   t.floating = FALSE; /* floating point values */
 +   t.sign = TRUE;      /* values are signed */
 +   t.norm = FALSE;     /* values are not limited to [0,1] or [-1,1] */
 +   t.width = 32;       /* 32-bit int */
 +   t.length = 4;       /* 4 elements per vector */
 +
 +   type = lp_build_int_elem_type(t);
 +   return LLVMVectorType(type, t.length);
 +}
 +
 +
  struct lp_type
  lp_int_type(struct lp_type type)
  {
-    struct lp_type int_type;
+    struct lp_type res_type;
  
-    memset(&int_type, 0, sizeof int_type);
-    int_type.width = type.width;
-    int_type.length = type.length;
-    return int_type;
+    memset(&res_type, 0, sizeof res_type);
+    res_type.width = type.width;
+    res_type.length = type.length;
+    return res_type;
+ }
+ /**
+  * Return the type with twice the bit width (hence half the number of elements).
+  */
+ struct lp_type
+ lp_wider_type(struct lp_type type)
+ {
+    struct lp_type res_type;
+    memcpy(&res_type, &type, sizeof res_type);
+    res_type.width *= 2;
+    res_type.length /= 2;
+    assert(res_type.length);
+    return res_type;
  }
  
  
index 118fb339089c3375d7434204fb660cbc67959416,2fb233d335f6b3546d7ef3041209ff903de24b1b..b7d8aed396dec41d0b984128521bf58b797453f1
  #include <pipe/p_compiler.h>
  
  
+ /**
+  * Native SIMD register width.
+  *
+  * 128 for all architectures we care about.
+  */
+ #define LP_NATIVE_VECTOR_WIDTH 128
  /**
   * 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
@@@ -134,6 -139,91 +139,91 @@@ struct lp_build_contex
  };
  
  
+ static INLINE struct lp_type
+ lp_type_float(unsigned width)
+ {
+    struct lp_type res_type;
+    memset(&res_type, 0, sizeof res_type);
+    res_type.floating = TRUE;
+    res_type.sign = TRUE;
+    res_type.width = width;
+    res_type.length = LP_NATIVE_VECTOR_WIDTH / width;
+    return res_type;
+ }
+ static INLINE struct lp_type
+ lp_type_int(unsigned width)
+ {
+    struct lp_type res_type;
+    memset(&res_type, 0, sizeof res_type);
+    res_type.sign = TRUE;
+    res_type.width = width;
+    res_type.length = LP_NATIVE_VECTOR_WIDTH / width;
+    return res_type;
+ }
+ static INLINE struct lp_type
+ lp_type_uint(unsigned width)
+ {
+    struct lp_type res_type;
+    memset(&res_type, 0, sizeof res_type);
+    res_type.width = width;
+    res_type.length = LP_NATIVE_VECTOR_WIDTH / width;
+    return res_type;
+ }
+ static INLINE struct lp_type
+ lp_type_unorm(unsigned width)
+ {
+    struct lp_type res_type;
+    memset(&res_type, 0, sizeof res_type);
+    res_type.norm = TRUE;
+    res_type.width = width;
+    res_type.length = LP_NATIVE_VECTOR_WIDTH / width;
+    return res_type;
+ }
+ static INLINE struct lp_type
+ lp_type_fixed(unsigned width)
+ {
+    struct lp_type res_type;
+    memset(&res_type, 0, sizeof res_type);
+    res_type.sign = TRUE;
+    res_type.fixed = TRUE;
+    res_type.width = width;
+    res_type.length = LP_NATIVE_VECTOR_WIDTH / width;
+    return res_type;
+ }
+ static INLINE struct lp_type
+ lp_type_ufixed(unsigned width)
+ {
+    struct lp_type res_type;
+    memset(&res_type, 0, sizeof res_type);
+    res_type.fixed = TRUE;
+    res_type.width = width;
+    res_type.length = LP_NATIVE_VECTOR_WIDTH / width;
+    return res_type;
+ }
  LLVMTypeRef
  lp_build_elem_type(struct lp_type type);
  
@@@ -162,14 -252,14 +252,18 @@@ LLVMTypeRe
  lp_build_int_vec_type(struct lp_type type);
  
  
 +LLVMTypeRef
 +lp_build_int32_vec4_type();
 +
 +
  struct lp_type
  lp_int_type(struct lp_type type);
  
  
+ struct lp_type
+ lp_wider_type(struct lp_type type);
  void
  lp_build_context_init(struct lp_build_context *bld,
                        LLVMBuilderRef builder,
index 696a9d5f6a841c55557e55df36d8b94fdc010449,1cc3c9227cc8175c91c16c3396a89fd5d8d2cf90..8d965175f8c32c90c93c12f7c3ec360046babd3a
   */
  
  #include "draw/draw_context.h"
+ #include "draw/draw_vbuf.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_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"
 +#include "lp_setup.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;
  
 +   /* This will also destroy llvmpipe->setup:
 +    */
     if (llvmpipe->draw)
        draw_destroy( llvmpipe->draw );
  
     for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
 -      lp_destroy_tile_cache(llvmpipe->cbuf_cache[i]);
        pipe_surface_reference(&llvmpipe->framebuffer.cbufs[i], NULL);
     }
 +
     pipe_surface_reference(&llvmpipe->framebuffer.zsbuf, NULL);
  
     for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
 -      lp_destroy_tex_tile_cache(llvmpipe->tex_cache[i]);
        pipe_texture_reference(&llvmpipe->texture[i], NULL);
     }
  
 -      lp_destroy_tex_tile_cache(llvmpipe->vertex_tex_cache[i]);
+    for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) {
+       pipe_texture_reference(&llvmpipe->vertex_textures[i], NULL);
+    }
     for (i = 0; i < Elements(llvmpipe->constants); i++) {
        if (llvmpipe->constants[i].buffer) {
           pipe_buffer_reference(&llvmpipe->constants[i].buffer, NULL);
@@@ -83,8 -138,33 +88,8 @@@ llvmpipe_is_texture_referenced( struct 
                                unsigned face, unsigned level)
  {
     struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
 -   unsigned i;
 -
 -   /* check if any of the bound drawing surfaces are this texture */
 -   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;
 -   }
  
 -   /* check if any of the tex_cache textures are this texture */
 -   for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
 -      if (llvmpipe->tex_cache[i] &&
 -            llvmpipe->tex_cache[i]->texture == texture)
 -         return PIPE_REFERENCED_FOR_READ;
 -   }
 -   for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) {
 -      if (llvmpipe->vertex_tex_cache[i] &&
 -          llvmpipe->vertex_tex_cache[i]->texture == texture)
 -         return PIPE_REFERENCED_FOR_READ;
 -   }
 -   
 -   return PIPE_UNREFERENCED;
 +   return lp_setup_is_texture_referenced(llvmpipe->setup, texture);
  }
  
  static unsigned int
@@@ -98,6 -178,7 +103,6 @@@ 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)
     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.bind_fragment_sampler_states  = llvmpipe_bind_sampler_states;
+    llvmpipe->pipe.bind_vertex_sampler_states  = llvmpipe_bind_vertex_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.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_fragment_sampler_textures = llvmpipe_set_sampler_textures;
+    llvmpipe->pipe.set_vertex_sampler_textures = llvmpipe_set_vertex_sampler_textures;
     llvmpipe->pipe.set_viewport_state = llvmpipe_set_viewport_state;
  
     llvmpipe->pipe.set_vertex_buffers = llvmpipe_set_vertex_buffers;
     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_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 );
 -   for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++)
 -      llvmpipe->vertex_tex_cache[i] = lp_create_tex_tile_cache(screen);
 -
 -
     /*
      * Create drawing context and plug our rendering stage into it.
      */
     if (!llvmpipe->draw) 
        goto fail;
  
-    /* FIXME: vertex sampler state
-     */
+    /* FIXME: devise alternative to draw_texture_samplers */
  
     if (debug_get_bool_option( "LP_NO_RAST", FALSE ))
        llvmpipe->no_rast = TRUE;
  
 -   llvmpipe->vbuf_backend = lp_create_vbuf_backend(llvmpipe);
 -   if (!llvmpipe->vbuf_backend)
 +   llvmpipe->setup = lp_setup_create( screen,
 +                                      llvmpipe->draw );
 +   if (!llvmpipe->setup)
        goto fail;
  
 -   llvmpipe->vbuf = draw_vbuf_stage(llvmpipe->draw, llvmpipe->vbuf_backend);
 -   if (!llvmpipe->vbuf)
 -      goto fail;
 -
 -   draw_set_rasterize_stage(llvmpipe->draw, llvmpipe->vbuf);
 -   draw_set_render(llvmpipe->draw, llvmpipe->vbuf_backend);
 -
 -
 -
     /* plug in AA line/point stages */
     draw_install_aaline_stage(llvmpipe->draw, &llvmpipe->pipe);
     draw_install_aapoint_stage(llvmpipe->draw, &llvmpipe->pipe);
index 194692045dc9504ffdbf49dd79722e72538d5bad,6411797cf5d280afe7f4909486fb11cc70b4c1a3..1ede6a6a72f9bc69bce5c690194dc3145962601d
  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 setup_context;
  
  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];
+    struct pipe_sampler_state *vertex_samplers[PIPE_MAX_VERTEX_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_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_texture *vertex_textures[PIPE_MAX_VERTEX_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_samplers;
+    unsigned num_vertex_textures;
     unsigned num_vertex_elements;
     unsigned num_vertex_buffers;
  
     
     /** 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;
 +   /** The tiling engine */
 +   struct setup_context *setup;
  
     /** The primitive drawing context */
     struct draw_context *draw;
  
 -   /** Draw module backend */
 -   struct vbuf_render *vbuf_backend;
 -   struct draw_stage *vbuf;
 -
 -   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];
 -   struct llvmpipe_tex_tile_cache *vertex_tex_cache[PIPE_MAX_VERTEX_SAMPLERS];
 -
 -   unsigned no_rast : 1;
 +   boolean no_rast;
  
 -   struct lp_jit_context jit_context;
  };
  
  
index 91fcbc01c6d4f7204812b8e7b2134ad9242842b5,c152b4413fcf00fc31d06ef7cbbe57744d60c3c9..3989cce7445e49b5266b58ecd5dbb004ae45d843
  
  
  
- boolean
+ void
  llvmpipe_draw_arrays(struct pipe_context *pipe, unsigned mode,
                       unsigned start, unsigned count)
  {
-    return llvmpipe_draw_elements(pipe, NULL, 0, mode, start, count);
+    llvmpipe_draw_elements(pipe, NULL, 0, mode, start, count);
  }
  
  
@@@ -58,7 -58,7 +58,7 @@@
   * Basically, map the vertex buffers (and drawing surfaces), then hand off
   * the drawing to the 'draw' module.
   */
- boolean
+ void
  llvmpipe_draw_range_elements(struct pipe_context *pipe,
                               struct pipe_buffer *indexBuffer,
                               unsigned indexSize,
     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);
 -
     /*
      * Map vertex buffers
      */
     draw_arrays(draw, mode, start, count);
  
     /*
-     * unmap vertex/index buffers - will cause draw module to flush
+     * unmap vertex/index buffers
      */
     for (i = 0; i < lp->num_vertex_buffers; i++) {
        draw_set_mapped_vertex_buffer(draw, i, NULL);
        draw_set_mapped_element_buffer(draw, 0, NULL);
     }
  
-    return TRUE;
+    /*
+     * TODO: Flush only when a user vertex/index buffer is present
+     * (or even better, modify draw module to do this
+     * internally when this condition is seen?)
+     */
+    draw_flush(draw);
 -
 -   /* Note: leave drawing surfaces mapped */
 -
 -   lp->dirty_render_cache = TRUE;
  }
  
  
- boolean
+ void
  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 );
+    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);
- }
index 14fbea6d99318d3ac95ebdb513feacf4f40cb6af,0000000000000000000000000000000000000000..97c46087da02243fe746c18bc77a834e094340ed
mode 100644,000000..100644
--- /dev/null
@@@ -1,109 -1,0 +1,109 @@@
-    if (pipe_reference((struct pipe_reference**)ptr, &f->reference)) {
 +/**************************************************************************
 + *
 + * 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 "util/u_memory.h"
 +#include "lp_fence.h"
 +
 +
 +struct lp_fence *
 +lp_fence_create(unsigned rank)
 +{
 +   struct lp_fence *fence = CALLOC_STRUCT(lp_fence);
 +
 +   pipe_reference_init(&fence->reference, 1);
 +
 +   pipe_mutex_init(fence->mutex);
 +   pipe_condvar_init(fence->signalled);
 +
 +   fence->rank = rank;
 +
 +   return fence;
 +}
 +
 +
 +static void
 +lp_fence_destroy(struct lp_fence *fence)
 +{
 +   pipe_mutex_destroy(fence->mutex);
 +   pipe_condvar_destroy(fence->signalled);
 +   FREE(fence);
 +}
 +
 +
 +static void
 +llvmpipe_fence_reference(struct pipe_screen *screen,
 +                         struct pipe_fence_handle **ptr,
 +                         struct pipe_fence_handle *fence)
 +{
 +   struct lp_fence *old = (struct lp_fence *) *ptr;
 +   struct lp_fence *f = (struct lp_fence *) fence;
 +
++   if (pipe_reference(&old->reference, &f->reference)) {
 +      lp_fence_destroy(old);
 +   }
 +}
 +
 +
 +static int
 +llvmpipe_fence_signalled(struct pipe_screen *screen,
 +                         struct pipe_fence_handle *fence,
 +                         unsigned flag)
 +{
 +   struct lp_fence *f = (struct lp_fence *) fence;
 +
 +   return f->count == f->rank;
 +}
 +
 +
 +static int
 +llvmpipe_fence_finish(struct pipe_screen *screen,
 +                      struct pipe_fence_handle *fence_handle,
 +                      unsigned flag)
 +{
 +   struct lp_fence *fence = (struct lp_fence *) fence_handle;
 +
 +   pipe_mutex_lock(fence->mutex);
 +   while (fence->count < fence->rank) {
 +      pipe_condvar_wait(fence->signalled, fence->mutex);
 +   }
 +   pipe_mutex_unlock(fence->mutex);
 +
 +   return 0;
 +}
 +
 +
 +
 +
 +void
 +llvmpipe_init_screen_fence_funcs(struct pipe_screen *screen)
 +{
 +   screen->fence_reference = llvmpipe_fence_reference;
 +   screen->fence_signalled = llvmpipe_fence_signalled;
 +   screen->fence_finish = llvmpipe_fence_finish;
 +}
index e8fb7d990f8963da0a482a127aac43a8c3b0a88a,277b690c02ca8d5ba6c31ef7c9a074e8490f45ba..1a6e939aa247752ee340ebe3f7df4fb92d70af23
@@@ -41,7 -41,6 +41,6 @@@
  #include "pipe/p_state.h"
  
  
- struct tgsi_sampler;
  struct llvmpipe_screen;
  
  
@@@ -78,8 -77,6 +77,6 @@@ struct lp_jit_contex
  {
     const float *constants;
  
-    void *dummy;                 /* remove me */
     float alpha_ref_value;
  
     /* FIXME: store (also?) in floats */
  #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")
+    lp_build_struct_get(_builder, _ptr, 1, "alpha_ref_value")
  
  #define lp_jit_context_blend_color(_builder, _ptr) \
-    lp_build_struct_get(_builder, _ptr, 3, "blend_color")
+    lp_build_struct_get(_builder, _ptr, 2, "blend_color")
  
- #define LP_JIT_CONTEXT_TEXTURES_INDEX 4
+ #define LP_JIT_CONTEXT_TEXTURES_INDEX 3
  
  #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,
 +(*lp_jit_frag_func)(const 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 *depth,
 +                    const int32_t c1,
 +                    const int32_t c2,
 +                    const int32_t c3,
 +                    const int32_t *step1,
 +                    const int32_t *step2,
 +                    const int32_t *step3);
 +
  
  void
  lp_jit_screen_cleanup(struct llvmpipe_screen *screen);
  
index 6772ff332ba48cb301170c29de3ffa87fcf7a554,0000000000000000000000000000000000000000..6535e69308908f5bc2618345d2e4c9c3fa53e4f6
mode 100644,000000..100644
--- /dev/null
@@@ -1,793 -1,0 +1,793 @@@
-    lp_tile_read_4ub(rast->cbuf_transfer->format,
 +/**************************************************************************
 + *
 + * 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 <limits.h>
 +#include "util/u_memory.h"
 +#include "util/u_math.h"
 +#include "util/u_cpu_detect.h"
 +#include "util/u_surface.h"
 +
 +#include "lp_scene_queue.h"
 +#include "lp_debug.h"
 +#include "lp_fence.h"
 +#include "lp_rast.h"
 +#include "lp_rast_priv.h"
 +#include "lp_tile_soa.h"
 +#include "lp_bld_debug.h"
 +#include "lp_scene.h"
 +
 +
 +/**
 + * Begin the rasterization phase.
 + * Map the framebuffer surfaces.  Initialize the 'rast' state.
 + */
 +static boolean
 +lp_rast_begin( struct lp_rasterizer *rast,
 +               const struct pipe_framebuffer_state *fb,
 +               boolean write_color,
 +               boolean write_zstencil )
 +{
 +   struct pipe_screen *screen = rast->screen;
 +   struct pipe_surface *cbuf, *zsbuf;
 +
 +   LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__);
 +
 +   util_copy_framebuffer_state(&rast->state.fb, fb);
 +
 +   rast->state.write_zstencil = write_zstencil;
 +   rast->state.write_color = write_color;
 +
 +   rast->check_for_clipped_tiles = (fb->width % TILE_SIZE != 0 ||
 +                                    fb->height % TILE_SIZE != 0);
 +
 +   /* XXX support multiple color buffers here */
 +   cbuf = rast->state.fb.cbufs[0];
 +   if (cbuf) {
 +      rast->cbuf_transfer = screen->get_tex_transfer(rast->screen,
 +                                                     cbuf->texture,
 +                                                     cbuf->face,
 +                                                     cbuf->level,
 +                                                     cbuf->zslice,
 +                                                     PIPE_TRANSFER_READ_WRITE,
 +                                                     0, 0,
 +                                                     fb->width, fb->height);
 +      if (!rast->cbuf_transfer)
 +         return FALSE;
 +
 +      rast->cbuf_map = screen->transfer_map(rast->screen, 
 +                                            rast->cbuf_transfer);
 +      if (!rast->cbuf_map)
 +         return FALSE;
 +   }
 +
 +   zsbuf = rast->state.fb.zsbuf;
 +   if (zsbuf) {
 +      rast->zsbuf_transfer = screen->get_tex_transfer(rast->screen,
 +                                                      zsbuf->texture,
 +                                                      zsbuf->face,
 +                                                      zsbuf->level,
 +                                                      zsbuf->zslice,
 +                                                      PIPE_TRANSFER_READ_WRITE,
 +                                                      0, 0,
 +                                                      fb->width, fb->height);
 +      if (!rast->zsbuf_transfer)
 +         return FALSE;
 +
 +      rast->zsbuf_map = screen->transfer_map(rast->screen, 
 +                                            rast->zsbuf_transfer);
 +      if (!rast->zsbuf_map)
 +         return FALSE;
 +   }
 +
 +   return TRUE;
 +}
 +
 +
 +/**
 + * Finish the rasterization phase.
 + * Unmap framebuffer surfaces.
 + */
 +static void
 +lp_rast_end( struct lp_rasterizer *rast )
 +{
 +   struct pipe_screen *screen = rast->screen;
 +
 +   if (rast->cbuf_map) 
 +      screen->transfer_unmap(screen, rast->cbuf_transfer);
 +
 +   if (rast->zsbuf_map) 
 +      screen->transfer_unmap(screen, rast->zsbuf_transfer);
 +
 +   if (rast->cbuf_transfer)
 +      screen->tex_transfer_destroy(rast->cbuf_transfer);
 +
 +   if (rast->zsbuf_transfer)
 +      screen->tex_transfer_destroy(rast->zsbuf_transfer);
 +
 +   rast->cbuf_transfer = NULL;
 +   rast->zsbuf_transfer = NULL;
 +   rast->cbuf_map = NULL;
 +   rast->zsbuf_map = NULL;
 +}
 +
 +
 +/**
 + * Begining rasterization of a tile.
 + * \param x  window X position of the tile, in pixels
 + * \param y  window Y position of the tile, in pixels
 + */
 +static void
 +lp_rast_start_tile( struct lp_rasterizer *rast,
 +                    unsigned thread_index,
 +                    unsigned x, unsigned y )
 +{
 +   LP_DBG(DEBUG_RAST, "%s %d,%d\n", __FUNCTION__, x, y);
 +
 +   rast->tasks[thread_index].x = x;
 +   rast->tasks[thread_index].y = y;
 +}
 +
 +
 +/**
 + * Clear the rasterizer's current color tile.
 + * This is a bin command called during bin processing.
 + */
 +void lp_rast_clear_color( struct lp_rasterizer *rast,
 +                          unsigned thread_index,
 +                          const union lp_rast_cmd_arg arg )
 +{
 +   const uint8_t *clear_color = arg.clear_color;
 +   uint8_t *color_tile = rast->tasks[thread_index].tile.color;
 +   
 +   LP_DBG(DEBUG_RAST, "%s 0x%x,0x%x,0x%x,0x%x\n", __FUNCTION__, 
 +              clear_color[0],
 +              clear_color[1],
 +              clear_color[2],
 +              clear_color[3]);
 +
 +   if (clear_color[0] == clear_color[1] &&
 +       clear_color[1] == clear_color[2] &&
 +       clear_color[2] == clear_color[3]) {
 +      memset(color_tile, clear_color[0], TILE_SIZE * TILE_SIZE * 4);
 +   }
 +   else {
 +      unsigned 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(color_tile, x, y, chan) = clear_color[chan];
 +   }
 +}
 +
 +
 +/**
 + * Clear the rasterizer's current z/stencil tile.
 + * This is a bin command called during bin processing.
 + */
 +void lp_rast_clear_zstencil( struct lp_rasterizer *rast,
 +                             unsigned thread_index,
 +                             const union lp_rast_cmd_arg arg)
 +{
 +   unsigned i, j;
 +   uint32_t *depth_tile = rast->tasks[thread_index].tile.depth;
 +   
 +   LP_DBG(DEBUG_RAST, "%s 0x%x\n", __FUNCTION__, arg.clear_zstencil);
 +
 +   for (i = 0; i < TILE_SIZE; i++)
 +      for (j = 0; j < TILE_SIZE; j++)
 +       depth_tile[i*TILE_SIZE + j] = arg.clear_zstencil;
 +}
 +
 +
 +/**
 + * Load tile color from the framebuffer surface.
 + * This is a bin command called during bin processing.
 + */
 +void lp_rast_load_color( struct lp_rasterizer *rast,
 +                         unsigned thread_index,
 +                         const union lp_rast_cmd_arg arg)
 +{
 +   struct lp_rasterizer_task *task = &rast->tasks[thread_index];
 +   const unsigned x = task->x;
 +   const unsigned y = task->y;
 +   int w = TILE_SIZE;
 +   int h = TILE_SIZE;
 +
 +   LP_DBG(DEBUG_RAST, "%s at %u, %u\n", __FUNCTION__, x, y);
 +
 +   if (x + w > rast->state.fb.width)
 +      w -= x + w - rast->state.fb.width;
 +
 +   if (y + h > rast->state.fb.height)
 +      h -= y + h - rast->state.fb.height;
 +
 +   assert(w >= 0);
 +   assert(h >= 0);
 +   assert(w <= TILE_SIZE);
 +   assert(h <= TILE_SIZE);
 +
-    lp_tile_write_4ub(rast->cbuf_transfer->format,
++   lp_tile_read_4ub(rast->cbuf_transfer->texture->format,
 +                     rast->tasks[thread_index].tile.color,
 +                     rast->cbuf_map, 
 +                     rast->cbuf_transfer->stride,
 +                     x, y,
 +                     w, h);
 +}
 +
 +
 +/**
 + * Load tile z/stencil from the framebuffer surface.
 + * This is a bin command called during bin processing.
 + */
 +void lp_rast_load_zstencil( struct lp_rasterizer *rast,
 +                            unsigned thread_index,
 +                            const union lp_rast_cmd_arg arg )
 +{
 +   LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__);
 +
 +   /* call u_tile func to load depth (and stencil?) from surface */
 +}
 +
 +
 +void lp_rast_set_state( struct lp_rasterizer *rast,
 +                        unsigned thread_index,
 +                        const union lp_rast_cmd_arg arg )
 +{
 +   const struct lp_rast_state *state = arg.set_state;
 +
 +   LP_DBG(DEBUG_RAST, "%s %p\n", __FUNCTION__, (void *) state);
 +
 +   /* just set the current state pointer for this rasterizer */
 +   rast->tasks[thread_index].current_state = state;
 +}
 +
 +
 +
 +/* Within a tile:
 + */
 +
 +/**
 + * Run the shader on all blocks in a tile.  This is used when a tile is
 + * completely contained inside a triangle.
 + * This is a bin command called during bin processing.
 + */
 +void lp_rast_shade_tile( struct lp_rasterizer *rast,
 +                         unsigned thread_index,
 +                         const union lp_rast_cmd_arg arg )
 +{
 +   /* Set c1,c2,c3 to large values so the in/out test always passes */
 +   const int32_t c1 = INT_MIN, c2 = INT_MIN, c3 = INT_MIN;
 +   const struct lp_rast_shader_inputs *inputs = arg.shade_tile;
 +   const unsigned tile_x = rast->tasks[thread_index].x;
 +   const unsigned tile_y = rast->tasks[thread_index].y;
 +   unsigned x, y;
 +
 +   LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__);
 +
 +   /* Use the existing preference for 4x4 (four quads) shading:
 +    */
 +   for (y = 0; y < TILE_SIZE; y += 4)
 +      for (x = 0; x < TILE_SIZE; x += 4)
 +         lp_rast_shade_quads( rast,
 +                              thread_index,
 +                              inputs,
 +                              tile_x + x,
 +                              tile_y + y,
 +                              c1, c2, c3);
 +}
 +
 +
 +/**
 + * Compute shading for a 4x4 block of pixels.
 + * This is a bin command called during bin processing.
 + */
 +void lp_rast_shade_quads( struct lp_rasterizer *rast,
 +                          unsigned thread_index,
 +                          const struct lp_rast_shader_inputs *inputs,
 +                          unsigned x, unsigned y,
 +                          int32_t c1, int32_t c2, int32_t c3)
 +{
 +   const struct lp_rast_state *state = rast->tasks[thread_index].current_state;
 +   struct lp_rast_tile *tile = &rast->tasks[thread_index].tile;
 +   void *color;
 +   void *depth;
 +   unsigned ix, iy;
 +   int block_offset;
 +
 +#ifdef DEBUG
 +   assert(state);
 +
 +   /* Sanity checks */
 +   assert(x % TILE_VECTOR_WIDTH == 0);
 +   assert(y % TILE_VECTOR_HEIGHT == 0);
 +
 +   assert((x % 4) == 0);
 +   assert((y % 4) == 0);
 +#endif
 +
 +   ix = x % TILE_SIZE;
 +   iy = y % TILE_SIZE;
 +
 +   /* offset of the 16x16 pixel block within the tile */
 +   block_offset = ((iy/4)*(16*16) + (ix/4)*16);
 +
 +   /* color buffer */
 +   color = tile->color + 4 * block_offset;
 +
 +   /* depth buffer */
 +   depth = tile->depth + block_offset;
 +
 +#ifdef DEBUG
 +   assert(lp_check_alignment(depth, 16));
 +   assert(lp_check_alignment(color, 16));
 +   assert(lp_check_alignment(state->jit_context.blend_color, 16));
 +
 +   assert(lp_check_alignment(inputs->step[0], 16));
 +   assert(lp_check_alignment(inputs->step[1], 16));
 +   assert(lp_check_alignment(inputs->step[2], 16));
 +#endif
 +
 +   /* run shader */
 +   state->jit_function( &state->jit_context,
 +                        x, y,
 +                        inputs->a0,
 +                        inputs->dadx,
 +                        inputs->dady,
 +                        color,
 +                        depth,
 +                        c1, c2, c3,
 +                        inputs->step[0], inputs->step[1], inputs->step[2]
 +                        );
 +}
 +
 +
 +/* End of tile:
 + */
 +
 +
 +/**
 + * Write the rasterizer's color tile to the framebuffer.
 + */
 +static void lp_rast_store_color( struct lp_rasterizer *rast,
 +                                 unsigned thread_index)
 +{
 +   const unsigned x = rast->tasks[thread_index].x;
 +   const unsigned y = rast->tasks[thread_index].y;
 +   int w = TILE_SIZE;
 +   int h = TILE_SIZE;
 +
 +   if (x + w > rast->state.fb.width)
 +      w -= x + w - rast->state.fb.width;
 +
 +   if (y + h > rast->state.fb.height)
 +      h -= y + h - rast->state.fb.height;
 +
 +   assert(w >= 0);
 +   assert(h >= 0);
 +   assert(w <= TILE_SIZE);
 +   assert(h <= TILE_SIZE);
 +
 +   LP_DBG(DEBUG_RAST, "%s [%u] %d,%d %dx%d\n", __FUNCTION__,
 +          thread_index, x, y, w, h);
 +
-    assert(rast->zsbuf_transfer->format == PIPE_FORMAT_Z32_UNORM);
++   lp_tile_write_4ub(rast->cbuf_transfer->texture->format,
 +                     rast->tasks[thread_index].tile.color,
 +                     rast->cbuf_map, 
 +                     rast->cbuf_transfer->stride,
 +                     x, y,
 +                     w, h);
 +}
 +
 +
 +static void
 +lp_tile_write_z32(const uint32_t *src, uint8_t *dst, unsigned dst_stride,
 +                  unsigned x0, unsigned y0, unsigned w, unsigned h)
 +{
 +   unsigned x, y;
 +   uint8_t *dst_row = dst + y0*dst_stride;
 +   for (y = 0; y < h; ++y) {
 +      uint32_t *dst_pixel = (uint32_t *)(dst_row + x0*4);
 +      for (x = 0; x < w; ++x) {
 +         *dst_pixel++ = *src++;
 +      }
 +      dst_row += dst_stride;
 +   }
 +}
 +
 +/**
 + * Write the rasterizer's z/stencil tile to the framebuffer.
 + */
 +static void lp_rast_store_zstencil( struct lp_rasterizer *rast,
 +                                    unsigned thread_index )
 +{
 +   const unsigned x = rast->tasks[thread_index].x;
 +   const unsigned y = rast->tasks[thread_index].y;
 +   unsigned w = TILE_SIZE;
 +   unsigned h = TILE_SIZE;
 +
 +   if (x + w > rast->state.fb.width)
 +      w -= x + w - rast->state.fb.width;
 +
 +   if (y + h > rast->state.fb.height)
 +      h -= y + h - rast->state.fb.height;
 +
 +   LP_DBG(DEBUG_RAST, "%s %d,%d %dx%d\n", __FUNCTION__, x, y, w, h);
 +
++   assert(rast->zsbuf_transfer->texture->format == PIPE_FORMAT_Z32_UNORM);
 +   lp_tile_write_z32(rast->tasks[thread_index].tile.depth,
 +                     rast->zsbuf_map, 
 +                     rast->zsbuf_transfer->stride,
 +                     x, y, w, h);
 +}
 +
 +
 +/**
 + * Write the rasterizer's tiles to the framebuffer.
 + */
 +static void
 +lp_rast_end_tile( struct lp_rasterizer *rast,
 +                  unsigned thread_index )
 +{
 +   LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__);
 +
 +   if (rast->state.write_color)
 +      lp_rast_store_color(rast, thread_index);
 +
 +   if (rast->state.write_zstencil)
 +      lp_rast_store_zstencil(rast, thread_index);
 +}
 +
 +
 +/**
 + * Signal on a fence.  This is called during bin execution/rasterization.
 + * Called per thread.
 + */
 +void lp_rast_fence( struct lp_rasterizer *rast,
 +                    unsigned thread_index,
 +                    const union lp_rast_cmd_arg arg )
 +{
 +   struct lp_fence *fence = arg.fence;
 +
 +   pipe_mutex_lock( fence->mutex );
 +
 +   fence->count++;
 +   assert(fence->count <= fence->rank);
 +
 +   LP_DBG(DEBUG_RAST, "%s count=%u rank=%u\n", __FUNCTION__,
 +          fence->count, fence->rank);
 +
 +   pipe_condvar_signal( fence->signalled );
 +
 +   pipe_mutex_unlock( fence->mutex );
 +}
 +
 +
 +/**
 + * When all the threads are done rasterizing a scene, one thread will
 + * call this function to reset the scene and put it onto the empty queue.
 + */
 +static void
 +release_scene( struct lp_rasterizer *rast,
 +             struct lp_scene *scene )
 +{
 +   util_unreference_framebuffer_state( &scene->fb );
 +
 +   lp_scene_reset( scene );
 +   lp_scene_enqueue( rast->empty_scenes, scene );
 +   rast->curr_scene = NULL;
 +}
 +
 +
 +/**
 + * Rasterize commands for a single bin.
 + * \param x, y  position of the bin's tile in the framebuffer
 + * Must be called between lp_rast_begin() and lp_rast_end().
 + * Called per thread.
 + */
 +static void
 +rasterize_bin( struct lp_rasterizer *rast,
 +               unsigned thread_index,
 +               const struct cmd_bin *bin,
 +               int x, int y)
 +{
 +   const struct cmd_block_list *commands = &bin->commands;
 +   struct cmd_block *block;
 +   unsigned k;
 +
 +   lp_rast_start_tile( rast, thread_index, x, y );
 +
 +   /* simply execute each of the commands in the block list */
 +   for (block = commands->head; block; block = block->next) {
 +      for (k = 0; k < block->count; k++) {
 +         block->cmd[k]( rast, thread_index, block->arg[k] );
 +      }
 +   }
 +
 +   lp_rast_end_tile( rast, thread_index );
 +}
 +
 +
 +/**
 + * Rasterize/execute all bins within a scene.
 + * Called per thread.
 + */
 +static void
 +rasterize_scene( struct lp_rasterizer *rast,
 +                unsigned thread_index,
 +                struct lp_scene *scene,
 +                bool write_depth )
 +{
 +   /* loop over scene bins, rasterize each */
 +#if 0
 +   {
 +      unsigned i, j;
 +      for (i = 0; i < scene->tiles_x; i++) {
 +         for (j = 0; j < scene->tiles_y; j++) {
 +            struct cmd_bin *bin = lp_get_bin(scene, i, j);
 +            rasterize_bin( rast, thread_index,
 +                           bin, i * TILE_SIZE, j * TILE_SIZE );
 +         }
 +      }
 +   }
 +#else
 +   {
 +      struct cmd_bin *bin;
 +      int x, y;
 +
 +      assert(scene);
 +      while ((bin = lp_scene_bin_iter_next(scene, &x, &y))) {
 +         rasterize_bin( rast, thread_index, bin, x * TILE_SIZE, y * TILE_SIZE);
 +      }
 +   }
 +#endif
 +}
 +
 +
 +/**
 + * Called by setup module when it has something for us to render.
 + */
 +void
 +lp_rasterize_scene( struct lp_rasterizer *rast,
 +                   struct lp_scene *scene,
 +                   const struct pipe_framebuffer_state *fb,
 +                   bool write_depth )
 +{
 +   boolean debug = false;
 +
 +   LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
 +
 +   if (debug) {
 +      unsigned x, y;
 +      printf("rasterize scene:\n");
 +      printf("  data size: %u\n", lp_scene_data_size(scene));
 +      for (y = 0; y < scene->tiles_y; y++) {
 +         for (x = 0; x < scene->tiles_x; x++) {
 +            printf("  bin %u, %u size: %u\n", x, y,
 +                   lp_scene_bin_size(scene, x, y));
 +         }
 +      }
 +   }
 +
 +   /* save framebuffer state in the bin */
 +   util_copy_framebuffer_state(&scene->fb, fb);
 +   scene->write_depth = write_depth;
 +
 +   if (rast->num_threads == 0) {
 +      /* no threading */
 +
 +      lp_rast_begin( rast, fb,
 +                     fb->cbufs[0]!= NULL,
 +                     fb->zsbuf != NULL && write_depth );
 +
 +      lp_scene_bin_iter_begin( scene );
 +      rasterize_scene( rast, 0, scene, write_depth );
 +
 +      release_scene( rast, scene );
 +
 +      lp_rast_end( rast );
 +   }
 +   else {
 +      /* threaded rendering! */
 +      unsigned i;
 +
 +      lp_scene_enqueue( rast->full_scenes, scene );
 +
 +      /* signal the threads that there's work to do */
 +      for (i = 0; i < rast->num_threads; i++) {
 +         pipe_semaphore_signal(&rast->tasks[i].work_ready);
 +      }
 +
 +      /* wait for work to complete */
 +      for (i = 0; i < rast->num_threads; i++) {
 +         pipe_semaphore_wait(&rast->tasks[i].work_done);
 +      }
 +   }
 +
 +   LP_DBG(DEBUG_SETUP, "%s done \n", __FUNCTION__);
 +}
 +
 +
 +/**
 + * This is the thread's main entrypoint.
 + * It's a simple loop:
 + *   1. wait for work
 + *   2. do work
 + *   3. signal that we're done
 + */
 +static void *
 +thread_func( void *init_data )
 +{
 +   struct lp_rasterizer_task *task = (struct lp_rasterizer_task *) init_data;
 +   struct lp_rasterizer *rast = task->rast;
 +   boolean debug = false;
 +
 +   while (1) {
 +      /* wait for work */
 +      if (debug)
 +         debug_printf("thread %d waiting for work\n", task->thread_index);
 +      pipe_semaphore_wait(&task->work_ready);
 +
 +      if (task->thread_index == 0) {
 +         /* thread[0]:
 +          *  - get next scene to rasterize
 +          *  - map the framebuffer surfaces
 +          */
 +         const struct pipe_framebuffer_state *fb;
 +         boolean write_depth;
 +
 +         rast->curr_scene = lp_scene_dequeue( rast->full_scenes );
 +
 +         lp_scene_bin_iter_begin( rast->curr_scene );
 +
 +         fb = &rast->curr_scene->fb;
 +         write_depth = rast->curr_scene->write_depth;
 +
 +         lp_rast_begin( rast, fb,
 +                        fb->cbufs[0] != NULL,
 +                        fb->zsbuf != NULL && write_depth );
 +      }
 +
 +      /* Wait for all threads to get here so that threads[1+] don't
 +       * get a null rast->curr_scene pointer.
 +       */
 +      pipe_barrier_wait( &rast->barrier );
 +
 +      /* do work */
 +      if (debug)
 +         debug_printf("thread %d doing work\n", task->thread_index);
 +      rasterize_scene(rast, 
 +                   task->thread_index,
 +                     rast->curr_scene, 
 +                   rast->curr_scene->write_depth);
 +      
 +      /* wait for all threads to finish with this scene */
 +      pipe_barrier_wait( &rast->barrier );
 +
 +      if (task->thread_index == 0) {
 +         /* thread[0]:
 +          * - release the scene object
 +          * - unmap the framebuffer surfaces
 +          */
 +         release_scene( rast, rast->curr_scene );
 +         lp_rast_end( rast );
 +      }
 +
 +      /* signal done with work */
 +      if (debug)
 +         debug_printf("thread %d done working\n", task->thread_index);
 +      pipe_semaphore_signal(&task->work_done);
 +   }
 +
 +   return NULL;
 +}
 +
 +
 +/**
 + * Initialize semaphores and spawn the threads.
 + */
 +static void
 +create_rast_threads(struct lp_rasterizer *rast)
 +{
 +   unsigned i;
 +
 +   rast->num_threads = util_cpu_caps.nr_cpus;
 +   rast->num_threads = debug_get_num_option("LP_NUM_THREADS", rast->num_threads);
 +   rast->num_threads = MIN2(rast->num_threads, MAX_THREADS);
 +
 +   /* NOTE: if num_threads is zero, we won't use any threads */
 +   for (i = 0; i < rast->num_threads; i++) {
 +      pipe_semaphore_init(&rast->tasks[i].work_ready, 0);
 +      pipe_semaphore_init(&rast->tasks[i].work_done, 0);
 +      rast->threads[i] = pipe_thread_create(thread_func,
 +                                            (void *) &rast->tasks[i]);
 +   }
 +}
 +
 +
 +
 +/**
 + * Create new lp_rasterizer.
 + * \param empty  the queue to put empty scenes on after we've finished
 + *               processing them.
 + */
 +struct lp_rasterizer *
 +lp_rast_create( struct pipe_screen *screen, struct lp_scene_queue *empty )
 +{
 +   struct lp_rasterizer *rast;
 +   unsigned i;
 +
 +   rast = CALLOC_STRUCT(lp_rasterizer);
 +   if(!rast)
 +      return NULL;
 +
 +   rast->screen = screen;
 +
 +   rast->empty_scenes = empty;
 +   rast->full_scenes = lp_scene_queue_create();
 +
 +   for (i = 0; i < Elements(rast->tasks); i++) {
 +      rast->tasks[i].tile.color = align_malloc( TILE_SIZE*TILE_SIZE*4, 16 );
 +      rast->tasks[i].tile.depth = align_malloc( TILE_SIZE*TILE_SIZE*4, 16 );
 +      rast->tasks[i].rast = rast;
 +      rast->tasks[i].thread_index = i;
 +   }
 +
 +   create_rast_threads(rast);
 +
 +   /* for synchronizing rasterization threads */
 +   pipe_barrier_init( &rast->barrier, rast->num_threads );
 +
 +   return rast;
 +}
 +
 +
 +/* Shutdown:
 + */
 +void lp_rast_destroy( struct lp_rasterizer *rast )
 +{
 +   unsigned i;
 +
 +   util_unreference_framebuffer_state(&rast->state.fb);
 +
 +   for (i = 0; i < Elements(rast->tasks); i++) {
 +      align_free(rast->tasks[i].tile.depth);
 +      align_free(rast->tasks[i].tile.color);
 +   }
 +
 +   /* for synchronizing rasterization threads */
 +   pipe_barrier_destroy( &rast->barrier );
 +
 +   FREE(rast);
 +}
 +
 +
 +/** Return number of rasterization threads */
 +unsigned
 +lp_rast_get_num_threads( struct lp_rasterizer *rast )
 +{
 +   return rast->num_threads;
 +}
index 017496ea5fc5f5289798c339a46d17414a59029f,9b47415f003350c7592894fb6338f50c7943e2b6..a28f6935b68fac8e3817a4c71ffc3b384860d10d
  
  
  #include "util/u_memory.h"
+ #include "util/u_format.h"
  #include "pipe/p_defines.h"
  #include "pipe/p_screen.h"
  
  #include "lp_texture.h"
  #include "lp_buffer.h"
 +#include "lp_fence.h"
  #include "lp_winsys.h"
  #include "lp_jit.h"
  #include "lp_screen.h"
@@@ -77,7 -77,9 +78,9 @@@ llvmpipe_get_param(struct pipe_screen *
     case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
        return PIPE_MAX_SAMPLERS;
     case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS:
-       return PIPE_MAX_SAMPLERS;
+       return PIPE_MAX_VERTEX_SAMPLERS;
+    case PIPE_CAP_MAX_COMBINED_SAMPLERS:
+       return PIPE_MAX_SAMPLERS + PIPE_MAX_VERTEX_SAMPLERS;
     case PIPE_CAP_NPOT_TEXTURES:
        return 1;
     case PIPE_CAP_TWO_SIDED_STENCIL:
@@@ -150,17 -152,17 +153,17 @@@ llvmpipe_is_format_supported( struct pi
  {
     struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
     struct llvmpipe_winsys *winsys = screen->winsys;
+    const struct util_format_description *format_desc;
+    format_desc = util_format_description(format);
+    if(!format_desc)
+       return FALSE;
  
     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:
        break;
     }
  
-    if(tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET)
-       return winsys->is_displaytarget_format_supported(winsys, format);
+    if(tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) {
+       if(format_desc->block.width != 1 ||
+          format_desc->block.height != 1)
+          return FALSE;
+       if(format_desc->layout != UTIL_FORMAT_LAYOUT_SCALAR &&
+          format_desc->layout != UTIL_FORMAT_LAYOUT_ARITH &&
+          format_desc->layout != UTIL_FORMAT_LAYOUT_ARRAY)
+          return FALSE;
+       if(format_desc->colorspace != UTIL_FORMAT_COLORSPACE_RGB &&
+          format_desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB)
+          return FALSE;
+    }
+    if(tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) {
+       if(!winsys->is_displaytarget_format_supported(winsys, format))
+          return FALSE;
+    }
+    if(tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL) {
+       if(format_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS)
+          return FALSE;
+       /* FIXME: Temporary restriction. See lp_state_fs.c. */
+       if(format_desc->block.bits != 32)
+          return FALSE;
+    }
+    /* FIXME: Temporary restrictions. See lp_bld_sample_soa.c */
+    if(tex_usage & PIPE_TEXTURE_USAGE_SAMPLER) {
+       if(format_desc->block.width != 1 ||
+          format_desc->block.height != 1)
+          return FALSE;
+       if(format_desc->layout != UTIL_FORMAT_LAYOUT_SCALAR &&
+          format_desc->layout != UTIL_FORMAT_LAYOUT_ARITH &&
+          format_desc->layout != UTIL_FORMAT_LAYOUT_ARRAY)
+          return FALSE;
+       if(format_desc->colorspace != UTIL_FORMAT_COLORSPACE_RGB &&
+          format_desc->colorspace != UTIL_FORMAT_COLORSPACE_SRGB &&
+          format_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS)
+          return FALSE;
+    }
  
     return TRUE;
  }
@@@ -254,7 -299,6 +300,7 @@@ llvmpipe_create_screen(struct llvmpipe_
  
     llvmpipe_init_screen_texture_funcs(&screen->base);
     llvmpipe_init_screen_buffer_funcs(&screen->base);
 +   llvmpipe_init_screen_fence_funcs(&screen->base);
  
     lp_jit_screen_init(screen);
  
index 1eb944a0de7901b88f1d1afd2da46a58eff5ebb6,b18f17c0cd34a2ef76f1b01e360d0f58b9d612d3..5cdcf4ecc985f0521ddcc9836aa8bc436ee5b5be
   **************************************************************************/
  
  /**
 - * \brief  Primitive rasterization/rendering (points, lines, triangles)
 + * Tiling engine.
   *
 - * \author  Keith Whitwell <keith@tungstengraphics.com>
 - * \author  Brian Paul
 + * Builds per-tile display lists and executes them on calls to
 + * lp_setup_flush().
   */
  
 -#include "lp_context.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_format.h"
 -#include "util/u_math.h"
 +#include "pipe/p_defines.h"
 +#include "pipe/p_inlines.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;
 -
 -   float pixel_offset;
 -
 -   struct quad_header quad[MAX_QUADS];
 -   struct quad_header *quad_ptrs[MAX_QUADS];
 -   unsigned count;
 +#include "util/u_pack_color.h"
 +#include "util/u_surface.h"
 +#include "lp_scene.h"
 +#include "lp_scene_queue.h"
 +#include "lp_buffer.h"
 +#include "lp_texture.h"
 +#include "lp_debug.h"
 +#include "lp_fence.h"
 +#include "lp_rast.h"
 +#include "lp_setup_context.h"
  
 -   struct quad_interp_coef coef;
 +#include "draw/draw_context.h"
 +#include "draw/draw_vbuf.h"
  
 -   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
 +/** XXX temporary value, temporary here */
 +#define MAX_SCENES 2
  
 -   unsigned winding;          /* which winding to cull */
 -};
  
 +static void set_scene_state( struct setup_context *, unsigned );
  
  
 -/**
 - * Execute fragment shader for the four fragments in the quad.
 - */
 -ALIGN_STACK
 -static void
 -shade_quads(struct llvmpipe_context *llvmpipe,
 -            struct quad_header *quads[],
 -            unsigned nr)
 +struct lp_scene *
 +lp_setup_get_current_scene(struct setup_context *setup)
  {
 -   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;
 -   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;
 +   if (!setup->scene) {
 +      /* wait for a free/empty bin */
 +      setup->scene = lp_scene_dequeue(setup->empty_scenes);
 +      if(0)lp_scene_reset( setup->scene ); /* XXX temporary? */
  
 -   /* 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 */
 -   if(llvmpipe->framebuffer.nr_cbufs >= 1 &&
 -      llvmpipe->framebuffer.cbufs[0]) {
 -      tile = lp_get_cached_tile(llvmpipe->cbuf_cache[0], x, y);
 -      color = &TILE_PIXEL(tile, x & (TILE_SIZE-1), y & (TILE_SIZE-1), 0);
 -   }
 -   else
 -      color = NULL;
 -
 -   /* 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*util_format_get_blocksize(llvmpipe->zsbuf_transfer->texture->format);
 +      lp_scene_set_framebuffer_size(setup->scene,
 +                                    setup->fb.width, 
 +                                    setup->fb.height);
     }
 -   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);
 +   return setup->scene;
  }
  
  
 -
 -
 -/**
 - * 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)
 +static void
 +first_triangle( struct setup_context *setup,
 +                const float (*v0)[4],
 +                const float (*v1)[4],
 +                const float (*v2)[4])
  {
 -   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;
 +   set_scene_state( setup, SETUP_ACTIVE );
 +   lp_setup_choose_triangle( setup );
 +   setup->triangle( setup, v0, v1, v2 );
  }
  
 -
 -
 -/**
 - * Clip setup->quad against the scissor/surface bounds.
 - */
 -static INLINE void
 -quad_clip( struct setup_context *setup, struct quad_header *quad )
 +static void
 +first_line( struct setup_context *setup,
 +          const float (*v0)[4],
 +          const float (*v1)[4])
  {
 -   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);
 +   set_scene_state( setup, SETUP_ACTIVE );
 +   lp_setup_choose_line( setup );
 +   setup->line( setup, v0, v1 );
  }
  
 -
 -
 -/**
 - * Given an X or Y coordinate, return the block/quad coordinate that it
 - * belongs to.
 - */
 -static INLINE int block( int x )
 +static void
 +first_point( struct setup_context *setup,
 +           const float (*v0)[4])
  {
 -   return x & ~(2-1);
 +   set_scene_state( setup, SETUP_ACTIVE );
 +   lp_setup_choose_point( setup );
 +   setup->point( setup, v0 );
  }
  
 -static INLINE int block_x( int x )
 +static void reset_context( struct setup_context *setup )
  {
 -   return x & ~(TILE_VECTOR_WIDTH - 1);
 -}
 +   LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
  
 +   /* Reset derived state */
 +   setup->constants.stored_size = 0;
 +   setup->constants.stored_data = NULL;
 +   setup->fs.stored = NULL;
 +   setup->dirty = ~0;
  
 -/**
 - * 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[4];
 -      struct quad_header *quad_ptrs[4];
 -      int x0 = block_x(quad->input.x0);
 -      unsigned i;
 -
 -      assert(nr_quads == 4);
 -
 -      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];
 -      }
 +   /* no current bin */
 +   setup->scene = NULL;
  
 -      shade_quads( lp, quad_ptrs, nr_quads );
 -#else
 -      shade_quads( lp, &quad, 1 );
 -#endif
 -   }
 +   /* Reset some state:
 +    */
 +   setup->clear.flags = 0;
 +
 +   /* Have an explicit "start-binning" call and get rid of this
 +    * pointer twiddling?
 +    */
 +   setup->line = first_line;
 +   setup->point = first_point;
 +   setup->triangle = first_triangle;
  }
  
  
 -/**
 - * Render a horizontal span of quads
 - */
 -static void flush_spans( struct setup_context *setup )
 +/** Rasterize all scene's bins */
 +static void
 +lp_setup_rasterize_scene( struct setup_context *setup,
 +                       boolean write_depth )
  {
 -   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));
 +   struct lp_scene *scene = lp_setup_get_current_scene(setup);
  
 -         shade_quads(setup->llvmpipe, setup->quad_ptrs, nr_quads );
 -      }
 -   }
 +   lp_rasterize_scene(setup->rast,
 +                      scene,
 +                      &setup->fb,
 +                      write_depth);
  
 +   reset_context( setup );
  
 -   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] */
 +   LP_DBG(DEBUG_SETUP, "%s done \n", __FUNCTION__);
  }
  
  
 -#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] )
 +static void
 +begin_binning( struct setup_context *setup )
  {
 -   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;
 -   }
 +   struct lp_scene *scene = lp_setup_get_current_scene(setup);
  
 -   /* 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));
 +   LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
  
 -   /* Prepare pixel offset for rasterisation:
 -    *  - pixel center (0.5, 0.5) for GL, or
 -    *  - assume (0.0, 0.0) for other APIs.
 -    */
 -   if (setup->llvmpipe->rasterizer->gl_rasterization_rules) {
 -      setup->pixel_offset = 0.5f;
 -   } else {
 -      setup->pixel_offset = 0.0f;
 +   if (setup->fb.cbufs[0]) {
 +      if (setup->clear.flags & PIPE_CLEAR_COLOR)
 +         lp_scene_bin_everywhere( scene, 
 +                            lp_rast_clear_color, 
 +                            setup->clear.color );
 +      else
 +         lp_scene_bin_everywhere( scene,
 +                            lp_rast_load_color,
 +                            lp_rast_arg_null() );
     }
  
 -   return TRUE;
 -}
 -
 +   if (setup->fb.zsbuf) {
 +      if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL)
 +         lp_scene_bin_everywhere( scene, 
 +                            lp_rast_clear_zstencil, 
 +                            setup->clear.zstencil );
 +      else
 +         lp_scene_bin_everywhere( scene,
 +                            lp_rast_load_zstencil,
 +                            lp_rast_arg_null() );
 +   }
  
 -/**
 - * 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 (pixel_offset, pixel_offset).
 -    *
 -    * 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] - setup->pixel_offset) +
 -                            dady * (setup->vmin[0][1] - setup->pixel_offset)));
 -
 -   /*
 -   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]);
 -   */
 +   LP_DBG(DEBUG_SETUP, "%s done\n", __FUNCTION__);
  }
  
  
 -/**
 - * 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)
 +/* This basically bins and then flushes any outstanding full-screen
 + * clears.  
 + *
 + * TODO: fast path for fullscreen clears and no triangles.
   */
 -static void const_pos_coeff( struct setup_context *setup,
 -                             uint vertSlot, unsigned i)
 +static void
 +execute_clears( struct setup_context *setup )
  {
 -   setup->coef.dadx[0][i] = 0;
 -   setup->coef.dady[0][i] = 0;
 +   LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
  
 -   /* need provoking vertex info!
 -    */
 -   setup->coef.a0[0][i] = setup->vprovoke[vertSlot][i];
 +   begin_binning( setup );
 +   lp_setup_rasterize_scene( setup, 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,
 -                         unsigned attrib,
 -                         uint vertSlot)
 +static void
 +set_scene_state( struct setup_context *setup,
 +           unsigned new_state )
  {
 -   unsigned i;
 -   for (i = 0; i < NUM_CHANNELS; ++i) {
 -      setup->coef.dadx[1 + attrib][i] = 0;
 -      setup->coef.dady[1 + attrib][i] = 0;
 +   unsigned old_state = setup->state;
  
 -      /* need provoking vertex info!
 -       */
 -      setup->coef.a0[1 + attrib][i] = setup->vprovoke[vertSlot][i];
 -   }
 -}
 +   if (old_state == new_state)
 +      return;
 +       
 +   LP_DBG(DEBUG_SETUP, "%s old %d new %d\n", __FUNCTION__, old_state, new_state);
  
 +   switch (new_state) {
 +   case SETUP_ACTIVE:
 +      begin_binning( setup );
 +      break;
  
 -/**
 - * 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] - setup->pixel_offset) +
 -                      dady * (setup->vmin[0][1] - setup->pixel_offset)));
 -
 -      /*
 -      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]);
 -      */
 +   case SETUP_CLEARED:
 +      if (old_state == SETUP_ACTIVE) {
 +         assert(0);
 +         return;
 +      }
 +      break;
 +      
 +   case SETUP_FLUSHED:
 +      if (old_state == SETUP_CLEARED)
 +         execute_clears( setup );
 +      else
 +         lp_setup_rasterize_scene( setup, TRUE );
 +      break;
     }
 -}
 -
  
 -/**
 - * 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] - setup->pixel_offset) +
 -                      dady * (setup->vmin[0][1] - setup->pixel_offset)));
 -   }
 +   setup->state = new_state;
  }
  
  
 -/**
 - * 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)
 +void
 +lp_setup_flush( struct setup_context *setup,
 +                unsigned flags )
  {
 -   /*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];
 -}
 +   LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
  
 +   set_scene_state( setup, SETUP_FLUSHED );
 +}
  
  
 -/**
 - * 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 )
 +void
 +lp_setup_bind_framebuffer( struct setup_context *setup,
 +                           const struct pipe_framebuffer_state *fb )
  {
 -   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;
 +   struct lp_scene *scene = lp_setup_get_current_scene(setup);
  
 -   /* z and w are done by linear interpolation:
 -    */
 -   tri_pos_coeff(setup, 0, 2);
 -   tri_pos_coeff(setup, 0, 3);
 +   LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
  
 -   /* setup interpolation for all the remaining attributes:
 -    */
 -   for (fragSlot = 0; fragSlot < lpfs->info.num_inputs; fragSlot++) {
 -      const uint vertSlot = vinfo->attrib[fragSlot].src_index;
 +   set_scene_state( setup, SETUP_FLUSHED );
  
 -      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);
 -      }
 +   util_copy_framebuffer_state(&setup->fb, fb);
  
 -      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;
 -      }
 -   }
 +   lp_scene_set_framebuffer_size(scene, setup->fb.width, setup->fb.height);
  }
  
  
 -
 -static void setup_tri_edges( struct setup_context *setup )
 +void
 +lp_setup_clear( struct setup_context *setup,
 +                const float *color,
 +                double depth,
 +                unsigned stencil,
 +                unsigned flags )
  {
 -   float vmin_x = setup->vmin[0][0] + setup->pixel_offset;
 -   float vmid_x = setup->vmid[0][0] + setup->pixel_offset;
 -
 -   float vmin_y = setup->vmin[0][1] - setup->pixel_offset;
 -   float vmid_y = setup->vmid[0][1] - setup->pixel_offset;
 -   float vmax_y = setup->vmax[0][1] - setup->pixel_offset;
 -
 -   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;
 -}
 +   struct lp_scene *scene = lp_setup_get_current_scene(setup);
 +   unsigned i;
  
 +   LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state);
  
 -/**
 - * 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;
 -      }
 +   if (flags & PIPE_CLEAR_COLOR) {
 +      for (i = 0; i < 4; ++i)
 +         setup->clear.color.clear_color[i] = float_to_ubyte(color[i]);
     }
  
 +   if (flags & PIPE_CLEAR_DEPTHSTENCIL) {
 +      setup->clear.zstencil.clear_zstencil = 
 +         util_pack_z_stencil(setup->fb.zsbuf->format, 
 +                             depth,
 +                             stencil);
 +   }
  
 -   /* 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;
 -}
 +   if (setup->state == SETUP_ACTIVE) {
 +      /* Add the clear to existing scene.  In the unusual case where
 +       * both color and depth-stencil are being cleared when there's
 +       * already been some rendering, we could discard the currently
 +       * binned scene and start again, but I don't see that as being
 +       * a common usage.
 +       */
 +      if (flags & PIPE_CLEAR_COLOR)
 +         lp_scene_bin_everywhere( scene, 
 +                            lp_rast_clear_color, 
 +                            setup->clear.color );
  
 +      if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL)
 +         lp_scene_bin_everywhere( scene, 
 +                            lp_rast_clear_zstencil, 
 +                            setup->clear.zstencil );
 +   }
 +   else {
 +      /* Put ourselves into the 'pre-clear' state, specifically to try
 +       * and accumulate multiple clears to color and depth_stencil
 +       * buffers which the app or state-tracker might issue
 +       * separately.
 +       */
 +      set_scene_state( setup, SETUP_CLEARED );
  
 -/**
 - * 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;
 +      setup->clear.flags |= flags;
 +   }
  }
  
  
  /**
 - * Do setup for triangle rasterization, then render the triangle.
 + * Emit a fence.
   */
 -void llvmpipe_setup_tri( struct setup_context *setup,
 -                const float (*v0)[4],
 -                const float (*v1)[4],
 -                const float (*v2)[4] )
 +struct pipe_fence_handle *
 +lp_setup_fence( struct setup_context *setup )
  {
 -   float det;
 +   struct lp_scene *scene = lp_setup_get_current_scene(setup);
 +   const unsigned rank = lp_scene_get_num_bins( scene ); /* xxx */
 +   struct lp_fence *fence = lp_fence_create(rank);
  
 -#if DEBUG_VERTS
 -   debug_printf("Setup triangle:\n");
 -   print_vertex(setup, v0);
 -   print_vertex(setup, v1);
 -   print_vertex(setup, v2);
 -#endif
 +   LP_DBG(DEBUG_SETUP, "%s rank %u\n", __FUNCTION__, rank);
  
 -   if (setup->llvmpipe->no_rast)
 -      return;
 -   
 -   det = calc_det(v0, v1, v2);
 -   /*
 -   debug_printf("%s\n", __FUNCTION__ );
 -   */
 +   set_scene_state( setup, SETUP_ACTIVE );
  
 -#if DEBUG_FRAGS
 -   setup->numFragsEmitted = 0;
 -   setup->numFragsWritten = 0;
 -#endif
 +   /* insert the fence into all command bins */
 +   lp_scene_bin_everywhere( scene,
 +                          lp_rast_fence,
 +                          lp_rast_arg_fence(fence) );
  
 -   if (cull_tri( setup, det ))
 -      return;
 +   return (struct pipe_fence_handle *) fence;
 +}
  
 -   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);
 +void 
 +lp_setup_set_triangle_state( struct setup_context *setup,
 +                             unsigned cull_mode,
 +                             boolean ccw_is_frontface)
 +{
 +   LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
  
 -   setup->span.y = 0;
 -   setup->span.right[0] = 0;
 -   setup->span.right[1] = 0;
 -   /*   setup->span.z_mode = tri_z_mode( setup->ctx ); */
 +   setup->ccw_is_frontface = ccw_is_frontface;
 +   setup->cullmode = cull_mode;
 +   setup->triangle = first_triangle;
 +}
  
 -   /*   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 );
 +void
 +lp_setup_set_fs_inputs( struct setup_context *setup,
 +                        const struct lp_shader_input *input,
 +                        unsigned nr )
 +{
 +   LP_DBG(DEBUG_SETUP, "%s %p %u\n", __FUNCTION__, (void *) input, nr);
  
 -#if DEBUG_FRAGS
 -   printf("Tri: %u frags emitted, %u written\n",
 -          setup->numFragsEmitted,
 -          setup->numFragsWritten);
 -#endif
 +   memcpy( setup->fs.input, input, nr * sizeof input[0] );
 +   setup->fs.nr_inputs = nr;
  }
  
 +void
 +lp_setup_set_fs_function( struct setup_context *setup,
 +                          lp_jit_frag_func jit_function )
 +{
 +   LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) jit_function);
 +   /* FIXME: reference count */
  
 +   setup->fs.current.jit_function = jit_function;
 +   setup->dirty |= LP_SETUP_NEW_FS;
 +}
  
 -/**
 - * 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)
 +void
 +lp_setup_set_fs_constants(struct setup_context *setup,
 +                          struct pipe_buffer *buffer)
  {
 -   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] - setup->pixel_offset) +
 -                            dady * (setup->vmin[0][1] - setup->pixel_offset)));
 -}
 +   LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) buffer);
  
 +   pipe_buffer_reference(&setup->constants.current, buffer);
  
 -/**
 - * 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] - setup->pixel_offset) +
 -                      dady * (setup->vmin[0][1] - setup->pixel_offset)));
 -   }
 +   setup->dirty |= LP_SETUP_NEW_CONSTANTS;
  }
  
  
 -/**
 - * 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)
 +void
 +lp_setup_set_alpha_ref_value( struct setup_context *setup,
 +                              float alpha_ref_value )
  {
 -   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] - setup->pixel_offset) +
 -                      dady * (setup->vmin[0][1] - setup->pixel_offset)));
 +   LP_DBG(DEBUG_SETUP, "%s %f\n", __FUNCTION__, alpha_ref_value);
 +
 +   if(setup->fs.current.jit_context.alpha_ref_value != alpha_ref_value) {
 +      setup->fs.current.jit_context.alpha_ref_value = alpha_ref_value;
 +      setup->dirty |= LP_SETUP_NEW_FS;
     }
  }
  
 -
 -/**
 - * 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])
 +void
 +lp_setup_set_blend_color( struct setup_context *setup,
 +                          const struct pipe_blend_color *blend_color )
  {
 -   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);
 +   LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
  
 -   /* setup interpolation for all the remaining attributes:
 -    */
 -   for (fragSlot = 0; fragSlot < lpfs->info.num_inputs; fragSlot++) {
 -      const uint vertSlot = vinfo->attrib[fragSlot].src_index;
 +   assert(blend_color);
  
 -      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;
 -      }
 +   if(memcmp(&setup->blend_color.current, blend_color, sizeof *blend_color) != 0) {
 +      memcpy(&setup->blend_color.current, blend_color, sizeof *blend_color);
 +      setup->dirty |= LP_SETUP_NEW_BLEND_COLOR;
     }
 -   return TRUE;
  }
  
  
 -/**
 - * Plot a pixel in a line segment.
 - */
 -static INLINE void
 -plot(struct setup_context *setup, int x, int y)
 +void 
 +lp_setup_set_flatshade_first( struct setup_context *setup,
 +                              boolean flatshade_first )
  {
 -   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;
 +   setup->flatshade_first = flatshade_first;
  }
  
  
 -/**
 - * 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])
 +void 
 +lp_setup_set_vertex_info( struct setup_context *setup,
 +                          struct vertex_info *vertex_info )
  {
 -   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;
 +   /* XXX: just silently holding onto the pointer:
 +    */
 +   setup->vertex_info = vertex_info;
 +}
  
 -   if (dx == 0 && dy == 0)
 -      return;
  
 -   if (!setup_line_coefficients(setup, v0, v1))
 -      return;
 +void
 +lp_setup_set_sampler_textures( struct setup_context *setup,
 +                               unsigned num, struct pipe_texture **texture)
 +{
 +   struct pipe_texture *dummy;
 +   unsigned i;
  
 -   assert(v0[0][0] < 1.0e9);
 -   assert(v0[0][1] < 1.0e9);
 -   assert(v1[0][0] < 1.0e9);
 -   assert(v1[0][1] < 1.0e9);
 +   LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
  
 -   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(num <= PIPE_MAX_SAMPLERS);
  
 -   assert(dx >= 0);
 -   assert(dy >= 0);
 -   assert(setup->llvmpipe->reduced_prim == PIPE_PRIM_LINES);
 +   for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
 +      struct pipe_texture *tex = i < num ? texture[i] : NULL;
  
 -   setup->quad[0].input.x0 = setup->quad[0].input.y0 = -1;
 -   setup->quad[0].inout.mask = 0x0;
 +      /* FIXME: hold on to the reference */
 +      dummy = NULL;
 +      pipe_texture_reference(&dummy, tex);
  
 -   /* 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;
 -         }
 +      if(tex) {
 +         struct llvmpipe_texture *lp_tex = llvmpipe_texture(tex);
 +         struct lp_jit_texture *jit_tex;
 +         jit_tex = &setup->fs.current.jit_context.textures[i];
-          jit_tex->width = tex->width[0];
-          jit_tex->height = tex->height[0];
++         jit_tex->width = tex->width0;
++         jit_tex->height = tex->height0;
 +         jit_tex->stride = lp_tex->stride[0];
 +         if(!lp_tex->dt)
 +            jit_tex->data = lp_tex->data;
 +         else
 +            /* FIXME: map the rendertarget */
 +            assert(0);
        }
     }
  
 -   /* draw final quad */
 -   if (setup->quad[0].inout.mask) {
 -      clip_emit_quad( setup, &setup->quad[0] );
 -   }
 +   setup->dirty |= LP_SETUP_NEW_FS;
  }
  
 -
 -static void
 -point_persp_coeff(struct setup_context *setup,
 -                  const float (*vert)[4],
 -                  unsigned attrib,
 -                  uint vertSlot)
 +boolean
 +lp_setup_is_texture_referenced( struct setup_context *setup,
 +                                const struct pipe_texture *texture )
  {
 -   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];
 -   }
 +   /* FIXME */
 +   return PIPE_UNREFERENCED;
  }
  
  
 -/**
 - * 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] )
 +lp_setup_update_state( struct setup_context *setup )
  {
 -   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;
 +   struct lp_scene *scene = lp_setup_get_current_scene(setup);
  
 -   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;
 +   LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
  
 -   /* setup Z, W */
 -   const_pos_coeff(setup, 0, 2);
 -   const_pos_coeff(setup, 0, 3);
 +   assert(setup->fs.current.jit_function);
  
 -   for (fragSlot = 0; fragSlot < lpfs->info.num_inputs; fragSlot++) {
 -      const uint vertSlot = vinfo->attrib[fragSlot].src_index;
 +   if(setup->dirty & LP_SETUP_NEW_BLEND_COLOR) {
 +      uint8_t *stored;
 +      unsigned i, j;
  
 -      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);
 -      }
 +      stored = lp_scene_alloc_aligned(scene, 4 * 16, 16);
  
 -      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;
 +      /* smear each blend color component across 16 ubyte elements */
 +      for (i = 0; i < 4; ++i) {
 +         uint8_t c = float_to_ubyte(setup->blend_color.current.color[i]);
 +         for (j = 0; j < 16; ++j)
 +            stored[i*16 + j] = c;
        }
 -   }
  
 +      setup->blend_color.stored = stored;
  
 -   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] );
 +      setup->fs.current.jit_context.blend_color = setup->blend_color.stored;
 +      setup->dirty |= LP_SETUP_NEW_FS;
     }
 -   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] );
 -               }
 +
 +
 +   if(setup->dirty & LP_SETUP_NEW_CONSTANTS) {
 +      struct pipe_buffer *buffer = setup->constants.current;
 +
 +      if(buffer) {
 +         unsigned current_size = buffer->size;
 +         const void *current_data = llvmpipe_buffer(buffer)->data;
 +
 +         /* TODO: copy only the actually used constants? */
 +
 +         if(setup->constants.stored_size != current_size ||
 +            !setup->constants.stored_data ||
 +            memcmp(setup->constants.stored_data,
 +                   current_data,
 +                   current_size) != 0) {
 +            void *stored;
 +
 +            stored = lp_scene_alloc(scene, current_size);
 +            if(stored) {
 +               memcpy(stored,
 +                      current_data,
 +                      current_size);
 +               setup->constants.stored_size = current_size;
 +               setup->constants.stored_data = stored;
              }
           }
        }
        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);
 -            }
 +         setup->constants.stored_size = 0;
 +         setup->constants.stored_data = NULL;
 +      }
  
 -            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] );
 -            }
 +      setup->fs.current.jit_context.constants = setup->constants.stored_data;
 +      setup->dirty |= LP_SETUP_NEW_FS;
 +   }
 +
 +
 +   if(setup->dirty & LP_SETUP_NEW_FS) {
 +      if(!setup->fs.stored ||
 +         memcmp(setup->fs.stored,
 +                &setup->fs.current,
 +                sizeof setup->fs.current) != 0) {
 +         /* The fs state that's been stored in the scene is different from
 +          * the new, current state.  So allocate a new lp_rast_state object
 +          * and append it to the bin's setup data buffer.
 +          */
 +         struct lp_rast_state *stored =
 +            (struct lp_rast_state *) lp_scene_alloc(scene, sizeof *stored);
 +         if(stored) {
 +            memcpy(stored,
 +                   &setup->fs.current,
 +                   sizeof setup->fs.current);
 +            setup->fs.stored = stored;
 +
 +            /* put the state-set command into all bins */
 +            lp_scene_bin_state_command( scene,
 +                                      lp_rast_set_state, 
 +                                      lp_rast_arg_state(setup->fs.stored) );
           }
        }
     }
 +
 +   setup->dirty = 0;
 +
 +   assert(setup->fs.stored);
  }
  
 -void llvmpipe_setup_prepare( struct setup_context *setup )
 +
 +
 +/* Only caller is lp_setup_vbuf_destroy()
 + */
 +void 
 +lp_setup_destroy( struct setup_context *setup )
  {
 -   struct llvmpipe_context *lp = setup->llvmpipe;
 +   reset_context( setup );
  
 -   if (lp->dirty) {
 -      llvmpipe_update_derived(lp);
 -   }
 +   pipe_buffer_reference(&setup->constants.current, NULL);
  
 -   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;
 +   /* free the scenes in the 'empty' queue */
 +   while (lp_scene_queue_count(setup->empty_scenes) > 0) {
 +      struct lp_scene *scene = lp_scene_dequeue(setup->empty_scenes);
 +      if (!scene)
 +         break;
 +      lp_scene_destroy(scene);
     }
 -}
 -
  
 +   lp_rast_destroy( setup->rast );
  
 -void llvmpipe_setup_destroy_context( struct setup_context *setup )
 -{
 -   align_free( setup );
 +   FREE( setup );
  }
  
  
  /**
 - * Create a new primitive setup/render stage.
 + * Create a new primitive tiling engine.  Plug it into the backend of
 + * the draw module.  Currently also creates a rasterizer to use with
 + * it.
   */
 -struct setup_context *llvmpipe_setup_create_context( struct llvmpipe_context *llvmpipe )
 +struct setup_context *
 +lp_setup_create( struct pipe_screen *screen,
 +                 struct draw_context *draw )
  {
 -   struct setup_context *setup;
     unsigned i;
 +   struct setup_context *setup = CALLOC_STRUCT(setup_context);
  
 -   setup = align_malloc(sizeof(struct setup_context), 16);
     if (!setup)
        return NULL;
  
 -   memset(setup, 0, sizeof *setup);
 -   setup->llvmpipe = llvmpipe;
 +   lp_setup_init_vbuf(setup);
 +
 +   setup->empty_scenes = lp_scene_queue_create();
 +   if (!setup->empty_scenes)
 +      goto fail;
  
 -   for (i = 0; i < MAX_QUADS; i++) {
 -      setup->quad[i].coef = &setup->coef;
 +   setup->rast = lp_rast_create( screen, setup->empty_scenes );
 +   if (!setup->rast) 
 +      goto fail;
 +
 +   setup->vbuf = draw_vbuf_stage(draw, &setup->base);
 +   if (!setup->vbuf)
 +      goto fail;
 +
 +   draw_set_rasterize_stage(draw, setup->vbuf);
 +   draw_set_render(draw, &setup->base);
 +
 +   /* create some empty scenes */
 +   for (i = 0; i < MAX_SCENES; i++) {
 +      struct lp_scene *scene = lp_scene_create();
 +      lp_scene_enqueue(setup->empty_scenes, scene);
     }
  
 -   setup->span.left[0] = 1000000;     /* greater than right[0] */
 -   setup->span.left[1] = 1000000;     /* greater than right[1] */
 +   setup->triangle = first_triangle;
 +   setup->line     = first_line;
 +   setup->point    = first_point;
 +   
 +   setup->dirty = ~0;
  
     return setup;
 +
 +fail:
 +   if (setup->rast)
 +      lp_rast_destroy( setup->rast );
 +   
 +   if (setup->vbuf)
 +      ;
 +
 +   if (setup->empty_scenes)
 +      lp_scene_queue_destroy(setup->empty_scenes);
 +
 +   FREE(setup);
 +   return NULL;
  }
  
index e15b987767c87203bb077c9e8988c665c21a1b54,0000000000000000000000000000000000000000..fe34903cf326e93c3ebe25a26b4777fe7414d157
mode 100644,000000..100644
--- /dev/null
@@@ -1,550 -1,0 +1,547 @@@
- #define MIN3(a,b,c) MIN2(MIN2(a,b),c)
- #define MAX3(a,b,c) MAX2(MAX2(a,b),c)
 +/**************************************************************************
 + *
 + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
 + * All Rights Reserved.
 + *
 + * Permission is hereby granted, free of charge, to any person obtaining a
 + * copy of this software and associated documentation files (the
 + * "Software"), to deal in the Software without restriction, including
 + * without limitation the rights to use, copy, modify, merge, publish,
 + * distribute, sub license, and/or sell copies of the Software, and to
 + * permit persons to whom the Software is furnished to do so, subject to
 + * the following conditions:
 + *
 + * The above copyright notice and this permission notice (including the
 + * next paragraph) shall be included in all copies or substantial portions
 + * of the Software.
 + *
 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
 + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
 + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 + *
 + **************************************************************************/
 +
 +/*
 + * Binning code for triangles
 + */
 +
 +#include "lp_setup_context.h"
 +#include "lp_rast.h"
 +#include "util/u_math.h"
 +#include "util/u_memory.h"
 +
 +#define NUM_CHANNELS 4
 +
 +/**
 + * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
 + */
 +static void constant_coef( struct lp_rast_triangle *tri,
 +                           unsigned slot,
 +                         const float value,
 +                           unsigned i )
 +{
 +   tri->inputs.a0[slot][i] = value;
 +   tri->inputs.dadx[slot][i] = 0;
 +   tri->inputs.dady[slot][i] = 0;
 +}
 +
 +/**
 + * Compute a0, dadx and dady for a linearly interpolated coefficient,
 + * for a triangle.
 + */
 +static void linear_coef( struct lp_rast_triangle *tri,
 +                         float oneoverarea,
 +                         unsigned slot,
 +                         const float (*v1)[4],
 +                         const float (*v2)[4],
 +                         const float (*v3)[4],
 +                         unsigned vert_attr,
 +                         unsigned i)
 +{
 +   float a1 = v1[vert_attr][i];
 +   float a2 = v2[vert_attr][i];
 +   float a3 = v3[vert_attr][i];
 +
 +   float da12 = a1 - a2;
 +   float da31 = a3 - a1;
 +   float dadx = (da12 * tri->dy31 - tri->dy12 * da31) * oneoverarea;
 +   float dady = (da31 * tri->dx12 - tri->dx31 * da12) * oneoverarea;
 +
 +   tri->inputs.dadx[slot][i] = dadx;
 +   tri->inputs.dady[slot][i] = dady;
 +
 +   /* calculate a0 as the value which would be sampled for the
 +    * fragment at (0,0), taking into account that we want to sample at
 +    * pixel centers, in other words (0.5, 0.5).
 +    *
 +    * this is neat but unfortunately not a good way to do things for
 +    * triangles with very large values of dadx or dady as it will
 +    * result in the subtraction and re-addition from a0 of a very
 +    * large number, which means we'll end up loosing a lot of the
 +    * fractional bits and precision from a0.  the way to fix this is
 +    * to define a0 as the sample at a pixel center somewhere near vmin
 +    * instead - i'll switch to this later.
 +    */
 +   tri->inputs.a0[slot][i] = (v1[vert_attr][i] -
 +                              (dadx * (v1[0][0] - 0.5f) +
 +                               dady * (v1[0][1] - 0.5f)));
 +}
 +
 +
 +/**
 + * Compute a0, dadx and dady for a perspective-corrected interpolant,
 + * for a triangle.
 + * We basically multiply the vertex value by 1/w before computing
 + * the plane coefficients (a0, dadx, dady).
 + * Later, when we compute the value at a particular fragment position we'll
 + * divide the interpolated value by the interpolated W at that fragment.
 + */
 +static void perspective_coef( struct lp_rast_triangle *tri,
 +                              float oneoverarea,
 +                              unsigned slot,
 +                            const float (*v1)[4],
 +                            const float (*v2)[4],
 +                            const float (*v3)[4],
 +                            unsigned vert_attr,
 +                              unsigned i)
 +{
 +   /* premultiply by 1/w  (v[0][3] is always 1/w):
 +    */
 +   float a1 = v1[vert_attr][i] * v1[0][3];
 +   float a2 = v2[vert_attr][i] * v2[0][3];
 +   float a3 = v3[vert_attr][i] * v3[0][3];
 +   float da12 = a1 - a2;
 +   float da31 = a3 - a1;
 +   float dadx = (da12 * tri->dy31 - tri->dy12 * da31) * oneoverarea;
 +   float dady = (da31 * tri->dx12 - tri->dx31 * da12) * oneoverarea;
 +
 +   tri->inputs.dadx[slot][i] = dadx;
 +   tri->inputs.dady[slot][i] = dady;
 +   tri->inputs.a0[slot][i] = (a1 -
 +                              (dadx * (v1[0][0] - 0.5f) +
 +                               dady * (v1[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 position_coef which should have already been computed.
 + * We could do a bit less work if we'd examine gl_FragCoord's swizzle mask.
 + */
 +static void
 +setup_fragcoord_coef(struct lp_rast_triangle *tri,
 +                     float oneoverarea,
 +                     unsigned slot,
 +                     const float (*v1)[4],
 +                     const float (*v2)[4],
 +                     const float (*v3)[4])
 +{
 +   /*X*/
 +   tri->inputs.a0[slot][0] = 0.0;
 +   tri->inputs.dadx[slot][0] = 1.0;
 +   tri->inputs.dady[slot][0] = 0.0;
 +   /*Y*/
 +   tri->inputs.a0[slot][1] = 0.0;
 +   tri->inputs.dadx[slot][1] = 0.0;
 +   tri->inputs.dady[slot][1] = 1.0;
 +   /*Z*/
 +   linear_coef(tri, oneoverarea, slot, v1, v2, v3, 0, 2);
 +   /*W*/
 +   linear_coef(tri, oneoverarea, slot, v1, v2, v3, 0, 3);
 +}
 +
 +
 +static void setup_facing_coef( struct lp_rast_triangle *tri,
 +                               unsigned slot,
 +                               boolean frontface )
 +{
 +   constant_coef( tri, slot, 1.0f - frontface, 0 );
 +   constant_coef( tri, slot, 0.0f, 1 ); /* wasted */
 +   constant_coef( tri, slot, 0.0f, 2 ); /* wasted */
 +   constant_coef( tri, slot, 0.0f, 3 ); /* wasted */
 +}
 +
 +
 +/**
 + * Compute the tri->coef[] array dadx, dady, a0 values.
 + */
 +static void setup_tri_coefficients( struct setup_context *setup,
 +                                  struct lp_rast_triangle *tri,
 +                                    float oneoverarea,
 +                                  const float (*v1)[4],
 +                                  const float (*v2)[4],
 +                                  const float (*v3)[4],
 +                                  boolean frontface)
 +{
 +   struct lp_scene *scene = lp_setup_get_current_scene(setup);
 +   unsigned slot;
 +
 +   /* Allocate space for the a0, dadx and dady arrays
 +    */
 +   {
 +      unsigned bytes;
 +      bytes = (setup->fs.nr_inputs + 1) * 4 * sizeof(float);
 +      tri->inputs.a0   = lp_scene_alloc_aligned( scene, bytes, 16 );
 +      tri->inputs.dadx = lp_scene_alloc_aligned( scene, bytes, 16 );
 +      tri->inputs.dady = lp_scene_alloc_aligned( scene, bytes, 16 );
 +   }
 +
 +   /* The internal position input is in slot zero:
 +    */
 +   setup_fragcoord_coef(tri, oneoverarea, 0, v1, v2, v3);
 +
 +   /* setup interpolation for all the remaining attributes:
 +    */
 +   for (slot = 0; slot < setup->fs.nr_inputs; slot++) {
 +      unsigned vert_attr = setup->fs.input[slot].src_index;
 +      unsigned i;
 +
 +      switch (setup->fs.input[slot].interp) {
 +      case LP_INTERP_CONSTANT:
 +         for (i = 0; i < NUM_CHANNELS; i++)
 +            constant_coef(tri, slot+1, v3[vert_attr][i], i);
 +         break;
 +
 +      case LP_INTERP_LINEAR:
 +         for (i = 0; i < NUM_CHANNELS; i++)
 +            linear_coef(tri, oneoverarea, slot+1, v1, v2, v3, vert_attr, i);
 +         break;
 +
 +      case LP_INTERP_PERSPECTIVE:
 +         for (i = 0; i < NUM_CHANNELS; i++)
 +            perspective_coef(tri, oneoverarea, slot+1, v1, v2, v3, vert_attr, i);
 +         break;
 +
 +      case LP_INTERP_POSITION:
 +         /* XXX: fix me - duplicates the values in slot zero.
 +          */
 +         setup_fragcoord_coef(tri, oneoverarea, slot+1, v1, v2, v3);
 +         break;
 +
 +      case LP_INTERP_FACING:
 +         setup_facing_coef(tri, slot+1, frontface);
 +         break;
 +
 +      default:
 +         assert(0);
 +      }
 +   }
 +}
 +
 +
 +
 +static inline int subpixel_snap( float a )
 +{
 +   return util_iround(FIXED_ONE * a);
 +}
 +
 +
 +/**
 + * Do basic setup for triangle rasterization and determine which
 + * framebuffer tiles are touched.  Put the triangle in the scene's
 + * bins for the tiles which we overlap.
 + */
 +static void 
 +do_triangle_ccw(struct setup_context *setup,
 +              const float (*v1)[4],
 +              const float (*v2)[4],
 +              const float (*v3)[4],
 +              boolean frontfacing )
 +{
 +   /* x/y positions in fixed point */
 +   const int x1 = subpixel_snap(v1[0][0]);
 +   const int x2 = subpixel_snap(v2[0][0]);
 +   const int x3 = subpixel_snap(v3[0][0]);
 +   const int y1 = subpixel_snap(v1[0][1]);
 +   const int y2 = subpixel_snap(v2[0][1]);
 +   const int y3 = subpixel_snap(v3[0][1]);
 +
 +   struct lp_scene *scene = lp_setup_get_current_scene(setup);
 +   struct lp_rast_triangle *tri = lp_scene_alloc_aligned( scene, sizeof *tri, 16 );
 +   float area, oneoverarea;
 +   int minx, maxx, miny, maxy;
 +
 +   tri->dx12 = x1 - x2;
 +   tri->dx23 = x2 - x3;
 +   tri->dx31 = x3 - x1;
 +
 +   tri->dy12 = y1 - y2;
 +   tri->dy23 = y2 - y3;
 +   tri->dy31 = y3 - y1;
 +
 +   area = (tri->dx12 * tri->dy31 - 
 +         tri->dx31 * tri->dy12);
 +
 +   /* Cull non-ccw and zero-sized triangles. 
 +    *
 +    * XXX: subject to overflow??
 +    */
 +   if (area <= 0) {
 +      lp_scene_putback_data( scene, sizeof *tri );
 +      return;
 +   }
 +
 +   /* Bounding rectangle (in pixels) */
 +   tri->minx = (MIN3(x1, x2, x3) + 0xf) >> FIXED_ORDER;
 +   tri->maxx = (MAX3(x1, x2, x3) + 0xf) >> FIXED_ORDER;
 +   tri->miny = (MIN3(y1, y2, y3) + 0xf) >> FIXED_ORDER;
 +   tri->maxy = (MAX3(y1, y2, y3) + 0xf) >> FIXED_ORDER;
 +   
 +   if (tri->miny == tri->maxy || 
 +       tri->minx == tri->maxx) {
 +      lp_scene_putback_data( scene, sizeof *tri );
 +      return;
 +   }
 +
 +   /* 
 +    */
 +   oneoverarea = ((float)FIXED_ONE) / (float)area;
 +
 +   /* Setup parameter interpolants:
 +    */
 +   setup_tri_coefficients( setup, tri, oneoverarea, v1, v2, v3, frontfacing );
 +
 +   /* half-edge constants, will be interated over the whole
 +    * rendertarget.
 +    */
 +   tri->c1 = tri->dy12 * x1 - tri->dx12 * y1;
 +   tri->c2 = tri->dy23 * x2 - tri->dx23 * y2;
 +   tri->c3 = tri->dy31 * x3 - tri->dx31 * y3;
 +
 +   /* correct for top-left fill convention:
 +    */
 +   if (tri->dy12 < 0 || (tri->dy12 == 0 && tri->dx12 > 0)) tri->c1++;
 +   if (tri->dy23 < 0 || (tri->dy23 == 0 && tri->dx23 > 0)) tri->c2++;
 +   if (tri->dy31 < 0 || (tri->dy31 == 0 && tri->dx31 > 0)) tri->c3++;
 +
 +   tri->dy12 *= FIXED_ONE;
 +   tri->dy23 *= FIXED_ONE;
 +   tri->dy31 *= FIXED_ONE;
 +
 +   tri->dx12 *= FIXED_ONE;
 +   tri->dx23 *= FIXED_ONE;
 +   tri->dx31 *= FIXED_ONE;
 +
 +   /* find trivial reject offsets for each edge for a single-pixel
 +    * sized block.  These will be scaled up at each recursive level to
 +    * match the active blocksize.  Scaling in this way works best if
 +    * the blocks are square.
 +    */
 +   tri->eo1 = 0;
 +   if (tri->dy12 < 0) tri->eo1 -= tri->dy12;
 +   if (tri->dx12 > 0) tri->eo1 += tri->dx12;
 +
 +   tri->eo2 = 0;
 +   if (tri->dy23 < 0) tri->eo2 -= tri->dy23;
 +   if (tri->dx23 > 0) tri->eo2 += tri->dx23;
 +
 +   tri->eo3 = 0;
 +   if (tri->dy31 < 0) tri->eo3 -= tri->dy31;
 +   if (tri->dx31 > 0) tri->eo3 += tri->dx31;
 +
 +   /* Calculate trivial accept offsets from the above.
 +    */
 +   tri->ei1 = tri->dx12 - tri->dy12 - tri->eo1;
 +   tri->ei2 = tri->dx23 - tri->dy23 - tri->eo2;
 +   tri->ei3 = tri->dx31 - tri->dy31 - tri->eo3;
 +
 +   {
 +      const int xstep1 = -tri->dy12;
 +      const int xstep2 = -tri->dy23;
 +      const int xstep3 = -tri->dy31;
 +
 +      const int ystep1 = tri->dx12;
 +      const int ystep2 = tri->dx23;
 +      const int ystep3 = tri->dx31;
 +      
 +      int qx, qy, ix, iy;
 +      int i = 0;
 +
 +      for (qy = 0; qy < 2; qy++) {
 +         for (qx = 0; qx < 2; qx++) {
 +            for (iy = 0; iy < 2; iy++) {
 +               for (ix = 0; ix < 2; ix++, i++) {
 +                  int x = qx * 2 + ix;
 +                  int y = qy * 2 + iy;
 +                  tri->inputs.step[0][i] = x * xstep1 + y * ystep1;
 +                  tri->inputs.step[1][i] = x * xstep2 + y * ystep2;
 +                  tri->inputs.step[2][i] = x * xstep3 + y * ystep3;
 +               }
 +            }
 +         }
 +      }
 +   }
 +
 +   /*
 +    * All fields of 'tri' are now set.  The remaining code here is
 +    * concerned with binning.
 +    */
 +
 +   /* Convert to tile coordinates:
 +    */
 +   minx = tri->minx / TILE_SIZE;
 +   miny = tri->miny / TILE_SIZE;
 +   maxx = tri->maxx / TILE_SIZE;
 +   maxy = tri->maxy / TILE_SIZE;
 +
 +   /* Determine which tile(s) intersect the triangle's bounding box
 +    */
 +   if (miny == maxy && minx == maxx)
 +   {
 +      /* Triangle is contained in a single tile:
 +       */
 +      lp_scene_bin_command( scene, minx, miny, lp_rast_triangle, 
 +                          lp_rast_arg_triangle(tri) );
 +   }
 +   else 
 +   {
 +      int c1 = (tri->c1 + 
 +                tri->dx12 * miny * TILE_SIZE - 
 +                tri->dy12 * minx * TILE_SIZE);
 +      int c2 = (tri->c2 + 
 +                tri->dx23 * miny * TILE_SIZE -
 +                tri->dy23 * minx * TILE_SIZE);
 +      int c3 = (tri->c3 +
 +                tri->dx31 * miny * TILE_SIZE -
 +                tri->dy31 * minx * TILE_SIZE);
 +
 +      int ei1 = tri->ei1 << TILE_ORDER;
 +      int ei2 = tri->ei2 << TILE_ORDER;
 +      int ei3 = tri->ei3 << TILE_ORDER;
 +
 +      int eo1 = tri->eo1 << TILE_ORDER;
 +      int eo2 = tri->eo2 << TILE_ORDER;
 +      int eo3 = tri->eo3 << TILE_ORDER;
 +
 +      int xstep1 = -(tri->dy12 << TILE_ORDER);
 +      int xstep2 = -(tri->dy23 << TILE_ORDER);
 +      int xstep3 = -(tri->dy31 << TILE_ORDER);
 +
 +      int ystep1 = tri->dx12 << TILE_ORDER;
 +      int ystep2 = tri->dx23 << TILE_ORDER;
 +      int ystep3 = tri->dx31 << TILE_ORDER;
 +      int x, y;
 +
 +
 +      /* Trivially accept or reject blocks, else jump to per-pixel
 +       * examination above.
 +       */
 +      for (y = miny; y <= maxy; y++)
 +      {
 +       int cx1 = c1;
 +       int cx2 = c2;
 +       int cx3 = c3;
 +       int in = 0;
 +
 +       for (x = minx; x <= maxx; x++)
 +       {
 +          if (cx1 + eo1 < 0 || 
 +              cx2 + eo2 < 0 ||
 +              cx3 + eo3 < 0) 
 +          {
 +             /* do nothing */
 +             if (in)
 +                break;
 +          }
 +          else if (cx1 + ei1 > 0 &&
 +                   cx2 + ei2 > 0 &&
 +                   cx3 + ei3 > 0) 
 +          {
 +             in = 1;
 +               /* triangle covers the whole tile- shade whole tile */
 +               lp_scene_bin_command( scene, x, y,
 +                                   lp_rast_shade_tile,
 +                                   lp_rast_arg_inputs(&tri->inputs) );
 +          }
 +          else 
 +          { 
 +             in = 1;
 +               /* shade partial tile */
 +               lp_scene_bin_command( scene, x, y,
 +                                   lp_rast_triangle, 
 +                                   lp_rast_arg_triangle(tri) );
 +          }
 +
 +          /* Iterate cx values across the region:
 +           */
 +          cx1 += xstep1;
 +          cx2 += xstep2;
 +          cx3 += xstep3;
 +       }
 +      
 +       /* Iterate c values down the region:
 +        */
 +       c1 += ystep1;
 +       c2 += ystep2;
 +       c3 += ystep3;    
 +      }
 +   }
 +}
 +
 +static void triangle_cw( struct setup_context *setup,
 +                       const float (*v0)[4],
 +                       const float (*v1)[4],
 +                       const float (*v2)[4] )
 +{
 +   do_triangle_ccw( setup, v1, v0, v2, !setup->ccw_is_frontface );
 +}
 +
 +static void triangle_ccw( struct setup_context *setup,
 +                       const float (*v0)[4],
 +                       const float (*v1)[4],
 +                       const float (*v2)[4] )
 +{
 +   do_triangle_ccw( setup, v0, v1, v2, setup->ccw_is_frontface );
 +}
 +
 +static void triangle_both( struct setup_context *setup,
 +                         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 */
 +   if (ex * fy - ey * fx < 0) 
 +      triangle_ccw( setup, v0, v1, v2 );
 +   else
 +      triangle_cw( setup, v0, v1, v2 );
 +}
 +
 +static void triangle_nop( struct setup_context *setup,
 +                        const float (*v0)[4],
 +                        const float (*v1)[4],
 +                        const float (*v2)[4] )
 +{
 +}
 +
 +
 +void 
 +lp_setup_choose_triangle( struct setup_context *setup )
 +{
 +   switch (setup->cullmode) {
 +   case PIPE_WINDING_NONE:
 +      setup->triangle = triangle_both;
 +      break;
 +   case PIPE_WINDING_CCW:
 +      setup->triangle = triangle_cw;
 +      break;
 +   case PIPE_WINDING_CW:
 +      setup->triangle = triangle_ccw;
 +      break;
 +   default:
 +      setup->triangle = triangle_nop;
 +      break;
 +   }
 +}
 +
 +
index 6017dc553a6fe0ebdc675a944cee703c1f30f9c8,7020da145f323ff8485f8e243918e6adc4dbcee2..25d135367414b6b4960b5ceb2e67cfa8fbae7c5f
  #define LP_NEW_VERTEX        0x1000
  #define LP_NEW_VS            0x2000
  #define LP_NEW_QUERY         0x4000
 +#define LP_NEW_BLEND_COLOR   0x8000
  
  
- struct tgsi_sampler;
  struct vertex_info;
  struct pipe_context;
  struct llvmpipe_context;
@@@ -127,6 -125,10 +126,10 @@@ 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_bind_vertex_sampler_states(struct pipe_context *,
+                                     unsigned num_samplers,
+                                     void **samplers);
  void llvmpipe_delete_sampler_state(struct pipe_context *, void *);
  
  void *
@@@ -173,6 -175,11 +176,11 @@@ void llvmpipe_set_sampler_textures( str
                                      unsigned num,
                                      struct pipe_texture ** );
  
+ void
+ llvmpipe_set_vertex_sampler_textures(struct pipe_context *,
+                                      unsigned num_textures,
+                                      struct pipe_texture **);
  void llvmpipe_set_viewport_state( struct pipe_context *,
                                    const struct pipe_viewport_state * );
  
@@@ -189,14 -196,14 +197,14 @@@ void llvmpipe_update_fs(struct llvmpipe
  void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe );
  
  
boolean llvmpipe_draw_arrays(struct pipe_context *pipe, unsigned mode,
void llvmpipe_draw_arrays(struct pipe_context *pipe, unsigned mode,
                             unsigned start, unsigned count);
  
boolean llvmpipe_draw_elements(struct pipe_context *pipe,
void llvmpipe_draw_elements(struct pipe_context *pipe,
                               struct pipe_buffer *indexBuffer,
                               unsigned indexSize,
                               unsigned mode, unsigned start, unsigned count);
- boolean
+ void
  llvmpipe_draw_range_elements(struct pipe_context *pipe,
                               struct pipe_buffer *indexBuffer,
                               unsigned indexSize,
                               unsigned max_index,
                               unsigned mode, unsigned start, unsigned count);
  
--void
- llvmpipe_set_edgeflags(struct pipe_context *pipe, const unsigned *edgeflags);
 -llvmpipe_map_transfers(struct llvmpipe_context *lp);
--
 -void
 -llvmpipe_unmap_transfers(struct llvmpipe_context *lp);
--
  void
  llvmpipe_map_texture_surfaces(struct llvmpipe_context *lp);
  
@@@ -215,4 -224,11 +219,4 @@@ voi
  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
index 48afe5f524224e84f7d2618c53b53c97afd25b0f,a94cd05ef20c7a9616dc4dbb6c985c2ce58f30fe..a10c5918df3d0d7a65c7a03e036c6f6fa7340178
@@@ -34,6 -34,7 +34,7 @@@
  #include "util/u_memory.h"
  #include "util/u_math.h"
  #include "util/u_debug_dump.h"
+ #include "draw/draw_context.h"
  #include "lp_screen.h"
  #include "lp_context.h"
  #include "lp_state.h"
@@@ -51,6 -52,11 +52,11 @@@ void llvmpipe_bind_blend_state( struct 
  {
     struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
  
+    if (llvmpipe->blend == blend)
+       return;
+    draw_flush(llvmpipe->draw);
     llvmpipe->blend = blend;
  
     llvmpipe->dirty |= LP_NEW_BLEND;
@@@ -67,16 -73,22 +73,21 @@@ void llvmpipe_set_blend_color( struct p
                             const struct pipe_blend_color *blend_color )
  {
     struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
 -   unsigned i, j;
 +
 +   if(!blend_color)
 +      return;
 +
 +   if(memcmp(&llvmpipe->blend_color, blend_color, sizeof *blend_color) == 0)
 +      return;
  
+    if(memcmp(&llvmpipe->blend_color, blend_color, sizeof *blend_color) == 0)
+       return;
+    draw_flush(llvmpipe->draw);
     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*16 + j] = c;
 -   }
 +   llvmpipe->dirty |= LP_NEW_BLEND_COLOR;
  }
  
  
@@@ -98,8 -110,16 +109,13 @@@ llvmpipe_bind_depth_stencil_state(struc
  {
     struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
  
-    llvmpipe->depth_stencil = (const struct pipe_depth_stencil_alpha_state *)depth_stencil;
+    if (llvmpipe->depth_stencil == depth_stencil)
+       return;
+    draw_flush(llvmpipe->draw);
+    llvmpipe->depth_stencil = 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;
  }
  
index cc7b09fd4d15cb1502c1bdcb818ff60a589fb4a5,6c1ef6bc42d827484788e4c4aaf1d4a79c62c8e9..78d046985b9dc50e0426da573483fe1277753e11
  #include "draw/draw_private.h"
  #include "lp_context.h"
  #include "lp_screen.h"
 -#include "lp_tex_cache.h"
 +#include "lp_setup.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.
 + * This function validates the vertex layout.
   */
 -struct vertex_info *
 -llvmpipe_get_vertex_info(struct llvmpipe_context *llvmpipe)
 +static void
 +compute_vertex_info(struct llvmpipe_context *llvmpipe)
  {
 +   const struct lp_fragment_shader *lpfs = llvmpipe->fs;
     struct vertex_info *vinfo = &llvmpipe->vertex_info;
-    const uint num = draw_num_vs_outputs(llvmpipe->draw);
++   const uint num = draw_num_shader_outputs(llvmpipe->draw);
 +   uint i;
  
 -   if (vinfo->num_attribs == 0) {
 -      /* compute vertex layout now */
 -      const struct lp_fragment_shader *lpfs = llvmpipe->fs;
 -      struct vertex_info *vinfo_vbuf = &llvmpipe->vertex_info_vbuf;
 -      const uint num = draw_current_shader_outputs(llvmpipe->draw);
 -      uint i;
 +   /* Tell setup to tell the draw module to simply emit the whole
 +    * post-xform vertex as-is.
 +    *
 +    * Not really sure if this is the best approach.
 +    */
 +   vinfo->num_attribs = 0;
 +   for (i = 0; i < num; i++) {
 +      draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, i);
 +   }
 +   draw_compute_vertex_size(vinfo);
  
 -      /* Tell draw_vbuf to simply emit the whole post-xform vertex
 -       * as-is.  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;
 -         enum interp_mode interp;
 +   lp_setup_set_vertex_info(llvmpipe->setup, vinfo);
  
 -         switch (lpfs->info.input_interpolate[i]) {
 -         case TGSI_INTERPOLATE_CONSTANT:
 -            interp = INTERP_CONSTANT;
 -            break;
 -         case TGSI_INTERPOLATE_LINEAR:
 -            interp = INTERP_LINEAR;
 -            break;
 -         case TGSI_INTERPOLATE_PERSPECTIVE:
 -            interp = INTERP_PERSPECTIVE;
 -            break;
 -         default:
 -            assert(0);
 -            interp = INTERP_LINEAR;
 -         }
 +/*
 +   llvmpipe->psize_slot = draw_find_vs_output(llvmpipe->draw,
 +                                              TGSI_SEMANTIC_PSIZE, 0);
 +*/
  
 +   /* Now match FS inputs against emitted vertex data.  It's also
 +    * entirely possible to just have a fixed layout for FS input,
 +    * determined by the fragment shader itself, and adjust the draw
 +    * outputs to match that.
 +    */
 +   {
 +      struct lp_shader_input inputs[PIPE_MAX_SHADER_INPUTS];
 +
 +      for (i = 0; i < lpfs->info.num_inputs; i++) {
 +
 +         /* This can be precomputed, except for flatshade:
 +          */
           switch (lpfs->info.input_semantic_name[i]) {
 +         case TGSI_SEMANTIC_FACE:
 +            inputs[i].interp = LP_INTERP_FACING;
 +            break;
           case TGSI_SEMANTIC_POSITION:
 -            interp = INTERP_POS;
 +            inputs[i].interp = LP_INTERP_POSITION;
              break;
 -
           case TGSI_SEMANTIC_COLOR:
 -            if (llvmpipe->rasterizer->flatshade) {
 -               interp = INTERP_CONSTANT;
 -            }
 +            /* Colors are linearly interpolated in the fragment shader
 +             * even when flatshading is active.  This just tells the
 +             * setup module to use coefficients with ddx==0 and
 +             * ddy==0.
 +             */
 +            if (llvmpipe->rasterizer->flatshade)
 +               inputs[i].interp = LP_INTERP_CONSTANT;
 +            else
 +               inputs[i].interp = LP_INTERP_LINEAR;
              break;
 -         }
  
 -         /* this includes texcoords and varying vars */
 -         src = draw_find_shader_output(llvmpipe->draw,
 -                                   lpfs->info.input_semantic_name[i],
 -                                   lpfs->info.input_semantic_index[i]);
 -         draw_emit_vertex_attr(vinfo, EMIT_4F, interp, src);
 -      }
 +         default:
 +            switch (lpfs->info.input_interpolate[i]) {
 +            case TGSI_INTERPOLATE_CONSTANT:
 +               inputs[i].interp = LP_INTERP_CONSTANT;
 +               break;
 +            case TGSI_INTERPOLATE_LINEAR:
 +               inputs[i].interp = LP_INTERP_LINEAR;
 +               break;
 +            case TGSI_INTERPOLATE_PERSPECTIVE:
 +               inputs[i].interp = LP_INTERP_PERSPECTIVE;
 +               break;
 +            default:
 +               assert(0);
 +               break;
 +            }
 +         }
  
 -      llvmpipe->psize_slot = draw_find_shader_output(llvmpipe->draw,
 -                                                 TGSI_SEMANTIC_PSIZE, 0);
 -      if (llvmpipe->psize_slot > 0) {
 -         draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT,
 -                               llvmpipe->psize_slot);
 +         /* Search for each input in current vs output:
 +          */
 +         inputs[i].src_index = 
-             draw_find_vs_output(llvmpipe->draw,
-                                 lpfs->info.input_semantic_name[i],
-                                 lpfs->info.input_semantic_index[i]);
++            draw_find_shader_output(llvmpipe->draw,
++                                    lpfs->info.input_semantic_name[i],
++                                    lpfs->info.input_semantic_index[i]);
        }
  
 -      draw_compute_vertex_size(vinfo);
 +      lp_setup_set_fs_inputs(llvmpipe->setup, 
 +                             inputs,
 +                             lpfs->info.num_inputs);
     }
 -
 -   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.
@@@ -170,26 -192,6 +170,6 @@@ compute_cliprect(struct llvmpipe_contex
  }
  
  
- #if 0
- static void 
- update_culling(struct llvmpipe_context *lp)
- {
-    struct lp_setup_context *setup = lp->setup;
-    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;
-    }
- }
- #endif
  /* Hopefully this will remain quite simple, otherwise need to pull in
   * something like the state tracker mechanism.
   */
@@@ -204,10 -206,15 +184,10 @@@ void llvmpipe_update_derived( struct ll
        llvmpipe->dirty |= LP_NEW_TEXTURE;
     }
        
 -   if (llvmpipe->dirty & (LP_NEW_SAMPLER |
 -                          LP_NEW_TEXTURE)) {
 -      /* TODO */
 -   }
 -
     if (llvmpipe->dirty & (LP_NEW_RASTERIZER |
                            LP_NEW_FS |
                            LP_NEW_VS))
 -      invalidate_vertex_layout( llvmpipe );
 +      compute_vertex_info( llvmpipe );
  
     if (llvmpipe->dirty & (LP_NEW_SCISSOR |
                            LP_NEW_RASTERIZER |
                            LP_NEW_TEXTURE))
        llvmpipe_update_fs( llvmpipe );
  
 +   if (llvmpipe->dirty & LP_NEW_BLEND_COLOR)
 +      lp_setup_set_blend_color(llvmpipe->setup,
 +                               &llvmpipe->blend_color);
 +
 +   if (llvmpipe->dirty & LP_NEW_DEPTH_STENCIL_ALPHA)
 +      lp_setup_set_alpha_ref_value(llvmpipe->setup, 
 +                                   llvmpipe->depth_stencil->alpha.ref_value);
 +
 +   if (llvmpipe->dirty & LP_NEW_CONSTANTS)
 +      lp_setup_set_fs_constants(llvmpipe->setup, 
 +                                llvmpipe->constants[PIPE_SHADER_FRAGMENT].buffer);
 +
 +   if (llvmpipe->dirty & LP_NEW_TEXTURE)
 +      lp_setup_set_sampler_textures(llvmpipe->setup, 
 +                                    llvmpipe->num_textures,
 +                                    llvmpipe->texture);
  
     llvmpipe->dirty = 0;
  }
 +
index 3ad58415e3927c8ddf7bd900a599de433363aba2,b73ca2d41ed2ebea5c064a9aa91e8d1dbbb413e9..3a669ba859ab7b9064ba20a606038852d9c9f28a
@@@ -84,8 -84,8 +84,8 @@@
  #include "lp_screen.h"
  #include "lp_context.h"
  #include "lp_buffer.h"
 +#include "lp_setup.h"
  #include "lp_state.h"
 -#include "lp_quad.h"
  #include "lp_tex_sample.h"
  #include "lp_debug.h"
  
@@@ -149,6 -149,20 +149,20 @@@ generate_depth(LLVMBuilderRef builder
     format_desc = util_format_description(key->zsbuf_format);
     assert(format_desc);
  
+    /*
+     * Depths are expected to be between 0 and 1, even if they are stored in
+     * floats. Setting these bits here will ensure that the lp_build_conv() call
+     * below won't try to unnecessarily clamp the incoming values.
+     */
+    if(src_type.floating) {
+       src_type.sign = FALSE;
+       src_type.norm = TRUE;
+    }
+    else {
+       assert(!src_type.sign);
+       assert(src_type.norm);
+    }
     /* Pick the depth type. */
     dst_type = lp_depth_type(format_desc, src_type.width*src_type.length);
  
     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
+    dst_ptr = LLVMBuildBitCast(builder,
+                               dst_ptr,
+                               LLVMPointerType(lp_build_vec_type(dst_type), 0), "");
  
     lp_build_depth_test(builder,
                         &key->depth,
  }
  
  
 +/**
 + * Generate the code to do inside/outside triangle testing for the
 + * four pixels in a 2x2 quad.  This will set the four elements of the
 + * quad mask vector to 0 or ~0.
 + * \param i  which quad of the quad group to test, in [0,3]
 + */
 +static void
 +generate_tri_edge_mask(LLVMBuilderRef builder,
 +                       unsigned i,
 +                       LLVMValueRef *mask,      /* ivec4, out */
 +                       LLVMValueRef c0,         /* int32 */
 +                       LLVMValueRef c1,         /* int32 */
 +                       LLVMValueRef c2,         /* int32 */
 +                       LLVMValueRef step0_ptr,  /* ivec4 */
 +                       LLVMValueRef step1_ptr,  /* ivec4 */
 +                       LLVMValueRef step2_ptr)  /* ivec4 */
 +{
 +   /*
 +     c0_vec = splat(c0)
 +     c1_vec = splat(c1)
 +     c2_vec = splat(c2)
 +     m0_vec = step0_ptr[i] > c0_vec
 +     m1_vec = step1_ptr[i] > c1_vec
 +     m2_vec = step2_ptr[i] > c2_vec
 +     mask = m0_vec & m1_vec & m2_vec
 +    */
 +   struct lp_type i32_type;
 +   LLVMTypeRef i32vec4_type;
 +
 +   LLVMValueRef index;
 +   LLVMValueRef c0_vec, c1_vec, c2_vec;
 +   LLVMValueRef step0_vec, step1_vec, step2_vec;
 +   LLVMValueRef m0_vec, m1_vec, m2_vec;
 +   LLVMValueRef m;
 +
 +   assert(i < 4);
 +   
 +   /* int32 vector type */
 +   memset(&i32_type, 0, sizeof i32_type);
 +   i32_type.floating = FALSE; /* values are integers */
 +   i32_type.sign = TRUE;      /* values are signed */
 +   i32_type.norm = FALSE;     /* values are not normalized */
 +   i32_type.width = 32;       /* 32-bit int values */
 +   i32_type.length = 4;       /* 4 elements per vector */
 +
 +   i32vec4_type = lp_build_int32_vec4_type();
 +
 +   /* c0_vec = {c0, c0, c0, c0}
 +    * Note that we emit this code four times but LLVM optimizes away
 +    * three instances of it.
 +    */
 +   c0_vec = lp_build_broadcast(builder, i32vec4_type, c0);
 +   c1_vec = lp_build_broadcast(builder, i32vec4_type, c1);
 +   c2_vec = lp_build_broadcast(builder, i32vec4_type, c2);
 +
 +   lp_build_name(c0_vec, "edgeconst0vec");
 +   lp_build_name(c1_vec, "edgeconst1vec");
 +   lp_build_name(c2_vec, "edgeconst2vec");
 +
 +   index = LLVMConstInt(LLVMInt32Type(), i, 0);
 +   step0_vec = LLVMBuildLoad(builder, LLVMBuildGEP(builder, step0_ptr, &index, 1, ""), "");
 +   step1_vec = LLVMBuildLoad(builder, LLVMBuildGEP(builder, step1_ptr, &index, 1, ""), "");
 +   step2_vec = LLVMBuildLoad(builder, LLVMBuildGEP(builder, step2_ptr, &index, 1, ""), "");
 +
 +   lp_build_name(step0_vec, "step0vec");
 +   lp_build_name(step1_vec, "step1vec");
 +   lp_build_name(step2_vec, "step2vec");
 +
 +   m0_vec = lp_build_compare(builder, i32_type, PIPE_FUNC_GREATER, step0_vec, c0_vec);
 +   m1_vec = lp_build_compare(builder, i32_type, PIPE_FUNC_GREATER, step1_vec, c1_vec);
 +   m2_vec = lp_build_compare(builder, i32_type, PIPE_FUNC_GREATER, step2_vec, c2_vec);
 +
 +   m = LLVMBuildAnd(builder, m0_vec, m1_vec, "");
 +   m = LLVMBuildAnd(builder, m, m2_vec, "");
 +
 +   lp_build_name(m, "inoutmaskvec");
 +
 +   *mask = m;
 +
 +   /*
 +    * if mask = {0,0,0,0} skip quad
 +    */
 +}
 +
 +
  /**
   * Generate the fragment shader, depth/stencil test, and alpha tests.
 + * \param i  which quad in the tile, in range [0,3]
   */
  static void
  generate_fs(struct llvmpipe_context *lp,
              struct lp_build_sampler_soa *sampler,
              LLVMValueRef *pmask,
              LLVMValueRef *color,
 -            LLVMValueRef depth_ptr)
 +            LLVMValueRef depth_ptr,
 +            LLVMValueRef c0,
 +            LLVMValueRef c1,
 +            LLVMValueRef c2,
 +            LLVMValueRef step0_ptr,
 +            LLVMValueRef step1_ptr,
 +            LLVMValueRef step2_ptr)
  {
     const struct tgsi_token *tokens = shader->base.tokens;
     LLVMTypeRef elem_type;
     unsigned attrib;
     unsigned chan;
  
 +   assert(i < 4);
 +
     elem_type = lp_build_elem_type(type);
     vec_type = lp_build_vec_type(type);
     int_vec_type = lp_build_int_vec_type(type);
     }
     lp_build_flow_scope_declare(flow, &z);
  
 +   /* do triangle edge testing */
 +   generate_tri_edge_mask(builder, i, pmask,
 +                          c0, c1, c2, step0_ptr, step1_ptr, step2_ptr);
 +
 +   /* 'mask' will control execution based on quad's pixel alive/killed state */
     lp_build_mask_begin(&mask, flow, type, *pmask);
  
 +
     early_depth_test =
        key->depth.enabled &&
        !key->alpha.enabled &&
@@@ -458,9 -369,6 +469,9 @@@ generate_blend(const struct pipe_blend_
  
  /**
   * Generate the runtime callable function for the whole fragment pipeline.
 + * Note that the function which we generate operates on a block of 16
 + * pixels at at time.  The block contains 2x2 quads.  Each quad contains
 + * 2x2 pixels.
   */
  static struct lp_fragment_shader_variant *
  generate_fragment(struct llvmpipe_context *lp,
     LLVMTypeRef fs_int_vec_type;
     LLVMTypeRef blend_vec_type;
     LLVMTypeRef blend_int_vec_type;
 -   LLVMTypeRef arg_types[9];
 +   LLVMTypeRef arg_types[14];
     LLVMTypeRef func_type;
 +   LLVMTypeRef int32_vec4_type = lp_build_int32_vec4_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;
 +   LLVMValueRef c0, c1, c2, step0_ptr, step1_ptr, step2_ptr;
     LLVMBasicBlockRef block;
     LLVMBuilderRef builder;
     LLVMValueRef x0;
     if (LP_DEBUG & DEBUG_JIT) {
        tgsi_dump(shader->base.tokens, 0);
        if(key->depth.enabled) {
+          debug_printf("depth.format = %s\n", pf_name(key->zsbuf_format));
           debug_printf("depth.func = %s\n", debug_dump_func(key->depth.func, TRUE));
           debug_printf("depth.writemask = %u\n", key->depth.writemask);
        }
        }
        else if(key->blend.blend_enable) {
           debug_printf("blend.rgb_func = %s\n",   debug_dump_blend_func  (key->blend.rgb_func, TRUE));
-          debug_printf("blend.rgb_src_factor = %s\n",   debug_dump_blend_factor(key->blend.rgb_src_factor, TRUE));
-          debug_printf("blend.rgb_dst_factor = %s\n",   debug_dump_blend_factor(key->blend.rgb_dst_factor, TRUE));
-          debug_printf("blend.alpha_func = %s\n",       debug_dump_blend_func  (key->blend.alpha_func, TRUE));
-          debug_printf("blend.alpha_src_factor = %s\n", debug_dump_blend_factor(key->blend.alpha_src_factor, TRUE));
-          debug_printf("blend.alpha_dst_factor = %s\n", debug_dump_blend_factor(key->blend.alpha_dst_factor, 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);
+       for(i = 0; i < PIPE_MAX_SAMPLERS; ++i) {
+          if(key->sampler[i].format) {
+             debug_printf("sampler[%u] = \n", i);
+             debug_printf("  .format = %s\n",
+                          pf_name(key->sampler[i].format));
+             debug_printf("  .target = %s\n",
+                          debug_dump_tex_target(key->sampler[i].target, TRUE));
+             debug_printf("  .pot = %u %u %u\n",
+                          key->sampler[i].pot_width,
+                          key->sampler[i].pot_height,
+                          key->sampler[i].pot_depth);
+             debug_printf("  .wrap = %s %s %s\n",
+                          debug_dump_tex_wrap(key->sampler[i].wrap_s, TRUE),
+                          debug_dump_tex_wrap(key->sampler[i].wrap_t, TRUE),
+                          debug_dump_tex_wrap(key->sampler[i].wrap_r, TRUE));
+             debug_printf("  .min_img_filter = %s\n",
+                          debug_dump_tex_filter(key->sampler[i].min_img_filter, TRUE));
+             debug_printf("  .min_mip_filter = %s\n",
+                          debug_dump_tex_mipfilter(key->sampler[i].min_mip_filter, TRUE));
+             debug_printf("  .mag_img_filter = %s\n",
+                          debug_dump_tex_filter(key->sampler[i].mag_img_filter, TRUE));
+             if(key->sampler[i].compare_mode != PIPE_TEX_COMPARE_NONE)
+                debug_printf("  .compare_func = %s\n", debug_dump_func(key->sampler[i].compare_func, TRUE));
+             debug_printf("  .normalized_coords = %u\n", key->sampler[i].normalized_coords);
+             debug_printf("  .prefilter = %u\n", key->sampler[i].prefilter);
+          }
+       }
     }
  
     variant = CALLOC_STRUCT(lp_fragment_shader_variant);
     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;
 +   fs_type.length = 4;      /* 4 elements per vector */
 +   num_fs = 4;              /* number of quads per block */
  
     memset(&blend_type, 0, sizeof blend_type);
     blend_type.floating = FALSE; /* values are integers */
     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 */
 +   arg_types[6] = LLVMPointerType(blend_vec_type, 0);  /* color */
 +   arg_types[7] = LLVMPointerType(fs_int_vec_type, 0); /* depth */
 +   arg_types[8] = LLVMInt32Type();                     /* c0 */
 +   arg_types[9] = LLVMInt32Type();                    /* c1 */
 +   arg_types[10] = LLVMInt32Type();                    /* c2 */
 +   /* Note: the step arrays are built as int32[16] but we interpret
 +    * them here as int32_vec4[4].
 +    */
 +   arg_types[11] = LLVMPointerType(int32_vec4_type, 0);/* step0 */
 +   arg_types[12] = LLVMPointerType(int32_vec4_type, 0);/* step1 */
 +   arg_types[13] = LLVMPointerType(int32_vec4_type, 0);/* step2 */
  
     func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0);
  
     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);
 +   color_ptr    = LLVMGetParam(variant->function, 6);
 +   depth_ptr    = LLVMGetParam(variant->function, 7);
 +   c0           = LLVMGetParam(variant->function, 8);
 +   c1           = LLVMGetParam(variant->function, 9);
 +   c2           = LLVMGetParam(variant->function, 10);
 +   step0_ptr    = LLVMGetParam(variant->function, 11);
 +   step1_ptr    = LLVMGetParam(variant->function, 12);
 +   step2_ptr    = LLVMGetParam(variant->function, 13);
  
     lp_build_name(context_ptr, "context");
     lp_build_name(x, "x");
     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");
 +   lp_build_name(c0, "c0");
 +   lp_build_name(c1, "c1");
 +   lp_build_name(c2, "c2");
 +   lp_build_name(step0_ptr, "step0");
 +   lp_build_name(step1_ptr, "step1");
 +   lp_build_name(step2_ptr, "step2");
  
     /*
      * Function body
  
     lp_build_interp_soa_init(&interp, shader->base.tokens, builder, fs_type,
                              a0_ptr, dadx_ptr, dady_ptr,
 -                            x0, y0, 2, 0);
 +                            x0, y0);
  
     /* code generated texture sampling */
     sampler = lp_llvm_sampler_soa_create(key->sampler, context_ptr);
  
 +   /* loop over quads in the block */
     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);
 +         lp_build_interp_soa_update(&interp, i);
  
 -      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,
                    i,
                    &interp,
                    sampler,
 -                  &fs_mask[i],
 +                  &fs_mask[i], /* output */
                    out_color,
 -                  depth_ptr_i);
 +                  depth_ptr_i,
 +                  c0, c1, c2,
 +                  step0_ptr, step1_ptr, step2_ptr);
  
        for(chan = 0; chan < NUM_CHANNELS; ++chan)
           fs_out_color[chan][i] = out_color[chan];
      * Translate the LLVM IR into machine code.
      */
  
+ #ifdef DEBUG
     if(LLVMVerifyFunction(variant->function, LLVMPrintMessageAction)) {
        LLVMDumpValue(variant->function);
-       abort();
+       assert(0);
     }
+ #endif
  
     LLVMRunFunctionPassManager(screen->pass, variant->function);
  
@@@ -751,7 -668,12 +792,12 @@@ llvmpipe_bind_fs_state(struct pipe_cont
  {
     struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
  
-    llvmpipe->fs = (struct lp_fragment_shader *) fs;
+    if (llvmpipe->fs == fs)
+       return;
+    draw_flush(llvmpipe->draw);
+    llvmpipe->fs = fs;
  
     llvmpipe->dirty |= LP_NEW_FS;
  }
@@@ -766,6 -688,7 +812,7 @@@ llvmpipe_delete_fs_state(struct pipe_co
     struct lp_fragment_shader_variant *variant;
  
     assert(fs != llvmpipe->fs);
+    (void) llvmpipe;
  
     variant = shader->variants;
     while(variant) {
@@@ -801,17 -724,18 +848,17 @@@ llvmpipe_set_constant_buffer(struct pip
     assert(shader < PIPE_SHADER_TYPES);
     assert(index == 0);
  
-    if(shader == PIPE_SHADER_VERTEX)
-       draw_flush(llvmpipe->draw);
 +   if(llvmpipe->constants[shader].buffer == buffer)
 +      return;
 +
+    draw_flush(llvmpipe->draw);
  
     /* note: reference counting */
     pipe_buffer_reference(&llvmpipe->constants[shader].buffer, buffer);
  
 -   if(shader == PIPE_SHADER_FRAGMENT) {
 -      llvmpipe->jit_context.constants = data;
 -   }
 -
     if(shader == PIPE_SHADER_VERTEX) {
-       draw_set_mapped_constant_buffer(llvmpipe->draw, data, size);
+       draw_set_mapped_constant_buffer(llvmpipe->draw, PIPE_SHADER_VERTEX,
+                                       data, size);
     }
  
     llvmpipe->dirty |= LP_NEW_CONSTANTS;
@@@ -890,7 -814,4 +937,7 @@@ llvmpipe_update_fs(struct llvmpipe_cont
        variant = generate_fragment(lp, shader, &key);
  
     shader->current = variant;
 +
 +   lp_setup_set_fs_function(lp->setup, 
 +                            shader->current->jit_function);
  }
index 282ed2e9ea3e17cb69190b70f7845a6b9ecb4d75,aa3b5a3f91ef1ce7971eccd40f166813109ba27f..7d4c310aae844f7a6458ef38e4d66dbdcf8c5565
@@@ -29,7 -29,6 +29,7 @@@
  #include "util/u_memory.h"
  #include "lp_context.h"
  #include "lp_state.h"
 +#include "lp_setup.h"
  #include "draw/draw_context.h"
  
  
@@@ -42,25 -41,18 +42,28 @@@ llvmpipe_create_rasterizer_state(struc
  }
  
  void llvmpipe_bind_rasterizer_state(struct pipe_context *pipe,
-                                     void *setup)
+                                     void *rasterizer)
  {
     struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
  
+    if (llvmpipe->rasterizer == rasterizer)
+       return;
     /* pass-through to draw module */
-    draw_set_rasterizer_state(llvmpipe->draw, setup);
+    draw_set_rasterizer_state(llvmpipe->draw, rasterizer);
  
-    llvmpipe->rasterizer = (struct pipe_rasterizer_state *)setup;
+    llvmpipe->rasterizer = rasterizer;
  
 +   /* Note: we can immediately set the triangle state here and
 +    * not worry about binning because we handle culling during
 +    * triangle setup, not when rasterizing the bins.
 +    */
 +   if (llvmpipe->rasterizer) {
 +      lp_setup_set_triangle_state( llvmpipe->setup,
 +                   llvmpipe->rasterizer->cull_mode,
 +                   llvmpipe->rasterizer->front_winding == PIPE_WINDING_CCW );
 +   }
 +
     llvmpipe->dirty |= LP_NEW_RASTERIZER;
  }
  
index e19394a4c92007623ebfd67236f2c4f9aef52b16,d382f9ca87e1cea4563785e21c423cda04bad305..976f81113fd1e4bea5176cb00ae2942168815c85
@@@ -37,6 -37,7 +37,6 @@@
  #include "lp_context.h"
  #include "lp_state.h"
  #include "lp_texture.h"
 -#include "lp_tex_cache.h"
  #include "draw/draw_context.h"
  
  
@@@ -76,6 -77,34 +76,34 @@@ llvmpipe_bind_sampler_states(struct pip
  }
  
  
+ void
+ llvmpipe_bind_vertex_sampler_states(struct pipe_context *pipe,
+                                     unsigned num_samplers,
+                                     void **samplers)
+ {
+    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+    unsigned i;
+    assert(num_samplers <= PIPE_MAX_VERTEX_SAMPLERS);
+    /* Check for no-op */
+    if (num_samplers == llvmpipe->num_vertex_samplers &&
+        !memcmp(llvmpipe->vertex_samplers, samplers, num_samplers * sizeof(void *)))
+       return;
+    draw_flush(llvmpipe->draw);
+    for (i = 0; i < num_samplers; ++i)
+       llvmpipe->vertex_samplers[i] = samplers[i];
+    for (i = num_samplers; i < PIPE_MAX_VERTEX_SAMPLERS; ++i)
+       llvmpipe->vertex_samplers[i] = NULL;
+    llvmpipe->num_vertex_samplers = num_samplers;
+    llvmpipe->dirty |= LP_NEW_SAMPLER;
+ }
  void
  llvmpipe_set_sampler_textures(struct pipe_context *pipe,
                                unsigned num, struct pipe_texture **texture)
        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->width0;
 -         jit_tex->height = tex->height0;
 -         jit_tex->stride = lp_tex->stride[0];
 -         if(!lp_tex->dt)
 -            jit_tex->data = lp_tex->data;
 -      }
     }
  
     llvmpipe->num_textures = num;
  }
  
  
 -      lp_tex_tile_cache_set_texture(llvmpipe->vertex_tex_cache[i], tex);
+ void
+ llvmpipe_set_vertex_sampler_textures(struct pipe_context *pipe,
+                                      unsigned num_textures,
+                                      struct pipe_texture **textures)
+ {
+    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+    uint i;
+    assert(num_textures <= PIPE_MAX_VERTEX_SAMPLERS);
+    /* Check for no-op */
+    if (num_textures == llvmpipe->num_vertex_textures &&
+        !memcmp(llvmpipe->vertex_textures, textures, num_textures * sizeof(struct pipe_texture *))) {
+       return;
+    }
+    draw_flush(llvmpipe->draw);
+    for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) {
+       struct pipe_texture *tex = i < num_textures ? textures[i] : NULL;
+       pipe_texture_reference(&llvmpipe->vertex_textures[i], tex);
+    }
+    llvmpipe->num_vertex_textures = num_textures;
+    llvmpipe->dirty |= LP_NEW_TEXTURE;
+ }
  void
  llvmpipe_delete_sampler_state(struct pipe_context *pipe,
                                void *sampler)
index 957e947fe029c92e1915a08f9d68cc37a98b85be,e37ff04f3df172aab3e3c764a645f2124c5f715f..0e9f03b90b85b12b6b120eb30bf5fcf23863e8c4
  /* Authors:  Keith Whitwell <keith@tungstengraphics.com>
   */
  
 +#include "pipe/p_state.h"
 +#include "util/u_surface.h"
  #include "lp_context.h"
  #include "lp_state.h"
  #include "lp_surface.h"
 -#include "lp_tile_cache.h"
 +#include "lp_setup.h"
  
  #include "draw/draw_context.h"
  
+ #include "util/u_format.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;
  
 -   draw_flush(lp->draw);
 +   boolean changed = !util_framebuffer_state_equal(&lp->framebuffer, fb);
  
 -   for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
 -      /* check if changing cbuf */
 -      if (lp->framebuffer.cbufs[i] != fb->cbufs[i]) {
 -         /* flush old */
 -         lp_tile_cache_map_transfers(lp->cbuf_cache[i]);
 -         lp_flush_tile_cache(lp->cbuf_cache[i]);
 +   if (changed) {
  
 -         /* assign new */
 -         pipe_surface_reference(&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 */
 -      pipe_surface_reference(&lp->framebuffer.zsbuf, fb->zsbuf);
 +      util_copy_framebuffer_state(&lp->framebuffer, fb);
  
        /* 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);
+          depth_bits = util_format_get_component_bits(lp->framebuffer.zsbuf->format,
+                                                      UTIL_FORMAT_COLORSPACE_ZS,
+                                                      0);
           if (depth_bits > 16) {
              mrd = 0.0000001;
           }
           }
           draw_set_mrd(lp->draw, mrd);
        }
 -   }
  
 -   lp->framebuffer.width = fb->width;
 -   lp->framebuffer.height = fb->height;
 +      lp_setup_bind_framebuffer( lp->setup, &lp->framebuffer );
  
 -   lp->dirty |= LP_NEW_FRAMEBUFFER;
 +      lp->dirty |= LP_NEW_FRAMEBUFFER;
 +   }
  }
index 1682e37354a345176a157e2ebd365bf8ac97c2db,2c135029ea2d1b5bd817c6f6d8ca5485bfe19fe3..2462378152ab9c3000c6a1f19814a88bd72b0ed0
  #include "pipe/p_defines.h"
  #include "pipe/p_inlines.h"
  #include "pipe/internal/p_winsys_screen.h"
+ #include "util/u_format.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"
  
@@@ -47,7 -50,6 +49,6 @@@
  /* Simple, maximally packed layout.
   */
  
  /* Conventional allocation path for non-display textures:
   */
  static boolean
@@@ -56,31 -58,31 +57,31 @@@ llvmpipe_texture_layout(struct llvmpipe
  {
     struct pipe_texture *pt = &lpt->base;
     unsigned level;
-    unsigned width = pt->width[0];
-    unsigned height = pt->height[0];
-    unsigned depth = pt->depth[0];
+    unsigned width = pt->width0;
+    unsigned height = pt->height0;
+    unsigned depth = pt->depth0;
  
     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);
+       unsigned nblocksx, nblocksy;
+       /* Allocate storage for whole quads. This is particularly important
+        * for depth surfaces, which are currently stored in a swizzled format. */
+       nblocksx = util_format_get_nblocksx(pt->format, align(width, 2));
+       nblocksy = util_format_get_nblocksy(pt->format, align(height, 2));
+       lpt->stride[level] = align(nblocksx * util_format_get_blocksize(pt->format), 16);
  
        lpt->level_offset[level] = buffer_size;
  
-       buffer_size += (pt->nblocksy[level] *
+       buffer_size += (nblocksy *
                        ((pt->target == PIPE_TEXTURE_CUBE) ? 6 : depth) *
                        lpt->stride[level]);
  
-       width  = minify(width);
-       height = minify(height);
-       depth = minify(depth);
+       width  = u_minify(width, 1);
+       height = u_minify(height, 1);
+       depth = u_minify(depth, 1);
     }
  
     lpt->data = align_malloc(buffer_size, 16);
@@@ -94,14 -96,10 +95,10 @@@ llvmpipe_displaytarget_layout(struct ll
  {
     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],
+                                           lpt->base.width0,
+                                           lpt->base.height0,
                                            16,
                                            &lpt->stride[0] );
  
@@@ -163,7 -161,7 +160,7 @@@ llvmpipe_texture_blanket(struct pipe_sc
     /* Only supports one type */
     if (base->target != PIPE_TEXTURE_2D ||
         base->last_level != 0 ||
-        base->depth[0] != 1) {
+        base->depth0 != 1) {
        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);
@@@ -220,8 -216,8 +215,8 @@@ llvmpipe_get_tex_surface(struct pipe_sc
        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->width = u_minify(pt->width0, level);
+       ps->height = u_minify(pt->height0, level);
        ps->offset = lpt->level_offset[level];
        ps->usage = usage;
  
  
        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. */
 +         /* Mark the surface as dirty. */
           lpt->timestamp++;
           llvmpipe_screen(screen)->timestamp++;
        }
        ps->level = level;
        ps->zslice = zslice;
  
+       /* XXX shouldn't that rather be
+          tex_height = align(ps->height, 2);
+          to account for alignment done in llvmpipe_texture_layout ?
+       */
        if (pt->target == PIPE_TEXTURE_CUBE) {
-          ps->offset += face * pt->nblocksy[level] * lpt->stride[level];
+          unsigned tex_height = ps->height;
+          ps->offset += face * util_format_get_nblocksy(pt->format, tex_height) * lpt->stride[level];
        }
        else if (pt->target == PIPE_TEXTURE_3D) {
-          ps->offset += zslice * pt->nblocksy[level] * lpt->stride[level];
+          unsigned tex_height = ps->height;
+          ps->offset += zslice * util_format_get_nblocksy(pt->format, tex_height) * lpt->stride[level];
        }
        else {
           assert(face == 0);
@@@ -294,14 -296,10 +295,10 @@@ llvmpipe_get_tex_transfer(struct pipe_s
     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;
  
        lpt->offset = lptex->level_offset[level];
  
+       /* XXX shouldn't that rather be
+          tex_height = align(u_minify(texture->height0, level), 2)
+          to account for alignment done in llvmpipe_texture_layout ?
+       */
        if (texture->target == PIPE_TEXTURE_CUBE) {
-          lpt->offset += face * pt->nblocksy * pt->stride;
+          unsigned tex_height = u_minify(texture->height0, level);
+          lpt->offset += face *  util_format_get_nblocksy(texture->format, tex_height) * pt->stride;
        }
        else if (texture->target == PIPE_TEXTURE_3D) {
-          lpt->offset += zslice * pt->nblocksy * pt->stride;
+          unsigned tex_height = u_minify(texture->height0, level);
+          lpt->offset += zslice * util_format_get_nblocksy(texture->format, tex_height) * pt->stride;
        }
        else {
           assert(face == 0);
@@@ -346,9 -350,11 +349,11 @@@ llvmpipe_transfer_map( struct pipe_scre
     struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
     ubyte *map, *xfer_map;
     struct llvmpipe_texture *lpt;
+    enum pipe_format format;
  
     assert(transfer->texture);
     lpt = llvmpipe_texture(transfer->texture);
+    format = lpt->base.format;
  
     if(lpt->dt) {
        struct llvmpipe_winsys *winsys = screen->winsys;
     if (transfer->texture && (transfer->usage & PIPE_TRANSFER_WRITE))
     {
        /* 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;
+       transfer->y / util_format_get_blockheight(format) * transfer->stride +
+       transfer->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
     /*printf("map = %p  xfer map = %p\n", map, xfer_map);*/
     return xfer_map;
  }
index 660cc30c820f3874458df6d96da83692d620363c,19d00b58d37aeb73e5b482a7292c36abce074d54..1b7be3cce0d010d9e76f7016fc92cb342edb15b3
@@@ -29,7 -29,7 +29,7 @@@
  #define LP_TILE_SOA_H
  
  #include "pipe/p_compiler.h"
- #include "tgsi/tgsi_exec.h" // for NUM_CHANNELS
+ #include "tgsi/tgsi_exec.h" /* for NUM_CHANNELS */
  
  
  #ifdef __cplusplus
@@@ -43,24 -43,23 +43,24 @@@ struct pipe_transfer
  /**
   * Cache tile size (width and height). This needs to be a power of two.
   */
 -#define TILE_SIZE 64
 +#define TILE_ORDER 6
 +#define TILE_SIZE (1 << TILE_ORDER)
  
  
 -#define TILE_VECTOR_HEIGHT 2
 -#define TILE_VECTOR_WIDTH 8
 +#define TILE_VECTOR_HEIGHT 4
 +#define TILE_VECTOR_WIDTH 4
  
  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_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 + \
 +   ((_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]])