diff options
26 files changed, 10560 insertions, 1 deletions
diff --git a/Makefile.X11 b/Makefile.X11 index e00c1acb17..1e432a97e0 100644 --- a/Makefile.X11 +++ b/Makefile.X11 @@ -1,4 +1,4 @@ -# $Id: Makefile.X11,v 1.86 2003/09/30 10:54:15 alanh Exp $ +# $Id: Makefile.X11,v 1.87 2003/09/30 11:02:38 alanh Exp $ # Mesa 3-D graphics library # Version: 5.1 @@ -240,6 +240,7 @@ linux-solo: if [ -d src/mesa/drivers/dri/radeon ] ; then touch src/mesa/drivers/dri/radeon/depend ; fi if [ -d src/mesa/drivers/dri/mga ] ; then touch src/mesa/drivers/dri/mga/depend ; fi if [ -d src/mesa/drivers/dri/i810 ] ; then touch src/mesa/drivers/dri/i810/depend ; fi + if [ -d src/mesa/drivers/dri/i830 ] ; then touch src/mesa/drivers/dri/i830/depend ; fi if [ -d src/mesa/drivers/dri/fb ] ; then touch src/mesa/drivers/dri/fb/depend ; fi if [ -d src/glut/mini ] ; then touch src/glut/mini/depend ; fi if [ -d progs/miniglx ] ; then touch progs/miniglx/depend ; fi @@ -250,6 +251,7 @@ linux-solo: if [ -d src/mesa/drivers/dri/radeon ] ; then cd src/mesa/drivers/dri/radeon ; $(MAKE) -f Makefile.X11 $@ ; fi if [ -d src/mesa/drivers/dri/mga ] ; then cd src/mesa/drivers/dri/mga ; $(MAKE) -f Makefile.X11 $@ ; fi if [ -d src/mesa/drivers/dri/i810 ] ; then cd src/mesa/drivers/dri/i810 ; $(MAKE) -f Makefile.X11 $@ ; fi + if [ -d src/mesa/drivers/dri/i830 ] ; then cd src/mesa/drivers/dri/i830 ; $(MAKE) -f Makefile.X11 $@ ; fi if [ -d src/mesa/drivers/dri/fb ] ; then cd src/mesa/drivers/dri/fb ; $(MAKE) -f Makefile.X11 $@ ; fi if [ -d src/glx/mini ] ; then cd src/glx/mini ; $(MAKE) -f Makefile.X11 $@ ; fi if [ -d src/glu/mini ] ; then cd src/glu/mini ; $(MAKE) -f Makefile.X11 $@ ; fi diff --git a/src/mesa/drivers/dri/i830/Makefile.X11 b/src/mesa/drivers/dri/i830/Makefile.X11 new file mode 100644 index 0000000000..e690ed6b2f --- /dev/null +++ b/src/mesa/drivers/dri/i830/Makefile.X11 @@ -0,0 +1,117 @@ +# $Id: Makefile.X11,v 1.1 2003/09/30 11:02:39 alanh Exp $ + +# Mesa 3-D graphics library +# Version: 5.0 +# Copyright (C) 1995-2002 Brian Paul + +TOP = ../../../../.. + +default: linux-solo + +SHARED_INCLUDES = $(INCLUDE_DIRS) -I. -I../common -Iserver +MINIGLX_INCLUDES = -I$(TOP)/src/glx/mini + +DEFINES += \ + -D_HAVE_SWRAST=1 \ + -D_HAVE_SWTNL=1 \ + -D_HAVE_SANITY=1 \ + -D_HAVE_CODEGEN=1 \ + -D_HAVE_LIGHTING=1 \ + -D_HAVE_TEXGEN=1 \ + -D_HAVE_USERCLIP=1 \ + -DGLX_DIRECT_RENDERING + +# Not yet +# MINIGLX_SOURCES = server/i810_dri.c + +DRIVER_SOURCES = \ + i830_context.c \ + i830_debug.c \ + i830_ioctl.c \ + i830_render.c \ + i830_screen.c \ + i830_span.c \ + i830_state.c \ + i830_tex.c \ + i830_texmem.c \ + i830_texstate.c \ + i830_tris.c \ + i830_vb.c \ + ../common/mm.c \ + ../common/utils.c \ + ../common/texmem.c \ + ../common/vblank.c + +INCLUDES = $(MINIGLX_INCLUDES) \ + $(SHARED_INCLUDES) + + +C_SOURCES = $(DRIVER_SOURCES) \ + $(MINIGLX_SOURCES) + +MESA_MODULES = $(TOP)/src/mesa/mesa.a + + +ifeq ($(WINDOW_SYSTEM),dri) +WINOBJ=$(MESABUILDDIR)/dri/dri.a +WINLIB= +else +WINOBJ= +WINLIB=-L$(MESA)/src/glx/mini +endif + +ASM_SOURCES = +OBJECTS = $(C_SOURCES:.c=.o) \ + $(ASM_SOURCES:.S=.o) + +### Include directories + +INCLUDE_DIRS = \ + -I$(TOP)/include \ + -I$(TOP)/src/mesa \ + -I$(TOP)/src/mesa/main \ + -I$(TOP)/src/mesa/glapi \ + -I$(TOP)/src/mesa/math \ + -I$(TOP)/src/mesa/transform \ + -I$(TOP)/src/mesa/swrast \ + -I$(TOP)/src/mesa/swrast_setup + + +##### RULES ##### + +.c.o: + $(CC) -c $(SHARED_INCLUDES) $(MINIGLX_INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@ + +.S.o: + $(CC) -c $(SHARED_INCLUDES) $(MINIGLX_INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@ + + +##### TARGETS ##### + +targets: depend i810_dri.so + +i810_dri.so: $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile.X11 + rm -f $@ && gcc -o $@ -shared $(OBJECTS) $(MESA_MODULES) $(WINOBJ) $(WINLIB) -lc $(GL_LIB_DEPS) + rm -f $(TOP)/lib/i810_dri.so && \ + install i810_dri.so $(TOP)/lib/i810_dri.so + +# Run 'make -f Makefile.X11 dep' to update the dependencies if you change +# what's included by any source file. +depend: $(C_SOURCES) $(ASM_SOURCES) + makedepend -fdepend -Y $(SHARED_INCLUDES) $(MINIGLX_INCLUDES) \ + $(C_SOURCES) $(ASM_SOURCES) + + +# Emacs tags +tags: + etags `find . -name \*.[ch]` `find ../include` + + +# Remove .o and backup files +clean: + -rm -f *.o */*.o *~ *.o *~ *.so server/*.o + + +include $(TOP)/Make-config + +include depend diff --git a/src/mesa/drivers/dri/i830/i830_3d_reg.h b/src/mesa/drivers/dri/i830/i830_3d_reg.h new file mode 100644 index 0000000000..eab1092094 --- /dev/null +++ b/src/mesa/drivers/dri/i830/i830_3d_reg.h @@ -0,0 +1,675 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_3d_reg.h,v 1.4 2002/12/10 01:26:53 dawes Exp $ */ +#define I830_SET_FIELD( var, mask, value ) (var &= ~(mask), var |= value) + +#define CMD_3D (0x3<<29) + +/* 3DPRIMITIVE, p104 */ +#define PRIM3D_INLINE (CMD_3D | (0x1f<<24)) +#define PRIM3D_INDIRECT_SEQ ((1<<23) | PRIM3D_INLINE) +#define PRIM3D_INDICES ((1<<23) | PRIM3D_INLINE | (1<<17)) + +#define PRIM3D_INLINE_CNT(used) ((used / 4) - 2) +#define PRIM3D_INDICES_CNT(num_indices) ((num_indices + 1) / 2) +#define PRIM3D_INDIRECT_CNT(verts) (verts) + +#define PRIM3D_TRILIST 0 +#define PRIM3D_TRISTRIP (0x1<<18) +#define PRIM3D_TRISTRIP_RVRSE (0x2<<18) +#define PRIM3D_TRIFAN (0x3<<18) +#define PRIM3D_POLY (0x4<<18) +#define PRIM3D_LINELIST (0x5<<18) +#define PRIM3D_LINESTRIP (0x6<<18) +#define PRIM3D_RECTLIST (0x7<<18) +#define PRIM3D_POINTLIST (0x8<<18) +#define PRIM3D_DIB (0x9<<18) + +/* STATE3D_ANTI_ALIASING, p 123 */ +#define STATE3D_AA_CMD (CMD_3D | (0x06<<24)) + +#define AA_LINE_ECAAR_WIDTH_ENABLE (1<<16) +#define AA_LINE_ECAAR_WIDTH_0_5 0 +#define AA_LINE_ECAAR_WIDTH_1_0 (1<<14) +#define AA_LINE_ECAAR_WIDTH_2_0 (2<<14) +#define AA_LINE_ECAAR_WIDTH_4_0 (3<<14) + +#define AA_LINE_REGION_WIDTH_ENABLE (1<<8) +#define AA_LINE_REGION_WIDTH_0_5 0 +#define AA_LINE_REGION_WIDTH_1_0 (1<<6) +#define AA_LINE_REGION_WIDTH_2_0 (2<<6) +#define AA_LINE_REGION_WIDTH_4_0 (3<<6) + +#define AA_LINE_ENABLE ((1<<1) | 1) +#define AA_LINE_DISABLE (1<<1) + +/* STATE3D_BUFFER_INFO, p 124 */ +#define STATE3D_BUF_INFO_CMD (CMD_3D | (0x1d<<24) | (0x8e<<16) | 1) +/* Dword 1 */ +#define BUF_3D_ID_COLOR_BACK (0x3<<24) +#define BUF_3D_ID_DEPTH (0x7<<24) +#define BUF_3D_USE_FENCE (1<<23) +#define BUF_3D_TILED_SURFACE (1<<22) +#define BUF_3D_TILE_WALK_X 0 +#define BUF_3D_TILE_WALK_Y (1<<21) +#define BUF_3D_PITCH(x) ((x)<<2) +/* Dword 2 */ +#define BUF_3D_ADDR(x) ((x) & ~0x3) + +/* STATE3D_COLOR_FACTOR_0, p127 */ +#define STATE3D_COLOR_FACTOR_CMD(stage) (CMD_3D | (0x1d<<24) | ((0x90 + (stage))<<16)) + +/* STATE3D_CONSTANT_BLEND_COLOR, p128 */ +#define STATE3D_CONST_BLEND_COLOR_CMD (CMD_3D | (0x1d<<24) | (0x88<<16)) + +/* STATE3D_DEFAULT_DIFFUSE, p128 */ +#define STATE3D_DFLT_DIFFUSE_CMD (CMD_3D | (0x1d<<24) | (0x99<<16)) + +/* STATE3D_DEFAULT_SPECULAR, p129 */ +#define STATE3D_DFLT_SPEC_CMD (CMD_3D | (0x1d<<24) | (0x9a<<16)) + +/* STATE3D_DEFAULT_Z, p129 */ +#define STATE3D_DFLT_Z_CMD (CMD_3D | (0x1d<<24) | (0x98<<16)) + +/* STATE3D_DEST_BUFFER_VARIABLES, p130 */ +#define STATE3D_DST_BUF_VARS_CMD (CMD_3D | (0x1d<<24) | (0x85<<16)) +/* Dword 1 */ +#define DSTORG_HORT_BIAS(x) ((x)<<20) +#define DSTORG_VERT_BIAS(x) ((x)<<16) +#define COLOR_4_2_2_CHNL_WRT_ALL 0 +#define COLOR_4_2_2_CHNL_WRT_Y (1<<12) +#define COLOR_4_2_2_CHNL_WRT_CR (2<<12) +#define COLOR_4_2_2_CHNL_WRT_CB (3<<12) +#define COLOR_4_2_2_CHNL_WRT_CRCB (4<<12) +#define COLR_BUF_8BIT 0 +#define COLR_BUF_RGB555 (1<<8) +#define COLR_BUF_RGB565 (2<<8) +#define COLR_BUF_ARGB8888 (3<<8) +#define DEPTH_IS_Z 0 +#define DEPTH_IS_W (1<<6) +#define DEPTH_FRMT_16_FIXED 0 +#define DEPTH_FRMT_16_FLOAT (1<<2) +#define DEPTH_FRMT_24_FIXED_8_OTHER (2<<2) +#define DEPTH_FRMT_24_FLOAT_8_OTHER (3<<2) +#define VERT_LINE_STRIDE_1 (1<<1) +#define VERT_LINE_STRIDE_0 0 +#define VERT_LINE_STRIDE_OFS_1 1 +#define VERT_LINE_STRIDE_OFS_0 0 + +/* STATE3D_DRAWING_RECTANGLE, p133 */ +#define STATE3D_DRAW_RECT_CMD (CMD_3D|(0x1d<<24)|(0x80<<16)|3) +/* Dword 1 */ +#define DRAW_RECT_DIS_DEPTH_OFS (1<<30) +#define DRAW_DITHER_OFS_X(x) ((x)<<26) +#define DRAW_DITHER_OFS_Y(x) ((x)<<24) +/* Dword 2 */ +#define DRAW_YMIN(x) ((x)<<16) +#define DRAW_XMIN(x) (x) +/* Dword 3 */ +#define DRAW_YMAX(x) ((x)<<16) +#define DRAW_XMAX(x) (x) +/* Dword 4 */ +#define DRAW_YORG(x) ((x)<<16) +#define DRAW_XORG(x) (x) + +/* STATE3D_ENABLES_1, p136 */ +#define STATE3D_ENABLES_1_CMD (CMD_3D|(0x3<<24)) +#define ENABLE_LOGIC_OP_MASK ((1<<23)|(1<<22)) +#define ENABLE_LOGIC_OP ((1<<23)|(1<<22)) +#define DISABLE_LOGIC_OP (1<<23) +#define ENABLE_STENCIL_TEST ((1<<21)|(1<<20)) +#define DISABLE_STENCIL_TEST (1<<21) +#define ENABLE_DEPTH_BIAS ((1<<11)|(1<<10)) +#define DISABLE_DEPTH_BIAS (1<<11) +#define ENABLE_SPEC_ADD_MASK ((1<<9)|(1<<8)) +#define ENABLE_SPEC_ADD ((1<<9)|(1<<8)) +#define DISABLE_SPEC_ADD (1<<9) +#define ENABLE_DIS_FOG_MASK ((1<<7)|(1<<6)) + /* prefixed I830 because ENABLE_FOG defined elsewhere */ +#define I830_ENABLE_FOG ((1<<7)|(1<<6)) +#define I830_DISABLE_FOG (1<<7) +#define ENABLE_DIS_ALPHA_TEST_MASK ((1<<5)|(1<<4)) +#define ENABLE_ALPHA_TEST ((1<<5)|(1<<4)) +#define DISABLE_ALPHA_TEST (1<<5) +#define ENABLE_DIS_CBLEND_MASK ((1<<3)|(1<<2)) +#define ENABLE_COLOR_BLEND ((1<<3)|(1<<2)) +#define DISABLE_COLOR_BLEND (1<<3) +#define ENABLE_DIS_DEPTH_TEST_MASK ((1<<1)|1) +#define ENABLE_DEPTH_TEST ((1<<1)|1) +#define DISABLE_DEPTH_TEST (1<<1) + +/* STATE3D_ENABLES_2, p138 */ +#define STATE3D_ENABLES_2_CMD (CMD_3D|(0x4<<24)) +#define ENABLE_STENCIL_WRITE ((1<<21)|(1<<20)) +#define DISABLE_STENCIL_WRITE (1<<21) +#define ENABLE_TEX_CACHE ((1<<17)|(1<<16)) +#define DISABLE_TEX_CACHE (1<<17) +#define ENABLE_DITHER ((1<<9)|(1<<8)) +#define DISABLE_DITHER (1<<9) +#define ENABLE_COLOR_MASK (1<<10) +#define WRITEMASK_ALPHA (1<<7) +#define WRITEMASK_ALPHA_SHIFT 7 +#define WRITEMASK_RED (1<<6) +#define WRITEMASK_RED_SHIFT 6 +#define WRITEMASK_GREEN (1<<5) +#define WRITEMASK_GREEN_SHIFT 5 +#define WRITEMASK_BLUE (1<<4) +#define WRITEMASK_BLUE_SHIFT 4 +#define WRITEMASK_MASK ((1<<4)|(1<<5)|(1<<6)|(1<<7)) +#define ENABLE_COLOR_WRITE ((1<<3)|(1<<2)) +#define DISABLE_COLOR_WRITE (1<<3) +#define ENABLE_DIS_DEPTH_WRITE_MASK 0x3 +#define ENABLE_DEPTH_WRITE ((1<<1)|1) +#define DISABLE_DEPTH_WRITE (1<<1) + +/* STATE3D_FOG_COLOR, p139 */ +#define STATE3D_FOG_COLOR_CMD (CMD_3D|(0x15<<24)) +#define FOG_COLOR_RED(x) ((x)<<16) +#define FOG_COLOR_GREEN(x) ((x)<<8) +#define FOG_COLOR_BLUE(x) (x) + +/* STATE3D_FOG_MODE, p140 */ +#define STATE3D_FOG_MODE_CMD (CMD_3D|(0x1d<<24)|(0x89<<16)|2) +/* Dword 1 */ +#define FOGFUNC_ENABLE (1<<31) +#define FOGFUNC_VERTEX 0 +#define FOGFUNC_PIXEL_EXP (1<<28) +#define FOGFUNC_PIXEL_EXP2 (2<<28) +#define FOGFUNC_PIXEL_LINEAR (3<<28) +#define FOGSRC_INDEX_Z (1<<27) +#define FOGSRC_INDEX_W ((1<<27)|(1<<25)) +#define FOG_LINEAR_CONST (1<<24) +#define FOG_CONST_1(x) ((x)<<4) +#define ENABLE_FOG_DENSITY (1<<23) +/* Dword 2 */ +#define FOG_CONST_2(x) (x) +/* Dword 3 */ +#define FOG_DENSITY(x) (x) + +/* STATE3D_INDEPENDENT_ALPHA_BLEND, p142 */ +#define STATE3D_INDPT_ALPHA_BLEND_CMD (CMD_3D|(0x0b<<24)) +#define ENABLE_INDPT_ALPHA_BLEND ((1<<23)|(1<<22)) +#define DISABLE_INDPT_ALPHA_BLEND (1<<23) +#define ALPHA_BLENDFUNC_MASK 0x3f0000 +#define ENABLE_ALPHA_BLENDFUNC (1<<21) +#define ABLENDFUNC_ADD 0 +#define ABLENDFUNC_SUB (1<<16) +#define ABLENDFUNC_RVSE_SUB (2<<16) +#define ABLENDFUNC_MIN (3<<16) +#define ABLENDFUNC_MAX (4<<16) +#define SRC_DST_ABLEND_MASK 0xfff +#define ENABLE_SRC_ABLEND_FACTOR (1<<11) +#define SRC_ABLEND_FACT(x) ((x)<<6) +#define ENABLE_DST_ABLEND_FACTOR (1<<5) +#define DST_ABLEND_FACT(x) (x) + +#define BLENDFACT_ZERO 0x01 +#define BLENDFACT_ONE 0x02 +#define BLENDFACT_SRC_COLR 0x03 +#define BLENDFACT_INV_SRC_COLR 0x04 +#define BLENDFACT_SRC_ALPHA 0x05 +#define BLENDFACT_INV_SRC_ALPHA 0x06 +#define BLENDFACT_DST_ALPHA 0x07 +#define BLENDFACT_INV_DST_ALPHA 0x08 +#define BLENDFACT_DST_COLR 0x09 +#define BLENDFACT_INV_DST_COLR 0x0a +#define BLENDFACT_SRC_ALPHA_SATURATE 0x0b +#define BLENDFACT_CONST_COLOR 0x0c +#define BLENDFACT_INV_CONST_COLOR 0x0d +#define BLENDFACT_CONST_ALPHA 0x0e +#define BLENDFACT_INV_CONST_ALPHA 0x0f + +/* STATE3D_MAP_BLEND_ARG, p152 */ +#define STATE3D_MAP_BLEND_ARG_CMD(stage) (CMD_3D|(0x0e<<24)|((stage)<<20)) + +#define TEXPIPE_COLOR 0 +#define TEXPIPE_ALPHA (1<<18) +#define TEXPIPE_KILL (2<<18) +#define TEXBLEND_ARG0 0 +#define TEXBLEND_ARG1 (1<<15) +#define TEXBLEND_ARG2 (2<<15) +#define TEXBLEND_ARG3 (3<<15) +#define TEXBLENDARG_MODIFY_PARMS (1<<6) +#define TEXBLENDARG_REPLICATE_ALPHA (1<<5) +#define TEXBLENDARG_INV_ARG (1<<4) +#define TEXBLENDARG_ONE 0 +#define TEXBLENDARG_FACTOR 0x01 +#define TEXBLENDARG_ACCUM 0x02 +#define TEXBLENDARG_DIFFUSE 0x03 +#define TEXBLENDARG_SPEC 0x04 +#define TEXBLENDARG_CURRENT 0x05 +#define TEXBLENDARG_TEXEL0 0x06 +#define TEXBLENDARG_TEXEL1 0x07 +#define TEXBLENDARG_TEXEL2 0x08 +#define TEXBLENDARG_TEXEL3 0x09 +#define TEXBLENDARG_FACTOR_N 0x0e + +/* STATE3D_MAP_BLEND_OP, p155 */ +#define STATE3D_MAP_BLEND_OP_CMD(stage) (CMD_3D|(0x0d<<24)|((stage)<<20)) +#if 0 +#define TEXPIPE_COLOR 0 +#define TEXPIPE_ALPHA (1<<18) +#define TEXPIPE_KILL (2<<18) +#endif +#define ENABLE_TEXOUTPUT_WRT_SEL (1<<17) +#define TEXOP_OUTPUT_CURRENT 0 +#define TEXOP_OUTPUT_ACCUM (1<<15) +#define ENABLE_TEX_CNTRL_STAGE ((1<<12)|(1<<11)) +#define DISABLE_TEX_CNTRL_STAGE (1<<12) +#define TEXOP_SCALE_SHIFT 9 +#define TEXOP_SCALE_1X (0 << TEXOP_SCALE_SHIFT) +#define TEXOP_SCALE_2X (1 << TEXOP_SCALE_SHIFT) +#define TEXOP_SCALE_4X (2 << TEXOP_SCALE_SHIFT) +#define TEXOP_MODIFY_PARMS (1<<8) +#define TEXOP_LAST_STAGE (1<<7) +#define TEXBLENDOP_KILLPIXEL 0x02 +#define TEXBLENDOP_ARG1 0x01 +#define TEXBLENDOP_ARG2 0x02 +#define TEXBLENDOP_MODULATE 0x03 +#define TEXBLENDOP_ADD 0x06 +#define TEXBLENDOP_ADDSIGNED 0x07 +#define TEXBLENDOP_BLEND 0x08 +#define TEXBLENDOP_BLEND_AND_ADD 0x09 +#define TEXBLENDOP_SUBTRACT 0x0a +#define TEXBLENDOP_DOT3 0x0b +#define TEXBLENDOP_DOT4 0x0c +#define TEXBLENDOP_MODULATE_AND_ADD 0x0d +#define TEXBLENDOP_MODULATE_2X_AND_ADD 0x0e +#define TEXBLENDOP_MODULATE_4X_AND_ADD 0x0f + +/* STATE3D_MAP_BUMP_TABLE, p160 TODO */ +/* STATE3D_MAP_COLOR_CHROMA_KEY, p161 TODO */ + +/* STATE3D_MAP_COORD_SET_BINDINGS, p162 */ +#define STATE3D_MAP_COORD_SETBIND_CMD (CMD_3D|(0x1d<<24)|(0x02<<16)) +#define TEXBIND_MASK3 ((1<<15)|(1<<14)|(1<<13)|(1<<12)) +#define TEXBIND_MASK2 ((1<<11)|(1<<10)|(1<<9)|(1<<8)) +#define TEXBIND_MASK1 ((1<<7)|(1<<6)|(1<<5)|(1<<4)) +#define TEXBIND_MASK0 ((1<<3)|(1<<2)|(1<<1)|1) + +#define TEXBIND_SET3(x) ((x)<<12) +#define TEXBIND_SET2(x) ((x)<<8) +#define TEXBIND_SET1(x) ((x)<<4) +#define TEXBIND_SET0(x) (x) + +#define TEXCOORDSRC_KEEP 0 +#define TEXCOORDSRC_DEFAULT 0x01 +#define TEXCOORDSRC_VTXSET_0 0x08 +#define TEXCOORDSRC_VTXSET_1 0x09 +#define TEXCOORDSRC_VTXSET_2 0x0a +#define TEXCOORDSRC_VTXSET_3 0x0b +#define TEXCOORDSRC_VTXSET_4 0x0c +#define TEXCOORDSRC_VTXSET_5 0x0d +#define TEXCOORDSRC_VTXSET_6 0x0e +#define TEXCOORDSRC_VTXSET_7 0x0f + +#define MAP_UNIT(unit) ((unit)<<16) +#define MAP_UNIT_MASK (3<<16) + +/* STATE3D_MAP_COORD_SETS, p164 */ +#define STATE3D_MAP_COORD_SET_CMD (CMD_3D|(0x1c<<24)|(0x01<<19)) +#define ENABLE_TEXCOORD_PARAMS (1<<15) +#define TEXCOORDS_ARE_NORMAL (1<<14) +#define TEXCOORDS_ARE_IN_TEXELUNITS 0 +#define TEXCOORDTYPE_CARTESIAN 0 +#define TEXCOORDTYPE_HOMOGENEOUS (1<<11) +#define TEXCOORDTYPE_VECTOR (2<<11) +#define ENABLE_ADDR_V_CNTL (1<<7) +#define ENABLE_ADDR_U_CNTL (1<<3) +#define TEXCOORD_ADDR_V_MODE(x) ((x)<<4) +#define TEXCOORD_ADDR_U_MODE(x) (x) +#define TEXCOORDMODE_WRAP 0 +#define TEXCOORDMODE_MIRROR 1 +#define TEXCOORDMODE_CLAMP 2 +#define TEXCOORDMODE_WRAP_SHORTEST 3 +#define TEXCOORDMODE_CLAMP_BORDER 4 +#define TEXCOORD_ADDR_V_MASK 0x70 +#define TEXCOORD_ADDR_U_MASK 0x7 + +/* STATE3D_MAP_CUBE, p168 TODO */ +#define STATE3D_MAP_CUBE (CMD_3D|(0x1c<<24)|(0x0a<<19)) +#define CUBE_NEGX_ENABLE (1<<5) +#define CUBE_POSX_ENABLE (1<<4) +#define CUBE_NEGY_ENABLE (1<<3) +#define CUBE_POSY_ENABLE (1<<2) +#define CUBE_NEGZ_ENABLE (1<<1) +#define CUBE_POSZ_ENABLE (1<<0) + + +/* STATE3D_MODES_1, p190 */ +#define STATE3D_MODES_1_CMD (CMD_3D|(0x08<<24)) +#define BLENDFUNC_MASK 0x3f0000 +#define ENABLE_COLR_BLND_FUNC (1<<21) +#define BLENDFUNC_ADD 0 +#define BLENDFUNC_SUB (1<<16) +#define BLENDFUNC_RVRSE_SUB (2<<16) +#define BLENDFUNC_MIN (3<<16) +#define BLENDFUNC_MAX (4<<16) +#define SRC_DST_BLND_MASK 0xfff +#define ENABLE_SRC_BLND_FACTOR (1<<11) +#define ENABLE_DST_BLND_FACTOR (1<<5) +#define SRC_BLND_FACT(x) ((x)<<6) +#define DST_BLND_FACT(x) (x) + +/* Use the blendfact defines for BLND_FACTOR macros */ +#if 0 +#define BLENDFACT_ZERO 0x01 +#define BLENDFACT_ONE 0x02 +#define BLENDFACT_SRC_COLR 0x03 +#define BLENDFACT_INV_SRC_COLR 0x04 +#define BLENDFACT_SRC_ALPHA 0x05 +#define BLENDFACT_INV_SRC_ALPHA 0x06 +#define BLENDFACT_DST_ALPHA 0x07 +#define BLENDFACT_INV_DST_ALPHA 0x08 +#define BLENDFACT_CONST_ALPHA 0x0e +#define BLENDFACT_INV_CONST_ALPHA 0x0f +#endif + +/* STATE3D_MODES_2, p192 */ +#define STATE3D_MODES_2_CMD (CMD_3D|(0x0f<<24)) +#define ENABLE_GLOBAL_DEPTH_BIAS (1<<22) +#define GLOBAL_DEPTH_BIAS(x) ((x)<<14) +#define ENABLE_ALPHA_TEST_FUNC (1<<13) +#define ENABLE_ALPHA_REF_VALUE (1<<8) +#define ALPHA_TEST_FUNC(x) ((x)<<9) +#define ALPHA_REF_VALUE(x) (x) + +#define ALPHA_TEST_REF_MASK 0x3fff +#define COMPAREFUNC_ALWAYS 0 +#define COMPAREFUNC_NEVER 0x1 +#define COMPAREFUNC_LESS 0x2 +#define COMPAREFUNC_EQUAL 0x3 +#define COMPAREFUNC_LEQUAL 0x4 +#define COMPAREFUNC_GREATER 0x5 +#define COMPAREFUNC_NOTEQUAL 0x6 +#define COMPAREFUNC_GEQUAL 0x7 + +/* STATE3D_MODES_3, p193 */ +#define STATE3D_MODES_3_CMD (CMD_3D|(0x02<<24)) +#define DEPTH_TEST_FUNC_MASK 0x1f0000 +#define ENABLE_DEPTH_TEST_FUNC (1<<20) +/* Uses COMPAREFUNC */ +#define DEPTH_TEST_FUNC(x) ((x)<<16) +#define ENABLE_ALPHA_SHADE_MODE (1<<11) +#define ENABLE_FOG_SHADE_MODE (1<<9) +#define ENABLE_SPEC_SHADE_MODE (1<<7) +#define ENABLE_COLOR_SHADE_MODE (1<<5) +#define ALPHA_SHADE_MODE(x) ((x)<<10) +#define FOG_SHADE_MODE(x) ((x)<<8) +#define SPEC_SHADE_MODE(x) ((x)<<6) +#define COLOR_SHADE_MODE(x) ((x)<<4) +#define CULLMODE_MASK 0xf +#define ENABLE_CULL_MODE (1<<3) +#define CULLMODE_BOTH 0 +#define CULLMODE_NONE 1 +#define CULLMODE_CW 2 +#define CULLMODE_CCW 3 + +#define SHADE_MODE_LINEAR 0 +#define SHADE_MODE_FLAT 0x1 + +/* STATE3D_MODES_4, p195 */ +#define STATE3D_MODES_4_CMD (CMD_3D|(0x16<<24)) +#define ENABLE_LOGIC_OP_FUNC (1<<23) +#define LOGIC_OP_FUNC(x) ((x)<<18) +#define LOGICOP_MASK ((1<<18)|(1<<19)|(1<<20)|(1<<21)) +#define LOGICOP_CLEAR 0 +#define LOGICOP_NOR 0x1 +#define LOGICOP_AND_INV 0x2 +#define LOGICOP_COPY_INV 0x3 +#define LOGICOP_AND_RVRSE 0x4 +#define LOGICOP_INV 0x5 +#define LOGICOP_XOR 0x6 +#define LOGICOP_NAND 0x7 +#define LOGICOP_AND 0x8 +#define LOGICOP_EQUIV 0x9 +#define LOGICOP_NOOP 0xa +#define LOGICOP_OR_INV 0xb +#define LOGICOP_COPY 0xc +#define LOGICOP_OR_RVRSE 0xd +#define LOGICOP_OR 0xe +#define LOGICOP_SET 0xf +#define MODE4_ENABLE_STENCIL_TEST_MASK ((1<<17)|(0xff00)) +#define ENABLE_STENCIL_TEST_MASK (1<<17) +#define STENCIL_TEST_MASK(x) ((x)<<8) +#define MODE4_ENABLE_STENCIL_WRITE_MASK ((1<<16)|(0x00ff)) +#define ENABLE_STENCIL_WRITE_MASK (1<<16) +#define STENCIL_WRITE_MASK(x) (x) + +/* STATE3D_MODES_5, p196 */ +#define STATE3D_MODES_5_CMD (CMD_3D|(0x0c<<24)) +#define ENABLE_SPRITE_POINT_TEX (1<<23) +#define SPRITE_POINT_TEX_ON (1<<22) +#define SPRITE_POINT_TEX_OFF 0 +#define FLUSH_RENDER_CACHE (1<<18) +#define FLUSH_TEXTURE_CACHE (1<<16) +#define FIXED_LINE_WIDTH_MASK 0xfc00 +#define ENABLE_FIXED_LINE_WIDTH (1<<15) +#define FIXED_LINE_WIDTH(x) ((x)<<10) +#define FIXED_POINT_WIDTH_MASK 0x3ff +#define ENABLE_FIXED_POINT_WIDTH (1<<9) +#define FIXED_POINT_WIDTH(x) (x) + +/* STATE3D_RASTERIZATION_RULES, p198 */ +#define STATE3D_RASTER_RULES_CMD (CMD_3D|(0x07<<24)) +#define ENABLE_POINT_RASTER_RULE (1<<15) +#define OGL_POINT_RASTER_RULE (1<<13) +#define ENABLE_LINE_STRIP_PROVOKE_VRTX (1<<8) +#define ENABLE_TRI_FAN_PROVOKE_VRTX (1<<5) +#define ENABLE_TRI_STRIP_PROVOKE_VRTX (1<<2) +#define LINE_STRIP_PROVOKE_VRTX(x) ((x)<<6) +#define TRI_FAN_PROVOKE_VRTX(x) ((x)<<3) +#define TRI_STRIP_PROVOKE_VRTX(x) (x) + +/* STATE3D_SCISSOR_ENABLE, p200 */ +#define STATE3D_SCISSOR_ENABLE_CMD (CMD_3D|(0x1c<<24)|(0x10<<19)) +#define ENABLE_SCISSOR_RECT ((1<<1) | 1) +#define DISABLE_SCISSOR_RECT (1<<1) + +/* STATE3D_SCISSOR_RECTANGLE_0, p201 */ +#define STATE3D_SCISSOR_RECT_0_CMD (CMD_3D|(0x1d<<24)|(0x81<<16)|1) +/* Dword 1 */ +#define SCISSOR_RECT_0_YMIN(x) ((x)<<16) +#define SCISSOR_RECT_0_XMIN(x) (x) +/* Dword 2 */ +#define SCISSOR_RECT_0_YMAX(x) ((x)<<16) +#define SCISSOR_RECT_0_XMAX(x) (x) + +/* STATE3D_STENCIL_TEST, p202 */ +#define STATE3D_STENCIL_TEST_CMD (CMD_3D|(0x09<<24)) +#define ENABLE_STENCIL_PARMS (1<<23) +#define STENCIL_OPS_MASK (0xffc000) +#define STENCIL_FAIL_OP(x) ((x)<<20) +#define STENCIL_PASS_DEPTH_FAIL_OP(x) ((x)<<17) +#define STENCIL_PASS_DEPTH_PASS_OP(x) ((x)<<14) + +#define STENCILOP_KEEP 0 +#define STENCILOP_ZERO 0x1 +#define STENCILOP_REPLACE 0x2 +#define STENCILOP_INCRSAT 0x3 +#define STENCILOP_DECRSAT 0x4 +#define STENCILOP_INCR 0x5 +#define STENCILOP_DECR 0x6 +#define STENCILOP_INVERT 0x7 + +#define ENABLE_STENCIL_TEST_FUNC_MASK ((1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)) +#define ENABLE_STENCIL_TEST_FUNC (1<<13) +/* Uses COMPAREFUNC */ +#define STENCIL_TEST_FUNC(x) ((x)<<9) +#define STENCIL_REF_VALUE_MASK ((1<<8)|0xff) +#define ENABLE_STENCIL_REF_VALUE (1<<8) +#define STENCIL_REF_VALUE(x) (x) + +/* STATE3D_VERTEX_FORMAT, p204 */ +#define STATE3D_VERTEX_FORMAT_CMD (CMD_3D|(0x05<<24)) +#define VRTX_HAS_POINT_WIDTH (1<<12) +#define VRTX_TEX_COORD_COUNT(x) ((x)<<8) +#define VRTX_HAS_SPEC (1<<7) +#define VRTX_HAS_DIFFUSE (1<<6) +#define VRTX_HAS_DEPTH_OFS (1<<5) +#define VRTX_HAS_XYZ (1<<1) +#define VRTX_HAS_XYZW (2<<1) +#define VRTX_HAS_XY (3<<1) +#define VRTX_HAS_XYW (4<<1) + +/* STATE3D_VERTEX_FORMAT_2, p206 */ +#define STATE3D_VERTEX_FORMAT_2_CMD (CMD_3D|(0x0a<<24)) +#define VRTX_TEX_SET_7_FMT(x) ((x)<<14) +#define VRTX_TEX_SET_6_FMT(x) ((x)<<12) +#define VRTX_TEX_SET_5_FMT(x) ((x)<<10) +#define VRTX_TEX_SET_4_FMT(x) ((x)<<8) +#define VRTX_TEX_SET_3_FMT(x) ((x)<<6) +#define VRTX_TEX_SET_2_FMT(x) ((x)<<4) +#define VRTX_TEX_SET_1_FMT(x) ((x)<<2) +#define VRTX_TEX_SET_0_FMT(x) (x) + +#define TEXCOORDFMT_2D 0 +#define TEXCOORDFMT_3D 1 +#define TEXCOORDFMT_4D 2 +#define TEXCOORDFMT_1D 3 + +/*New stuff picked up along the way */ + +#define MLC_LOD_BIAS_MASK ((1<<7)-1) + + +/* STATE3D_VERTEX_TRANSFORM, p207 */ +#define STATE3D_VERTEX_TRANS_CMD (CMD_3D|(0x1d<<24)|(0x8b<<16)|0) +#define STATE3D_VERTEX_TRANS_MTX_CMD (CMD_3D|(0x1d<<24)|(0x8b<<16)|6) +/* Dword 1 */ +#define ENABLE_VIEWPORT_TRANSFORM ((1<<31)|(1<<30)) +#define DISABLE_VIEWPORT_TRANSFORM (1<<31) +#define ENABLE_PERSP_DIVIDE ((1<<29)|(1<<28)) +#define DISABLE_PERSP_DIVIDE (1<<29) +#define VRTX_TRANS_LOAD_MATRICES 0x7421 +#define VRTX_TRANS_NO_LOAD_MATRICES 0x0000 +/* Dword 2 -> 7 are matrix elements */ + +/* STATE3D_W_STATE, p209 */ +#define STATE3D_W_STATE_CMD (CMD_3D|(0x1d<<24)|(0x8d<<16)|1) +/* Dword 1 */ +#define MAGIC_W_STATE_DWORD1 0x00000008 +/* Dword 2 */ +#define WFAR_VALUE(x) (x) + +/* if defining I830_ENABLE_4_TEXTURES, do it in i830_drm.h, too */ + +#define I830PACKCOLOR4444(r,g,b,a) \ + ((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4)) + +#define I830PACKCOLOR1555(r,g,b,a) \ + ((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \ + ((a) ? 0x8000 : 0)) + +#define I830PACKCOLOR565(r,g,b) \ + ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3)) + +#define I830PACKCOLOR8888(r,g,b,a) \ + ((a<<24) | (r<<16) | (g<<8) | b) + + +/* Stipple command, carried over from the i810, apparently: + */ +#define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16)) +#define ST1_ENABLE (1<<16) +#define ST1_MASK (0xffff) + + + +#define STATE3D_LOAD_STATE_IMMEDIATE_2 ((0x3<<29)|(0x1d<<24)|(0x03<<16)) +#define LOAD_TEXTURE_MAP0 (1<<11) + +#define TM0S0_ADDRESS_MASK 0xfffffffc +#define TM0S0_USE_FENCE (1<<1) + +#define TM0S1_HEIGHT_SHIFT 21 +#define TM0S1_WIDTH_SHIFT 10 +#define TM0S1_PALETTE_SELECT (1<<9) +#define TM0S1_MAPSURF_FORMAT_MASK (0x7 << 6) +#define TM0S1_MAPSURF_FORMAT_SHIFT 6 +#define MAPSURF_8BIT_INDEXED (0<<6) +#define MAPSURF_8BIT (1<<6) +#define MAPSURF_16BIT (2<<6) +#define MAPSURF_32BIT (3<<6) +#define MAPSURF_411 (4<<6) +#define MAPSURF_422 (5<<6) +#define MAPSURF_COMPRESSED (6<<6) +#define MAPSURF_4BIT_INDEXED (7<<6) +#define TM0S1_MT_FORMAT_MASK (0x7 << 3) +#define TM0S1_MT_FORMAT_SHIFT 3 +#define MT_4BIT_IDX_ARGB8888 (7<<3) /* SURFACE_4BIT_INDEXED */ +#define MT_8BIT_IDX_RGB565 (0<<3) /* SURFACE_8BIT_INDEXED */ +#define MT_8BIT_IDX_ARGB1555 (1<<3) +#define MT_8BIT_IDX_ARGB4444 (2<<3) +#define MT_8BIT_IDX_AY88 (3<<3) +#define MT_8BIT_IDX_ABGR8888 (4<<3) +#define MT_8BIT_IDX_BUMP_88DVDU (5<<3) +#define MT_8BIT_IDX_BUMP_655LDVDU (6<<3) +#define MT_8BIT_IDX_ARGB8888 (7<<3) +#define MT_8BIT_I8 (0<<3) /* SURFACE_8BIT */ +#define MT_8BIT_L8 (1<<3) +#define MT_16BIT_RGB565 (0<<3) /* SURFACE_16BIT */ +#define MT_16BIT_ARGB1555 (1<<3) +#define MT_16BIT_ARGB4444 (2<<3) +#define MT_16BIT_AY88 (3<<3) +#define MT_16BIT_DIB_ARGB1555_8888 (4<<3) +#define MT_16BIT_BUMP_88DVDU (5<<3) +#define MT_16BIT_BUMP_655LDVDU (6<<3) +#define MT_16BIT_DIB_RGB565_8888 (7<<3) +#define MT_32BIT_ARGB8888 (0<<3) /* SURFACE_32BIT */ +#define MT_32BIT_ABGR8888 (1<<3) +#define MT_32BIT_BUMP_XLDVDU_8888 (6<<3) +#define MT_32BIT_DIB_8888 (7<<3) +#define MT_411_YUV411 (0<<3) /* SURFACE_411 */ +#define MT_422_YCRCB_SWAPY (0<<3) /* SURFACE_422 */ +#define MT_422_YCRCB_NORMAL (1<<3) +#define MT_422_YCRCB_SWAPUV (2<<3) +#define MT_422_YCRCB_SWAPUVY (3<<3) +#define MT_COMPRESS_DXT1 (0<<3) /* SURFACE_COMPRESSED */ +#define MT_COMPRESS_DXT2_3 (1<<3) +#define MT_COMPRESS_DXT4_5 (2<<3) +#define MT_COMPRESS_FXT1 (3<<3) +#define TM0S1_COLORSPACE_CONVERSION (1 << 2) +#define TM0S1_TILED_SURFACE (1 << 1) +#define TM0S1_TILE_WALK (1 << 0) + +#define TM0S2_PITCH_SHIFT 21 +#define TM0S2_CUBE_FACE_ENA_SHIFT 15 +#define TM0S2_MAP_FORMAT (1<<14) +#define TM0S2_VERTICAL_LINE_STRIDE (1<<13) +#define TM0S2_VERITCAL_LINE_STRIDE_OFF (1<<12) +#define TM0S2_OUTPUT_CHAN_SHIFT 10 +#define TM0S2_OUTPUT_CHAN_MASK (3<<10) + +#define TM0S3_MIP_FILTER_MASK (0x3<<30) +#define TM0S3_MIP_FILTER_SHIFT 30 +#define MIPFILTER_NONE 0 +#define MIPFILTER_NEAREST 1 +#define MIPFILTER_LINEAR 3 +#define TM0S3_MAG_FILTER_MASK (0x3<<28) +#define TM0S3_MAG_FILTER_SHIFT 28 +#define TM0S3_MIN_FILTER_MASK (0x3<<26) +#define TM0S3_MIN_FILTER_SHIFT 26 +#define FILTER_NEAREST 0 +#define FILTER_LINEAR 1 +#define FILTER_ANISOTROPIC 2 + +#define TM0S3_LOD_BIAS_SHIFT 17 +#define TM0S3_LOD_BIAS_MASK (0x1ff<<17) +#define TM0S3_MAX_MIP_SHIFT 9 +#define TM0S3_MAX_MIP_MASK (0xff<<9) +#define TM0S3_MIN_MIP_SHIFT 3 +#define TM0S3_MIN_MIP_MASK (0x3f<<3) +#define TM0S3_KILL_PIXEL (1<<2) +#define TM0S3_KEYED_FILTER (1<<1) +#define TM0S3_CHROMA_KEY (1<<0) + + +/* STATE3D_MAP_TEXEL_STREAM, p188 */ +#define STATE3D_MAP_TEX_STREAM_CMD (CMD_3D|(0x1c<<24)|(0x05<<19)) +#define DISABLE_TEX_STREAM_BUMP (1<<12) +#define ENABLE_TEX_STREAM_BUMP ((1<<12)|(1<<11)) +#define TEX_MODIFY_UNIT_0 0 +#define TEX_MODIFY_UNIT_1 (1<<8) +#define ENABLE_TEX_STREAM_COORD_SET (1<<7) +#define TEX_STREAM_COORD_SET(x) ((x)<<4) +#define ENABLE_TEX_STREAM_MAP_IDX (1<<3) +#define TEX_STREAM_MAP_IDX(x) (x) diff --git a/src/mesa/drivers/dri/i830/i830_context.c b/src/mesa/drivers/dri/i830/i830_context.c new file mode 100644 index 0000000000..254fa28462 --- /dev/null +++ b/src/mesa/drivers/dri/i830/i830_context.c @@ -0,0 +1,588 @@ +/************************************************************************** + * + * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * **************************************************************************/ +/* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_context.c,v 1.9 2003/02/06 04:18:00 dawes Exp $ */ + +/* + * Authors: + * Jeff Hartmann <jhartmann@2d3d.com> + * Graeme Fisher <graeme@2d3d.co.za> + * Abraham vd Merwe <abraham@2d3d.co.za> + * + * Heavily Based on I810 driver written by: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include "glheader.h" +#include "context.h" +#include "matrix.h" +#include "simple_list.h" +#include "extensions.h" +#include "imports.h" + +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "tnl/tnl.h" +#include "array_cache/acache.h" + +#include "tnl/t_pipeline.h" + +#include "i830_screen.h" +#include "i830_dri.h" + +#include "i830_state.h" +#include "i830_tex.h" +#include "i830_span.h" +#include "i830_tris.h" +#include "i830_vb.h" +#include "i830_ioctl.h" + + +#include "utils.h" +#ifndef I830_DEBUG +int I830_DEBUG = (0); +#endif + +/*************************************** + * Mesa's Driver Functions + ***************************************/ + +#define DRIVER_DATE "20021115" + +static const GLubyte *i830DDGetString( GLcontext *ctx, GLenum name ) +{ + const char * chipset; + static char buffer[128]; + + switch (name) { + case GL_VENDOR: + switch (I830_CONTEXT(ctx)->i830Screen->deviceID) { + case PCI_CHIP_845_G: + return (GLubyte *)"2d3D, Inc"; + + case PCI_CHIP_I830_M: + return (GLubyte *)"VA Linux, Inc"; + + case PCI_CHIP_I855_GM: + case PCI_CHIP_I865_G: + default: + return (GLubyte *)"Tungsten Graphics, Inc"; + } + break; + + case GL_RENDERER: + switch (I830_CONTEXT(ctx)->i830Screen->deviceID) { + case PCI_CHIP_845_G: + chipset = "Intel(R) 845G"; break; + case PCI_CHIP_I830_M: + chipset = "Intel(R) 830M"; break; + case PCI_CHIP_I855_GM: + chipset = "Intel(R) 852GM/855GM"; break; + case PCI_CHIP_I865_G: + chipset = "Intel(R) 865G"; break; + default: + chipset = "Unknown Intel Chipset"; break; + } + + (void) driGetRendererString( buffer, chipset, DRIVER_DATE, 0 ); + return (GLubyte *) buffer; + + default: + return NULL; + } +} + +static void i830BufferSize(GLframebuffer *buffer, + GLuint *width, GLuint *height) +{ + GET_CURRENT_CONTEXT(ctx); + i830ContextPtr imesa = I830_CONTEXT(ctx); + /* Need to lock to make sure the driDrawable is uptodate. This + * information is used to resize Mesa's software buffers, so it has + * to be correct. + */ + LOCK_HARDWARE(imesa); + *width = imesa->driDrawable->w; + *height = imesa->driDrawable->h; + UNLOCK_HARDWARE(imesa); +} + + +/* Extension strings exported by the i830 driver. + */ +static const char * const card_extensions[] = +{ + "GL_ARB_multisample", + "GL_ARB_multitexture", + "GL_ARB_texture_border_clamp", + "GL_ARB_texture_compression", + "GL_ARB_texture_env_add", + "GL_ARB_texture_env_combine", + "GL_ARB_texture_env_dot3", + "GL_ARB_texture_mirrored_repeat", + "GL_EXT_blend_color", + "GL_EXT_blend_func_separate", + "GL_EXT_blend_minmax", + "GL_EXT_blend_subtract", + "GL_EXT_fog_coord", + "GL_EXT_secondary_color", + "GL_EXT_stencil_wrap", + "GL_EXT_texture_edge_clamp", + "GL_EXT_texture_env_add", + "GL_EXT_texture_env_combine", + "GL_EXT_texture_env_dot3", + "GL_EXT_texture_filter_anisotropic", + "GL_EXT_texture_lod_bias", + "GL_IBM_texture_mirrored_repeat", + "GL_INGR_blend_func_separate", + "GL_MESA_ycbcr_texture", + "GL_NV_texture_rectangle", + "GL_SGIS_generate_mipmap", + "GL_SGIS_texture_border_clamp", + "GL_SGIS_texture_edge_clamp", + NULL +}; + + +extern const struct gl_pipeline_stage _i830_render_stage; + +static const struct gl_pipeline_stage *i830_pipeline[] = { + &_tnl_vertex_transform_stage, + &_tnl_normal_transform_stage, + &_tnl_lighting_stage, + &_tnl_fog_coordinate_stage, + &_tnl_texgen_stage, + &_tnl_texture_transform_stage, + /* REMOVE: point attenuation stage */ +#if 1 + &_i830_render_stage, /* ADD: unclipped rastersetup-to-dma */ +#endif + &_tnl_render_stage, + 0, +}; + + +static const struct dri_debug_control debug_control[] = +{ + { "fall", DEBUG_FALLBACKS }, + { "tex", DEBUG_TEXTURE }, + { "ioctl", DEBUG_IOCTL }, + { "prim", DEBUG_PRIMS }, + { "vert", DEBUG_VERTS }, + { "state", DEBUG_STATE }, + { "verb", DEBUG_VERBOSE }, + { "dri", DEBUG_DRI }, + { "dma", DEBUG_DMA }, + { "san", DEBUG_SANITY }, + { "sync", DEBUG_SYNC }, + { "sleep", DEBUG_SLEEP }, + { NULL, 0 } +}; + + +GLboolean i830CreateContext( const __GLcontextModes *mesaVis, + __DRIcontextPrivate *driContextPriv, + void *sharedContextPrivate) +{ + GLcontext *ctx , *shareCtx; + i830ContextPtr imesa; + __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; + i830ScreenPrivate *screen = (i830ScreenPrivate *)sPriv->private; + I830SAREAPtr saPriv=(I830SAREAPtr) + (((GLubyte *)sPriv->pSAREA)+screen->sarea_priv_offset); + + /* Allocate i830 context */ + imesa = (i830ContextPtr) CALLOC_STRUCT(i830_context_t); + if (!imesa) return GL_FALSE; + + /* Allocate the Mesa context */ + if (sharedContextPrivate) + shareCtx = ((i830ContextPtr) sharedContextPrivate)->glCtx; + else + shareCtx = NULL; + imesa->glCtx = _mesa_create_context(mesaVis, shareCtx, (void*) imesa, GL_TRUE); + if (!imesa->glCtx) { + FREE(imesa); + return GL_FALSE; + } + driContextPriv->driverPrivate = imesa; + + + imesa->i830Screen = screen; + imesa->driScreen = sPriv; + imesa->sarea = saPriv; + imesa->glBuffer = NULL; + + + (void) memset( imesa->texture_heaps, 0, sizeof( imesa->texture_heaps ) ); + make_empty_list( & imesa->swapped ); + + imesa->nr_heaps = 1; + imesa->texture_heaps[0] = driCreateTextureHeap( 0, imesa, + screen->textureSize, + 12, + I830_NR_TEX_REGIONS, + imesa->sarea->texList, + & imesa->sarea->texAge, + & imesa->swapped, + sizeof( struct i830_texture_object_t ), + (destroy_texture_object_t *) i830DestroyTexObj ); + + + /* Set the maximum texture size small enough that we can guarantee + * that both texture units can bind a maximal texture and have them + * in memory at once. + */ + + ctx = imesa->glCtx; + ctx->Const.MaxTextureUnits = 2; + + /* FIXME: driCalcualteMaxTextureLevels assumes that mipmaps are tightly + * FIXME: packed, but they're not in Intel graphics hardware. + */ + driCalculateMaxTextureLevels( imesa->texture_heaps, + imesa->nr_heaps, + & ctx->Const, + 4, + 11, /* max 2D texture size is 2048x2048 */ + 0, /* 3D textures unsupported */ + 0, /* cube textures unsupported. */ + 0, /* texture rectangles unsupported. */ + 12, + GL_FALSE ); + + ctx->Const.MaxTextureMaxAnisotropy = 2.0; + + ctx->Const.MinLineWidth = 1.0; + ctx->Const.MinLineWidthAA = 1.0; + ctx->Const.MaxLineWidth = 3.0; + ctx->Const.MaxLineWidthAA = 3.0; + ctx->Const.LineWidthGranularity = 1.0; + + ctx->Const.MinPointSize = 1.0; + ctx->Const.MinPointSizeAA = 1.0; + ctx->Const.MaxPointSize = 255.0; + ctx->Const.MaxPointSizeAA = 3.0; + ctx->Const.PointSizeGranularity = 1.0; + + ctx->Driver.GetBufferSize = i830BufferSize; + ctx->Driver.ResizeBuffers = _swrast_alloc_buffers; + ctx->Driver.GetString = i830DDGetString; + + /* Who owns who? */ + ctx->DriverCtx = (void *) imesa; + imesa->glCtx = ctx; + + /* Initialize the software rasterizer and helper modules. */ + _swrast_CreateContext( ctx ); + _ac_CreateContext( ctx ); + _tnl_CreateContext( ctx ); + _swsetup_CreateContext( ctx ); + + /* Install the customized pipeline: */ + _tnl_destroy_pipeline( ctx ); + _tnl_install_pipeline( ctx, i830_pipeline ); + + /* Configure swrast to match hardware characteristics: */ + _swrast_allow_pixel_fog( ctx, GL_FALSE ); + _swrast_allow_vertex_fog( ctx, GL_TRUE ); + + /* Dri stuff */ + imesa->hHWContext = driContextPriv->hHWContext; + imesa->driFd = sPriv->fd; + imesa->driHwLock = &sPriv->pSAREA->lock; + imesa->vertex_format = 0; + + imesa->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24; + + switch(mesaVis->depthBits) { + case 16: + imesa->depth_scale = 1.0/0xffff; + imesa->depth_clear_mask = ~0; + imesa->ClearDepth = 0xffff; + break; + case 24: + imesa->depth_scale = 1.0/0xffffff; + imesa->depth_clear_mask = 0x00ffffff; + imesa->stencil_clear_mask = 0xff000000; + imesa->ClearDepth = 0x00ffffff; + break; + case 32: /* Not supported */ + default: + break; + } + /* Completely disable stenciling for now, there are some serious issues + * with stencil. + */ +#if 0 + imesa->hw_stencil = 0; +#endif + + imesa->RenderIndex = ~0; + imesa->dirty = ~0; + imesa->upload_cliprects = GL_TRUE; + + imesa->CurrentTexObj[0] = 0; + imesa->CurrentTexObj[1] = 0; + + imesa->do_irqs = (imesa->i830Screen->irq_active && + !getenv("I830_NO_IRQS")); + + _math_matrix_ctr (&imesa->ViewportMatrix); + + driInitExtensions( ctx, card_extensions, GL_TRUE ); + i830DDInitStateFuncs( ctx ); + i830DDInitTextureFuncs( ctx ); + i830InitTriFuncs (ctx); + i830DDInitSpanFuncs( ctx ); + i830DDInitIoctlFuncs( ctx ); + i830InitVB (ctx); + i830DDInitState (ctx); + +#if DO_DEBUG + I830_DEBUG = driParseDebugString( getenv( "I830_DEBUG" ), + debug_control ); + I830_DEBUG |= driParseDebugString( getenv( "INTEL_DEBUG" ), + debug_control ); +#endif + + if (getenv("I830_NO_RAST") || + getenv("INTEL_NO_RAST")) { + fprintf(stderr, "disabling 3D rasterization\n"); + FALLBACK(imesa, I830_FALLBACK_USER, 1); + } + + + return GL_TRUE; +} + +void i830DestroyContext(__DRIcontextPrivate *driContextPriv) +{ + i830ContextPtr imesa = (i830ContextPtr) driContextPriv->driverPrivate; + + assert(imesa); /* should never be null */ + if (imesa) { + GLboolean release_texture_heaps; + + + release_texture_heaps = (imesa->glCtx->Shared->RefCount == 1); + _swsetup_DestroyContext (imesa->glCtx); + _tnl_DestroyContext (imesa->glCtx); + _ac_DestroyContext (imesa->glCtx); + _swrast_DestroyContext (imesa->glCtx); + + i830FreeVB (imesa->glCtx); + + /* free the Mesa context */ + imesa->glCtx->DriverCtx = NULL; + _mesa_destroy_context(imesa->glCtx); + + if ( release_texture_heaps ) { + /* This share group is about to go away, free our private + * texture object data. + */ + int i; + + assert( is_empty_list( & imesa->swapped ) ); + + for ( i = 0 ; i < imesa->nr_heaps ; i++ ) { + driDestroyTextureHeap( imesa->texture_heaps[ i ] ); + imesa->texture_heaps[ i ] = NULL; + } + } + + Xfree (imesa); + } +} + +void i830XMesaSetFrontClipRects( i830ContextPtr imesa ) +{ + __DRIdrawablePrivate *dPriv = imesa->driDrawable; + + imesa->numClipRects = dPriv->numClipRects; + imesa->pClipRects = dPriv->pClipRects; + imesa->drawX = dPriv->x; + imesa->drawY = dPriv->y; + + i830EmitDrawingRectangle( imesa ); + imesa->upload_cliprects = GL_TRUE; +} + +void i830XMesaSetBackClipRects( i830ContextPtr imesa ) +{ + __DRIdrawablePrivate *dPriv = imesa->driDrawable; + + if (imesa->sarea->pf_enabled == 0 && dPriv->numBackClipRects == 0) { + imesa->numClipRects = dPriv->numClipRects; + imesa->pClipRects = dPriv->pClipRects; + imesa->drawX = dPriv->x; + imesa->drawY = dPriv->y; + } else { + imesa->numClipRects = dPriv->numBackClipRects; + imesa->pClipRects = dPriv->pBackClipRects; + imesa->drawX = dPriv->backX; + imesa->drawY = dPriv->backY; + } + + i830EmitDrawingRectangle( imesa ); + imesa->upload_cliprects = GL_TRUE; +} + +static void i830XMesaWindowMoved( i830ContextPtr imesa ) +{ + switch (imesa->glCtx->Color._DrawDestMask) { + case FRONT_LEFT_BIT: + i830XMesaSetFrontClipRects( imesa ); + break; + case BACK_LEFT_BIT: + i830XMesaSetBackClipRects( imesa ); + break; + default: + /* glDrawBuffer(GL_NONE or GL_FRONT_AND_BACK): software fallback */ + i830XMesaSetFrontClipRects( imesa ); + } +} + +GLboolean i830UnbindContext(__DRIcontextPrivate *driContextPriv) +{ + i830ContextPtr imesa = (i830ContextPtr) driContextPriv->driverPrivate; + if (imesa) { + /* Might want to change this so texblend isn't always updated */ + imesa->dirty |= (I830_UPLOAD_CTX | + I830_UPLOAD_BUFFERS | + I830_UPLOAD_STIPPLE | + I830_UPLOAD_TEXBLEND0 | + I830_UPLOAD_TEXBLEND1); + + if (imesa->CurrentTexObj[0]) imesa->dirty |= I830_UPLOAD_TEX0; + if (imesa->CurrentTexObj[1]) imesa->dirty |= I830_UPLOAD_TEX1; + } + return GL_TRUE; +} + +GLboolean i830MakeCurrent(__DRIcontextPrivate *driContextPriv, + __DRIdrawablePrivate *driDrawPriv, + __DRIdrawablePrivate *driReadPriv) +{ + + if (driContextPriv) { + i830ContextPtr imesa = (i830ContextPtr) driContextPriv->driverPrivate; + + if ( imesa->driDrawable != driDrawPriv ) { + /* Shouldn't the readbuffer be stored also? */ + imesa->driDrawable = driDrawPriv; + i830XMesaWindowMoved( imesa ); + } + + _mesa_make_current2(imesa->glCtx, + (GLframebuffer *) driDrawPriv->driverPrivate, + (GLframebuffer *) driReadPriv->driverPrivate); + + if (!imesa->glCtx->Viewport.Width) + _mesa_set_viewport(imesa->glCtx, 0, 0, + driDrawPriv->w, driDrawPriv->h); + } else { + _mesa_make_current(0,0); + } + + return GL_TRUE; +} + +void i830GetLock( i830ContextPtr imesa, GLuint flags ) +{ + __DRIdrawablePrivate *dPriv = imesa->driDrawable; + __DRIscreenPrivate *sPriv = imesa->driScreen; + I830SAREAPtr sarea = imesa->sarea; + int me = imesa->hHWContext; + unsigned i; + + drmGetLock(imesa->driFd, imesa->hHWContext, flags); + + /* If the window moved, may need to set a new cliprect now. + * + * NOTE: This releases and regains the hw lock, so all state + * checking must be done *after* this call: + */ + DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv); + + /* If we lost context, need to dump all registers to hardware. + * Note that we don't care about 2d contexts, even if they perform + * accelerated commands, so the DRI locking in the X server is even + * more broken than usual. + */ + + if (sarea->ctxOwner != me) { + imesa->upload_cliprects = GL_TRUE; + imesa->dirty |= (I830_UPLOAD_CTX | + I830_UPLOAD_BUFFERS | + I830_UPLOAD_STIPPLE); + + if(imesa->CurrentTexObj[0]) imesa->dirty |= I830_UPLOAD_TEX0; + if(imesa->CurrentTexObj[1]) imesa->dirty |= I830_UPLOAD_TEX1; + if(imesa->TexBlendWordsUsed[0]) imesa->dirty |= I830_UPLOAD_TEXBLEND0; + if(imesa->TexBlendWordsUsed[1]) imesa->dirty |= I830_UPLOAD_TEXBLEND1; + + sarea->perf_boxes = imesa->perf_boxes | I830_BOX_LOST_CONTEXT; + sarea->ctxOwner = me; + } + + /* Shared texture managment - if another client has played with + * texture space, figure out which if any of our textures have been + * ejected, and update our global LRU. + */ + + for ( i = 0 ; i < imesa->nr_heaps ; i++ ) { + DRI_AGE_TEXTURES( imesa->texture_heaps[ i ] ); + } + + if (imesa->lastStamp != dPriv->lastStamp) { + i830XMesaWindowMoved( imesa ); + imesa->lastStamp = dPriv->lastStamp; + } + + sarea->last_quiescent = -1; /* just kill it for now */ +} + +void i830SwapBuffers( __DRIdrawablePrivate *dPriv ) +{ + if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { + i830ContextPtr imesa; + GLcontext *ctx; + imesa = (i830ContextPtr) dPriv->driContextPriv->driverPrivate; + ctx = imesa->glCtx; + if (ctx->Visual.doubleBufferMode) { + _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */ + if ( 0 /*imesa->doPageFlip*/ ) { /* doPageFlip is never set !!! */ + i830PageFlip( dPriv ); + } else { + i830CopyBuffer( dPriv ); + } + } + } else { + /* XXX this shouldn't be an error but we can't handle it for now */ + _mesa_problem(NULL, "%s: drawable has no context!\n", __FUNCTION__); + } +} diff --git a/src/mesa/drivers/dri/i830/i830_context.h b/src/mesa/drivers/dri/i830/i830_context.h new file mode 100644 index 0000000000..2bb71cb719 --- /dev/null +++ b/src/mesa/drivers/dri/i830/i830_context.h @@ -0,0 +1,310 @@ +/* + * GLX Hardware Device Driver for Intel i830 + * Copyright (C) 1999 Keith Whitwell + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/* Adapted for use in the I830M driver: + * Jeff Hartmann <jhartmann@2d3d.com> + */ +/* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_context.h,v 1.7 2003/02/06 04:18:01 dawes Exp $ */ + +#ifndef I830CONTEXT_INC +#define I830CONTEXT_INC + +typedef struct i830_context_t i830Context; +typedef struct i830_context_t *i830ContextPtr; +typedef struct i830_texture_object_t *i830TextureObjectPtr; + + +#include "mtypes.h" +#include "drm.h" +#include "mm.h" + +#include "i830_screen.h" +#include "i830_tex.h" + +#define TAG(x) i830##x +#include "tnl_dd/t_dd_vertex.h" +#undef TAG + +#define DV_PF_555 (1<<8) +#define DV_PF_565 (2<<8) +#define DV_PF_8888 (3<<8) + +#define I830_TEX_MAXLEVELS 10 + +#define I830_CONTEXT(ctx) ((i830ContextPtr)(ctx->DriverCtx)) +#define GET_DISPATCH_AGE(imesa) imesa->sarea->last_dispatch +#define GET_ENQUEUE_AGE(imesa) imesa->sarea->last_enqueue + + +typedef void (*i830_tri_func)(i830ContextPtr, i830Vertex *, i830Vertex *, + i830Vertex *); +typedef void (*i830_line_func)(i830ContextPtr, i830Vertex *, i830Vertex *); +typedef void (*i830_point_func)(i830ContextPtr, i830Vertex *); + +#define I830_FALLBACK_TEXTURE 0x1 +#define I830_FALLBACK_DRAW_BUFFER 0x2 +#define I830_FALLBACK_READ_BUFFER 0x4 +#define I830_FALLBACK_COLORMASK 0x8 +#define I830_FALLBACK_RENDERMODE 0x10 +#define I830_FALLBACK_STENCIL 0x20 +#define I830_FALLBACK_STIPPLE 0x40 +#define I830_FALLBACK_USER 0x80 + +struct i830_context_t +{ + GLint refcount; + GLcontext *glCtx; + + /*From I830 stuff*/ + int TextureMode; + GLuint renderindex; + GLuint TexBlendWordsUsed[I830_TEXBLEND_COUNT]; + GLuint TexBlend[I830_TEXBLEND_COUNT][I830_TEXBLEND_SIZE]; + GLuint Init_TexBlend[I830_TEXBLEND_COUNT][I830_TEXBLEND_SIZE]; + GLuint Init_TexBlendWordsUsed[I830_TEXBLEND_COUNT]; + GLuint Init_TexBlendColorPipeNum[I830_TEXBLEND_COUNT]; + GLuint TexBlendColorPipeNum[I830_TEXBLEND_COUNT]; + GLuint Init_BufferSetup[I830_DEST_SETUP_SIZE]; + GLuint LodBias[2]; + + GLenum palette_format; + GLuint palette[256]; + + + GLuint Init_Setup[I830_CTX_SETUP_SIZE]; + GLuint vertex_prim; + drmBufPtr vertex_dma_buffer; + + GLboolean mask_red; + GLboolean mask_green; + GLboolean mask_blue; + GLboolean mask_alpha; + + GLubyte clear_red; + GLubyte clear_green; + GLubyte clear_blue; + GLubyte clear_alpha; + + GLfloat depth_scale; + int depth_clear_mask; + int stencil_clear_mask; + int ClearDepth; + int hw_stencil; + + GLuint MonoColor; + + GLuint LastTexEnabled; + GLuint TexEnabledMask; + + /* Texture object bookkeeping + */ + unsigned nr_heaps; + driTexHeap * texture_heaps[1]; + driTextureObject swapped; + + struct i830_texture_object_t *CurrentTexObj[2]; + + /* Rasterization and vertex state: + */ + GLuint Fallback; + GLuint NewGLState; + + /* Temporaries for translating away float colors: + */ + struct gl_client_array UbyteColor; + struct gl_client_array UbyteSecondaryColor; + + /* State for i830vb.c and i830tris.c. + */ + GLuint SetupNewInputs; + GLuint SetupIndex; + GLuint RenderIndex; + GLmatrix ViewportMatrix; + GLenum render_primitive; + GLenum reduced_primitive; + GLuint hw_primitive; + GLuint vertex_format; + char *verts; + + drmBufPtr vertex_buffer; + char *vertex_addr; + GLuint vertex_low; + GLuint vertex_high; + GLuint vertex_last_prim; + + GLboolean upload_cliprects; + + + /* Fallback rasterization functions + */ + i830_point_func draw_point; + i830_line_func draw_line; + i830_tri_func draw_tri; + + /* Hardware state + */ + GLuint dirty; /* I810_UPLOAD_* */ + GLuint Setup[I830_CTX_SETUP_SIZE]; + GLuint BufferSetup[I830_DEST_SETUP_SIZE]; + GLuint StippleSetup[I830_STP_SETUP_SIZE]; + int vertex_size; + int vertex_stride_shift; + unsigned int lastStamp; + GLboolean hw_stipple; + + GLenum TexEnvImageFmt[2]; + + /* State which can't be computed completely on the fly: + */ + GLuint LcsCullMode; + GLuint LcsLineWidth; + GLuint LcsPointSize; + + /* Funny mesa mirrors + */ + GLuint ClearColor; + + /* DRI stuff + */ + GLuint needClip; + GLframebuffer *glBuffer; + + /* These refer to the current draw (front vs. back) buffer: + */ + char *drawMap; /* draw buffer address in virtual mem */ + char *readMap; + int drawX; /* origin of drawable in draw buffer */ + int drawY; + GLuint numClipRects; /* cliprects for that buffer */ + XF86DRIClipRectPtr pClipRects; + + int lastSwap; + int texAge; + int ctxAge; + int dirtyAge; + int perf_boxes; + + int do_irqs; + + GLboolean scissor; + XF86DRIClipRectRec draw_rect; + XF86DRIClipRectRec scissor_rect; + + drmContext hHWContext; + drmLock *driHwLock; + int driFd; + + __DRIdrawablePrivate *driDrawable; + __DRIscreenPrivate *driScreen; + i830ScreenPrivate *i830Screen; + I830SAREAPtr sarea; +}; + + +#define I830_TEX_UNIT_ENABLED(unit) (1<<unit) +#define VALID_I830_TEXTURE_OBJECT(tobj) (tobj) + +#define I830_CONTEXT(ctx) ((i830ContextPtr)(ctx->DriverCtx)) +#define I830_DRIVER_DATA(vb) ((i830VertexBufferPtr)((vb)->driver_data)) +#define GET_DISPATCH_AGE(imesa) imesa->sarea->last_dispatch +#define GET_ENQUEUE_AGE(imesa) imesa->sarea->last_enqueue + + +/* Lock the hardware and validate our state. + */ +#define LOCK_HARDWARE( imesa ) \ +do { \ + char __ret=0; \ + DRM_CAS(imesa->driHwLock, imesa->hHWContext, \ + (DRM_LOCK_HELD|imesa->hHWContext), __ret); \ + if (__ret) \ + i830GetLock( imesa, 0 ); \ +}while (0) + + + /* Unlock the hardware using the global current context + */ +#define UNLOCK_HARDWARE(imesa) \ +do { \ + imesa->perf_boxes |= imesa->sarea->perf_boxes; \ + DRM_UNLOCK(imesa->driFd, imesa->driHwLock, imesa->hHWContext); \ +} while (0) + + /* This is the wrong way to do it, I'm sure. Otherwise the drm + * bitches that I've already got the heavyweight lock. At worst, + * this is 3 ioctls. The best solution probably only gets me down + * to 2 ioctls in the worst case. + */ +#define LOCK_HARDWARE_QUIESCENT( imesa ) do { \ + LOCK_HARDWARE( imesa ); \ + i830RegetLockQuiescent( imesa ); \ +} while(0) + + + +extern void i830GetLock(i830ContextPtr imesa, GLuint flags); +extern void i830EmitHwStateLocked(i830ContextPtr imesa); +extern void i830EmitDrawingRectangle(i830ContextPtr imesa); +extern void i830XMesaSetBackClipRects(i830ContextPtr imesa); +extern void i830XMesaSetFrontClipRects(i830ContextPtr imesa); +extern void i830DDExtensionsInit(GLcontext *ctx); +extern void i830DDInitDriverFuncs(GLcontext *ctx); +extern void i830DDUpdateHwState(GLcontext *ctx); + +#define SUBPIXEL_X 0.125 +#define SUBPIXEL_Y 0.125 + + +/* ================================================================ + * Debugging: + */ +#define DO_DEBUG 1 +#if DO_DEBUG +extern int I830_DEBUG; +#else +#define I830_DEBUG 0 +#endif + +#define DEBUG_TEXTURE 0x1 +#define DEBUG_STATE 0x2 +#define DEBUG_IOCTL 0x4 +#define DEBUG_PRIMS 0x8 +#define DEBUG_VERTS 0x10 +#define DEBUG_FALLBACKS 0x20 +#define DEBUG_VERBOSE 0x40 +#define DEBUG_DRI 0x80 +#define DEBUG_DMA 0x100 +#define DEBUG_SANITY 0x200 +#define DEBUG_SYNC 0x400 +#define DEBUG_SLEEP 0x800 + + +#define PCI_CHIP_845_G 0x2562 +#define PCI_CHIP_I830_M 0x3577 +#define PCI_CHIP_I855_GM 0x3582 +#define PCI_CHIP_I865_G 0x2572 + + +#endif + diff --git a/src/mesa/drivers/dri/i830/i830_debug.c b/src/mesa/drivers/dri/i830/i830_debug.c new file mode 100644 index 0000000000..66c698ba30 --- /dev/null +++ b/src/mesa/drivers/dri/i830/i830_debug.c @@ -0,0 +1,377 @@ +/************************************************************************** + +Copyright 2001 2d3d Inc., Delray Beach, FL + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_debug.c,v 1.3 2002/12/10 01:26:53 dawes Exp $ */ + +/* + * Author: + * Jeff Hartmann <jhartmann@2d3d.com> + */ + +#include "glheader.h" +#include "context.h" +#include "macros.h" +#include "enums.h" +#include "dd.h" + +#include "mm.h" + +#include "i830_screen.h" +#include "i830_dri.h" + +#include "i830_context.h" +#include "i830_state.h" +#include "i830_tex.h" +#include "i830_vb.h" +#include "i830_tris.h" +#include "i830_ioctl.h" +#include "i830_debug.h" + +#include "swrast/swrast.h" +#include "array_cache/acache.h" +#include "tnl/tnl.h" +#include "swrast_setup/swrast_setup.h" + +#include "tnl/t_pipeline.h" + + +#define TINY_VERTEX_FORMAT (STATE3D_VERTEX_FORMAT_CMD | \ + VRTX_TEX_COORD_COUNT(0) | \ + VRTX_HAS_DIFFUSE | \ + VRTX_HAS_XYZ) + +#define NOTEX_VERTEX_FORMAT (STATE3D_VERTEX_FORMAT_CMD | \ + VRTX_TEX_COORD_COUNT(0) | \ + VRTX_HAS_DIFFUSE | \ + VRTX_HAS_SPEC | \ + VRTX_HAS_XYZW) + +#define TEX0_VERTEX_FORMAT (STATE3D_VERTEX_FORMAT_CMD | \ + VRTX_TEX_COORD_COUNT(1) | \ + VRTX_HAS_DIFFUSE | \ + VRTX_HAS_SPEC | \ + VRTX_HAS_XYZW) + +#define TEX1_VERTEX_FORMAT (STATE3D_VERTEX_FORMAT_CMD | \ + VRTX_TEX_COORD_COUNT(2) | \ + VRTX_HAS_DIFFUSE | \ + VRTX_HAS_SPEC | \ + VRTX_HAS_XYZW) + +#define PROJ_VF2 (STATE3D_VERTEX_FORMAT_2_CMD | \ + VRTX_TEX_SET_0_FMT(TEXCOORDFMT_3D) | \ + VRTX_TEX_SET_1_FMT(TEXCOORDFMT_3D) | \ + VRTX_TEX_SET_2_FMT(TEXCOORDFMT_3D) | \ + VRTX_TEX_SET_3_FMT(TEXCOORDFMT_3D)) + +#define NON_PROJ_VF2 (STATE3D_VERTEX_FORMAT_2_CMD | \ + VRTX_TEX_SET_0_FMT(TEXCOORDFMT_2D) | \ + VRTX_TEX_SET_1_FMT(TEXCOORDFMT_2D) | \ + VRTX_TEX_SET_2_FMT(TEXCOORDFMT_2D) | \ + VRTX_TEX_SET_3_FMT(TEXCOORDFMT_2D)) + +void i830DumpContextState( i830ContextPtr imesa ) +{ + GLuint *Context = imesa->Setup; + + fprintf(stderr, "%s\n", __FUNCTION__); + fprintf(stderr, "STATE1 : 0x%08x\n", Context[I830_CTXREG_STATE1]); + fprintf(stderr, "STATE2 : 0x%08x\n", Context[I830_CTXREG_STATE2]); + fprintf(stderr, "STATE3 : 0x%08x\n", Context[I830_CTXREG_STATE3]); + fprintf(stderr, "STATE4 : 0x%08x\n", Context[I830_CTXREG_STATE4]); + fprintf(stderr, "STATE5 : 0x%08x\n", Context[I830_CTXREG_STATE5]); + fprintf(stderr, "IALPHAB : 0x%08x\n", Context[I830_CTXREG_IALPHAB]); + fprintf(stderr, "STENCILTST : 0x%08x\n", Context[I830_CTXREG_STENCILTST]); + fprintf(stderr, "ENABLES_1 : 0x%08x\n", Context[I830_CTXREG_ENABLES_1]); + fprintf(stderr, "ENABLES_2 : 0x%08x\n", Context[I830_CTXREG_ENABLES_2]); + fprintf(stderr, "AA : 0x%08x\n", Context[I830_CTXREG_AA]); + fprintf(stderr, "FOGCOLOR : 0x%08x\n", Context[I830_CTXREG_FOGCOLOR]); + fprintf(stderr, "BCOLOR0 : 0x%08x\n", Context[I830_CTXREG_BLENDCOLR0]); + fprintf(stderr, "BCOLOR : 0x%08x\n", Context[I830_CTXREG_BLENDCOLR]); + fprintf(stderr, "VF : 0x%08x\n", Context[I830_CTXREG_VF]); + fprintf(stderr, "VF2 : 0x%08x\n", Context[I830_CTXREG_VF2]); + fprintf(stderr, "MCSB0 : 0x%08x\n", Context[I830_CTXREG_MCSB0]); + fprintf(stderr, "MCSB1 : 0x%08x\n", Context[I830_CTXREG_MCSB1]); +} + +void i830DumpBufferState( i830ContextPtr imesa ) +{ + GLuint *Buffer = imesa->BufferSetup; + + fprintf(stderr, "%s\n", __FUNCTION__); + fprintf(stderr, "CBUFADDR : 0x%08x\n", Buffer[I830_DESTREG_CBUFADDR]); + fprintf(stderr, "DBUFADDR : 0x%08x\n", Buffer[I830_DESTREG_DBUFADDR]); + fprintf(stderr, "DV0 : 0x%08x\n", Buffer[I830_DESTREG_DV0]); + fprintf(stderr, "DV1 : 0x%08x\n", Buffer[I830_DESTREG_DV1]); + fprintf(stderr, "SENABLE : 0x%08x\n", Buffer[I830_DESTREG_SENABLE]); + fprintf(stderr, "SR0 : 0x%08x\n", Buffer[I830_DESTREG_SR0]); + fprintf(stderr, "SR1 : 0x%08x\n", Buffer[I830_DESTREG_SR1]); + fprintf(stderr, "SR2 : 0x%08x\n", Buffer[I830_DESTREG_SR2]); + fprintf(stderr, "DR0 : 0x%08x\n", Buffer[I830_DESTREG_DR0]); + fprintf(stderr, "DR1 : 0x%08x\n", Buffer[I830_DESTREG_DR1]); + fprintf(stderr, "DR2 : 0x%08x\n", Buffer[I830_DESTREG_DR2]); + fprintf(stderr, "DR3 : 0x%08x\n", Buffer[I830_DESTREG_DR3]); + fprintf(stderr, "DR4 : 0x%08x\n", Buffer[I830_DESTREG_DR4]); +} + +void i830DumpStippleState( i830ContextPtr imesa ) +{ + GLuint *Buffer = imesa->BufferSetup; + + fprintf(stderr, "%s\n", __FUNCTION__); + fprintf(stderr, "ST1 : 0x%08x\n", Buffer[I830_STPREG_ST1]); +} + +void i830DumpTextureState( i830ContextPtr imesa, int unit ) +{ + i830TextureObjectPtr t = imesa->CurrentTexObj[unit]; + + if(t) { + fprintf(stderr, "%s : unit %d\n", __FUNCTION__, unit); + fprintf(stderr, "TM0LI : 0x%08x\n", t->Setup[I830_TEXREG_TM0LI]); + fprintf(stderr, "TM0S0 : 0x%08x\n", t->Setup[I830_TEXREG_TM0S0]); + fprintf(stderr, "TM0S1 : 0x%08x\n", t->Setup[I830_TEXREG_TM0S1]); + fprintf(stderr, "TM0S2 : 0x%08x\n", t->Setup[I830_TEXREG_TM0S2]); + fprintf(stderr, "TM0S3 : 0x%08x\n", t->Setup[I830_TEXREG_TM0S3]); + fprintf(stderr, "TM0S4 : 0x%08x\n", t->Setup[I830_TEXREG_TM0S4]); + fprintf(stderr, "NOP0 : 0x%08x\n", t->Setup[I830_TEXREG_NOP0]); + fprintf(stderr, "NOP1 : 0x%08x\n", t->Setup[I830_TEXREG_NOP1]); + fprintf(stderr, "NOP2 : 0x%08x\n", t->Setup[I830_TEXREG_NOP2]); + fprintf(stderr, "MCS : 0x%08x\n", t->Setup[I830_TEXREG_MCS]); + } +} + +void i830DumpTextureBlendState( i830ContextPtr imesa, int unit ) +{ + GLuint *TexBlend = imesa->TexBlend[unit]; + GLuint length = imesa->TexBlendWordsUsed[unit]; + int i; + + fprintf(stderr, "%s : unit %d : length %d\n", __FUNCTION__, unit, length); + for(i = 0; i < length; i++) { + fprintf(stderr, "[%d] : 0x%08x\n", i, TexBlend[i]); + } +} + +void i830VertexSanity( i830ContextPtr imesa, drmI830Vertex vertex ) +{ + I830SAREAPtr sarea = imesa->sarea; + char *prim_name; + int size = 0; + int vfmt_size = 0; + int hw_nr_vertex = 0; + int hw_start_vertex = 0; + + /* Do a bunch of sanity checks on the vertices sent to the hardware */ + + size = vertex.used - 4; + if(imesa->vertex_size && (size % imesa->vertex_size) != 0) { + fprintf(stderr, "\n\nVertex size does not match imesa " + "internal state\n"); + fprintf(stderr, "Buffer size : %d\n", size); + fprintf(stderr, "Vertex size : %d\n", imesa->vertex_size); + } + + /* Check to see if the vertex format is good, and get its size */ + if (sarea->ContextState[I830_CTXREG_VF] == TINY_VERTEX_FORMAT) { + vfmt_size = 16; /* 4 dwords */ + } else if (sarea->ContextState[I830_CTXREG_VF] == + NOTEX_VERTEX_FORMAT) { + vfmt_size = 24; /* 6 dwords */ + } else if (sarea->ContextState[I830_CTXREG_VF] == + TEX0_VERTEX_FORMAT) { + vfmt_size = 32; /* 8 dwords */ + if (sarea->ContextState[I830_CTXREG_VF2] != NON_PROJ_VF2) { + fprintf(stderr, "\n\nTex 0 vertex format, but proj " + "texturing\n"); + } + } else if(sarea->ContextState[I830_CTXREG_VF] == + TEX1_VERTEX_FORMAT) { + if (sarea->ContextState[I830_CTXREG_VF2] == NON_PROJ_VF2) + vfmt_size = 40; /* 10 dwords */ + else + vfmt_size = 48; /* 12 dwords */ + } else { + fprintf(stderr, "\n\nUnknown vertex format : vf : %08x " + "vf2 : %08x\n", + sarea->ContextState[I830_CTXREG_VF], + sarea->ContextState[I830_CTXREG_VF2]); + } + + if(vfmt_size && (size % vfmt_size) != 0) { + fprintf(stderr, "\n\nVertex size does not match hardware " + "internal state\n"); + fprintf(stderr, "Buffer size : %d\n", size); + fprintf(stderr, "Vertex size : %d\n", vfmt_size); + } + + switch(sarea->vertex_prim) { + case PRIM3D_POINTLIST: + hw_start_vertex = 0; + hw_nr_vertex = 1; + prim_name = "PointList"; + break; + + case PRIM3D_LINELIST: + hw_start_vertex = 0; + hw_nr_vertex = 2; + prim_name = "LineList"; + break; + + case PRIM3D_LINESTRIP: + hw_start_vertex = 2; + hw_nr_vertex = 1; + prim_name = "LineStrip"; + break; + + case PRIM3D_TRILIST: + hw_start_vertex = 0; + hw_nr_vertex = 3; + prim_name = "TriList"; + break; + + case PRIM3D_TRISTRIP: + hw_start_vertex = 3; + hw_nr_vertex = 1; + prim_name = "TriStrip"; + break; + + case PRIM3D_TRIFAN: + hw_start_vertex = 3; + hw_nr_vertex = 1; + prim_name = "TriFan"; + break; + + case PRIM3D_POLY: + hw_start_vertex = 3; + hw_nr_vertex = 1; + prim_name = "Polygons"; + break; + default: + prim_name = "Unknown"; + fprintf(stderr, "\n\nUnknown primitive type : %08x\n", + sarea->vertex_prim); + } + + if (hw_nr_vertex && vfmt_size) { + int temp_size = size - (hw_start_vertex * vfmt_size); + int remaining = (temp_size % (hw_nr_vertex * vfmt_size)); + + if (remaining != 0) { + fprintf(stderr, "\n\nThis buffer contains an improper" + " multiple of vertices for this primitive : %s\n", + prim_name); + fprintf(stderr, "Number of vertices in buffer : %d\n", + size / vfmt_size); + fprintf(stderr, "temp_size : %d\n", temp_size); + fprintf(stderr, "remaining vertices : %d", + remaining / vfmt_size); + } + } + if (1) { + fprintf(stderr, "\n\nPrim name (%s), vertices (%d)\n", + prim_name, + size / vfmt_size); + } +} + +void i830EmitHwStateLockedDebug( i830ContextPtr imesa ) +{ + int i; + + if ((imesa->dirty & I830_UPLOAD_TEX0_IMAGE) && imesa->CurrentTexObj[0]) { + i830UploadTexImagesLocked(imesa, imesa->CurrentTexObj[0]); + } + + if ((imesa->dirty & I830_UPLOAD_TEX1_IMAGE) && imesa->CurrentTexObj[1]) { + i830UploadTexImagesLocked(imesa, imesa->CurrentTexObj[1]); + } + + if (imesa->dirty & I830_UPLOAD_CTX) { + memcpy( imesa->sarea->ContextState, + imesa->Setup, sizeof(imesa->Setup) ); + i830DumpContextState(imesa); + } + + for(i = 0; i < I830_TEXTURE_COUNT; i++) { + if ((imesa->dirty & I830_UPLOAD_TEX_N(i)) && imesa->CurrentTexObj[i]) { + imesa->sarea->dirty |= I830_UPLOAD_TEX_N(i); + memcpy(imesa->sarea->TexState[i], + imesa->CurrentTexObj[i]->Setup, + sizeof(imesa->sarea->TexState[i])); + i830DumpTextureState(imesa, i); + } + } + /* Need to figure out if texturing state, or enable changed. */ + + for(i = 0; i < I830_TEXBLEND_COUNT; i++) { + if (imesa->dirty & I830_UPLOAD_TEXBLEND_N(i)) { + imesa->sarea->dirty |= I830_UPLOAD_TEXBLEND_N(i); + memcpy(imesa->sarea->TexBlendState[i],imesa->TexBlend[i], + imesa->TexBlendWordsUsed[i] * 4); + imesa->sarea->TexBlendStateWordsUsed[i] = + imesa->TexBlendWordsUsed[i]; + i830DumpTextureBlendState(imesa, i); + } + } + + if (imesa->dirty & I830_UPLOAD_BUFFERS) { + memcpy( imesa->sarea->BufferState,imesa->BufferSetup, + sizeof(imesa->BufferSetup) ); + i830DumpBufferState(imesa); + } + + if (imesa->dirty & I830_UPLOAD_STIPPLE) { + fprintf(stderr, "UPLOAD_STIPPLE\n"); + memcpy( imesa->sarea->StippleState,imesa->StippleSetup, + sizeof(imesa->StippleSetup) ); + i830DumpStippleState(imesa); + } + + if (imesa->dirty & I830_UPLOAD_TEX_PALETTE_SHARED) { + memcpy( imesa->sarea->Palette[0],imesa->palette, + sizeof(imesa->sarea->Palette[0])); + } else { + i830TextureObjectPtr p; + if (imesa->dirty & I830_UPLOAD_TEX_PALETTE_N(0)) { + p = imesa->CurrentTexObj[0]; + memcpy( imesa->sarea->Palette[0],p->palette, + sizeof(imesa->sarea->Palette[0])); + } + if (imesa->dirty & I830_UPLOAD_TEX_PALETTE_N(1)) { + p = imesa->CurrentTexObj[1]; + memcpy( imesa->sarea->Palette[1], + p->palette, + sizeof(imesa->sarea->Palette[1])); + } + } + imesa->sarea->dirty |= (imesa->dirty & ~(I830_UPLOAD_TEX_MASK | + I830_UPLOAD_TEXBLEND_MASK)); + + imesa->upload_cliprects = GL_TRUE; + imesa->dirty = 0; +} diff --git a/src/mesa/drivers/dri/i830/i830_debug.h b/src/mesa/drivers/dri/i830/i830_debug.h new file mode 100644 index 0000000000..deb84f7b0a --- /dev/null +++ b/src/mesa/drivers/dri/i830/i830_debug.h @@ -0,0 +1,48 @@ +/************************************************************************** + +Copyright 2001 2d3d Inc., Delray Beach, FL + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_debug.h,v 1.3 2002/12/10 01:26:53 dawes Exp $ */ + +/* + * Author: + * Jeff Hartmann <jhartmann@2d3d.com> + */ + +/* Defines for sanity checking and debug output */ +#ifndef I830DEBUG_INC +#define I830DEBUG_INC + + +void i830DumpContextState( i830ContextPtr imesa ); +void i830DumpStippleState( i830ContextPtr imesa ); +void i830DumpBufferState( i830ContextPtr imesa ); +void i830DumpTextureState( i830ContextPtr imesa, int unit ); +void i830DumpTextureBlendState( i830ContextPtr imesa, int unit ); +void i830VertexSanity( i830ContextPtr imesa, drmI830Vertex vertex ); +void i830EmitHwStateLockedDebug( i830ContextPtr imesa ); + +#endif diff --git a/src/mesa/drivers/dri/i830/i830_ioctl.c b/src/mesa/drivers/dri/i830/i830_ioctl.c new file mode 100644 index 0000000000..607b813e53 --- /dev/null +++ b/src/mesa/drivers/dri/i830/i830_ioctl.c @@ -0,0 +1,841 @@ + +/************************************************************************** + +Copyright 2001 VA Linux Systems Inc., Fremont, California. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_ioctl.c,v 1.5 2002/12/10 01:26:53 dawes Exp $ */ + +/* + * Author: + * Jeff Hartmann <jhartmann@2d3d.com> + * Graeme Fisher <graeme@2d3d.co.za> + * Abraham vd Merwe <abraham@2d3d.co.za> + * + * Heavily based on the I810 driver, which was written by: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include <stdio.h> +#include <unistd.h> +#include <errno.h> + +#include "glheader.h" +#include "mtypes.h" +#include "macros.h" +#include "dd.h" +#include "swrast/swrast.h" + +#include "mm.h" + +#include "i830_screen.h" +#include "i830_dri.h" + +#include "i830_context.h" +#include "i830_ioctl.h" +#include "i830_state.h" +#include "i830_debug.h" + +#include "drm.h" + +static drmBufPtr i830_get_buffer_ioctl( i830ContextPtr imesa ) +{ + drmI830DMA dma; + drmBufPtr buf; + int retcode,i = 0; + while (1) { + retcode = drmCommandWriteRead(imesa->driFd, + DRM_I830_GETBUF, + &dma, + sizeof(drmI830DMA)); + if (dma.granted == 1 && retcode == 0) + break; + + if (++i > 1000) { + imesa->sarea->perf_boxes |= I830_BOX_WAIT; + retcode = drmCommandNone(imesa->driFd, DRM_I830_FLUSH); + i = 0; + } + } + + buf = &(imesa->i830Screen->bufs->list[dma.request_idx]); + buf->idx = dma.request_idx; + buf->used = 0; + buf->total = dma.request_size; + buf->address = (drmAddress)dma.virtual; + + return buf; +} + +static void i830ClearDrawQuad(i830ContextPtr imesa, float left, + float right, + float bottom, float top, GLubyte red, + GLubyte green, GLubyte blue, GLubyte alpha) +{ + GLuint *vb = i830AllocDmaLowLocked( imesa, 128 ); + i830Vertex tmp; + int i; + + /* PRIM3D_TRIFAN */ + + /* initial vertex, left bottom */ + tmp.v.x = left; + tmp.v.y = bottom; + tmp.v.z = 1.0; + tmp.v.w = 1.0; + tmp.v.color.red = red; + tmp.v.color.green = green; + tmp.v.color.blue = blue; + tmp.v.color.alpha = alpha; + tmp.v.specular.red = 0; + tmp.v.specular.green = 0; + tmp.v.specular.blue = 0; + tmp.v.specular.alpha = 0; + tmp.v.u0 = 0.0f; + tmp.v.v0 = 0.0f; + for (i = 0 ; i < 8 ; i++) + vb[i] = tmp.ui[i]; + + /* right bottom */ + vb += 8; + tmp.v.x = right; + for (i = 0 ; i < 8 ; i++) + vb[i] = tmp.ui[i]; + + /* right top */ + vb += 8; + tmp.v.y = top; + for (i = 0 ; i < 8 ; i++) + vb[i] = tmp.ui[i]; + + /* left top */ + vb += 8; + tmp.v.x = left; + for (i = 0 ; i < 8 ; i++) + vb[i] = tmp.ui[i]; +} + +static void i830ClearWithTris(GLcontext *ctx, GLbitfield mask, + GLboolean all, + GLint cx, GLint cy, GLint cw, GLint ch) +{ + i830ContextPtr imesa = I830_CONTEXT( ctx ); + __DRIdrawablePrivate *dPriv = imesa->driDrawable; + i830ScreenPrivate *i830Screen = imesa->i830Screen; + I830SAREAPtr sarea = imesa->sarea; + GLuint old_vertex_prim; + GLuint old_dirty; + int x0, y0, x1, y1; + + if (I830_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "Clearing with triangles\n"); + + old_dirty = imesa->dirty & ~I830_UPLOAD_CLIPRECTS; + /* Discard all the dirty flags except the cliprect one, reset later */ + imesa->dirty &= I830_UPLOAD_CLIPRECTS; + + if(!all) { + x0 = cx; + y0 = cy; + x1 = x0 + cw; + y1 = y0 + ch; + } else { + x0 = 0; + y0 = 0; + x1 = x0 + dPriv->w; + y1 = y0 + dPriv->h; + } + + /* Clip to Screen */ + if (x0 < 0) x0 = 0; + if (y0 < 0) y0 = 0; + if (x1 > i830Screen->width-1) x1 = i830Screen->width-1; + if (y1 > i830Screen->height-1) y1 = i830Screen->height-1; + + LOCK_HARDWARE(imesa); + memcpy(sarea->ContextState, + imesa->Init_Setup, + sizeof(imesa->Setup) ); + memcpy(sarea->BufferState, + imesa->BufferSetup, + sizeof(imesa->BufferSetup) ); + sarea->StippleState[I830_STPREG_ST1] = 0; + + old_vertex_prim = imesa->hw_primitive; + imesa->hw_primitive = PRIM3D_TRIFAN; + + if(mask & DD_FRONT_LEFT_BIT) { + GLuint tmp = sarea->ContextState[I830_CTXREG_ENABLES_2]; + + sarea->dirty |= (I830_UPLOAD_CTX | I830_UPLOAD_BUFFERS | + I830_UPLOAD_TEXBLEND0); + + sarea->TexBlendState[0][0] = (STATE3D_MAP_BLEND_OP_CMD(0) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXOP_LAST_STAGE | + TEXBLENDOP_ARG1); + sarea->TexBlendState[0][1] = (STATE3D_MAP_BLEND_OP_CMD(0) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + sarea->TexBlendState[0][2] = (STATE3D_MAP_BLEND_ARG_CMD(0) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + sarea->TexBlendState[0][3] = (STATE3D_MAP_BLEND_ARG_CMD(0) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + sarea->TexBlendStateWordsUsed[0] = 4; + + tmp &= ~(ENABLE_STENCIL_WRITE | ENABLE_DEPTH_WRITE); + tmp |= (DISABLE_STENCIL_WRITE | + DISABLE_DEPTH_WRITE | + (imesa->mask_red << WRITEMASK_RED_SHIFT) | + (imesa->mask_green << WRITEMASK_GREEN_SHIFT) | + (imesa->mask_blue << WRITEMASK_BLUE_SHIFT) | + (imesa->mask_alpha << WRITEMASK_ALPHA_SHIFT)); + sarea->ContextState[I830_CTXREG_ENABLES_2] = tmp; + + if(0) + fprintf(stderr, "fcdq : r_mask(%d) g_mask(%d) b_mask(%d) a_mask(%d)\n", + imesa->mask_red, imesa->mask_green, imesa->mask_blue, + imesa->mask_alpha); + + sarea->BufferState[I830_DESTREG_CBUFADDR] = i830Screen->fbOffset; + + if(0) + fprintf(stderr, "fcdq : x0(%d) x1(%d) y0(%d) y1(%d)\n" + "r(0x%x) g(0x%x) b(0x%x) a(0x%x)\n", + x0, x1, y0, y1, imesa->clear_red, imesa->clear_green, + imesa->clear_blue, imesa->clear_alpha); + + i830ClearDrawQuad(imesa, (float)x0, (float)x1, (float)y0, (float)y1, + imesa->clear_red, imesa->clear_green, + imesa->clear_blue, imesa->clear_alpha); + i830FlushPrimsLocked( imesa ); + } + + if(mask & DD_BACK_LEFT_BIT) { + GLuint tmp = sarea->ContextState[I830_CTXREG_ENABLES_2]; + + sarea->dirty |= (I830_UPLOAD_CTX | I830_UPLOAD_BUFFERS | + I830_UPLOAD_TEXBLEND0); + + sarea->TexBlendState[0][0] = (STATE3D_MAP_BLEND_OP_CMD(0) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXOP_LAST_STAGE | + TEXBLENDOP_ARG1); + sarea->TexBlendState[0][1] = (STATE3D_MAP_BLEND_OP_CMD(0) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + sarea->TexBlendState[0][2] = (STATE3D_MAP_BLEND_ARG_CMD(0) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + sarea->TexBlendState[0][3] = (STATE3D_MAP_BLEND_ARG_CMD(0) | + TEXPIPE_ALPHA | + TEXBLEND_ARG2 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + sarea->TexBlendStateWordsUsed[0] = 4; + + tmp &= ~(ENABLE_STENCIL_WRITE | ENABLE_DEPTH_WRITE); + tmp |= (DISABLE_STENCIL_WRITE | + DISABLE_DEPTH_WRITE | + (imesa->mask_red << WRITEMASK_RED_SHIFT) | + (imesa->mask_green << WRITEMASK_GREEN_SHIFT) | + (imesa->mask_blue << WRITEMASK_BLUE_SHIFT) | + (imesa->mask_alpha << WRITEMASK_ALPHA_SHIFT)); + + if(0) + fprintf(stderr, "bcdq : r_mask(%d) g_mask(%d) b_mask(%d) a_mask(%d)\n", + imesa->mask_red, imesa->mask_green, imesa->mask_blue, + imesa->mask_alpha); + + sarea->ContextState[I830_CTXREG_ENABLES_2] = tmp; + + sarea->BufferState[I830_DESTREG_CBUFADDR] = i830Screen->backOffset; + + if(0) + fprintf(stderr, "bcdq : x0(%d) x1(%d) y0(%d) y1(%d)\n" + "r(0x%x) g(0x%x) b(0x%x) a(0x%x)\n", + x0, x1, y0, y1, imesa->clear_red, imesa->clear_green, + imesa->clear_blue, imesa->clear_alpha); + + i830ClearDrawQuad(imesa, (float)x0, (float)x1, (float)y0, (float)y1, + imesa->clear_red, imesa->clear_green, + imesa->clear_blue, imesa->clear_alpha); + i830FlushPrimsLocked( imesa ); + } + + if(mask & DD_STENCIL_BIT) { + GLuint s_mask = ctx->Stencil.WriteMask[0]; + + sarea->dirty |= (I830_UPLOAD_CTX | I830_UPLOAD_BUFFERS | + I830_UPLOAD_TEXBLEND0); + + sarea->TexBlendState[0][0] = (STATE3D_MAP_BLEND_OP_CMD(0) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXOP_LAST_STAGE | + TEXBLENDOP_ARG1); + sarea->TexBlendState[0][1] = (STATE3D_MAP_BLEND_OP_CMD(0) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + sarea->TexBlendState[0][2] = (STATE3D_MAP_BLEND_ARG_CMD(0) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + sarea->TexBlendState[0][3] = (STATE3D_MAP_BLEND_ARG_CMD(0) | + TEXPIPE_ALPHA | + TEXBLEND_ARG2 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + sarea->TexBlendStateWordsUsed[0] = 4; + + sarea->ContextState[I830_CTXREG_ENABLES_1] |= (ENABLE_STENCIL_TEST | + ENABLE_DEPTH_TEST); + + sarea->ContextState[I830_CTXREG_ENABLES_2] &= ~(ENABLE_STENCIL_WRITE | + ENABLE_DEPTH_WRITE | + ENABLE_COLOR_WRITE); + + sarea->ContextState[I830_CTXREG_ENABLES_2] |= + (ENABLE_STENCIL_WRITE | + DISABLE_DEPTH_WRITE | + (1 << WRITEMASK_RED_SHIFT) | + (1 << WRITEMASK_GREEN_SHIFT) | + (1 << WRITEMASK_BLUE_SHIFT) | + (1 << WRITEMASK_ALPHA_SHIFT) | + ENABLE_COLOR_WRITE); + + sarea->ContextState[I830_CTXREG_STATE4] &= + ~MODE4_ENABLE_STENCIL_WRITE_MASK; + + sarea->ContextState[I830_CTXREG_STATE4] |= + (ENABLE_STENCIL_WRITE_MASK | + STENCIL_WRITE_MASK(s_mask)); + + sarea->ContextState[I830_CTXREG_STENCILTST] &= + ~(STENCIL_OPS_MASK | + STENCIL_REF_VALUE_MASK | + ENABLE_STENCIL_TEST_FUNC_MASK); + + sarea->ContextState[I830_CTXREG_STENCILTST] |= + (ENABLE_STENCIL_PARMS | + ENABLE_STENCIL_REF_VALUE | + ENABLE_STENCIL_TEST_FUNC | + STENCIL_FAIL_OP(STENCILOP_REPLACE) | + STENCIL_PASS_DEPTH_FAIL_OP(STENCILOP_REPLACE) | + STENCIL_PASS_DEPTH_PASS_OP(STENCILOP_REPLACE) | + STENCIL_REF_VALUE((ctx->Stencil.Clear & 0xff)) | + STENCIL_TEST_FUNC(COMPAREFUNC_ALWAYS)); + + if(0) + fprintf(stderr, "Enables_1 (0x%x) Enables_2 (0x%x) StenTst (0x%x)\n" + "Modes_4 (0x%x)\n", + sarea->ContextState[I830_CTXREG_ENABLES_1], + sarea->ContextState[I830_CTXREG_ENABLES_2], + sarea->ContextState[I830_CTXREG_STENCILTST], + sarea->ContextState[I830_CTXREG_STATE4]); + + sarea->BufferState[I830_DESTREG_CBUFADDR] = i830Screen->fbOffset; + + i830ClearDrawQuad(imesa, (float)x0, (float)x1, (float)y0, (float)y1, + 255, 255, 255, 255); + i830FlushPrimsLocked( imesa ); + } + + UNLOCK_HARDWARE(imesa); + imesa->dirty = old_dirty; + imesa->dirty |= (I830_UPLOAD_CTX | + I830_UPLOAD_BUFFERS | + I830_UPLOAD_TEXBLEND0); + + imesa->hw_primitive = old_vertex_prim; +} + +static void i830Clear(GLcontext *ctx, GLbitfield mask, GLboolean all, + GLint cx1, GLint cy1, GLint cw, GLint ch) +{ + i830ContextPtr imesa = I830_CONTEXT( ctx ); + __DRIdrawablePrivate *dPriv = imesa->driDrawable; + const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask); + drmI830Clear clear; + GLbitfield tri_mask = 0; + int i; + GLint cx, cy; + + /* flip top to bottom */ + cy = dPriv->h-cy1-ch; + cx = cx1 + imesa->drawX; + cy += imesa->drawY; + + if(0) fprintf(stderr, "\nClearColor : 0x%08x\n", imesa->ClearColor); + + clear.flags = 0; + clear.clear_color = imesa->ClearColor; + clear.clear_depth = 0; + clear.clear_colormask = 0; + clear.clear_depthmask = 0; + + I830_FIREVERTICES( imesa ); + + if (mask & DD_FRONT_LEFT_BIT) { + if(colorMask == ~0) { + clear.flags |= I830_FRONT; + } else { + tri_mask |= DD_FRONT_LEFT_BIT; + } + mask &= ~DD_FRONT_LEFT_BIT; + } + + if (mask & DD_BACK_LEFT_BIT) { + if(colorMask == ~0) { + clear.flags |= I830_BACK; + } else { + tri_mask |= DD_BACK_LEFT_BIT; + } + mask &= ~DD_BACK_LEFT_BIT; + } + + if (mask & DD_DEPTH_BIT) { + clear.flags |= I830_DEPTH; + clear.clear_depthmask = imesa->depth_clear_mask; + clear.clear_depth = (GLuint)(ctx->Depth.Clear * imesa->ClearDepth); + mask &= ~DD_DEPTH_BIT; + } + + if((mask & DD_STENCIL_BIT) && imesa->hw_stencil) { + if (ctx->Stencil.WriteMask[0] != 0xff) { + tri_mask |= DD_STENCIL_BIT; + } else { + clear.flags |= I830_DEPTH; + clear.clear_depthmask |= imesa->stencil_clear_mask; + clear.clear_depth |= (ctx->Stencil.Clear & 0xff) << 24; + } + mask &= ~DD_STENCIL_BIT; + } + + /* First check for clears that need to happen with triangles */ + if(tri_mask) { + i830ClearWithTris(ctx, tri_mask, all, cx, cy, cw, ch); + } + + if (clear.flags) { + LOCK_HARDWARE( imesa ); + + for (i = 0 ; i < imesa->numClipRects ; ) + { + int nr = MIN2(i + I830_NR_SAREA_CLIPRECTS, imesa->numClipRects); + XF86DRIClipRectRec *box = imesa->pClipRects; + drm_clip_rect_t *b = (drm_clip_rect_t *)imesa->sarea->boxes; + int n = 0; + + if (!all) { + for ( ; i < nr ; i++) { + GLint x = box[i].x1; + GLint y = box[i].y1; + GLint w = box[i].x2 - x; + GLint h = box[i].y2 - y; + + if (x < cx) w -= cx - x, x = cx; + if (y < cy) h -= cy - y, y = cy; + if (x + w > cx + cw) w = cx + cw - x; + if (y + h > cy + ch) h = cy + ch - y; + if (w <= 0) continue; + if (h <= 0) continue; + + b->x1 = x; + b->y1 = y; + b->x2 = x + w; + b->y2 = y + h; + b++; + n++; + } + } else { + for ( ; i < nr ; i++) { + *b++ = *(drm_clip_rect_t *)&box[i]; + n++; + } + } + + imesa->sarea->nbox = n; + drmCommandWrite(imesa->driFd, DRM_I830_CLEAR, + &clear, sizeof(drmI830Clear)); + } + + UNLOCK_HARDWARE( imesa ); + imesa->upload_cliprects = GL_TRUE; + } + + if (mask) + _swrast_Clear( ctx, mask, all, cx1, cy1, cw, ch ); +} + + + +/* + * Copy the back buffer to the front buffer. + */ +void i830CopyBuffer( const __DRIdrawablePrivate *dPriv ) +{ + i830ContextPtr imesa; + XF86DRIClipRectPtr pbox; + int nbox, i, tmp; + + assert(dPriv); + assert(dPriv->driContextPriv); + assert(dPriv->driContextPriv->driverPrivate); + + imesa = (i830ContextPtr) dPriv->driContextPriv->driverPrivate; + + I830_FIREVERTICES( imesa ); + LOCK_HARDWARE( imesa ); + + imesa->sarea->perf_boxes |= imesa->perf_boxes; + imesa->perf_boxes = 0; + + pbox = dPriv->pClipRects; + nbox = dPriv->numClipRects; + + for (i = 0 ; i < nbox ; ) + { + int nr = MIN2(i + I830_NR_SAREA_CLIPRECTS, dPriv->numClipRects); + XF86DRIClipRectRec *b = (XF86DRIClipRectRec *)imesa->sarea->boxes; + + imesa->sarea->nbox = nr - i; + + for ( ; i < nr ; i++) + *b++ = pbox[i]; + drmCommandNone(imesa->driFd, DRM_I830_SWAP); + } + + tmp = GET_ENQUEUE_AGE(imesa); + UNLOCK_HARDWARE( imesa ); + + /* multiarb will suck the life out of the server without this throttle: + */ + if (GET_DISPATCH_AGE(imesa) < imesa->lastSwap) { + i830WaitAge(imesa, imesa->lastSwap); + } + + imesa->lastSwap = tmp; + imesa->upload_cliprects = GL_TRUE; +} + +/* Flip the front & back buffes + */ +void i830PageFlip( const __DRIdrawablePrivate *dPriv ) +{ +#if 0 + i830ContextPtr imesa; + int tmp, ret; + + if (I830_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s\n", __FUNCTION__); + + assert(dPriv); + assert(dPriv->driContextPriv); + assert(dPriv->driContextPriv->driverPrivate); + + imesa = (i830ContextPtr) dPriv->driContextPriv->driverPrivate; + + I830_FIREVERTICES( imesa ); + LOCK_HARDWARE( imesa ); + + imesa->sarea->perf_boxes |= imesa->perf_boxes; + imesa->perf_boxes = 0; + + if (dPriv->pClipRects) { + *(XF86DRIClipRectRec *)imesa->sarea->boxes = dPriv->pClipRects[0]; + imesa->sarea->nbox = 1; + } + + ret = drmCommandNone(imesa->driFd, DRM_I830_FLIP); + if (ret) { + fprintf(stderr, "%s: %d\n", __FUNCTION__, ret); + UNLOCK_HARDWARE( imesa ); + exit(1); + } + + tmp = GET_ENQUEUE_AGE(imesa); + UNLOCK_HARDWARE( imesa ); + + /* multiarb will suck the life out of the server without this throttle: + */ + if (GET_DISPATCH_AGE(imesa) < imesa->lastSwap) { + i830WaitAge(imesa, imesa->lastSwap); + } + + i830SetDrawBuffer( imesa->glCtx, imesa->glCtx->Color.DriverDrawBuffer ); + imesa->upload_cliprects = GL_TRUE; + imesa->lastSwap = tmp; +#endif +} + +/* This waits for *everybody* to finish rendering -- overkill. + */ +void i830DmaFinish( i830ContextPtr imesa ) +{ + I830_FIREVERTICES( imesa ); + LOCK_HARDWARE_QUIESCENT( imesa ); + UNLOCK_HARDWARE( imesa ); +} + +void i830RegetLockQuiescent( i830ContextPtr imesa ) +{ + drmUnlock(imesa->driFd, imesa->hHWContext); + i830GetLock( imesa, DRM_LOCK_QUIESCENT ); +} + +void i830WaitAgeLocked( i830ContextPtr imesa, int age ) +{ + int i = 0; + while (++i < 5000) { + drmCommandNone(imesa->driFd, DRM_I830_GETAGE); + if (GET_DISPATCH_AGE(imesa) >= age) return; + imesa->sarea->perf_boxes |= I830_BOX_WAIT; + UNLOCK_HARDWARE( imesa ); + if (I830_DEBUG & DEBUG_SLEEP) fprintf(stderr, "."); + usleep(1); + LOCK_HARDWARE( imesa ); + } + /* If that didn't work, just do a flush: + */ + drmCommandNone(imesa->driFd, DRM_I830_FLUSH); +} + +void i830WaitAge( i830ContextPtr imesa, int age ) +{ + int i = 0; + if (GET_DISPATCH_AGE(imesa) >= age) return; + + while (1) { + drmCommandNone(imesa->driFd, DRM_I830_GETAGE); + if (GET_DISPATCH_AGE(imesa) >= age) return; + imesa->perf_boxes |= I830_BOX_WAIT; + + if (imesa->do_irqs) { + drmI830IrqEmit ie; + drmI830IrqWait iw; + int ret; + + ie.irq_seq = &iw.irq_seq; + + LOCK_HARDWARE( imesa ); + ret = drmCommandWriteRead( imesa->driFd, DRM_I830_IRQ_EMIT, &ie, sizeof(ie) ); + if ( ret ) { + fprintf( stderr, "%s: drmI830IrqEmit: %d\n", __FUNCTION__, ret ); + exit(1); + } + UNLOCK_HARDWARE(imesa); + + ret = drmCommandWrite( imesa->driFd, DRM_I830_IRQ_WAIT, &iw, sizeof(iw) ); + if ( ret ) { + fprintf( stderr, "%s: drmI830IrqWait: %d\n", __FUNCTION__, ret ); + exit(1); + } + } else { + if (++i > 5000) usleep(1); + } + } +} + +static void age_imesa( i830ContextPtr imesa, int age ) +{ + if (imesa->CurrentTexObj[0]) imesa->CurrentTexObj[0]->base.timestamp = age; + if (imesa->CurrentTexObj[1]) imesa->CurrentTexObj[1]->base.timestamp = age; +} + +void i830FlushPrimsLocked( i830ContextPtr imesa ) +{ + XF86DRIClipRectPtr pbox = (XF86DRIClipRectPtr)imesa->pClipRects; + int nbox = imesa->numClipRects; + drmBufPtr buffer = imesa->vertex_buffer; + I830SAREAPtr sarea = imesa->sarea; + drmI830Vertex vertex; + int i, nr; + + if (I830_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s dirty: %08x\n", __FUNCTION__, imesa->dirty); + + + vertex.idx = buffer->idx; + vertex.used = imesa->vertex_low; + vertex.discard = 0; + sarea->vertex_prim = imesa->hw_primitive; + + /* Reset imesa vars: + */ + imesa->vertex_buffer = 0; + imesa->vertex_addr = 0; + imesa->vertex_low = 0; + imesa->vertex_high = 0; + imesa->vertex_last_prim = 0; + + if (imesa->dirty) { + if (I830_DEBUG & DEBUG_SANITY) + i830EmitHwStateLockedDebug(imesa); + else + i830EmitHwStateLocked(imesa); + } + + if (I830_DEBUG & DEBUG_IOCTL) + fprintf(stderr,"%s: Vertex idx %d used %d discard %d\n", + __FUNCTION__, vertex.idx, vertex.used, vertex.discard); + + if (!nbox) { + vertex.used = 0; + vertex.discard = 1; + if (drmCommandWrite (imesa->driFd, DRM_I830_VERTEX, + &vertex, sizeof(drmI830Vertex))) { + fprintf(stderr, "DRM_I830_VERTEX: %d\n", -errno); + UNLOCK_HARDWARE(imesa); + exit(1); + } + return; + } + + for (i = 0 ; i < nbox ; i = nr ) { + XF86DRIClipRectPtr b = sarea->boxes; + int j; + + nr = MIN2(i + I830_NR_SAREA_CLIPRECTS, nbox); + sarea->nbox = nr - i; + + for ( j = i ; j < nr ; j++) { + b[j-i] = pbox[j]; + } + + /* Finished with the buffer? + */ + if (nr == nbox) + vertex.discard = 1; + + /* Do a bunch of sanity checks on the vertices sent to the hardware */ + if (I830_DEBUG & DEBUG_SANITY) { + i830VertexSanity(imesa, vertex); + + for ( j = 0 ; j < sarea->nbox ; j++) { + fprintf(stderr, "box %d/%d %d,%d %d,%d\n", + j, sarea->nbox, b[j].x1, b[j].y1, b[j].x2, b[j].y2); + } + } + + drmCommandWrite (imesa->driFd, DRM_I830_VERTEX, + &vertex, sizeof(drmI830Vertex)); + age_imesa(imesa, imesa->sarea->last_enqueue); + } + + imesa->dirty = 0; + imesa->upload_cliprects = GL_FALSE; +} + +void i830FlushPrimsGetBufferLocked( i830ContextPtr imesa ) +{ + if (imesa->vertex_buffer) + i830FlushPrimsLocked( imesa ); + imesa->vertex_buffer = i830_get_buffer_ioctl( imesa ); + imesa->vertex_addr = (char *)imesa->vertex_buffer->address; + + /* leave room for instruction header & footer: + */ + imesa->vertex_high = imesa->vertex_buffer->total - 4; + imesa->vertex_low = 4; + imesa->vertex_last_prim = imesa->vertex_low; +} + +void i830FlushPrimsGetBuffer( i830ContextPtr imesa ) +{ + LOCK_HARDWARE(imesa); + i830FlushPrimsGetBufferLocked( imesa ); + UNLOCK_HARDWARE(imesa); +} + + +void i830FlushPrims( i830ContextPtr imesa ) +{ + if (imesa->vertex_buffer) { + LOCK_HARDWARE( imesa ); + i830FlushPrimsLocked( imesa ); + UNLOCK_HARDWARE( imesa ); + } +} + +int i830_check_copy(int fd) +{ + return drmCommandNone(fd, DRM_I830_DOCOPY); +} + +static void i830DDFlush( GLcontext *ctx ) +{ + i830ContextPtr imesa = I830_CONTEXT( ctx ); + I830_FIREVERTICES( imesa ); +} + +static void i830DDFinish( GLcontext *ctx ) +{ + i830ContextPtr imesa = I830_CONTEXT( ctx ); + i830DmaFinish( imesa ); +} + +void i830DDInitIoctlFuncs( GLcontext *ctx ) +{ + ctx->Driver.Flush = i830DDFlush; + ctx->Driver.Clear = i830Clear; + ctx->Driver.Finish = i830DDFinish; +} + diff --git a/src/mesa/drivers/dri/i830/i830_ioctl.h b/src/mesa/drivers/dri/i830/i830_ioctl.h new file mode 100644 index 0000000000..4c64b8d7ab --- /dev/null +++ b/src/mesa/drivers/dri/i830/i830_ioctl.h @@ -0,0 +1,105 @@ + +/************************************************************************** + +Copyright 2001 VA Linux Systems Inc., Fremont, California. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_ioctl.h,v 1.3 2002/10/30 12:51:35 alanh Exp $ */ + +/* + * Author: + * Jeff Hartmann <jhartmann@2d3d.com> + * Graeme Fisher <graeme@2d3d.co.za> + * Abraham vd Merwe <abraham@2d3d.co.za> + * + * Heavily based on the I810 driver, which was written by: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef I830_IOCTL_H +#define I830_IOCTL_H + +#include "i830_context.h" + +GLuint *i830AllocDwords (i830ContextPtr imesa, int dwords); +void i830EmitPrim( i830ContextPtr imesa ); +void i830FlushPrims( i830ContextPtr mmesa ); +void i830FlushPrimsLocked( i830ContextPtr mmesa ); +void i830FlushPrimsGetBuffer( i830ContextPtr imesa ); +void i830FlushPrimsGetBufferLocked( i830ContextPtr imesa ); +void i830WaitAgeLocked( i830ContextPtr imesa, int age ); +void i830WaitAge( i830ContextPtr imesa, int age ); +void i830DmaFinish( i830ContextPtr imesa ); +void i830RegetLockQuiescent( i830ContextPtr imesa ); +void i830DDInitIoctlFuncs( GLcontext *ctx ); +void i830CopyBuffer( const __DRIdrawablePrivate *dpriv ); +void i830PageFlip( const __DRIdrawablePrivate *dpriv ); +int i830_check_copy(int fd); + +#define I830_STATECHANGE(imesa, flag) \ +do { \ + if (imesa->vertex_low != imesa->vertex_last_prim) \ + i830FlushPrims(imesa); \ + imesa->dirty |= flag; \ +} while (0) + + +#define I830_FIREVERTICES(imesa) \ +do { \ + if (imesa->vertex_buffer) { \ + i830FlushPrims(imesa); \ +} \ +} while (0) + + +static __inline GLuint *i830AllocDmaLow( i830ContextPtr imesa, int bytes ) +{ + if (imesa->vertex_low + bytes > imesa->vertex_high) { + i830FlushPrimsGetBuffer( imesa ); + } + + { + GLuint *start = (GLuint *)(imesa->vertex_addr + imesa->vertex_low); + imesa->vertex_low += bytes; + return start; + } +} + +static __inline GLuint *i830AllocDmaLowLocked( i830ContextPtr imesa, + int bytes ) +{ + if (imesa->vertex_low + bytes > imesa->vertex_high) { + i830FlushPrimsGetBufferLocked( imesa ); + } + + { + GLuint *start = (GLuint *)(imesa->vertex_addr + imesa->vertex_low); + imesa->vertex_low += bytes; + return start; + } +} + + +#endif diff --git a/src/mesa/drivers/dri/i830/i830_render.c b/src/mesa/drivers/dri/i830/i830_render.c new file mode 100644 index 0000000000..5df05dfde8 --- /dev/null +++ b/src/mesa/drivers/dri/i830/i830_render.c @@ -0,0 +1,267 @@ +/* + * Intel i810 DRI driver for Mesa 3.5 + * + * Copyright (C) 1999-2000 Keith Whitwell All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL KEITH WHITWELL BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: + * Keith Whitwell <keith@tungstengraphics.com> + * Adapted for use on the I830: + * Jeff Hartmann <jhartmann@2d3d.com> + */ +/* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_render.c,v 1.2 2002/12/10 01:26:53 dawes Exp $ */ + +/* + * Render unclipped vertex buffers by emitting vertices directly to + * dma buffers. Use strip/fan hardware acceleration where possible. + * + */ +#include "glheader.h" +#include "context.h" +#include "macros.h" +#include "imports.h" +#include "mtypes.h" +#include "enums.h" + +#include "tnl/t_context.h" + +#include "i830_screen.h" +#include "i830_dri.h" + +#include "i830_context.h" +#include "i830_tris.h" +#include "i830_state.h" +#include "i830_vb.h" +#include "i830_ioctl.h" + +/* + * Render unclipped vertex buffers by emitting vertices directly to + * dma buffers. Use strip/fan hardware primitives where possible. + * Try to simulate missing primitives with indexed vertices. + */ +#define HAVE_POINTS 0 /* Has it, but can't use because subpixel has to + * be adjusted for points on the I830/I845G + */ +#define HAVE_LINES 1 +#define HAVE_LINE_STRIPS 1 +#define HAVE_TRIANGLES 1 +#define HAVE_TRI_STRIPS 1 +#define HAVE_TRI_STRIP_1 0 /* has it, template can't use it yet */ +#define HAVE_TRI_FANS 1 +#define HAVE_POLYGONS 1 +#define HAVE_QUADS 0 +#define HAVE_QUAD_STRIPS 0 + +#define HAVE_ELTS 0 + +static GLuint hw_prim[GL_POLYGON+1] = { + 0, + PRIM3D_LINELIST, + PRIM3D_LINESTRIP, + PRIM3D_LINESTRIP, + PRIM3D_TRILIST, + PRIM3D_TRISTRIP, + PRIM3D_TRIFAN, + 0, + 0, + PRIM3D_POLY +}; + +static const GLenum reduced_prim[GL_POLYGON+1] = { + GL_POINTS, + GL_LINES, + GL_LINES, + GL_LINES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES +}; + +static const int scale_prim[GL_POLYGON+1] = { + 0, /* fallback case */ + 1, + 2, + 2, + 1, + 3, + 3, + 0, /* fallback case */ + 0, /* fallback case */ + 3 +}; + +/* Fallback to normal rendering. Should now never be called. + */ +static void VERT_FALLBACK( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + tnl->Driver.Render.PrimitiveNotify( ctx, flags & PRIM_MODE_MASK ); + tnl->Driver.Render.BuildVertices( ctx, start, count, ~0 ); + tnl->Driver.Render.PrimTabVerts[flags&PRIM_MODE_MASK]( ctx, start, + count, flags ); + I830_CONTEXT(ctx)->SetupNewInputs = VERT_BIT_CLIP; +} + + +#define LOCAL_VARS i830ContextPtr imesa = I830_CONTEXT(ctx) +#define INIT( prim ) do { \ + I830_STATECHANGE(imesa, 0); \ + i830RasterPrimitive( ctx, reduced_prim[prim], hw_prim[prim] ); \ +} while (0) + +#define NEW_PRIMITIVE() I830_STATECHANGE( imesa, 0 ) +#define NEW_BUFFER() I830_FIREVERTICES( imesa ) +#define GET_CURRENT_VB_MAX_VERTS() \ + (((int)imesa->vertex_high - (int)imesa->vertex_low) / (imesa->vertex_size*4)) +#define GET_SUBSEQUENT_VB_MAX_VERTS() \ + (I830_DMA_BUF_SZ-8) / (imesa->vertex_size * 4) + +#define EMIT_VERTS( ctx, j, nr ) \ + i830_emit_contiguous_verts(ctx, j, (j)+(nr)) + +#define TAG(x) i830_##x +#include "tnl_dd/t_dd_dmatmp.h" + + +/**********************************************************************/ +/* Render pipeline stage */ +/**********************************************************************/ + +/* Heuristic for i830, which can only emit a single primitive per dma + * buffer, and has only a small number of dma buffers. + */ +static GLboolean choose_render( struct vertex_buffer *VB, int bufsz ) +{ + int nr_prims = 0; + int nr_rprims = 0; + int nr_rverts = 0; + int rprim = 0; + int i = 0, length, flags = 0; + + + for (i = VB->FirstPrimitive ; !(flags & PRIM_LAST) ; i += length) { + flags = VB->Primitive[i]; + length = VB->PrimitiveLength[i]; + if (!length) + continue; + + if (!hw_prim[flags & PRIM_MODE_MASK]) + return GL_FALSE; + + nr_prims++; + nr_rverts += length * scale_prim[flags & PRIM_MODE_MASK]; + + if (reduced_prim[flags&PRIM_MODE_MASK] != rprim) { + nr_rprims++; + rprim = reduced_prim[flags&PRIM_MODE_MASK]; + } + } + + nr_prims += i / bufsz; + nr_rprims += nr_rverts / bufsz; + + if ((nr_prims > nr_rprims * 2) || + (nr_prims > nr_rprims + 3)) + return GL_FALSE; + + return GL_TRUE; +} + + +static GLboolean i830_run_render( GLcontext *ctx, + struct gl_pipeline_stage *stage ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint i, length, flags = 0; + /* Don't handle clipping or indexed vertices. + */ + if (VB->ClipOrMask || imesa->RenderIndex != 0 || VB->Elts || + !choose_render( VB, GET_SUBSEQUENT_VB_MAX_VERTS() )) { + return GL_TRUE; + } + + imesa->SetupNewInputs = VERT_BIT_CLIP; + + tnl->Driver.Render.Start( ctx ); + + for (i = VB->FirstPrimitive ; !(flags & PRIM_LAST) ; i += length) { + flags = VB->Primitive[i]; + length= VB->PrimitiveLength[i]; + if (length) + i830_render_tab_verts[flags & PRIM_MODE_MASK]( ctx, i, i + length, + flags ); + } + + tnl->Driver.Render.Finish( ctx ); + + return GL_FALSE; /* finished the pipe */ +} + + +static void i830_check_render( GLcontext *ctx, + struct gl_pipeline_stage *stage ) +{ + GLuint inputs = VERT_BIT_CLIP | VERT_BIT_COLOR0; + if (ctx->RenderMode == GL_RENDER) { + if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) + inputs |= VERT_BIT_COLOR1; + + if (ctx->Texture.Unit[0]._ReallyEnabled) + inputs |= VERT_BIT_TEX0; + + if (ctx->Texture.Unit[1]._ReallyEnabled) + inputs |= VERT_BIT_TEX1; + + if (ctx->Fog.Enabled) + inputs |= VERT_BIT_FOG; + } + + stage->inputs = inputs; +} + +static void dtr( struct gl_pipeline_stage *stage ) +{ + (void)stage; +} + + +const struct gl_pipeline_stage _i830_render_stage = +{ + "i830 render", + (_DD_NEW_SEPARATE_SPECULAR | + _NEW_TEXTURE| + _NEW_FOG| + _NEW_RENDERMODE), /* re-check (new inputs) */ + 0, /* re-run (always runs) */ + GL_TRUE, /* active */ + 0, 0, /* inputs (set in check_render), outputs */ + 0, 0, /* changed_inputs, private */ + dtr, /* destructor */ + i830_check_render, /* check - initially set to alloc data */ + i830_run_render /* run */ +}; diff --git a/src/mesa/drivers/dri/i830/i830_screen.c b/src/mesa/drivers/dri/i830/i830_screen.c new file mode 100644 index 0000000000..a1079f6f56 --- /dev/null +++ b/src/mesa/drivers/dri/i830/i830_screen.c @@ -0,0 +1,371 @@ +/************************************************************************** + * + * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * **************************************************************************/ +/* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_screen.c,v 1.3 2002/12/10 01:26:53 dawes Exp $ */ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Adapted for use on the I830M: + * Jeff Hartmann <jhartmann@2d3d.com> + */ + + +#include "glheader.h" +#include "context.h" +#include "matrix.h" +#include "simple_list.h" + +#include "i830_screen.h" +#include "i830_dri.h" + +#include "i830_state.h" +#include "i830_tex.h" +#include "i830_span.h" +#include "i830_tris.h" +#include "i830_ioctl.h" + +#include "i830_dri.h" + + +static int i830_malloc_proxy_buf(drmBufMapPtr buffers) +{ + char *buffer; + drmBufPtr buf; + int i; + + buffer = Xmalloc(I830_DMA_BUF_SZ); + if(buffer == NULL) return -1; + for(i = 0; i < I830_DMA_BUF_NR; i++) { + buf = &(buffers->list[i]); + buf->address = (drmAddress)buffer; + } + + return 0; +} + +static drmBufMapPtr i830_create_empty_buffers(void) +{ + drmBufMapPtr retval; + + retval = (drmBufMapPtr)Xmalloc(sizeof(drmBufMap)); + if(retval == NULL) return NULL; + memset(retval, 0, sizeof(drmBufMap)); + retval->list = (drmBufPtr)Xmalloc(sizeof(drmBuf) * I830_DMA_BUF_NR); + if(retval->list == NULL) { + Xfree(retval); + return NULL; + } + + memset(retval->list, 0, sizeof(drmBuf) * I830_DMA_BUF_NR); + return retval; +} + +static void i830PrintDRIInfo(i830ScreenPrivate *i830Screen, + __DRIscreenPrivate *sPriv, + I830DRIPtr gDRIPriv) +{ + GLuint size = (gDRIPriv->ringSize + + i830Screen->textureSize + + i830Screen->depth.size + + i830Screen->back.size + + sPriv->fbSize + + I830_DMA_BUF_NR * I830_DMA_BUF_SZ + + 32768 /* Context Memory */ + + 16*4096 /* Ring buffer */ + + 64*1024 /* Scratch buffer */ + + 4096 /* Cursor */); + GLuint size_low = (gDRIPriv->ringSize + + i830Screen->textureSize + + sPriv->fbSize + + I830_DMA_BUF_NR * I830_DMA_BUF_SZ + + 32768 /* Context Memory */ + + 16*4096 /* Ring buffer */ + + 64*1024 /* Scratch buffer */); + + fprintf(stderr, "\nFront size : 0x%x\n", sPriv->fbSize); + fprintf(stderr, "Front offset : 0x%x\n", i830Screen->fbOffset); + fprintf(stderr, "Back size : 0x%x\n", i830Screen->back.size); + fprintf(stderr, "Back offset : 0x%x\n", i830Screen->backOffset); + fprintf(stderr, "Depth size : 0x%x\n", i830Screen->depth.size); + fprintf(stderr, "Depth offset : 0x%x\n", i830Screen->depthOffset); + fprintf(stderr, "Texture size : 0x%x\n", i830Screen->textureSize); + fprintf(stderr, "Texture offset : 0x%x\n", i830Screen->textureOffset); + fprintf(stderr, "Ring offset : 0x%x\n", gDRIPriv->ringOffset); + fprintf(stderr, "Ring size : 0x%x\n", gDRIPriv->ringSize); + fprintf(stderr, "Memory : 0x%x\n", gDRIPriv->mem); + fprintf(stderr, "Used Memory : low(0x%x) high(0x%x)\n", size_low, size); +} + +static GLboolean i830InitDriver(__DRIscreenPrivate *sPriv) +{ + i830ScreenPrivate *i830Screen; + I830DRIPtr gDRIPriv = (I830DRIPtr)sPriv->pDevPriv; + + /* Check the DRI externsion version */ + if ( sPriv->driMajor != 4 || sPriv->driMinor < 0 ) { + __driUtilMessage( "i830 DRI driver expected DRI version 4.0.x " + "but got version %d.%d.%d", + sPriv->driMajor, sPriv->driMinor, sPriv->driPatch ); + return GL_FALSE; + } + + /* Check that the DDX driver version is compatible */ + if (sPriv->ddxMajor != 1 || sPriv->ddxMinor < 0) { + __driUtilMessage("i830 DRI driver expected DDX driver version 1.0.x but got version %d.%d.%d", sPriv->ddxMajor, sPriv->ddxMinor, sPriv->ddxPatch); + return GL_FALSE; + } + + /* Check that the DRM driver version is compatible */ + if (sPriv->drmMajor != 1 || sPriv->drmMinor < 3) { + __driUtilMessage("i830 DRI driver expected DRM driver version 1.3.x but got version %d.%d.%d", sPriv->drmMajor, sPriv->drmMinor, sPriv->drmPatch); + return GL_FALSE; + } + + /* Allocate the private area */ + i830Screen = (i830ScreenPrivate *)Xmalloc(sizeof(i830ScreenPrivate)); + if (!i830Screen) { + fprintf(stderr,"\nERROR! Allocating private area failed\n"); + return GL_FALSE; + } + + i830Screen->driScrnPriv = sPriv; + sPriv->private = (void *)i830Screen; + + i830Screen->deviceID = gDRIPriv->deviceID; + i830Screen->width = gDRIPriv->width; + i830Screen->height = gDRIPriv->height; + i830Screen->mem = gDRIPriv->mem; + i830Screen->cpp = gDRIPriv->cpp; + i830Screen->fbStride = gDRIPriv->fbStride; + i830Screen->fbOffset = gDRIPriv->fbOffset; + + switch (gDRIPriv->bitsPerPixel) { + case 15: i830Screen->fbFormat = DV_PF_555; break; + case 16: i830Screen->fbFormat = DV_PF_565; break; + case 32: i830Screen->fbFormat = DV_PF_8888; break; + } + + i830Screen->backOffset = gDRIPriv->backOffset; + i830Screen->depthOffset = gDRIPriv->depthOffset; + i830Screen->backPitch = gDRIPriv->auxPitch; + i830Screen->backPitchBits = gDRIPriv->auxPitchBits; + i830Screen->textureOffset = gDRIPriv->textureOffset; + i830Screen->textureSize = gDRIPriv->textureSize; + i830Screen->logTextureGranularity = gDRIPriv->logTextureGranularity; + + + i830Screen->bufs = i830_create_empty_buffers(); + if(i830Screen->bufs == NULL) { + fprintf(stderr,"\nERROR: Failed to create empty buffers in %s \n", + __FUNCTION__); + Xfree(i830Screen); + return GL_FALSE; + } + + /* Check if you need to create a fake buffer */ + if(i830_check_copy(sPriv->fd) == 1) { + i830_malloc_proxy_buf(i830Screen->bufs); + i830Screen->use_copy_buf = 1; + } else { + i830Screen->use_copy_buf = 0; + } + + i830Screen->back.handle = gDRIPriv->backbuffer; + i830Screen->back.size = gDRIPriv->backbufferSize; + + if (drmMap(sPriv->fd, + i830Screen->back.handle, + i830Screen->back.size, + (drmAddress *)&i830Screen->back.map) != 0) { + fprintf(stderr, "\nERROR: line %d, Function %s, File %s\n", + __LINE__, __FUNCTION__, __FILE__); + Xfree(i830Screen); + sPriv->private = NULL; + return GL_FALSE; + } + + i830Screen->depth.handle = gDRIPriv->depthbuffer; + i830Screen->depth.size = gDRIPriv->depthbufferSize; + + if (drmMap(sPriv->fd, + i830Screen->depth.handle, + i830Screen->depth.size, + (drmAddress *)&i830Screen->depth.map) != 0) { + fprintf(stderr, "\nERROR: line %d, Function %s, File %s\n", + __LINE__, __FUNCTION__, __FILE__); + Xfree(i830Screen); + drmUnmap(i830Screen->back.map, i830Screen->back.size); + sPriv->private = NULL; + return GL_FALSE; + } + + i830Screen->tex.handle = gDRIPriv->textures; + i830Screen->tex.size = gDRIPriv->textureSize; + + if (drmMap(sPriv->fd, + i830Screen->tex.handle, + i830Screen->tex.size, + (drmAddress *)&i830Screen->tex.map) != 0) { + fprintf(stderr, "\nERROR: line %d, Function %s, File %s\n", + __LINE__, __FUNCTION__, __FILE__); + Xfree(i830Screen); + drmUnmap(i830Screen->back.map, i830Screen->back.size); + drmUnmap(i830Screen->depth.map, i830Screen->depth.size); + sPriv->private = NULL; + return GL_FALSE; + } + + i830Screen->sarea_priv_offset = gDRIPriv->sarea_priv_offset; + + if (0) i830PrintDRIInfo(i830Screen, sPriv, gDRIPriv); + + i830Screen->drmMinor = sPriv->drmMinor; + + if (sPriv->drmMinor >= 3) { + int ret; + drmI830GetParam gp; + + gp.param = I830_PARAM_IRQ_ACTIVE; + gp.value = &i830Screen->irq_active; + + ret = drmCommandWriteRead( sPriv->fd, DRM_I830_GETPARAM, + &gp, sizeof(gp)); + if (ret) { + fprintf(stderr, "drmI830GetParam: %d\n", ret); + return GL_FALSE; + } + } + +#if 0 + if (sPriv->drmMinor >= 3) { + int ret; + drmI830SetParam sp; + + sp.param = I830_SETPARAM_PERF_BOXES; + sp.value = (getenv("I830_DO_BOXES") != 0); + + ret = drmCommandWrite( sPriv->fd, DRM_I830_SETPARAM, + &sp, sizeof(sp)); + if (ret) + fprintf(stderr, "Couldn't set perfboxes: %d\n", ret); + } +#endif + + return GL_TRUE; +} + + +static void i830DestroyScreen(__DRIscreenPrivate *sPriv) +{ + i830ScreenPrivate *i830Screen = (i830ScreenPrivate *)sPriv->private; + + /* Need to unmap all the bufs and maps here: + */ + drmUnmap(i830Screen->back.map, i830Screen->back.size); + drmUnmap(i830Screen->depth.map, i830Screen->depth.size); + drmUnmap(i830Screen->tex.map, i830Screen->tex.size); + Xfree(i830Screen); + sPriv->private = NULL; +} + +static GLboolean i830CreateBuffer(__DRIscreenPrivate *driScrnPriv, + __DRIdrawablePrivate *driDrawPriv, + const __GLcontextModes *mesaVis, + GLboolean isPixmap ) +{ + if (isPixmap) { + return GL_FALSE; /* not implemented */ + } else { +#if 0 + GLboolean swStencil = (mesaVis->stencilBits > 0 && + mesaVis->depthBits != 24); +#else + GLboolean swStencil = mesaVis->stencilBits > 0; +#endif + driDrawPriv->driverPrivate = (void *) + _mesa_create_framebuffer(mesaVis, + GL_FALSE, /* software depth buffer? */ + swStencil, + mesaVis->accumRedBits > 0, + GL_FALSE /* s/w alpha planes */); + + return (driDrawPriv->driverPrivate != NULL); + } +} + +static void i830DestroyBuffer(__DRIdrawablePrivate *driDrawPriv) +{ + _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate)); +} + +static GLboolean i830OpenCloseFullScreen (__DRIcontextPrivate *driContextPriv) +{ + return GL_TRUE; +} + +static const struct __DriverAPIRec i830API = { + .InitDriver = i830InitDriver, + .DestroyScreen = i830DestroyScreen, + .CreateContext = i830CreateContext, + .DestroyContext = i830DestroyContext, + .CreateBuffer = i830CreateBuffer, + .DestroyBuffer = i830DestroyBuffer, + .SwapBuffers = i830SwapBuffers, + .MakeCurrent = i830MakeCurrent, + .UnbindContext = i830UnbindContext, + .OpenFullScreen = i830OpenCloseFullScreen, + .CloseFullScreen = i830OpenCloseFullScreen, + .GetSwapInfo = NULL, + .GetMSC = NULL, + .WaitForMSC = NULL, + .WaitForSBC = NULL, + .SwapBuffersMSC = NULL +}; + + +/* + * This is the bootstrap function for the driver. + * The __driCreateScreen name is the symbol that libGL.so fetches. + * Return: pointer to a __DRIscreenPrivate. + */ +#ifndef _SOLO +void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc, + int numConfigs, __GLXvisualConfig *config) +{ + __DRIscreenPrivate *psp; + psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &i830API); + return (void *) psp; +} +#else +void *__driCreateScreen(struct DRIDriverRec *driver, + struct DRIDriverContextRec *driverContext) +{ + __DRIscreenPrivate *psp; + psp = __driUtilCreateScreen(driver, driverContext, &i830API); + return (void *) psp; +} +#endif diff --git a/src/mesa/drivers/dri/i830/i830_screen.h b/src/mesa/drivers/dri/i830/i830_screen.h new file mode 100644 index 0000000000..8153828ffc --- /dev/null +++ b/src/mesa/drivers/dri/i830/i830_screen.h @@ -0,0 +1,107 @@ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Adapted for use on the I830M: + * Jeff Hartmann <jhartmann@2d3d.com> + */ + +#ifndef _I830_INIT_H_ +#define _I830_INIT_H_ + +#include <sys/time.h> +#include "dri_util.h" + + +typedef struct { + drmHandle handle; + drmSize size; + char *map; +} i830Region, *i830RegionPtr; + +typedef struct +{ + + i830Region front; + i830Region back; + i830Region depth; + i830Region tex; + + int deviceID; + int width; + int height; + int mem; + + int cpp; /* for front and back buffers */ + int bitsPerPixel; + + int fbFormat; + int fbOffset; + int fbStride; + + int backOffset; + int depthOffset; + + int backPitch; + int backPitchBits; + + int textureOffset; + int textureSize; + int logTextureGranularity; + + __DRIscreenPrivate *driScrnPriv; + drmBufMapPtr bufs; + int use_copy_buf; + unsigned int sarea_priv_offset; + + int drmMinor; + int irq_active; +}i830ScreenPrivate; + + +extern GLboolean +i830CreateContext( const __GLcontextModes *mesaVis, + __DRIcontextPrivate *driContextPriv, + void *sharedContextPrivate ); + +extern void +i830DestroyContext(__DRIcontextPrivate *driContextPriv); + +extern GLboolean +i830UnbindContext(__DRIcontextPrivate *driContextPriv); + +extern GLboolean +i830MakeCurrent(__DRIcontextPrivate *driContextPriv, + __DRIdrawablePrivate *driDrawPriv, + __DRIdrawablePrivate *driReadPriv); + +extern void +i830SwapBuffers(__DRIdrawablePrivate *driDrawPriv); + +#endif diff --git a/src/mesa/drivers/dri/i830/i830_span.c b/src/mesa/drivers/dri/i830/i830_span.c new file mode 100644 index 0000000000..34830bf58c --- /dev/null +++ b/src/mesa/drivers/dri/i830/i830_span.c @@ -0,0 +1,370 @@ +/************************************************************************** + +Copyright 2001 VA Linux Systems Inc., Fremont, California. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_span.c,v 1.4 2002/12/10 01:26:53 dawes Exp $ */ + +/* + * Author: + * Jeff Hartmann <jhartmann@2d3d.com> + * + * Heavily based on the I810 driver, which was written by: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include "glheader.h" +#include "macros.h" +#include "mtypes.h" +#include "colormac.h" + +#include "i830_screen.h" +#include "i830_dri.h" + +#include "i830_span.h" +#include "i830_ioctl.h" +#include "swrast/swrast.h" + + +#define DBG 0 + +#define LOCAL_VARS \ + i830ContextPtr imesa = I830_CONTEXT(ctx); \ + __DRIdrawablePrivate *dPriv = imesa->driDrawable; \ + i830ScreenPrivate *i830Screen = imesa->i830Screen; \ + GLuint pitch = i830Screen->backPitch * i830Screen->cpp; \ + GLuint height = dPriv->h; \ + char *buf = (char *)(imesa->drawMap + \ + dPriv->x * i830Screen->cpp + \ + dPriv->y * pitch); \ + char *read_buf = (char *)(imesa->readMap + \ + dPriv->x * i830Screen->cpp + \ + dPriv->y * pitch); \ + GLushort p; \ + (void) read_buf; (void) buf; (void) p + +#define LOCAL_DEPTH_VARS \ + i830ContextPtr imesa = I830_CONTEXT(ctx); \ + __DRIdrawablePrivate *dPriv = imesa->driDrawable; \ + i830ScreenPrivate *i830Screen = imesa->i830Screen; \ + GLuint pitch = i830Screen->backPitch * i830Screen->cpp; \ + GLuint height = dPriv->h; \ + char *buf = (char *)(i830Screen->depth.map + \ + dPriv->x * i830Screen->cpp + \ + dPriv->y * pitch) + +#define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS + +#define INIT_MONO_PIXEL(p,color)\ + p = PACK_COLOR_565(color[0],color[1],color[2]) + +#define CLIPPIXEL(_x,_y) (_x >= minx && _x < maxx && \ + _y >= miny && _y < maxy) + +#define CLIPSPAN( _x, _y, _n, _x1, _n1, _i ) \ + if ( _y < miny || _y >= maxy ) { \ + _n1 = 0, _x1 = x; \ + } else { \ + _n1 = _n; \ + _x1 = _x; \ + if ( _x1 < minx ) _i += (minx-_x1), n1 -= (minx-_x1), _x1 = minx; \ + if ( _x1 + _n1 >= maxx ) n1 -= (_x1 + n1 - maxx); \ + } + +#define Y_FLIP(_y) (height - _y - 1) + + +#define HW_LOCK() + +#define HW_CLIPLOOP() \ + do { \ + __DRIdrawablePrivate *dPriv = imesa->driDrawable; \ + int _nc = dPriv->numClipRects; \ + while (_nc--) { \ + int minx = dPriv->pClipRects[_nc].x1 - dPriv->x; \ + int miny = dPriv->pClipRects[_nc].y1 - dPriv->y; \ + int maxx = dPriv->pClipRects[_nc].x2 - dPriv->x; \ + int maxy = dPriv->pClipRects[_nc].y2 - dPriv->y; + + +#define HW_ENDCLIPLOOP() \ + } \ + } while (0) + +#define HW_UNLOCK() + +/* 16 bit, 565 rgb color spanline and pixel functions + */ +#define WRITE_RGBA( _x, _y, r, g, b, a ) \ + *(GLushort *)(buf + _x*2 + _y*pitch) = ( (((int)r & 0xf8) << 8) | \ + (((int)g & 0xfc) << 3) | \ + (((int)b & 0xf8) >> 3)) +#define WRITE_PIXEL( _x, _y, p ) \ + *(GLushort *)(buf + _x*2 + _y*pitch) = p + +#define READ_RGBA( rgba, _x, _y ) \ +do { \ + GLushort p = *(GLushort *)(read_buf + _x*2 + _y*pitch); \ + rgba[0] = (((p >> 11) & 0x1f) * 255) / 31; \ + rgba[1] = (((p >> 5) & 0x3f) * 255) / 63; \ + rgba[2] = (((p >> 0) & 0x1f) * 255) / 31; \ + rgba[3] = 255; \ +} while(0) + +#define TAG(x) i830##x##_565 +#include "spantmp.h" + + + + +/* 15 bit, 555 rgb color spanline and pixel functions + */ +#define WRITE_RGBA( _x, _y, r, g, b, a ) \ + *(GLushort *)(buf + _x*2 + _y*pitch) = (((r & 0xf8) << 7) | \ + ((g & 0xf8) << 3) | \ + ((b & 0xf8) >> 3)) + +#define WRITE_PIXEL( _x, _y, p ) \ + *(GLushort *)(buf + _x*2 + _y*pitch) = p + +#define READ_RGBA( rgba, _x, _y ) \ +do { \ + GLushort p = *(GLushort *)(read_buf + _x*2 + _y*pitch); \ + rgba[0] = (p >> 7) & 0xf8; \ + rgba[1] = (p >> 3) & 0xf8; \ + rgba[2] = (p << 3) & 0xf8; \ + rgba[3] = 255; \ +} while(0) + +#define TAG(x) i830##x##_555 +#include "spantmp.h" + +/* 16 bit depthbuffer functions. + */ +#define WRITE_DEPTH( _x, _y, d ) \ + *(GLushort *)(buf + _x*2 + _y*pitch) = d; + +#define READ_DEPTH( d, _x, _y ) \ + d = *(GLushort *)(buf + _x*2 + _y*pitch); + + +#define TAG(x) i830##x##_16 +#include "depthtmp.h" + + +#undef LOCAL_VARS +#define LOCAL_VARS \ + i830ContextPtr imesa = I830_CONTEXT(ctx); \ + __DRIdrawablePrivate *dPriv = imesa->driDrawable; \ + i830ScreenPrivate *i830Screen = imesa->i830Screen; \ + GLuint pitch = i830Screen->backPitch * i830Screen->cpp; \ + GLuint height = dPriv->h; \ + char *buf = (char *)(imesa->drawMap + \ + dPriv->x * i830Screen->cpp + \ + dPriv->y * pitch); \ + char *read_buf = (char *)(imesa->readMap + \ + dPriv->x * i830Screen->cpp + \ + dPriv->y * pitch); \ + GLuint p = I830_CONTEXT( ctx )->MonoColor; \ + (void) read_buf; (void) buf; (void) p + +#undef INIT_MONO_PIXEL +#define INIT_MONO_PIXEL(p,color)\ + p = PACK_COLOR_888(color[0],color[1],color[2]) + +/* 32 bit, 8888 argb color spanline and pixel functions + */ +#define WRITE_RGBA(_x, _y, r, g, b, a) \ + *(GLuint *)(buf + _x*4 + _y*pitch) = ((r << 16) | \ + (g << 8) | \ + (b << 0) | \ + (a << 24) ) + +#define WRITE_PIXEL(_x, _y, p) \ + *(GLuint *)(buf + _x*4 + _y*pitch) = p + + +#define READ_RGBA(rgba, _x, _y) \ + do { \ + GLuint p = *(GLuint *)(read_buf + _x*4 + _y*pitch); \ + rgba[0] = (p >> 16) & 0xff; \ + rgba[1] = (p >> 8) & 0xff; \ + rgba[2] = (p >> 0) & 0xff; \ + rgba[3] = (p >> 24) & 0xff; \ + } while (0) + +#define TAG(x) i830##x##_8888 +#include "spantmp.h" + +/* 24 bit depthbuffer functions. + */ +#define WRITE_DEPTH( _x, _y, d ) \ + *(GLuint *)(buf + _x*4 + _y*pitch) = 0xffffff & d; + +#define READ_DEPTH( d, _x, _y ) \ + d = *(GLuint *)(buf + _x*4 + _y*pitch) & 0xffffff; + +#define TAG(x) i830##x##_24 +#include "depthtmp.h" + +/* 24/8 bit interleaved depth/stencil functions + */ +#define WRITE_DEPTH( _x, _y, d ) { \ + GLuint tmp = *(GLuint *)(buf + _x*4 + _y*pitch); \ + tmp &= 0xff000000; \ + tmp |= (d) & 0xffffff; \ + *(GLuint *)(buf + _x*4 + _y*pitch) = tmp; \ +} + +#define READ_DEPTH( d, _x, _y ) \ + d = *(GLuint *)(buf + _x*4 + _y*pitch) & 0xffffff; + + +#define TAG(x) i830##x##_24_8 +#include "depthtmp.h" + +#define WRITE_STENCIL( _x, _y, d ) { \ + GLuint tmp = *(GLuint *)(buf + _x*4 + _y*pitch); \ + tmp &= 0xffffff; \ + tmp |= (d<<24); \ + *(GLuint *)(buf + _x*4 + _y*pitch) = tmp; \ +} + +#define READ_STENCIL( d, _x, _y ) \ + d = *(GLuint *)(buf + _x*4 + _y*pitch) >> 24; + +#define TAG(x) i830##x##_24_8 +#include "stenciltmp.h" + +/* + * This function is called to specify which buffer to read and write + * for software rasterization (swrast) fallbacks. This doesn't necessarily + * correspond to glDrawBuffer() or glReadBuffer() calls. + */ +static void i830SetBuffer(GLcontext *ctx, GLframebuffer *colorBuffer, + GLuint bufferBit) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + if (bufferBit == FRONT_LEFT_BIT) { + imesa->drawMap = (char *)imesa->driScreen->pFB; + imesa->readMap = (char *)imesa->driScreen->pFB; + } else if (bufferBit == BACK_LEFT_BIT) { + imesa->drawMap = imesa->i830Screen->back.map; + imesa->readMap = imesa->i830Screen->back.map; + } else { + ASSERT(0); + } +} + + + +/* Move locking out to get reasonable span performance. + */ +void i830SpanRenderStart( GLcontext *ctx ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + I830_FIREVERTICES(imesa); + LOCK_HARDWARE(imesa); + i830RegetLockQuiescent( imesa ); +} + +void i830SpanRenderFinish( GLcontext *ctx ) +{ + i830ContextPtr imesa = I830_CONTEXT( ctx ); + _swrast_flush( ctx ); + UNLOCK_HARDWARE( imesa ); +} + +void i830DDInitSpanFuncs( GLcontext *ctx ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + i830ScreenPrivate *i830Screen = imesa->i830Screen; + + struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx); + + swdd->SetBuffer = i830SetBuffer; + + switch (i830Screen->fbFormat) { + case DV_PF_555: + swdd->WriteRGBASpan = i830WriteRGBASpan_555; + swdd->WriteRGBSpan = i830WriteRGBSpan_555; + swdd->WriteMonoRGBASpan = i830WriteMonoRGBASpan_555; + swdd->WriteRGBAPixels = i830WriteRGBAPixels_555; + swdd->WriteMonoRGBAPixels = i830WriteMonoRGBAPixels_555; + swdd->ReadRGBASpan = i830ReadRGBASpan_555; + swdd->ReadRGBAPixels = i830ReadRGBAPixels_555; + + swdd->ReadDepthSpan = i830ReadDepthSpan_16; + swdd->WriteDepthSpan = i830WriteDepthSpan_16; + swdd->ReadDepthPixels = i830ReadDepthPixels_16; + swdd->WriteDepthPixels = i830WriteDepthPixels_16; + break; + + case DV_PF_565: + swdd->WriteRGBASpan = i830WriteRGBASpan_565; + swdd->WriteRGBSpan = i830WriteRGBSpan_565; + swdd->WriteMonoRGBASpan = i830WriteMonoRGBASpan_565; + swdd->WriteRGBAPixels = i830WriteRGBAPixels_565; + swdd->WriteMonoRGBAPixels = i830WriteMonoRGBAPixels_565; + swdd->ReadRGBASpan = i830ReadRGBASpan_565; + swdd->ReadRGBAPixels = i830ReadRGBAPixels_565; + + swdd->ReadDepthSpan = i830ReadDepthSpan_16; + swdd->WriteDepthSpan = i830WriteDepthSpan_16; + swdd->ReadDepthPixels = i830ReadDepthPixels_16; + swdd->WriteDepthPixels = i830WriteDepthPixels_16; + break; + + case DV_PF_8888: + swdd->WriteRGBASpan = i830WriteRGBASpan_8888; + swdd->WriteRGBSpan = i830WriteRGBSpan_8888; + swdd->WriteMonoRGBASpan = i830WriteMonoRGBASpan_8888; + swdd->WriteRGBAPixels = i830WriteRGBAPixels_8888; + swdd->WriteMonoRGBAPixels = i830WriteMonoRGBAPixels_8888; + swdd->ReadRGBASpan = i830ReadRGBASpan_8888; + swdd->ReadRGBAPixels = i830ReadRGBAPixels_8888; + + if(imesa->hw_stencil) { + swdd->ReadDepthSpan = i830ReadDepthSpan_24_8; + swdd->WriteDepthSpan = i830WriteDepthSpan_24_8; + swdd->ReadDepthPixels = i830ReadDepthPixels_24_8; + swdd->WriteDepthPixels = i830WriteDepthPixels_24_8; + + swdd->WriteStencilSpan = i830WriteStencilSpan_24_8; + swdd->ReadStencilSpan = i830ReadStencilSpan_24_8; + swdd->WriteStencilPixels = i830WriteStencilPixels_24_8; + swdd->ReadStencilPixels = i830ReadStencilPixels_24_8; + } else { + swdd->ReadDepthSpan = i830ReadDepthSpan_24; + swdd->WriteDepthSpan = i830WriteDepthSpan_24; + swdd->ReadDepthPixels = i830ReadDepthPixels_24; + swdd->WriteDepthPixels = i830WriteDepthPixels_24; + } + break; + } + + swdd->SpanRenderStart = i830SpanRenderStart; + swdd->SpanRenderFinish = i830SpanRenderFinish; +} diff --git a/src/mesa/drivers/dri/i830/i830_span.h b/src/mesa/drivers/dri/i830/i830_span.h new file mode 100644 index 0000000000..0135468ffa --- /dev/null +++ b/src/mesa/drivers/dri/i830/i830_span.h @@ -0,0 +1,46 @@ +/************************************************************************** + +Copyright 2001 VA Linux Systems Inc., Fremont, California. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_span.h,v 1.2 2002/09/11 00:29:26 dawes Exp $ */ + +/* + * Author: + * Jeff Hartmann <jhartmann@2d3d.com> + * + * Heavily based on the I810 driver, which was written by: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef _I830_SPAN_H +#define _I830_SPAN_H + +extern void i830DDInitSpanFuncs( GLcontext *ctx ); + +extern void i830SpanRenderFinish( GLcontext *ctx ); +extern void i830SpanRenderStart( GLcontext *ctx ); + +#endif diff --git a/src/mesa/drivers/dri/i830/i830_state.c b/src/mesa/drivers/dri/i830/i830_state.c new file mode 100644 index 0000000000..6eb46fac46 --- /dev/null +++ b/src/mesa/drivers/dri/i830/i830_state.c @@ -0,0 +1,1796 @@ +/************************************************************************** + +Copyright 2001 2d3d Inc., Delray Beach, FL + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_state.c,v 1.6 2003/01/28 22:47:06 dawes Exp $ */ + +/* + * Author: + * Jeff Hartmann <jhartmann@2d3d.com> + * + * Heavily based on the I810 driver, which was written by: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include "glheader.h" +#include "context.h" +#include "macros.h" +#include "enums.h" +#include "dd.h" + +#include "texmem.h" + +#include "i830_screen.h" +#include "i830_dri.h" + +#include "i830_context.h" +#include "i830_state.h" +#include "i830_tex.h" +#include "i830_vb.h" +#include "i830_tris.h" +#include "i830_ioctl.h" + +#include "swrast/swrast.h" +#include "array_cache/acache.h" +#include "tnl/tnl.h" +#include "swrast_setup/swrast_setup.h" + +#include "tnl/t_pipeline.h" + +static __inline__ GLuint i830PackColor(GLuint format, + GLubyte r, GLubyte g, + GLubyte b, GLubyte a) +{ + + if (I830_DEBUG&DEBUG_DRI) + fprintf(stderr, "%s\n", __FUNCTION__); + + switch (format) { + case DV_PF_555: + return I830PACKCOLOR1555(r,g,b,a); + case DV_PF_565: + return I830PACKCOLOR565(r,g,b); + case DV_PF_8888: + return I830PACKCOLOR8888(r,g,b,a); + default: + fprintf(stderr, "unknown format %d\n", (int)format); + return 0; + } +} + +static void i830StencilFunc(GLcontext *ctx, GLenum func, GLint ref, + GLuint mask) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + int test = 0; + + mask = mask & 0xff; + + if (I830_DEBUG&DEBUG_DRI) + fprintf(stderr, "%s : func: %s, ref : 0x%x, mask: 0x%x\n", __FUNCTION__, + _mesa_lookup_enum_by_nr(func), ref, mask); + + switch(func) { + case GL_NEVER: + test = COMPAREFUNC_NEVER; + break; + case GL_LESS: + test = COMPAREFUNC_LESS; + break; + case GL_LEQUAL: + test = COMPAREFUNC_LEQUAL; + break; + case GL_GREATER: + test = COMPAREFUNC_GREATER; + break; + case GL_GEQUAL: + test = COMPAREFUNC_GEQUAL; + break; + case GL_NOTEQUAL: + test = COMPAREFUNC_NOTEQUAL; + break; + case GL_EQUAL: + test = COMPAREFUNC_EQUAL; + break; + case GL_ALWAYS: + test = COMPAREFUNC_ALWAYS; + break; + default: + return; + } + + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_TEST_MASK; + imesa->Setup[I830_CTXREG_STATE4] |= (ENABLE_STENCIL_TEST_MASK | + STENCIL_TEST_MASK(mask)); + imesa->Setup[I830_CTXREG_STENCILTST] &= ~(STENCIL_REF_VALUE_MASK | + ENABLE_STENCIL_TEST_FUNC_MASK); + imesa->Setup[I830_CTXREG_STENCILTST] |= (ENABLE_STENCIL_REF_VALUE | + ENABLE_STENCIL_TEST_FUNC | + STENCIL_REF_VALUE(ref) | + STENCIL_TEST_FUNC(test)); +} + +static void i830StencilMask(GLcontext *ctx, GLuint mask) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + + if (I830_DEBUG&DEBUG_DRI) + fprintf(stderr, "%s : mask 0x%x\n", __FUNCTION__, mask); + + mask = mask & 0xff; + + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK; + imesa->Setup[I830_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK | + STENCIL_WRITE_MASK(mask)); +} + +static void i830StencilOp(GLcontext *ctx, GLenum fail, GLenum zfail, + GLenum zpass) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + int fop, dfop, dpop; + + if (I830_DEBUG&DEBUG_DRI) + fprintf(stderr, "%s: fail : %s, zfail: %s, zpass : %s\n", __FUNCTION__, + _mesa_lookup_enum_by_nr(fail), + _mesa_lookup_enum_by_nr(zfail), + _mesa_lookup_enum_by_nr(zpass)); + + fop = 0; dfop = 0; dpop = 0; + + switch(fail) { + case GL_KEEP: + fop = STENCILOP_KEEP; + break; + case GL_ZERO: + fop = STENCILOP_ZERO; + break; + case GL_REPLACE: + fop = STENCILOP_REPLACE; + break; + case GL_INCR: + fop = STENCILOP_INCRSAT; + break; + case GL_DECR: + fop = STENCILOP_DECRSAT; + break; + case GL_INCR_WRAP: + fop = STENCILOP_INCR; + break; + case GL_DECR_WRAP: + fop = STENCILOP_DECR; + break; + case GL_INVERT: + fop = STENCILOP_INVERT; + break; + default: + break; + } + switch(zfail) { + case GL_KEEP: + dfop = STENCILOP_KEEP; + break; + case GL_ZERO: + dfop = STENCILOP_ZERO; + break; + case GL_REPLACE: + dfop = STENCILOP_REPLACE; + break; + case GL_INCR: + dfop = STENCILOP_INCRSAT; + break; + case GL_DECR: + dfop = STENCILOP_DECRSAT; + break; + case GL_INCR_WRAP: + dfop = STENCILOP_INCR; + break; + case GL_DECR_WRAP: + dfop = STENCILOP_DECR; + break; + case GL_INVERT: + dfop = STENCILOP_INVERT; + break; + default: + break; + } + switch(zpass) { + case GL_KEEP: + dpop = STENCILOP_KEEP; + break; + case GL_ZERO: + dpop = STENCILOP_ZERO; + break; + case GL_REPLACE: + dpop = STENCILOP_REPLACE; + break; + case GL_INCR: + dpop = STENCILOP_INCRSAT; + break; + case GL_DECR: + dpop = STENCILOP_DECRSAT; + break; + case GL_INCR_WRAP: + dpop = STENCILOP_INCR; + break; + case GL_DECR_WRAP: + dpop = STENCILOP_DECR; + break; + case GL_INVERT: + dpop = STENCILOP_INVERT; + break; + default: + break; + } + + + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_STENCILTST] &= ~(STENCIL_OPS_MASK); + imesa->Setup[I830_CTXREG_STENCILTST] |= (ENABLE_STENCIL_PARMS | + STENCIL_FAIL_OP(fop) | + STENCIL_PASS_DEPTH_FAIL_OP(dfop) | + STENCIL_PASS_DEPTH_PASS_OP(dpop)); +} + +static void i830AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + int test = 0; + GLuint refByte = (GLint) (ref * 255.0); + + switch(func) { + case GL_NEVER: + test = COMPAREFUNC_NEVER; + break; + case GL_LESS: + test = COMPAREFUNC_LESS; + break; + case GL_LEQUAL: + test = COMPAREFUNC_LEQUAL; + break; + case GL_GREATER: + test = COMPAREFUNC_GREATER; + break; + case GL_GEQUAL: + test = COMPAREFUNC_GEQUAL; + break; + case GL_NOTEQUAL: + test = COMPAREFUNC_NOTEQUAL; + break; + case GL_EQUAL: + test = COMPAREFUNC_EQUAL; + break; + case GL_ALWAYS: + test = COMPAREFUNC_ALWAYS; + break; + default: + return; + } + + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_STATE2] &= ~ALPHA_TEST_REF_MASK; + imesa->Setup[I830_CTXREG_STATE2] |= (ENABLE_ALPHA_TEST_FUNC | + ENABLE_ALPHA_REF_VALUE | + ALPHA_TEST_FUNC(test) | + ALPHA_REF_VALUE(refByte)); +} + +/* This function makes sure that the proper enables are + * set for LogicOp, Independant Alpha Blend, and Blending. + * It needs to be called from numerous places where we + * could change the LogicOp or Independant Alpha Blend without subsequent + * calls to glEnable. + */ +static void i830EvalLogicOpBlendState(GLcontext *ctx) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + + if (ctx->Color.ColorLogicOpEnabled) { + imesa->Setup[I830_CTXREG_ENABLES_1] &= ~(ENABLE_COLOR_BLEND | + ENABLE_LOGIC_OP_MASK); + imesa->Setup[I830_CTXREG_ENABLES_1] |= (DISABLE_COLOR_BLEND | + ENABLE_LOGIC_OP); + imesa->Setup[I830_CTXREG_IALPHAB] &= ~ENABLE_INDPT_ALPHA_BLEND; + imesa->Setup[I830_CTXREG_IALPHAB] |= DISABLE_INDPT_ALPHA_BLEND; + } else if (ctx->Color.BlendEnabled) { + imesa->Setup[I830_CTXREG_ENABLES_1] &= ~(ENABLE_COLOR_BLEND | + ENABLE_LOGIC_OP_MASK); + imesa->Setup[I830_CTXREG_ENABLES_1] |= (ENABLE_COLOR_BLEND | + DISABLE_LOGIC_OP); + imesa->Setup[I830_CTXREG_IALPHAB] &= ~ENABLE_INDPT_ALPHA_BLEND; + if (imesa->Setup[I830_CTXREG_IALPHAB] & SRC_DST_ABLEND_MASK) { + imesa->Setup[I830_CTXREG_IALPHAB] |= ENABLE_INDPT_ALPHA_BLEND; + } else { + imesa->Setup[I830_CTXREG_IALPHAB] |= DISABLE_INDPT_ALPHA_BLEND; + } + } else { + imesa->Setup[I830_CTXREG_ENABLES_1] &= ~(ENABLE_COLOR_BLEND | + ENABLE_LOGIC_OP_MASK); + imesa->Setup[I830_CTXREG_ENABLES_1] |= (DISABLE_COLOR_BLEND | + DISABLE_LOGIC_OP); + imesa->Setup[I830_CTXREG_IALPHAB] &= ~ENABLE_INDPT_ALPHA_BLEND; + imesa->Setup[I830_CTXREG_IALPHAB] |= DISABLE_INDPT_ALPHA_BLEND; + } +} + +static void i830BlendColor(GLcontext *ctx, const GLfloat color[4]) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + GLubyte r, g, b, a; + + if (I830_DEBUG&DEBUG_DRI) + fprintf(stderr, "%s\n", __FUNCTION__); + + FLOAT_COLOR_TO_UBYTE_COLOR(r, color[RCOMP]); + FLOAT_COLOR_TO_UBYTE_COLOR(g, color[GCOMP]); + FLOAT_COLOR_TO_UBYTE_COLOR(b, color[BCOMP]); + FLOAT_COLOR_TO_UBYTE_COLOR(a, color[ACOMP]); + + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_BLENDCOLR] = ((a << 24) | + (r << 16) | + (g << 8) | + b); +} + +static void i830BlendEquation(GLcontext *ctx, GLenum mode) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + int func = ENABLE_ALPHA_BLENDFUNC; + + if (I830_DEBUG&DEBUG_DRI) + fprintf(stderr, "%s %s\n", __FUNCTION__, + _mesa_lookup_enum_by_nr(mode)); + + /* This will catch a logicop blend equation */ + i830EvalLogicOpBlendState(ctx); + + switch(mode) { + case GL_FUNC_ADD_EXT: + func |= BLENDFUNC_ADD; + break; + case GL_MIN_EXT: + func |= BLENDFUNC_MIN; + break; + case GL_MAX_EXT: + func |= BLENDFUNC_MAX; + break; + case GL_FUNC_SUBTRACT_EXT: + func |= BLENDFUNC_SUB; + break; + case GL_FUNC_REVERSE_SUBTRACT_EXT: + func |= BLENDFUNC_RVRSE_SUB; + break; + default: return; + } + + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_STATE1] &= ~BLENDFUNC_MASK; + imesa->Setup[I830_CTXREG_STATE1] |= func; + if (0) fprintf(stderr, "%s : STATE1 : 0x%08x\n", + __FUNCTION__, + imesa->Setup[I830_CTXREG_STATE1]); +} + +static void i830BlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + int func = (ENABLE_SRC_BLND_FACTOR|ENABLE_DST_BLND_FACTOR); + + if (I830_DEBUG&DEBUG_DRI) + fprintf(stderr, "%s %s %s\n", __FUNCTION__, + _mesa_lookup_enum_by_nr(sfactor), + _mesa_lookup_enum_by_nr(dfactor)); + + switch(sfactor) { + case GL_ZERO: + func |= SRC_BLND_FACT(BLENDFACT_ZERO); + break; + case GL_SRC_ALPHA: + func |= SRC_BLND_FACT(BLENDFACT_SRC_ALPHA); + break; + case GL_ONE: + func |= SRC_BLND_FACT(BLENDFACT_ONE); + break; + case GL_DST_COLOR: + func |= SRC_BLND_FACT(BLENDFACT_DST_COLR); + break; + case GL_ONE_MINUS_DST_COLOR: + func |= SRC_BLND_FACT(BLENDFACT_INV_DST_COLR); + break; + case GL_ONE_MINUS_SRC_ALPHA: + func |= SRC_BLND_FACT(BLENDFACT_INV_SRC_ALPHA); + break; + case GL_DST_ALPHA: + func |= SRC_BLND_FACT(BLENDFACT_DST_ALPHA); + break; + case GL_ONE_MINUS_DST_ALPHA: + func |= SRC_BLND_FACT(BLENDFACT_INV_DST_ALPHA); + break; + case GL_SRC_ALPHA_SATURATE: + func |= SRC_BLND_FACT(BLENDFACT_SRC_ALPHA_SATURATE); + break; + case GL_CONSTANT_COLOR_EXT: + func |= SRC_BLND_FACT(BLENDFACT_CONST_COLOR); + break; + case GL_ONE_MINUS_CONSTANT_COLOR_EXT: + func |= SRC_BLND_FACT(BLENDFACT_INV_CONST_COLOR); + break; + case GL_CONSTANT_ALPHA_EXT: + func |= SRC_BLND_FACT(BLENDFACT_CONST_ALPHA); + break; + case GL_ONE_MINUS_CONSTANT_ALPHA_EXT: + func |= SRC_BLND_FACT(BLENDFACT_INV_CONST_ALPHA); + break; + default: + return; + } + + switch(dfactor) { + case GL_SRC_ALPHA: + func |= DST_BLND_FACT(BLENDFACT_SRC_ALPHA); + break; + case GL_ONE_MINUS_SRC_ALPHA: + func |= DST_BLND_FACT(BLENDFACT_INV_SRC_ALPHA); + break; + case GL_ZERO: + func |= DST_BLND_FACT(BLENDFACT_ZERO); + break; + case GL_ONE: + func |= DST_BLND_FACT(BLENDFACT_ONE); + break; + case GL_SRC_COLOR: + func |= DST_BLND_FACT(BLENDFACT_SRC_COLR); + break; + case GL_ONE_MINUS_SRC_COLOR: + func |= DST_BLND_FACT(BLENDFACT_INV_SRC_COLR); + break; + case GL_DST_ALPHA: + func |= DST_BLND_FACT(BLENDFACT_DST_ALPHA); + break; + case GL_ONE_MINUS_DST_ALPHA: + func |= DST_BLND_FACT(BLENDFACT_INV_DST_ALPHA); + break; + case GL_CONSTANT_COLOR_EXT: + func |= DST_BLND_FACT(BLENDFACT_CONST_COLOR); + break; + case GL_ONE_MINUS_CONSTANT_COLOR_EXT: + func |= DST_BLND_FACT(BLENDFACT_INV_CONST_COLOR); + break; + case GL_CONSTANT_ALPHA_EXT: + func |= DST_BLND_FACT(BLENDFACT_CONST_ALPHA); + break; + case GL_ONE_MINUS_CONSTANT_ALPHA_EXT: + func |= DST_BLND_FACT(BLENDFACT_INV_CONST_ALPHA); + break; + default: + return; + } + + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_IALPHAB] &= ~SRC_DST_ABLEND_MASK; + imesa->Setup[I830_CTXREG_STATE1] &= ~SRC_DST_BLND_MASK; + imesa->Setup[I830_CTXREG_STATE1] |= func; + /* Insure Independant Alpha Blend is really disabled. */ + i830EvalLogicOpBlendState(ctx); +} + +static void i830BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, + GLenum dfactorRGB, GLenum sfactorA, + GLenum dfactorA ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + int funcA = (ENABLE_SRC_ABLEND_FACTOR|ENABLE_DST_ABLEND_FACTOR); + int funcRGB = (ENABLE_SRC_BLND_FACTOR|ENABLE_DST_BLND_FACTOR); + + if (I830_DEBUG&DEBUG_DRI) + fprintf(stderr, "%s\n", __FUNCTION__); + + switch(sfactorA) { + case GL_ZERO: + funcA |= SRC_ABLEND_FACT(BLENDFACT_ZERO); + break; + case GL_SRC_ALPHA: + funcA |= SRC_ABLEND_FACT(BLENDFACT_SRC_ALPHA); + break; + case GL_ONE: + funcA |= SRC_ABLEND_FACT(BLENDFACT_ONE); + break; + case GL_DST_COLOR: + funcA |= SRC_ABLEND_FACT(BLENDFACT_DST_COLR); + break; + case GL_ONE_MINUS_DST_COLOR: + funcA |= SRC_ABLEND_FACT(BLENDFACT_INV_DST_COLR); + break; + case GL_ONE_MINUS_SRC_ALPHA: + funcA |= SRC_ABLEND_FACT(BLENDFACT_INV_SRC_ALPHA); + break; + case GL_DST_ALPHA: + funcA |= SRC_ABLEND_FACT(BLENDFACT_DST_ALPHA); + break; + case GL_ONE_MINUS_DST_ALPHA: + funcA |= SRC_ABLEND_FACT(BLENDFACT_INV_DST_ALPHA); + break; + case GL_SRC_ALPHA_SATURATE: + funcA |= SRC_ABLEND_FACT(BLENDFACT_SRC_ALPHA_SATURATE); + break; + case GL_CONSTANT_COLOR_EXT: + funcA |= SRC_ABLEND_FACT(BLENDFACT_CONST_COLOR); + break; + case GL_ONE_MINUS_CONSTANT_COLOR_EXT: + funcA |= SRC_ABLEND_FACT(BLENDFACT_INV_CONST_COLOR); + break; + case GL_CONSTANT_ALPHA_EXT: + funcA |= SRC_ABLEND_FACT(BLENDFACT_CONST_ALPHA); + break; + case GL_ONE_MINUS_CONSTANT_ALPHA_EXT: + funcA |= SRC_ABLEND_FACT(BLENDFACT_INV_CONST_ALPHA); + break; + default: return; + } + + switch(dfactorA) { + case GL_SRC_ALPHA: + funcA |= DST_ABLEND_FACT(BLENDFACT_SRC_ALPHA); + break; + case GL_ONE_MINUS_SRC_ALPHA: + funcA |= DST_ABLEND_FACT(BLENDFACT_INV_SRC_ALPHA); + break; + case GL_ZERO: + funcA |= DST_ABLEND_FACT(BLENDFACT_ZERO); + break; + case GL_ONE: + funcA |= DST_ABLEND_FACT(BLENDFACT_ONE); + break; + case GL_SRC_COLOR: + funcA |= DST_ABLEND_FACT(BLENDFACT_SRC_COLR); + break; + case GL_ONE_MINUS_SRC_COLOR: + funcA |= DST_ABLEND_FACT(BLENDFACT_INV_SRC_COLR); + break; + case GL_DST_ALPHA: + funcA |= DST_ABLEND_FACT(BLENDFACT_DST_ALPHA); + break; + case GL_ONE_MINUS_DST_ALPHA: + funcA |= DST_ABLEND_FACT(BLENDFACT_INV_DST_ALPHA); + break; + case GL_CONSTANT_COLOR_EXT: + funcA |= DST_ABLEND_FACT(BLENDFACT_CONST_COLOR); + break; + case GL_ONE_MINUS_CONSTANT_COLOR_EXT: + funcA |= DST_ABLEND_FACT(BLENDFACT_INV_CONST_COLOR); + break; + case GL_CONSTANT_ALPHA_EXT: + funcA |= DST_ABLEND_FACT(BLENDFACT_CONST_ALPHA); + break; + case GL_ONE_MINUS_CONSTANT_ALPHA_EXT: + funcA |= DST_ABLEND_FACT(BLENDFACT_INV_CONST_ALPHA); + break; + default: return; + } + + switch(sfactorRGB) { + case GL_ZERO: + funcRGB |= SRC_BLND_FACT(BLENDFACT_ZERO); + break; + case GL_SRC_ALPHA: + funcRGB |= SRC_BLND_FACT(BLENDFACT_SRC_ALPHA); + break; + case GL_ONE: + funcRGB |= SRC_BLND_FACT(BLENDFACT_ONE); + break; + case GL_DST_COLOR: + funcRGB |= SRC_BLND_FACT(BLENDFACT_DST_COLR); + break; + case GL_ONE_MINUS_DST_COLOR: + funcRGB |= SRC_BLND_FACT(BLENDFACT_INV_DST_COLR); + break; + case GL_ONE_MINUS_SRC_ALPHA: + funcRGB |= SRC_BLND_FACT(BLENDFACT_INV_SRC_ALPHA); + break; + case GL_DST_ALPHA: + funcRGB |= SRC_BLND_FACT(BLENDFACT_DST_ALPHA); + break; + case GL_ONE_MINUS_DST_ALPHA: + funcRGB |= SRC_BLND_FACT(BLENDFACT_INV_DST_ALPHA); + break; + case GL_SRC_ALPHA_SATURATE: + funcRGB |= SRC_BLND_FACT(BLENDFACT_SRC_ALPHA_SATURATE); + break; + case GL_CONSTANT_COLOR_EXT: + funcRGB |= SRC_BLND_FACT(BLENDFACT_CONST_COLOR); + break; + case GL_ONE_MINUS_CONSTANT_COLOR_EXT: + funcRGB |= SRC_BLND_FACT(BLENDFACT_INV_CONST_COLOR); + break; + case GL_CONSTANT_ALPHA_EXT: + funcRGB |= SRC_BLND_FACT(BLENDFACT_CONST_ALPHA); + break; + case GL_ONE_MINUS_CONSTANT_ALPHA_EXT: + funcRGB |= SRC_BLND_FACT(BLENDFACT_INV_CONST_ALPHA); + break; + default: return; + } + + switch(dfactorRGB) { + case GL_SRC_ALPHA: + funcRGB |= DST_BLND_FACT(BLENDFACT_SRC_ALPHA); + break; + case GL_ONE_MINUS_SRC_ALPHA: + funcRGB |= DST_BLND_FACT(BLENDFACT_INV_SRC_ALPHA); + break; + case GL_ZERO: + funcRGB |= DST_BLND_FACT(BLENDFACT_ZERO); + break; + case GL_ONE: + funcRGB |= DST_BLND_FACT(BLENDFACT_ONE); + break; + case GL_SRC_COLOR: + funcRGB |= DST_BLND_FACT(BLENDFACT_SRC_COLR); + break; + case GL_ONE_MINUS_SRC_COLOR: + funcRGB |= DST_BLND_FACT(BLENDFACT_INV_SRC_COLR); + break; + case GL_DST_ALPHA: + funcRGB |= DST_BLND_FACT(BLENDFACT_DST_ALPHA); + break; + case GL_ONE_MINUS_DST_ALPHA: + funcRGB |= DST_BLND_FACT(BLENDFACT_INV_DST_ALPHA); + break; + case GL_CONSTANT_COLOR_EXT: + funcRGB |= DST_BLND_FACT(BLENDFACT_CONST_COLOR); + break; + case GL_ONE_MINUS_CONSTANT_COLOR_EXT: + funcRGB |= DST_BLND_FACT(BLENDFACT_INV_CONST_COLOR); + break; + case GL_CONSTANT_ALPHA_EXT: + funcRGB |= DST_BLND_FACT(BLENDFACT_CONST_ALPHA); + break; + case GL_ONE_MINUS_CONSTANT_ALPHA_EXT: + funcRGB |= DST_BLND_FACT(BLENDFACT_INV_CONST_ALPHA); + break; + default: return; + } + + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_IALPHAB] &= ~SRC_DST_ABLEND_MASK; + imesa->Setup[I830_CTXREG_IALPHAB] |= funcA; + imesa->Setup[I830_CTXREG_STATE1] &= ~SRC_DST_BLND_MASK; + imesa->Setup[I830_CTXREG_STATE1] |= funcRGB; + + /* Insure Independant Alpha Blend is really enabled if + * Blending is already enabled. + */ + i830EvalLogicOpBlendState(ctx); +} + +static void i830DepthFunc(GLcontext *ctx, GLenum func) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + int test = 0; + + if (I830_DEBUG&DEBUG_DRI) + fprintf(stderr, "%s\n", __FUNCTION__); + + switch(func) { + case GL_NEVER: + test = COMPAREFUNC_NEVER; + break; + case GL_LESS: + test = COMPAREFUNC_LESS; + break; + case GL_LEQUAL: + test = COMPAREFUNC_LEQUAL; + break; + case GL_GREATER: + test = COMPAREFUNC_GREATER; + break; + case GL_GEQUAL: + test = COMPAREFUNC_GEQUAL; + break; + case GL_NOTEQUAL: + test = COMPAREFUNC_NOTEQUAL; + break; + case GL_EQUAL: + test = COMPAREFUNC_EQUAL; + break; + case GL_ALWAYS: + test = COMPAREFUNC_ALWAYS; + break; + default: return; + } + + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_STATE3] &= ~DEPTH_TEST_FUNC_MASK; + imesa->Setup[I830_CTXREG_STATE3] |= (ENABLE_DEPTH_TEST_FUNC | + DEPTH_TEST_FUNC(test)); +} + +static void i830DepthMask(GLcontext *ctx, GLboolean flag) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + + if (I830_DEBUG&DEBUG_DRI) + fprintf(stderr, "%s flag (%d)\n", __FUNCTION__, flag); + + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + + imesa->Setup[I830_CTXREG_ENABLES_2] &= ~ENABLE_DIS_DEPTH_WRITE_MASK; + + if (flag && ctx->Depth.Test) + imesa->Setup[I830_CTXREG_ENABLES_2] |= ENABLE_DEPTH_WRITE; + else + imesa->Setup[I830_CTXREG_ENABLES_2] |= DISABLE_DEPTH_WRITE; +} + +/* ============================================================= + * Polygon stipple + * + * The i830 supports a 4x4 stipple natively, GL wants 32x32. + * Fortunately stipple is usually a repeating pattern. + */ +static void i830PolygonStipple( GLcontext *ctx, const GLubyte *mask ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + const GLubyte *m = mask; + GLubyte p[4]; + int i,j,k; + int active = (ctx->Polygon.StippleFlag && + imesa->reduced_primitive == GL_TRIANGLES); + GLuint newMask; + + if (active) { + I830_STATECHANGE(imesa, I830_UPLOAD_STIPPLE); + imesa->StippleSetup[I830_STPREG_ST1] &= ~ST1_ENABLE; + } + + p[0] = mask[12] & 0xf; p[0] |= p[0] << 4; + p[1] = mask[8] & 0xf; p[1] |= p[1] << 4; + p[2] = mask[4] & 0xf; p[2] |= p[2] << 4; + p[3] = mask[0] & 0xf; p[3] |= p[3] << 4; + + for (k = 0 ; k < 8 ; k++) + for (j = 3 ; j >= 0; j--) + for (i = 0 ; i < 4 ; i++, m++) + if (*m != p[j]) { + imesa->hw_stipple = 0; + return; + } + + newMask = (((p[0] & 0xf) << 0) | + ((p[1] & 0xf) << 4) | + ((p[2] & 0xf) << 8) | + ((p[3] & 0xf) << 12)); + + + if (newMask == 0xffff || newMask == 0x0) { + /* this is needed to make conform pass */ + imesa->hw_stipple = 0; + return; + } + + imesa->StippleSetup[I830_STPREG_ST1] &= ~0xffff; + imesa->StippleSetup[I830_STPREG_ST1] |= newMask; + imesa->hw_stipple = 1; + + if (active) + imesa->StippleSetup[I830_STPREG_ST1] |= ST1_ENABLE; +} + +static void i830PolygonStippleFallback( GLcontext *ctx, const GLubyte *mask ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + imesa->hw_stipple = 0; + (void) i830PolygonStipple; +} + +/* ============================================================= + * Hardware clipping + */ +static void i830Scissor(GLcontext *ctx, GLint x, GLint y, + GLsizei w, GLsizei h) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + int x1 = x; + int y1 = imesa->driDrawable->h - (y + h); + int x2 = x + w - 1; + int y2 = y1 + h - 1; + + if (I830_DEBUG&DEBUG_DRI) + fprintf(stderr, "[%s] x(%d) y(%d) w(%d) h(%d)\n", __FUNCTION__, + x, y, w, h); + + if (x1 < 0) x1 = 0; + if (y1 < 0) y1 = 0; + if (x2 < 0) x2 = 0; + if (y2 < 0) y2 = 0; + + if (x2 >= imesa->i830Screen->width) x2 = imesa->i830Screen->width-1; + if (y2 >= imesa->i830Screen->height) y2 = imesa->i830Screen->height-1; + if (x1 >= imesa->i830Screen->width) x1 = imesa->i830Screen->width-1; + if (y1 >= imesa->i830Screen->height) y1 = imesa->i830Screen->height-1; + + + I830_STATECHANGE(imesa, I830_UPLOAD_BUFFERS); + imesa->BufferSetup[I830_DESTREG_SR1] = (y1 << 16) | (x1 & 0xffff); + imesa->BufferSetup[I830_DESTREG_SR2] = (y2 << 16) | (x2 & 0xffff); +} + +static void i830LogicOp(GLcontext *ctx, GLenum opcode) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + int tmp = 0; + + if (I830_DEBUG&DEBUG_DRI) + fprintf(stderr, "%s\n", __FUNCTION__); + + /* FIXME: This should be a look-up table, like the r200 driver. */ + switch(opcode) { + case GL_CLEAR: + tmp = LOGICOP_CLEAR; + break; + case GL_AND: + tmp = LOGICOP_AND; + break; + case GL_AND_REVERSE: + tmp = LOGICOP_AND_RVRSE; + break; + case GL_COPY: + tmp = LOGICOP_COPY; + break; + case GL_COPY_INVERTED: + tmp = LOGICOP_COPY_INV; + break; + case GL_AND_INVERTED: + tmp = LOGICOP_AND_INV; + break; + case GL_NOOP: + tmp = LOGICOP_NOOP; + break; + case GL_XOR: + tmp = LOGICOP_XOR; + break; + case GL_OR: + tmp = LOGICOP_OR; + break; + case GL_OR_INVERTED: + tmp = LOGICOP_OR_INV; + break; + case GL_NOR: + tmp = LOGICOP_NOR; + break; + case GL_EQUIV: + tmp = LOGICOP_EQUIV; + break; + case GL_INVERT: + tmp = LOGICOP_INV; + break; + case GL_OR_REVERSE: + tmp = LOGICOP_OR_RVRSE; + break; + case GL_NAND: + tmp = LOGICOP_NAND; + break; + case GL_SET: + tmp = LOGICOP_SET; + break; + default: + return; + } + + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_STATE4] &= ~LOGICOP_MASK; + imesa->Setup[I830_CTXREG_STATE4] |= LOGIC_OP_FUNC(tmp); + + /* Make sure all the enables are correct */ + i830EvalLogicOpBlendState(ctx); +} + +/* Fallback to swrast for select and feedback. + */ +static void i830RenderMode( GLcontext *ctx, GLenum mode ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + FALLBACK( imesa, I830_FALLBACK_RENDERMODE, (mode != GL_RENDER) ); +} + +static void i830DrawBuffer(GLcontext *ctx, GLenum mode ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + + /* + * _DrawDestMask is easier to cope with than <mode>. + */ + switch ( ctx->Color._DrawDestMask ) { + case FRONT_LEFT_BIT: + I830_FIREVERTICES(imesa); + I830_STATECHANGE(imesa, I830_UPLOAD_BUFFERS); + imesa->BufferSetup[I830_DESTREG_CBUFADDR] = imesa->i830Screen->fbOffset; + i830XMesaSetFrontClipRects( imesa ); + FALLBACK( imesa, I830_FALLBACK_DRAW_BUFFER, GL_FALSE ); + break; + case BACK_LEFT_BIT: + I830_FIREVERTICES(imesa); + I830_STATECHANGE(imesa, I830_UPLOAD_BUFFERS); + imesa->BufferSetup[I830_DESTREG_CBUFADDR] = + imesa->i830Screen->backOffset; + i830XMesaSetBackClipRects( imesa ); + FALLBACK( imesa, I830_FALLBACK_DRAW_BUFFER, GL_FALSE ); + break; + default: + /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */ + FALLBACK( imesa, I830_FALLBACK_DRAW_BUFFER, GL_TRUE ); + return; + } + + /* We want to update the s/w rast state too so that i830SetBuffer() + * gets called. + */ + _swrast_DrawBuffer(ctx, mode); +} + +static void i830ReadBuffer(GLcontext *ctx, GLenum mode ) +{ + /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */ +} + +static void i830ClearColor(GLcontext *ctx, const GLfloat color[4]) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + + CLAMPED_FLOAT_TO_UBYTE(imesa->clear_red, color[0]); + CLAMPED_FLOAT_TO_UBYTE(imesa->clear_green, color[1]); + CLAMPED_FLOAT_TO_UBYTE(imesa->clear_blue, color[2]); + CLAMPED_FLOAT_TO_UBYTE(imesa->clear_alpha, color[3]); + + imesa->ClearColor = i830PackColor(imesa->i830Screen->fbFormat, + imesa->clear_red, + imesa->clear_green, + imesa->clear_blue, + imesa->clear_alpha); +} + +static void i830CullFaceFrontFace(GLcontext *ctx, GLenum unused) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + GLuint mode = CULLMODE_BOTH; + + if (I830_DEBUG&DEBUG_DRI) + fprintf(stderr, "%s\n", __FUNCTION__); + + if (ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK) { + mode = CULLMODE_CW; + + if (ctx->Polygon.CullFaceMode == GL_FRONT) + mode ^= (CULLMODE_CW ^ CULLMODE_CCW); + if (ctx->Polygon.FrontFace != GL_CCW) + mode ^= (CULLMODE_CW ^ CULLMODE_CCW); + } + + imesa->LcsCullMode = mode; + + if (ctx->Polygon.CullFlag) { + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_STATE3] &= ~CULLMODE_MASK; + imesa->Setup[I830_CTXREG_STATE3] |= ENABLE_CULL_MODE | mode; + } +} + +static void i830LineWidth( GLcontext *ctx, GLfloat widthf ) +{ + i830ContextPtr imesa = I830_CONTEXT( ctx ); + int width; + + if (I830_DEBUG&DEBUG_DRI) + fprintf(stderr, "%s\n", __FUNCTION__); + + width = FloatToInt(widthf * 2); + CLAMP_SELF(width, 1, 15); + + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_STATE5] &= ~FIXED_LINE_WIDTH_MASK; + imesa->Setup[I830_CTXREG_STATE5] |= (ENABLE_FIXED_LINE_WIDTH | + FIXED_LINE_WIDTH(width)); +} + +static void i830PointSize(GLcontext *ctx, GLfloat size) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + GLint point_size = FloatToInt(size); + + if (I830_DEBUG&DEBUG_DRI) + fprintf(stderr, "%s\n", __FUNCTION__); + + CLAMP_SELF(point_size, 1, 256); + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_STATE5] &= ~FIXED_POINT_WIDTH_MASK; + imesa->Setup[I830_CTXREG_STATE5] |= (ENABLE_FIXED_POINT_WIDTH | + FIXED_POINT_WIDTH(point_size)); +} + + +/* ============================================================= + * Color masks + */ + +static void i830ColorMask(GLcontext *ctx, + GLboolean r, GLboolean g, + GLboolean b, GLboolean a) +{ + i830ContextPtr imesa = I830_CONTEXT( ctx ); + GLuint tmp = 0; + + if (I830_DEBUG&DEBUG_DRI) + fprintf(stderr, "%s r(%d) g(%d) b(%d) a(%d)\n", __FUNCTION__, r, g, b, a); + + imesa->mask_red = !r; + imesa->mask_green = !g; + imesa->mask_blue = !b; + imesa->mask_alpha = !a; + + tmp = (imesa->Setup[I830_CTXREG_ENABLES_2] & ~WRITEMASK_MASK) | + ENABLE_COLOR_MASK | + ENABLE_COLOR_WRITE | + ((!r) << WRITEMASK_RED_SHIFT) | + ((!g) << WRITEMASK_GREEN_SHIFT) | + ((!b) << WRITEMASK_BLUE_SHIFT) | + ((!a) << WRITEMASK_ALPHA_SHIFT); + + if (tmp != imesa->Setup[I830_CTXREG_ENABLES_2]) { + I830_FIREVERTICES(imesa); + imesa->dirty |= I830_UPLOAD_CTX; + imesa->Setup[I830_CTXREG_ENABLES_2] = tmp; + } +} + +static void update_specular( GLcontext *ctx ) +{ + i830ContextPtr imesa = I830_CONTEXT( ctx ); + + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_ENABLES_1] &= ~ENABLE_SPEC_ADD_MASK; + + if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) + imesa->Setup[I830_CTXREG_ENABLES_1] |= ENABLE_SPEC_ADD; + else + imesa->Setup[I830_CTXREG_ENABLES_1] |= DISABLE_SPEC_ADD; +} + +static void i830LightModelfv(GLcontext *ctx, GLenum pname, + const GLfloat *param) +{ + if (I830_DEBUG&DEBUG_DRI) + fprintf(stderr, "%s\n", __FUNCTION__); + + if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) { + update_specular( ctx ); + } +} + +/* In Mesa 3.5 we can reliably do native flatshading. + */ +static void i830ShadeModel(GLcontext *ctx, GLenum mode) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + + +#define SHADE_MODE_MASK ((1<<10)|(1<<8)|(1<<6)|(1<<4)) + + imesa->Setup[I830_CTXREG_STATE3] &= ~SHADE_MODE_MASK; + + if (mode == GL_FLAT) { + imesa->Setup[I830_CTXREG_STATE3] |= (ALPHA_SHADE_MODE(SHADE_MODE_FLAT) | + FOG_SHADE_MODE(SHADE_MODE_FLAT) | + SPEC_SHADE_MODE(SHADE_MODE_FLAT) | + COLOR_SHADE_MODE(SHADE_MODE_FLAT)); + } else { + imesa->Setup[I830_CTXREG_STATE3] |= (ALPHA_SHADE_MODE(SHADE_MODE_LINEAR) | + FOG_SHADE_MODE(SHADE_MODE_LINEAR) | + SPEC_SHADE_MODE(SHADE_MODE_LINEAR) | + COLOR_SHADE_MODE(SHADE_MODE_LINEAR)); + } +} + +/* ============================================================= + * Fog + */ +static void i830Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + + if (I830_DEBUG&DEBUG_DRI) + fprintf(stderr, "%s\n", __FUNCTION__); + + if (pname == GL_FOG_COLOR) { + GLuint color = (((GLubyte)(ctx->Fog.Color[0]*255.0F) << 16) | + ((GLubyte)(ctx->Fog.Color[1]*255.0F) << 8) | + ((GLubyte)(ctx->Fog.Color[2]*255.0F) << 0)); + + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_FOGCOLOR] = (STATE3D_FOG_COLOR_CMD | color); + } +} + +/* ============================================================= + */ + +static void i830Enable(GLcontext *ctx, GLenum cap, GLboolean state) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + + switch(cap) { + case GL_LIGHTING: + case GL_COLOR_SUM_EXT: + update_specular( ctx ); + break; + + case GL_ALPHA_TEST: + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_ALPHA_TEST_MASK; + if (state) + imesa->Setup[I830_CTXREG_ENABLES_1] |= ENABLE_ALPHA_TEST; + else + imesa->Setup[I830_CTXREG_ENABLES_1] |= DISABLE_ALPHA_TEST; + + break; + + case GL_BLEND: + case GL_COLOR_LOGIC_OP: + case GL_INDEX_LOGIC_OP: + i830EvalLogicOpBlendState(ctx); + break; + + case GL_DITHER: + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_ENABLES_2] &= ~ENABLE_DITHER; + + if (state) + imesa->Setup[I830_CTXREG_ENABLES_2] |= ENABLE_DITHER; + else + imesa->Setup[I830_CTXREG_ENABLES_2] |= DISABLE_DITHER; + break; + + case GL_DEPTH_TEST: + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_DEPTH_TEST_MASK; + + if (state) + imesa->Setup[I830_CTXREG_ENABLES_1] |= ENABLE_DEPTH_TEST; + else + imesa->Setup[I830_CTXREG_ENABLES_1] |= DISABLE_DEPTH_TEST; + + /* Also turn off depth writes when GL_DEPTH_TEST is disabled: + */ + i830DepthMask( ctx, state ); + break; + + case GL_SCISSOR_TEST: + I830_STATECHANGE(imesa, I830_UPLOAD_BUFFERS); + + if (state) + imesa->BufferSetup[I830_DESTREG_SENABLE] = + (STATE3D_SCISSOR_ENABLE_CMD | + ENABLE_SCISSOR_RECT); + else + imesa->BufferSetup[I830_DESTREG_SENABLE] = + (STATE3D_SCISSOR_ENABLE_CMD | + DISABLE_SCISSOR_RECT); + + imesa->upload_cliprects = GL_TRUE; + break; + + case GL_LINE_SMOOTH: + if (imesa->reduced_primitive == GL_LINES) { + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + + imesa->Setup[I830_CTXREG_AA] &= ~AA_LINE_ENABLE; + if (state) + imesa->Setup[I830_CTXREG_AA] |= AA_LINE_ENABLE; + else + imesa->Setup[I830_CTXREG_AA] |= AA_LINE_DISABLE; + } + break; + + case GL_FOG: + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_FOG_MASK; + if (state) + imesa->Setup[I830_CTXREG_ENABLES_1] |= I830_ENABLE_FOG; + else + imesa->Setup[I830_CTXREG_ENABLES_1] |= I830_DISABLE_FOG; + break; + + case GL_CULL_FACE: + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_STATE3] &= ~CULLMODE_MASK; + if (state) + imesa->Setup[I830_CTXREG_STATE3] |= (ENABLE_CULL_MODE | + imesa->LcsCullMode); + else + imesa->Setup[I830_CTXREG_STATE3] |= (ENABLE_CULL_MODE | + CULLMODE_NONE); + break; + + case GL_TEXTURE_2D: +/* I830_STATECHANGE(imesa, I830_UPLOAD_CTX); */ +/* imesa->Setup[I830_CTXREG_ENABLES_1] &= ~ENABLE_SPEC_ADD_MASK; */ + break; + + case GL_STENCIL_TEST: + if (imesa->hw_stencil) { + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_ENABLES_1] &= ~ENABLE_STENCIL_TEST; + + if (state) { + imesa->Setup[I830_CTXREG_ENABLES_1] |= ENABLE_STENCIL_TEST; + } else { + imesa->Setup[I830_CTXREG_ENABLES_1] |= DISABLE_STENCIL_TEST; + } + } else { + FALLBACK( imesa, I830_FALLBACK_STENCIL, state ); + } + break; + + case GL_POLYGON_STIPPLE: +#if 0 + /* The stipple command worked on my 855GM box, but not my 845G. + * I'll do more testing later to find out exactly which hardware + * supports it. Disabled for now. + */ + if (imesa->hw_stipple && imesa->reduced_primitive == GL_TRIANGLES) + { + I830_STATECHANGE(imesa, I830_UPLOAD_STIPPLE); + imesa->StippleSetup[I830_STPREG_ST1] &= ~ST1_ENABLE; + if (state) + imesa->StippleSetup[I830_STPREG_ST1] |= ST1_ENABLE; + } +#endif + break; + + default: + ; + } +} + + +void i830EmitDrawingRectangle( i830ContextPtr imesa ) +{ + __DRIdrawablePrivate *dPriv = imesa->driDrawable; + i830ScreenPrivate *i830Screen = imesa->i830Screen; + int x0 = imesa->drawX; + int y0 = imesa->drawY; + int x1 = x0 + dPriv->w; + int y1 = y0 + dPriv->h; + + /* Don't set drawing rectangle */ + if (I830_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s x0(%d) x1(%d) y0(%d) y1(%d)\n", __FUNCTION__, + x0, x1, y0, y1); + + /* Coordinate origin of the window - may be offscreen. + */ + imesa->BufferSetup[I830_DESTREG_DR4] = ((y0<<16) | + (((unsigned)x0)&0xFFFF)); + + /* Clip to screen. + */ + if (x0 < 0) x0 = 0; + if (y0 < 0) y0 = 0; + if (x1 > i830Screen->width-1) x1 = i830Screen->width-1; + if (y1 > i830Screen->height-1) y1 = i830Screen->height-1; + + + /* Onscreen drawing rectangle. + */ + imesa->BufferSetup[I830_DESTREG_DR2] = ((y0<<16) | x0); + imesa->BufferSetup[I830_DESTREG_DR3] = (((y1+1)<<16) | (x1+1)); + + + /* Just add in our dirty flag, since we might be called when locked */ + /* Might want to modify how this is done. */ + imesa->dirty |= I830_UPLOAD_BUFFERS; + + if (0) + fprintf(stderr, "[%s] DR2(0x%08x) DR3(0x%08x) DR4(0x%08x)\n", + __FUNCTION__, + imesa->BufferSetup[I830_DESTREG_DR2], + imesa->BufferSetup[I830_DESTREG_DR3], + imesa->BufferSetup[I830_DESTREG_DR4]); +} + +/* This could be done in hardware, will do once I have the driver + * up and running. + */ +static void i830CalcViewport( GLcontext *ctx ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + const GLfloat *v = ctx->Viewport._WindowMap.m; + GLfloat *m = imesa->ViewportMatrix.m; + + /* See also i830_translate_vertex. SUBPIXEL adjustments can be done + * via state vars, too. + */ + m[MAT_SX] = v[MAT_SX]; + m[MAT_TX] = v[MAT_TX] + SUBPIXEL_X; + m[MAT_SY] = - v[MAT_SY]; + m[MAT_TY] = - v[MAT_TY] + imesa->driDrawable->h + SUBPIXEL_Y; + m[MAT_SZ] = v[MAT_SZ] * imesa->depth_scale; + m[MAT_TZ] = v[MAT_TZ] * imesa->depth_scale; +} + +static void i830Viewport( GLcontext *ctx, + GLint x, GLint y, + GLsizei width, GLsizei height ) +{ + i830CalcViewport( ctx ); +} + +static void i830DepthRange( GLcontext *ctx, + GLclampd nearval, GLclampd farval ) +{ + i830CalcViewport( ctx ); +} + +void i830PrintDirty( const char *msg, GLuint state ) +{ + fprintf(stderr, "%s (0x%x): %s%s%s%s%s%s%s\n", + msg, + (unsigned int) state, + (state & I830_UPLOAD_TEX0) ? "upload-tex0, " : "", + (state & I830_UPLOAD_TEX1) ? "upload-tex1, " : "", + (state & I830_UPLOAD_CTX) ? "upload-ctx, " : "", + (state & I830_UPLOAD_BUFFERS) ? "upload-bufs, " : "", + (state & I830_UPLOAD_TEXBLEND0) ? "upload-blend0, " : "", + (state & I830_UPLOAD_TEXBLEND1) ? "upload-blend1, " : "", + (state & I830_UPLOAD_STIPPLE) ? "stipple, " : "" + ); +} + +/* Push the state into the sarea and/or texture memory. + */ +void i830EmitHwStateLocked( i830ContextPtr imesa ) +{ + int i; + + if (I830_DEBUG & DEBUG_STATE) + i830PrintDirty( __FUNCTION__, imesa->dirty ); + + if ((imesa->dirty & I830_UPLOAD_TEX0_IMAGE) && imesa->CurrentTexObj[0]) + i830UploadTexImagesLocked(imesa, imesa->CurrentTexObj[0]); + if ((imesa->dirty & I830_UPLOAD_TEX1_IMAGE) && imesa->CurrentTexObj[1]) + i830UploadTexImagesLocked(imesa, imesa->CurrentTexObj[1]); + if (imesa->dirty & I830_UPLOAD_CTX) { + memcpy( imesa->sarea->ContextState, + imesa->Setup, sizeof(imesa->Setup) ); + } + + for (i = 0; i < I830_TEXTURE_COUNT; i++) { + if ((imesa->dirty & I830_UPLOAD_TEX_N(i)) && imesa->CurrentTexObj[i]) { + imesa->sarea->dirty |= I830_UPLOAD_TEX_N(i); + memcpy(imesa->sarea->TexState[i], + imesa->CurrentTexObj[i]->Setup, + sizeof(imesa->sarea->TexState[i])); + + imesa->sarea->TexState[i][I830_TEXREG_TM0S3] &= ~TM0S3_LOD_BIAS_MASK; + imesa->sarea->TexState[i][I830_TEXREG_TM0S3] |= imesa->LodBias[i]; + + /* Update the LRU usage */ + if (imesa->CurrentTexObj[i]->base.memBlock) + driUpdateTextureLRU( (driTextureObject *) + imesa->CurrentTexObj[i] ); + } + } + /* Need to figure out if texturing state, or enable changed. */ + + for (i = 0; i < I830_TEXBLEND_COUNT; i++) { + if (imesa->dirty & I830_UPLOAD_TEXBLEND_N(i)) { + imesa->sarea->dirty |= I830_UPLOAD_TEXBLEND_N(i); + memcpy(imesa->sarea->TexBlendState[i],imesa->TexBlend[i], + imesa->TexBlendWordsUsed[i] * 4); + imesa->sarea->TexBlendStateWordsUsed[i] = + imesa->TexBlendWordsUsed[i]; + } + } + + if (imesa->dirty & I830_UPLOAD_BUFFERS) { + memcpy( imesa->sarea->BufferState,imesa->BufferSetup, + sizeof(imesa->BufferSetup) ); + } + + if (imesa->dirty & I830_UPLOAD_STIPPLE) { + memcpy( imesa->sarea->StippleState,imesa->StippleSetup, + sizeof(imesa->StippleSetup) ); + } + + if (imesa->dirty & I830_UPLOAD_TEX_PALETTE_SHARED) { + memcpy( imesa->sarea->Palette[0],imesa->palette, + sizeof(imesa->sarea->Palette[0])); + } else { + i830TextureObjectPtr p; + if (imesa->dirty & I830_UPLOAD_TEX_PALETTE_N(0)) { + p = imesa->CurrentTexObj[0]; + memcpy( imesa->sarea->Palette[0],p->palette, + sizeof(imesa->sarea->Palette[0])); + } + if (imesa->dirty & I830_UPLOAD_TEX_PALETTE_N(1)) { + p = imesa->CurrentTexObj[1]; + memcpy( imesa->sarea->Palette[1], + p->palette, + sizeof(imesa->sarea->Palette[1])); + } + } + + imesa->sarea->dirty |= (imesa->dirty & ~(I830_UPLOAD_TEX_MASK | + I830_UPLOAD_TEXBLEND_MASK)); + + imesa->upload_cliprects = GL_TRUE; + imesa->dirty = 0; +} + + +void i830DDInitState( GLcontext *ctx ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + i830ScreenPrivate *i830Screen = imesa->i830Screen; + int i, j; + + imesa->clear_red = 0; + imesa->clear_green = 0; + imesa->clear_blue = 0; + imesa->clear_alpha = 0; + + imesa->mask_red = GL_FALSE; + imesa->mask_green = GL_FALSE; + imesa->mask_blue = GL_FALSE; + imesa->mask_alpha = GL_FALSE; + + /* Zero all texture state */ + for (i = 0; i < I830_TEXBLEND_COUNT; i++) { + for (j = 0; j < I830_TEXBLEND_SIZE; j++) { + imesa->TexBlend[i][j] = 0; + imesa->Init_TexBlend[i][j] = 0; + } + imesa->TexBlendWordsUsed[i] = 0; + imesa->Init_TexBlendWordsUsed[i] = 0; + imesa->TexBlendColorPipeNum[i] = 0; + imesa->Init_TexBlendColorPipeNum[i] = 0; + } + + /* Set default blend state */ + imesa->TexBlend[0][0] = (STATE3D_MAP_BLEND_OP_CMD(0) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXOP_LAST_STAGE | + TEXBLENDOP_ARG1); + imesa->TexBlend[0][1] = (STATE3D_MAP_BLEND_OP_CMD(0) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[0][2] = (STATE3D_MAP_BLEND_ARG_CMD(0) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_DIFFUSE); + imesa->TexBlend[0][3] = (STATE3D_MAP_BLEND_ARG_CMD(0) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_DIFFUSE); + + imesa->TexBlendWordsUsed[0] = 4; + imesa->TexBlendColorPipeNum[0] = 0; + + imesa->Init_TexBlend[0][0] = (STATE3D_MAP_BLEND_OP_CMD(0) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXOP_LAST_STAGE | + TEXBLENDOP_ARG1); + imesa->Init_TexBlend[0][1] = (STATE3D_MAP_BLEND_OP_CMD(0) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->Init_TexBlend[0][2] = (STATE3D_MAP_BLEND_ARG_CMD(0) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->Init_TexBlend[0][3] = (STATE3D_MAP_BLEND_ARG_CMD(0) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->Init_TexBlendWordsUsed[0] = 4; + imesa->Init_TexBlendColorPipeNum[0] = 0; + + memset(imesa->Setup, 0, sizeof(imesa->Setup)); + + imesa->Setup[I830_CTXREG_VF] = (STATE3D_VERTEX_FORMAT_CMD | + VRTX_TEX_COORD_COUNT(1) | + VRTX_HAS_DIFFUSE | + VRTX_HAS_SPEC | + VRTX_HAS_XYZW); + imesa->vertex_format = 0; + imesa->Setup[I830_CTXREG_VF2] = (STATE3D_VERTEX_FORMAT_2_CMD | + VRTX_TEX_SET_0_FMT(TEXCOORDFMT_2D) | + VRTX_TEX_SET_1_FMT(TEXCOORDFMT_2D) | + VRTX_TEX_SET_2_FMT(TEXCOORDFMT_2D) | + VRTX_TEX_SET_3_FMT(TEXCOORDFMT_2D)); + + imesa->Setup[I830_CTXREG_AA] = (STATE3D_AA_CMD | + AA_LINE_ECAAR_WIDTH_ENABLE | + AA_LINE_ECAAR_WIDTH_1_0 | + AA_LINE_REGION_WIDTH_ENABLE | + AA_LINE_REGION_WIDTH_1_0 | + AA_LINE_DISABLE); + + imesa->Setup[I830_CTXREG_ENABLES_1] = (STATE3D_ENABLES_1_CMD | + DISABLE_LOGIC_OP | + DISABLE_STENCIL_TEST | + DISABLE_DEPTH_BIAS | + DISABLE_SPEC_ADD | + I830_DISABLE_FOG | + DISABLE_ALPHA_TEST | + DISABLE_COLOR_BLEND | + DISABLE_DEPTH_TEST); + + if (imesa->hw_stencil) { + imesa->Setup[I830_CTXREG_ENABLES_2] = (STATE3D_ENABLES_2_CMD | + ENABLE_STENCIL_WRITE | + ENABLE_TEX_CACHE | + ENABLE_DITHER | + ENABLE_COLOR_MASK | + /* set no color comps disabled */ + ENABLE_COLOR_WRITE | + ENABLE_DEPTH_WRITE); + } else { + imesa->Setup[I830_CTXREG_ENABLES_2] = (STATE3D_ENABLES_2_CMD | + DISABLE_STENCIL_WRITE | + ENABLE_TEX_CACHE | + ENABLE_DITHER | + ENABLE_COLOR_MASK | + /* set no color comps disabled */ + ENABLE_COLOR_WRITE | + ENABLE_DEPTH_WRITE); + } + + imesa->Setup[I830_CTXREG_STATE1] = (STATE3D_MODES_1_CMD | + ENABLE_COLR_BLND_FUNC | + BLENDFUNC_ADD | + ENABLE_SRC_BLND_FACTOR | + SRC_BLND_FACT(BLENDFACT_ONE) | + ENABLE_DST_BLND_FACTOR | + DST_BLND_FACT(BLENDFACT_ZERO) ); + + imesa->Setup[I830_CTXREG_STATE2] = (STATE3D_MODES_2_CMD | + ENABLE_GLOBAL_DEPTH_BIAS | + GLOBAL_DEPTH_BIAS(0) | + ENABLE_ALPHA_TEST_FUNC | + ALPHA_TEST_FUNC(COMPAREFUNC_ALWAYS) | + ALPHA_REF_VALUE(0) ); + + imesa->Setup[I830_CTXREG_STATE3] = (STATE3D_MODES_3_CMD | + ENABLE_DEPTH_TEST_FUNC | + DEPTH_TEST_FUNC(COMPAREFUNC_LESS) | + ENABLE_ALPHA_SHADE_MODE | + ALPHA_SHADE_MODE(SHADE_MODE_LINEAR) | + ENABLE_FOG_SHADE_MODE | + FOG_SHADE_MODE(SHADE_MODE_LINEAR) | + ENABLE_SPEC_SHADE_MODE | + SPEC_SHADE_MODE(SHADE_MODE_LINEAR) | + ENABLE_COLOR_SHADE_MODE | + COLOR_SHADE_MODE(SHADE_MODE_LINEAR) | + ENABLE_CULL_MODE | + CULLMODE_NONE); + + imesa->Setup[I830_CTXREG_STATE4] = (STATE3D_MODES_4_CMD | + ENABLE_LOGIC_OP_FUNC | + LOGIC_OP_FUNC(LOGICOP_COPY) | + ENABLE_STENCIL_TEST_MASK | + STENCIL_TEST_MASK(0xff) | + ENABLE_STENCIL_WRITE_MASK | + STENCIL_WRITE_MASK(0xff)); + + imesa->Setup[I830_CTXREG_STENCILTST] = (STATE3D_STENCIL_TEST_CMD | + ENABLE_STENCIL_PARMS | + STENCIL_FAIL_OP(STENCILOP_KEEP) | + STENCIL_PASS_DEPTH_FAIL_OP(STENCILOP_KEEP) | + STENCIL_PASS_DEPTH_PASS_OP(STENCILOP_KEEP) | + ENABLE_STENCIL_TEST_FUNC | + STENCIL_TEST_FUNC(COMPAREFUNC_ALWAYS) | + ENABLE_STENCIL_REF_VALUE | + STENCIL_REF_VALUE(0) ); + + imesa->Setup[I830_CTXREG_STATE5] = (STATE3D_MODES_5_CMD | + FLUSH_TEXTURE_CACHE | + ENABLE_SPRITE_POINT_TEX | + SPRITE_POINT_TEX_OFF | + ENABLE_FIXED_LINE_WIDTH | + FIXED_LINE_WIDTH(0x2) | /* 1.0 */ + ENABLE_FIXED_POINT_WIDTH | + FIXED_POINT_WIDTH(1) ); + + imesa->Setup[I830_CTXREG_IALPHAB] = (STATE3D_INDPT_ALPHA_BLEND_CMD | + DISABLE_INDPT_ALPHA_BLEND | + ENABLE_ALPHA_BLENDFUNC | + ABLENDFUNC_ADD); + + imesa->Setup[I830_CTXREG_FOGCOLOR] = (STATE3D_FOG_COLOR_CMD | + FOG_COLOR_RED(0) | + FOG_COLOR_GREEN(0) | + FOG_COLOR_BLUE(0)); + + imesa->Setup[I830_CTXREG_BLENDCOLR0] = (STATE3D_CONST_BLEND_COLOR_CMD); + + imesa->Setup[I830_CTXREG_BLENDCOLR] = 0; + + imesa->Setup[I830_CTXREG_MCSB0] = STATE3D_MAP_COORD_SETBIND_CMD; + imesa->Setup[I830_CTXREG_MCSB1] = (TEXBIND_SET3(TEXCOORDSRC_VTXSET_3) | + TEXBIND_SET2(TEXCOORDSRC_VTXSET_2) | + TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) | + TEXBIND_SET0(TEXCOORDSRC_VTXSET_0)); + + imesa->LcsCullMode = CULLMODE_CW; /* GL default */ + + memset(imesa->BufferSetup, 0, sizeof(imesa->BufferSetup)); + memset(imesa->StippleSetup, 0, sizeof(imesa->StippleSetup)); + + + if (imesa->glCtx->Visual.doubleBufferMode && + imesa->sarea->pf_current_page == 0) { + imesa->drawMap = i830Screen->back.map; + imesa->readMap = i830Screen->back.map; + imesa->BufferSetup[I830_DESTREG_CBUFADDR] = i830Screen->backOffset; + imesa->BufferSetup[I830_DESTREG_DBUFADDR] = 0; + } else { + /* use front buffer by default */ + imesa->drawMap = (char *)imesa->driScreen->pFB; + imesa->readMap = (char *)imesa->driScreen->pFB; + imesa->BufferSetup[I830_DESTREG_CBUFADDR] = i830Screen->fbOffset; + imesa->BufferSetup[I830_DESTREG_DBUFADDR] = 0; + } + + imesa->BufferSetup[I830_DESTREG_DV0] = STATE3D_DST_BUF_VARS_CMD; + + switch (i830Screen->fbFormat) { + case DV_PF_555: + case DV_PF_565: + imesa->BufferSetup[I830_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */ + DSTORG_VERT_BIAS(0x8) | /* .5 */ + i830Screen->fbFormat | + DEPTH_IS_Z | + DEPTH_FRMT_16_FIXED); + break; + case DV_PF_8888: + imesa->BufferSetup[I830_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */ + DSTORG_VERT_BIAS(0x8) | /* .5 */ + i830Screen->fbFormat | + DEPTH_IS_Z | + DEPTH_FRMT_24_FIXED_8_OTHER); + break; + } + imesa->BufferSetup[I830_DESTREG_SENABLE] = (STATE3D_SCISSOR_ENABLE_CMD | + DISABLE_SCISSOR_RECT); + imesa->BufferSetup[I830_DESTREG_SR0] = STATE3D_SCISSOR_RECT_0_CMD; + imesa->BufferSetup[I830_DESTREG_SR1] = 0; + imesa->BufferSetup[I830_DESTREG_SR2] = 0; + + imesa->BufferSetup[I830_DESTREG_DR0] = STATE3D_DRAW_RECT_CMD; + imesa->BufferSetup[I830_DESTREG_DR1] = 0; + imesa->BufferSetup[I830_DESTREG_DR2] = 0; + imesa->BufferSetup[I830_DESTREG_DR3] = (((i830Screen->height)<<16) | + (i830Screen->width)); + imesa->BufferSetup[I830_DESTREG_DR4] = 0; + + memcpy( imesa->Init_Setup, + imesa->Setup, + sizeof(imesa->Setup) ); + memcpy( imesa->Init_BufferSetup, + imesa->BufferSetup, + sizeof(imesa->BufferSetup) ); + +} + +static void i830InvalidateState( GLcontext *ctx, GLuint new_state ) +{ + _swrast_InvalidateState( ctx, new_state ); + _swsetup_InvalidateState( ctx, new_state ); + _ac_InvalidateState( ctx, new_state ); + _tnl_InvalidateState( ctx, new_state ); + I830_CONTEXT(ctx)->NewGLState |= new_state; +} + +void i830DDInitStateFuncs(GLcontext *ctx) +{ + /* Callbacks for internal Mesa events. + */ + ctx->Driver.UpdateState = i830InvalidateState; + + /* API callbacks + */ + ctx->Driver.AlphaFunc = i830AlphaFunc; + ctx->Driver.BlendEquation = i830BlendEquation; + ctx->Driver.BlendFunc = i830BlendFunc; + ctx->Driver.BlendFuncSeparate = i830BlendFuncSeparate; + ctx->Driver.BlendColor = i830BlendColor; + ctx->Driver.ClearColor = i830ClearColor; + ctx->Driver.ColorMask = i830ColorMask; + ctx->Driver.CullFace = i830CullFaceFrontFace; + ctx->Driver.DepthFunc = i830DepthFunc; + ctx->Driver.DepthMask = i830DepthMask; + ctx->Driver.Enable = i830Enable; + ctx->Driver.Fogfv = i830Fogfv; + ctx->Driver.FrontFace = i830CullFaceFrontFace; + ctx->Driver.LineWidth = i830LineWidth; + ctx->Driver.PointSize = i830PointSize; + ctx->Driver.LogicOpcode = i830LogicOp; + ctx->Driver.PolygonStipple = i830PolygonStippleFallback; + ctx->Driver.RenderMode = i830RenderMode; + ctx->Driver.Scissor = i830Scissor; + ctx->Driver.DrawBuffer = i830DrawBuffer; + ctx->Driver.ReadBuffer = i830ReadBuffer; + ctx->Driver.ShadeModel = i830ShadeModel; + ctx->Driver.DepthRange = i830DepthRange; + ctx->Driver.Viewport = i830Viewport; + ctx->Driver.LightModelfv = i830LightModelfv; + + ctx->Driver.StencilFunc = i830StencilFunc; + ctx->Driver.StencilMask = i830StencilMask; + ctx->Driver.StencilOp = i830StencilOp; + + /* Pixel path fallbacks. + */ + ctx->Driver.Accum = _swrast_Accum; + ctx->Driver.Bitmap = _swrast_Bitmap; + ctx->Driver.CopyPixels = _swrast_CopyPixels; + ctx->Driver.DrawPixels = _swrast_DrawPixels; + ctx->Driver.ReadPixels = _swrast_ReadPixels; + + /* Swrast hooks for imaging extensions: + */ + ctx->Driver.CopyColorTable = _swrast_CopyColorTable; + ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable; + ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D; + ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D; +} diff --git a/src/mesa/drivers/dri/i830/i830_state.h b/src/mesa/drivers/dri/i830/i830_state.h new file mode 100644 index 0000000000..b651651246 --- /dev/null +++ b/src/mesa/drivers/dri/i830/i830_state.h @@ -0,0 +1,68 @@ +/************************************************************************** + +Copyright 2001 VA Linux Systems Inc., Fremont, California. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_state.h,v 1.3 2002/12/10 01:26:53 dawes Exp $ */ + +/* + * Author: + * Jeff Hartmann <jhartmann@2d3d.com> + * + * Heavily based on the I810 driver, which was written by: + * Keith Whitwell <keith@tungstengraphics.com> + */ +#ifndef _I830_STATE_H +#define _I830_STATE_H + +#include "i830_context.h" +#include "colormac.h" +#define FloatToInt(F) ((int)(F)) + +/* + * * This function/macro is sensitive to precision. Test carefully + * * if you change it. + * */ +#define FLOAT_COLOR_TO_UBYTE_COLOR(b, f) \ + do { \ + union {GLfloat r; GLuint i; } tmp; \ + tmp.r = f; \ + b = ((tmp.i >= IEEE_ONE) \ + ? ((GLint)tmp.i < 0) ? (GLubyte)0 : (GLubyte)255 \ + : (tmp.r = tmp.r*(255.0F/256.0F) + 32768.0F, \ + (GLubyte)tmp.i)); \ + } while (0) + + + +extern void i830DDInitState( GLcontext *ctx ); +extern void i830DDInitStateFuncs( GLcontext *ctx ); + +extern void i830PrintDirty( const char *msg, GLuint state ); +extern void i830SetDrawBuffer(GLcontext *ctx, GLenum mode ); + +extern void i830Fallback( i830ContextPtr imesa, GLuint bit, GLboolean mode ); +#define FALLBACK( imesa, bit, mode ) i830Fallback( imesa, bit, mode ) +#endif diff --git a/src/mesa/drivers/dri/i830/i830_tex.c b/src/mesa/drivers/dri/i830/i830_tex.c new file mode 100644 index 0000000000..14a70a0905 --- /dev/null +++ b/src/mesa/drivers/dri/i830/i830_tex.c @@ -0,0 +1,579 @@ +/************************************************************************** + +Copyright 2001 2d3d Inc., Delray Beach, FL + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_tex.c,v 1.5 2003/05/07 21:56:31 dawes Exp $ */ + +/* + * Author: + * Jeff Hartmann <jhartmann@2d3d.com> + * + * Heavily based on the I810 driver, which was written by: + * Keith Whitwell <keithw@tungstengraphics.com> + */ + +#include "glheader.h" +#include "mtypes.h" +#include "imports.h" +#include "simple_list.h" +#include "enums.h" +#include "texstore.h" +#include "teximage.h" +#include "texformat.h" +#include "texmem.h" +#include "swrast/swrast.h" + +#include "mm.h" + +#include "i830_screen.h" +#include "i830_dri.h" +#include "i830_context.h" +#include "i830_tex.h" +#include "i830_state.h" +#include "i830_ioctl.h" + +/* + * Compute the 'S2.4' lod bias factor from the floating point OpenGL bias. + */ +static void i830ComputeLodBias( i830ContextPtr imesa, unsigned unit, + GLfloat bias ) +{ + int b; + + b = (int) (bias * 16.0); + if(b > 63) b = 63; + else if (b < -64) b = -64; + imesa->LodBias[ unit ] = ((b << TM0S3_LOD_BIAS_SHIFT) & + TM0S3_LOD_BIAS_MASK); +} + + +/** + * Set the texture wrap modes. + * + * The i830M (and related graphics cores) do not support GL_CLAMP. The Intel + * drivers for "other operating systems" implement GL_CLAMP as + * GL_CLAMP_TO_EDGE, so the same is done here. + * + * \param t Texture object whose wrap modes are to be set + * \param swrap Wrap mode for the \a s texture coordinate + * \param twrap Wrap mode for the \a t texture coordinate + */ + +static void i830SetTexWrapping(i830TextureObjectPtr tex, + GLenum swrap, GLenum twrap) +{ + tex->Setup[I830_TEXREG_MCS] &= ~(TEXCOORD_ADDR_U_MASK|TEXCOORD_ADDR_V_MASK); + + switch( swrap ) { + case GL_REPEAT: + tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP); + break; + case GL_CLAMP: + case GL_CLAMP_TO_EDGE: + tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP); + break; + case GL_CLAMP_TO_BORDER: + tex->Setup[I830_TEXREG_MCS] |= + TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP_BORDER); + break; + case GL_MIRRORED_REPEAT: + tex->Setup[I830_TEXREG_MCS] |= + TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_MIRROR); + break; + default: + _mesa_problem(NULL, "bad S wrap mode in %s", __FUNCTION__); + } + + switch( twrap ) { + case GL_REPEAT: + tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP); + break; + case GL_CLAMP: + case GL_CLAMP_TO_EDGE: + tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP); + break; + case GL_CLAMP_TO_BORDER: + tex->Setup[I830_TEXREG_MCS] |= + TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP_BORDER); + break; + case GL_MIRRORED_REPEAT: + tex->Setup[I830_TEXREG_MCS] |= + TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_MIRROR); + break; + default: + _mesa_problem(NULL, "bad T wrap mode in %s", __FUNCTION__); + } +} + +static void i830SetTexMaxAnisotropy( i830TextureObjectPtr t, GLfloat max ) +{ + t->max_anisotropy = max; +} + + +/** + * Set the texture magnification and minification modes. + * + * \param t Texture whose filter modes are to be set + * \param minf Texture minification mode + * \param magf Texture magnification mode + * \param bias LOD bias for this texture unit. + */ + +static void i830SetTexFilter( i830TextureObjectPtr t, + GLenum minf, GLenum magf ) +{ + int minFilt = 0, mipFilt = 0, magFilt = 0; + + if(I830_DEBUG&DEBUG_DRI) + fprintf(stderr, "%s\n", __FUNCTION__); + + if ( t->max_anisotropy > 1.0 ) { + minFilt = FILTER_ANISOTROPIC; + magFilt = FILTER_ANISOTROPIC; + } + else { + switch (minf) { + case GL_NEAREST: + minFilt = FILTER_NEAREST; + mipFilt = MIPFILTER_NONE; + break; + case GL_LINEAR: + minFilt = FILTER_LINEAR; + mipFilt = MIPFILTER_NONE; + break; + case GL_NEAREST_MIPMAP_NEAREST: + minFilt = FILTER_NEAREST; + mipFilt = MIPFILTER_NEAREST; + break; + case GL_LINEAR_MIPMAP_NEAREST: + minFilt = FILTER_LINEAR; + mipFilt = MIPFILTER_NEAREST; + break; + case GL_NEAREST_MIPMAP_LINEAR: + minFilt = FILTER_NEAREST; + mipFilt = MIPFILTER_LINEAR; + break; + case GL_LINEAR_MIPMAP_LINEAR: + minFilt = FILTER_LINEAR; + mipFilt = MIPFILTER_LINEAR; + break; + default: + _mesa_problem(NULL, "%s: Unsupported min. filter %d", __FUNCTION__, + (int) minf ); + break; + } + + switch (magf) { + case GL_NEAREST: + magFilt = FILTER_NEAREST; + break; + case GL_LINEAR: + magFilt = FILTER_LINEAR; + break; + default: + _mesa_problem(NULL, "%s: Unsupported mag. filter %d", __FUNCTION__, + (int) magf ); + break; + } + } + + t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_FILTER_MASK; + t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIP_FILTER_MASK; + t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAG_FILTER_MASK; + t->Setup[I830_TEXREG_TM0S3] |= ((minFilt << TM0S3_MIN_FILTER_SHIFT) | + (mipFilt << TM0S3_MIP_FILTER_SHIFT) | + (magFilt << TM0S3_MAG_FILTER_SHIFT)); +} + +static void i830SetTexBorderColor(i830TextureObjectPtr t, GLubyte color[4]) +{ + if(I830_DEBUG&DEBUG_DRI) + fprintf(stderr, "%s\n", __FUNCTION__); + + t->Setup[I830_TEXREG_TM0S4] = + I830PACKCOLOR8888(color[0],color[1],color[2],color[3]); +} + + +/** + * Allocate space for and load the mesa images into the texture memory block. + * This will happen before drawing with a new texture, or drawing with a + * texture after it was swapped out or teximaged again. + */ + +static i830TextureObjectPtr i830AllocTexObj( struct gl_texture_object *texObj ) +{ + i830TextureObjectPtr t; + + t = CALLOC_STRUCT( i830_texture_object_t ); + texObj->DriverData = t; + if ( t != NULL ) { + /* Initialize non-image-dependent parts of the state: + */ + t->base.tObj = texObj; + + t->Setup[I830_TEXREG_TM0LI] = STATE3D_LOAD_STATE_IMMEDIATE_2; + t->Setup[I830_TEXREG_TM0S0] = TM0S0_USE_FENCE; + t->Setup[I830_TEXREG_TM0S1] = 0; + t->Setup[I830_TEXREG_TM0S2] = 0; + t->Setup[I830_TEXREG_TM0S3] = 0; + + t->Setup[I830_TEXREG_NOP0] = 0; + t->Setup[I830_TEXREG_NOP1] = 0; + t->Setup[I830_TEXREG_NOP2] = 0; + + t->Setup[I830_TEXREG_MCS] = (STATE3D_MAP_COORD_SET_CMD | + MAP_UNIT(0) | + ENABLE_TEXCOORD_PARAMS | + TEXCOORDS_ARE_NORMAL | + TEXCOORDTYPE_CARTESIAN | + ENABLE_ADDR_V_CNTL | + TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP) | + ENABLE_ADDR_U_CNTL | + TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP)); + + make_empty_list( & t->base ); + + i830SetTexWrapping( t, texObj->WrapS, texObj->WrapT ); + i830SetTexMaxAnisotropy( t, texObj->MaxAnisotropy ); + i830SetTexFilter( t, texObj->MinFilter, texObj->MagFilter ); + i830SetTexBorderColor( t, texObj->_BorderChan ); + } + + return t; +} + + +static void i830TexParameter( GLcontext *ctx, GLenum target, + struct gl_texture_object *tObj, + GLenum pname, const GLfloat *params ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + i830TextureObjectPtr t = (i830TextureObjectPtr) tObj->DriverData; + GLuint unit = ctx->Texture.CurrentUnit; + if (!t) + return; + + if ( target != GL_TEXTURE_2D ) + return; + + /* Can't do the update now as we don't know whether to flush + * vertices or not. Setting imesa->NewGLState means that + * i830UpdateTextureState() will be called before any triangles are + * rendered. If a statechange has occurred, it will be detected at + * that point, and buffered vertices flushed. + */ + switch (pname) { + case GL_TEXTURE_MIN_FILTER: + case GL_TEXTURE_MAG_FILTER: + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + i830SetTexMaxAnisotropy( t, tObj->MaxAnisotropy ); + i830SetTexFilter( t, tObj->MinFilter, tObj->MagFilter ); + break; + + case GL_TEXTURE_WRAP_S: + case GL_TEXTURE_WRAP_T: + i830SetTexWrapping( t, tObj->WrapS, tObj->WrapT ); + break; + + case GL_TEXTURE_BORDER_COLOR: + i830SetTexBorderColor( t, tObj->_BorderChan ); + break; + + case GL_TEXTURE_BASE_LEVEL: + case GL_TEXTURE_MAX_LEVEL: + case GL_TEXTURE_MIN_LOD: + case GL_TEXTURE_MAX_LOD: + /* The i830 and its successors can do a lot of this without + * reloading the textures. A project for someone? + */ + I830_FIREVERTICES( I830_CONTEXT(ctx) ); + driSwapOutTextureObject( (driTextureObject *) t ); + break; + + default: + return; + } + + if (t == imesa->CurrentTexObj[unit]) { + I830_STATECHANGE( imesa, I830_UPLOAD_TEX0 ); + } +} + + +static void i830TexEnv( GLcontext *ctx, GLenum target, + GLenum pname, const GLfloat *param ) +{ + i830ContextPtr imesa = I830_CONTEXT( ctx ); + GLuint unit = ctx->Texture.CurrentUnit; + + /* Only one env color. Need a fallback if env colors are different + * and texture setup references env color in both units. + */ + switch (pname) { + case GL_TEXTURE_ENV_COLOR: + case GL_TEXTURE_ENV_MODE: + case GL_COMBINE_RGB_EXT: + case GL_COMBINE_ALPHA_EXT: + case GL_SOURCE0_RGB_EXT: + case GL_SOURCE1_RGB_EXT: + case GL_SOURCE2_RGB_EXT: + case GL_SOURCE0_ALPHA_EXT: + case GL_SOURCE1_ALPHA_EXT: + case GL_SOURCE2_ALPHA_EXT: + case GL_OPERAND0_RGB_EXT: + case GL_OPERAND1_RGB_EXT: + case GL_OPERAND2_RGB_EXT: + case GL_OPERAND0_ALPHA_EXT: + case GL_OPERAND1_ALPHA_EXT: + case GL_OPERAND2_ALPHA_EXT: + case GL_RGB_SCALE_EXT: + case GL_ALPHA_SCALE: + imesa->TexEnvImageFmt[unit] = 0; /* force recalc of env state */ + break; + + case GL_TEXTURE_LOD_BIAS_EXT: + i830ComputeLodBias( imesa, unit, *param ); + I830_STATECHANGE( imesa, I830_UPLOAD_TEX_N(unit) ); + break; + + default: + break; + } +} + +static void i830TexImage2D( GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint border, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ) +{ + driTextureObject * t = (driTextureObject *) texObj->DriverData; + if (t) { + I830_FIREVERTICES( I830_CONTEXT(ctx) ); + driSwapOutTextureObject( t ); + } + else { + t = (driTextureObject *) i830AllocTexObj( texObj ); + if (!t) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); + return; + } + } + + _mesa_store_teximage2d( ctx, target, level, internalFormat, + width, height, border, format, type, + pixels, packing, texObj, texImage ); +} + +static void i830TexSubImage2D( GLcontext *ctx, + GLenum target, + GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ) +{ + driTextureObject * t = (driTextureObject *) texObj->DriverData; + if (t) { + I830_FIREVERTICES( I830_CONTEXT(ctx) ); + driSwapOutTextureObject( t ); + } + _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width, + height, format, type, pixels, packing, texObj, + texImage); + +} + + +static void i830BindTexture( GLcontext *ctx, GLenum target, + struct gl_texture_object *tObj ) +{ + if (!tObj->DriverData) { + i830AllocTexObj( tObj ); + } +} + + +static void i830DeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj ) +{ + driTextureObject * t = (driTextureObject *) tObj->DriverData; + + if ( t != NULL ) { + i830ContextPtr imesa = I830_CONTEXT( ctx ); + + if ( imesa ) { + I830_FIREVERTICES( imesa ); + } + + driDestroyTextureObject( t ); + } +} + + +static const struct gl_texture_format * +i830ChooseTextureFormat( GLcontext *ctx, GLint internalFormat, + GLenum format, GLenum type ) +{ + i830ContextPtr imesa = I830_CONTEXT( ctx ); + const GLboolean do32bpt = ( imesa->i830Screen->cpp == 4 && + imesa->i830Screen->textureSize > 4*1024*1024); + + switch ( internalFormat ) { + case 4: + case GL_RGBA: + case GL_COMPRESSED_RGBA: + if ( format == GL_BGRA ) { + if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) { + return &_mesa_texformat_argb8888; + } + else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) { + return &_mesa_texformat_argb4444; + } + else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) { + return &_mesa_texformat_argb1555; + } + } + return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444; + + case 3: + case GL_RGB: + case GL_COMPRESSED_RGB: + if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) { + return &_mesa_texformat_rgb565; + } + return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565; + + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444; + + case GL_RGBA4: + case GL_RGBA2: + return &_mesa_texformat_argb4444; + + case GL_RGB5_A1: + return &_mesa_texformat_argb1555; + + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565; + + case GL_RGB5: + case GL_RGB4: + case GL_R3_G3_B2: + return &_mesa_texformat_rgb565; + + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + case GL_COMPRESSED_ALPHA: + return &_mesa_texformat_al88; + + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + case GL_COMPRESSED_LUMINANCE: + return &_mesa_texformat_l8; + + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + case GL_COMPRESSED_LUMINANCE_ALPHA: + return &_mesa_texformat_al88; + + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + case GL_COMPRESSED_INTENSITY: + return &_mesa_texformat_i8; + + case GL_YCBCR_MESA: + if (type == GL_UNSIGNED_SHORT_8_8_MESA || + type == GL_UNSIGNED_BYTE) + return &_mesa_texformat_ycbcr; + else + return &_mesa_texformat_ycbcr_rev; + + default: + fprintf(stderr, "unexpected texture format in %s\n", __FUNCTION__); + return NULL; + } + + return NULL; /* never get here */ +} + +void i830DDInitTextureFuncs( GLcontext *ctx ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + + ctx->Driver.TexEnv = i830TexEnv; + ctx->Driver.ChooseTextureFormat = i830ChooseTextureFormat; + ctx->Driver.TexImage1D = _mesa_store_teximage1d; + ctx->Driver.TexImage2D = i830TexImage2D; + ctx->Driver.TexImage3D = _mesa_store_teximage3d; + ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d; + ctx->Driver.TexSubImage2D = i830TexSubImage2D; + ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d; + ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d; + ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d; + ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d; + ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d; + ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d; + ctx->Driver.BindTexture = i830BindTexture; + ctx->Driver.DeleteTexture = i830DeleteTexture; + ctx->Driver.TexParameter = i830TexParameter; + ctx->Driver.UpdateTexturePalette = NULL; + ctx->Driver.IsTextureResident = driIsTextureResident; + ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage; + + driInitTextureObjects( ctx, & imesa->swapped, + DRI_TEXMGR_DO_TEXTURE_2D + | DRI_TEXMGR_DO_TEXTURE_RECT ); +} diff --git a/src/mesa/drivers/dri/i830/i830_tex.h b/src/mesa/drivers/dri/i830/i830_tex.h new file mode 100644 index 0000000000..dbfcbe3963 --- /dev/null +++ b/src/mesa/drivers/dri/i830/i830_tex.h @@ -0,0 +1,71 @@ +/* + * GLX Hardware Device Driver for Intel i810 + * Copyright (C) 1999 Keith Whitwell + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Adapted for use in the I830M driver: + * Jeff Hartmann <jhartmann@2d3d.com> + */ + +#ifndef I830TEX_INC +#define I830TEX_INC + +#include "mtypes.h" +#include "i830_context.h" +#include "i830_3d_reg.h" +#include "texmem.h" + +#define I830_TEX_MAXLEVELS 10 + +struct i830_texture_object_t +{ + driTextureObject base; + + int texelBytes; + int Pitch; + int Height; + char *BufAddr; + GLenum palette_format; + GLuint palette[256]; + struct { + const struct gl_texture_image *image; + int offset; /* into BufAddr */ + int height; + int internalFormat; + } image[6][I830_TEX_MAXLEVELS]; + + /* Support for multitexture. + */ + + GLuint current_unit; + GLuint Setup[I830_TEX_SETUP_SIZE]; + GLuint dirty; + + GLfloat max_anisotropy; +}; + +void i830UpdateTextureState( GLcontext *ctx ); +void i830DDInitTextureFuncs( GLcontext *ctx ); +void i830UpdateTexUnitProj( GLcontext *ctx, GLuint unit, GLboolean state ); + +void i830DestroyTexObj( i830ContextPtr imesa, i830TextureObjectPtr t ); +int i830UploadTexImagesLocked( i830ContextPtr imesa, i830TextureObjectPtr t ); + +#endif diff --git a/src/mesa/drivers/dri/i830/i830_texmem.c b/src/mesa/drivers/dri/i830/i830_texmem.c new file mode 100644 index 0000000000..6cb5531349 --- /dev/null +++ b/src/mesa/drivers/dri/i830/i830_texmem.c @@ -0,0 +1,214 @@ +/************************************************************************** + +Copyright 2001 2d3d Inc., Delray Beach, FL + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_texmem.c,v 1.3 2002/12/10 01:26:53 dawes Exp $ */ + +/* + * Author: + * Jeff Hartmann <jhartmann@2d3d.com> + * + * Heavily based on the I810 driver, which was written by: + * Keith Whitwell <keithw@tungstengraphics.com> + */ + +#include "glheader.h" +#include "macros.h" +#include "mtypes.h" +#include "simple_list.h" +#include "enums.h" +#include "texformat.h" + +#include "i830_screen.h" +#include "i830_dri.h" + +#include "i830_context.h" +#include "i830_tex.h" +#include "i830_state.h" +#include "i830_ioctl.h" + + +void i830DestroyTexObj(i830ContextPtr imesa, i830TextureObjectPtr t) +{ + unsigned i; + + + /* See if it was the driver's current object. + */ + if ( imesa != NULL ) { + for ( i = 0 ; i < imesa->glCtx->Const.MaxTextureUnits ; i++ ) { + if ( t == imesa->CurrentTexObj[ i ] ) { + imesa->CurrentTexObj[ i ] = NULL; + imesa->dirty &= ~(I830_UPLOAD_TEX0 << i); + } + } + } +} + +/* From linux kernel i386 header files, copes with odd sizes better + * than COPY_DWORDS would: + */ +static __inline__ void * __memcpy(void * to, const void * from, size_t n) +{ +int d0, d1, d2; +__asm__ __volatile__( + "rep ; movsl\n\t" + "testb $2,%b4\n\t" + "je 1f\n\t" + "movsw\n" + "1:\ttestb $1,%b4\n\t" + "je 2f\n\t" + "movsb\n" + "2:" + : "=&c" (d0), "=&D" (d1), "=&S" (d2) + :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from) + : "memory"); +return (to); +} + + +/* Upload an image from mesa's internal copy. + */ +static void i830UploadTexLevel( i830ContextPtr imesa, + i830TextureObjectPtr t, int hwlevel ) +{ + const struct gl_texture_image *image = t->image[0][hwlevel].image; + int j; + + if (!image || !image->Data) + return; + + if (image->Width * image->TexFormat->TexelBytes == t->Pitch) { + GLubyte *dst = (GLubyte *)(t->BufAddr + t->image[0][hwlevel].offset); + GLubyte *src = (GLubyte *)image->Data; + + memcpy( dst, src, t->Pitch * image->Height ); + } + else switch (image->TexFormat->TexelBytes) { + case 1: + { + GLubyte *dst = (GLubyte *)(t->BufAddr + t->image[0][hwlevel].offset); + GLubyte *src = (GLubyte *)image->Data; + + for (j = 0 ; j < image->Height ; j++, dst += t->Pitch) { + __memcpy(dst, src, image->Width ); + src += image->Width; + } + } + break; + + case 2: + { + GLushort *dst = (GLushort *)(t->BufAddr + t->image[0][hwlevel].offset); + GLushort *src = (GLushort *)image->Data; + + for (j = 0 ; j < image->Height ; j++, dst += (t->Pitch/2)) { + __memcpy(dst, src, image->Width * 2 ); + src += image->Width; + } + } + break; + + case 4: + { + GLuint *dst = (GLuint *)(t->BufAddr + t->image[0][hwlevel].offset); + GLuint *src = (GLuint *)image->Data; + + for (j = 0 ; j < image->Height ; j++, dst += (t->Pitch/4)) { + __memcpy(dst, src, image->Width * 4 ); + src += image->Width; + } + } + break; + + default: + fprintf(stderr, "%s: Not supported texel size %d\n", + __FUNCTION__, image->TexFormat->TexelBytes); + } +} + + +/* This is called with the lock held. May have to eject our own and/or + * other client's texture objects to make room for the upload. + */ + +int i830UploadTexImagesLocked( i830ContextPtr imesa, i830TextureObjectPtr t ) +{ + int ofs; + + if ( t->base.memBlock == NULL ) { + int heap; + + heap = driAllocateTexture( imesa->texture_heaps, imesa->nr_heaps, + (driTextureObject *) t ); + if ( heap == -1 ) { + return -1; + } + + /* Set the base offset of the texture image */ + ofs = t->base.memBlock->ofs; + t->BufAddr = imesa->i830Screen->tex.map + ofs; + t->Setup[I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE | + (imesa->i830Screen->textureOffset + ofs)); + + if (t == imesa->CurrentTexObj[0]) + imesa->dirty |= I830_UPLOAD_TEX0; + + if (t == imesa->CurrentTexObj[1]) + imesa->dirty |= I830_UPLOAD_TEX1; +#if 0 + if (t == imesa->CurrentTexObj[2]) + I830_STATECHANGE(imesa, I830_UPLOAD_TEX2); + + if (t == imesa->CurrentTexObj[3]) + I830_STATECHANGE(imesa, I830_UPLOAD_TEX3); +#endif + } + + + /* Let the world know we've used this memory recently. + */ + driUpdateTextureLRU( (driTextureObject *) t ); + + if (imesa->texture_heaps[0]->timestamp >= GET_DISPATCH_AGE(imesa)) + i830WaitAgeLocked( imesa, imesa->texture_heaps[0]->timestamp ); + + /* Upload any images that are new */ + if (t->base.dirty_images[0]) { + int i; + const int numLevels = t->base.lastLevel - t->base.firstLevel + 1; + + for (i = 0 ; i < numLevels ; i++) { + if ( (t->base.dirty_images[0] & (1 << (i+t->base.firstLevel))) != 0 ) { + i830UploadTexLevel( imesa, t, i ); + } + } + t->base.dirty_images[0] = 0; + imesa->sarea->perf_boxes |= I830_BOX_TEXTURE_LOAD; + } + + return 0; +} diff --git a/src/mesa/drivers/dri/i830/i830_texstate.c b/src/mesa/drivers/dri/i830/i830_texstate.c new file mode 100644 index 0000000000..03c98d2ee9 --- /dev/null +++ b/src/mesa/drivers/dri/i830/i830_texstate.c @@ -0,0 +1,1607 @@ +/************************************************************************** + +Copyright 2001 2d3d Inc., Delray Beach, FL + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_texstate.c,v 1.3 2002/12/10 01:26:53 dawes Exp $ */ + +/* + * Author: + * Jeff Hartmann <jhartmann@2d3d.com> + * + * Heavily based on the I810 driver, which was written by: + * Keith Whitwell <keithw@tungstengraphics.com> + */ + +#include "glheader.h" +#include "macros.h" +#include "mtypes.h" +#include "simple_list.h" +#include "enums.h" +#include "texformat.h" +#include "texstore.h" +#include "texutil.h" + +#include "mm.h" + +#include "i830_screen.h" +#include "i830_dri.h" + +#include "i830_context.h" +#include "i830_tex.h" +#include "i830_state.h" +#include "i830_ioctl.h" + +#define I830_TEX_UNIT_ENABLED(unit) (1<<unit) + +static void i830SetTexImages( i830ContextPtr imesa, + struct gl_texture_object *tObj ) +{ + GLuint total_height, pitch, i, textureFormat; + i830TextureObjectPtr t = (i830TextureObjectPtr) tObj->DriverData; + const struct gl_texture_image *baseImage = tObj->Image[tObj->BaseLevel]; + GLint firstLevel, lastLevel, numLevels; + + switch( baseImage->TexFormat->MesaFormat ) { + case MESA_FORMAT_L8: + t->texelBytes = 1; + textureFormat = MAPSURF_8BIT | MT_8BIT_L8; + break; + + case MESA_FORMAT_I8: + t->texelBytes = 1; + textureFormat = MAPSURF_8BIT | MT_8BIT_I8; + break; + + case MESA_FORMAT_AL88: + t->texelBytes = 2; + textureFormat = MAPSURF_16BIT | MT_16BIT_AY88; + break; + + case MESA_FORMAT_RGB565: + t->texelBytes = 2; + textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565; + break; + + case MESA_FORMAT_ARGB1555: + t->texelBytes = 2; + textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555; + break; + + case MESA_FORMAT_ARGB4444: + t->texelBytes = 2; + textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB4444; + break; + + case MESA_FORMAT_ARGB8888: + t->texelBytes = 4; + textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888; + break; + + case MESA_FORMAT_YCBCR_REV: + t->texelBytes = 2; + textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL | + TM0S1_COLORSPACE_CONVERSION); + break; + + case MESA_FORMAT_YCBCR: + t->texelBytes = 2; + textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY | /* ??? */ + TM0S1_COLORSPACE_CONVERSION); + break; + + default: + fprintf(stderr, "%s: bad image format\n", __FUNCTION__); + free( t ); + return; + } + + /* Compute which mipmap levels we really want to send to the hardware. + * This depends on the base image size, GL_TEXTURE_MIN_LOD, + * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL. + * Yes, this looks overly complicated, but it's all needed. + */ + switch (tObj->Target) { + case GL_TEXTURE_1D: + case GL_TEXTURE_2D: + firstLevel = tObj->BaseLevel + (GLint) (tObj->MinLod + 0.5); + firstLevel = MAX2(firstLevel, tObj->BaseLevel); + lastLevel = tObj->BaseLevel + (GLint) (tObj->MaxLod + 0.5); + lastLevel = MAX2(lastLevel, tObj->BaseLevel); + lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2); + lastLevel = MIN2(lastLevel, tObj->MaxLevel); + lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */ + break; + case GL_TEXTURE_RECTANGLE_NV: + firstLevel = lastLevel = 0; + break; + default: + fprintf(stderr, "%s: bad target %s\n", __FUNCTION__, + _mesa_lookup_enum_by_nr(tObj->Target)); + return; + } + + + /* save these values */ + t->base.firstLevel = firstLevel; + t->base.lastLevel = lastLevel; + + + /* Figure out the amount of memory required to hold all the mipmap + * levels. Choose the smallest pitch to accomodate the largest + * mipmap: + */ + numLevels = lastLevel - firstLevel + 1; + + /* Pitch would be subject to additional rules if texture memory were + * tiled. Currently it isn't. + */ + if (0) { + pitch = 128; + while (pitch < tObj->Image[firstLevel]->Width * t->texelBytes) + pitch *= 2; + } + else { + pitch = tObj->Image[firstLevel]->Width * t->texelBytes; + pitch = (pitch + 3) & ~3; + } + + + /* All images must be loaded at this pitch. Count the number of + * lines required: + */ + for ( total_height = i = 0 ; i < numLevels ; i++ ) { + t->image[0][i].image = tObj->Image[firstLevel + i]; + if (!t->image[0][i].image) + break; + + t->image[0][i].offset = total_height * pitch; + t->image[0][i].internalFormat = baseImage->Format; + total_height += t->image[0][i].image->Height; + } + + t->Pitch = pitch; + t->base.totalSize = total_height*pitch; + t->Setup[I830_TEXREG_TM0S1] = + (((tObj->Image[firstLevel]->Height - 1) << TM0S1_HEIGHT_SHIFT) | + ((tObj->Image[firstLevel]->Width - 1) << TM0S1_WIDTH_SHIFT) | + textureFormat); + t->Setup[I830_TEXREG_TM0S2] = + ((((pitch / 4) - 1) << TM0S2_PITCH_SHIFT)); + t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAX_MIP_MASK; + t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_MIP_MASK; + t->Setup[I830_TEXREG_TM0S3] |= ((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT; + t->dirty = I830_UPLOAD_TEX0 | I830_UPLOAD_TEX1; + + LOCK_HARDWARE( imesa ); + i830UploadTexImagesLocked( imesa, t ); + UNLOCK_HARDWARE( imesa ); +} + +/* ================================================================ + * Texture combine functions + */ +static __inline__ GLuint GetTexelOp(GLint unit) +{ + switch(unit) { + case 0: return TEXBLENDARG_TEXEL0; + case 1: return TEXBLENDARG_TEXEL1; + case 2: return TEXBLENDARG_TEXEL2; + case 3: return TEXBLENDARG_TEXEL3; + default: return TEXBLENDARG_TEXEL0; + } +} + +static void i830SetBlend_GL1_2(i830ContextPtr imesa, int curTex, + GLenum envMode, GLenum format) +{ + GLuint texel_op = GetTexelOp(curTex); + + if(I830_DEBUG&DEBUG_TEXTURE) + fprintf(stderr, "%s %s %s unit (%d) texel_op(0x%x)\n", + __FUNCTION__, + _mesa_lookup_enum_by_nr(format), + _mesa_lookup_enum_by_nr(envMode), + curTex, + texel_op); + + switch(envMode) { + case GL_REPLACE: + switch(format) { + case GL_ALPHA: + imesa->TexBlend[curTex][0] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][1] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][2] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlend[curTex][3] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + texel_op); + imesa->TexBlendColorPipeNum[curTex] = 0; + imesa->TexBlendWordsUsed[curTex] = 4; + break; + case GL_LUMINANCE: + case GL_RGB: + case GL_YCBCR_MESA: + imesa->TexBlend[curTex][0] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][1] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][2] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + texel_op); + imesa->TexBlend[curTex][3] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlendColorPipeNum[curTex] = 0; + imesa->TexBlendWordsUsed[curTex] = 4; + break; + + case GL_INTENSITY: + case GL_LUMINANCE_ALPHA: + case GL_RGBA: + imesa->TexBlend[curTex][0] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][1] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][2] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + texel_op); + imesa->TexBlend[curTex][3] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + texel_op); + imesa->TexBlendColorPipeNum[curTex] = 0; + imesa->TexBlendWordsUsed[curTex] = 4; + break; + default: + /* Always set to passthru if something is funny */ + imesa->TexBlend[curTex][0] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][1] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][2] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlend[curTex][3] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlendColorPipeNum[curTex] = 0; + imesa->TexBlendWordsUsed[curTex] = 4; + break; + } + break; + + case GL_MODULATE: + switch(format) { + case GL_ALPHA: + imesa->TexBlend[curTex][0] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][1] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_MODULATE); + imesa->TexBlend[curTex][2] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlend[curTex][3] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + texel_op); + imesa->TexBlend[curTex][4] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG2 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlendColorPipeNum[curTex] = 0; + imesa->TexBlendWordsUsed[curTex] = 5; + break; + + case GL_LUMINANCE: + case GL_RGB: + case GL_YCBCR_MESA: + imesa->TexBlend[curTex][0] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_MODULATE); + imesa->TexBlend[curTex][1] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][2] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + texel_op); + imesa->TexBlend[curTex][3] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG2 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlend[curTex][4] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlendColorPipeNum[curTex] = 0; + imesa->TexBlendWordsUsed[curTex] = 5; + break; + + case GL_INTENSITY: + case GL_LUMINANCE_ALPHA: + case GL_RGBA: + imesa->TexBlend[curTex][0] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_MODULATE); + imesa->TexBlend[curTex][1] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_MODULATE); + imesa->TexBlend[curTex][2] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + texel_op); + imesa->TexBlend[curTex][3] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG2 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlend[curTex][4] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + texel_op); + imesa->TexBlend[curTex][5] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG2 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlendColorPipeNum[curTex] = 0; + imesa->TexBlendWordsUsed[curTex] = 6; + break; + default: + /* Always set to passthru if something is funny */ + imesa->TexBlend[curTex][0] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][1] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][2] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlend[curTex][3] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlendColorPipeNum[curTex] = 0; + imesa->TexBlendWordsUsed[curTex] = 4; + break; + } + break; + + case GL_DECAL: + switch(format) { + case GL_RGB: + case GL_YCBCR_MESA: + imesa->TexBlend[curTex][0] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][1] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][2] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + texel_op); + imesa->TexBlend[curTex][3] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlendColorPipeNum[curTex] = 0; + imesa->TexBlendWordsUsed[curTex] = 4; + break; + + case GL_RGBA: + imesa->TexBlend[curTex][0] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_BLEND); + imesa->TexBlend[curTex][1] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][2] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG0 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_REPLICATE_ALPHA | + texel_op); + imesa->TexBlend[curTex][3] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + texel_op); + imesa->TexBlend[curTex][4] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG2 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlend[curTex][5] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlendColorPipeNum[curTex] = 0; + imesa->TexBlendWordsUsed[curTex] = 6; + break; + default: + /* Always set to passthru if something is funny */ + imesa->TexBlend[curTex][0] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][1] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][2] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlend[curTex][3] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlendColorPipeNum[curTex] = 0; + imesa->TexBlendWordsUsed[curTex] = 4; + break; + } + break; + + case GL_BLEND: + switch(format) { + case GL_ALPHA: + imesa->TexBlend[curTex][0] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][1] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_MODULATE); + imesa->TexBlend[curTex][2] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlend[curTex][3] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + texel_op); + imesa->TexBlend[curTex][4] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG2 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlendColorPipeNum[curTex] = 0; + imesa->TexBlendWordsUsed[curTex] = 5; + break; + + case GL_LUMINANCE: + case GL_RGB: + case GL_YCBCR_MESA: + imesa->TexBlend[curTex][0] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_BLEND); + imesa->TexBlend[curTex][1] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][2] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG0 | + TEXBLENDARG_MODIFY_PARMS | + texel_op); + imesa->TexBlend[curTex][3] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_FACTOR_N); + imesa->TexBlend[curTex][4] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG2 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlend[curTex][5] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlendColorPipeNum[curTex] = 0; + imesa->TexBlendWordsUsed[curTex] = 6; + break; + + case GL_INTENSITY: + imesa->TexBlend[curTex][0] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_BLEND); + imesa->TexBlend[curTex][1] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_BLEND); + imesa->TexBlend[curTex][2] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG0 | + TEXBLENDARG_MODIFY_PARMS | + texel_op); + imesa->TexBlend[curTex][3] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_FACTOR_N); + imesa->TexBlend[curTex][4] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG2 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlend[curTex][5] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG0 | + TEXBLENDARG_MODIFY_PARMS | + texel_op); + imesa->TexBlend[curTex][6] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_FACTOR_N); + imesa->TexBlend[curTex][7] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG2 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlendColorPipeNum[curTex] = 0; + imesa->TexBlendWordsUsed[curTex] = 8; + break; + + case GL_LUMINANCE_ALPHA: + case GL_RGBA: + imesa->TexBlend[curTex][0] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_BLEND); + imesa->TexBlend[curTex][1] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_MODULATE); + imesa->TexBlend[curTex][2] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG0 | + TEXBLENDARG_MODIFY_PARMS | + texel_op); + imesa->TexBlend[curTex][3] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_FACTOR_N); + imesa->TexBlend[curTex][4] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG2 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlend[curTex][5] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + texel_op); + imesa->TexBlend[curTex][6] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG2 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlendColorPipeNum[curTex] = 0; + imesa->TexBlendWordsUsed[curTex] = 7; + break; + default: + /* Always set to passthru if something is funny */ + imesa->TexBlend[curTex][0] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][1] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][2] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlend[curTex][3] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlendColorPipeNum[curTex] = 0; + imesa->TexBlendWordsUsed[curTex] = 4; + break; + } + break; + + case GL_ADD: + switch(format) { + case GL_ALPHA: + imesa->TexBlend[curTex][0] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][1] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_MODULATE); + imesa->TexBlend[curTex][2] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlend[curTex][3] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + texel_op); + imesa->TexBlend[curTex][4] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG2 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlendColorPipeNum[curTex] = 0; + imesa->TexBlendWordsUsed[curTex] = 5; + break; + case GL_LUMINANCE: + case GL_RGB: + case GL_YCBCR_MESA: + imesa->TexBlend[curTex][0] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ADD); + imesa->TexBlend[curTex][1] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][2] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + texel_op); + imesa->TexBlend[curTex][3] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG2 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlend[curTex][4] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlendColorPipeNum[curTex] = 0; + imesa->TexBlendWordsUsed[curTex] = 5; + break; + + case GL_INTENSITY: + imesa->TexBlend[curTex][0] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ADD); + imesa->TexBlend[curTex][1] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ADD); + imesa->TexBlend[curTex][2] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + texel_op); + imesa->TexBlend[curTex][3] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG2 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlend[curTex][4] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + texel_op); + imesa->TexBlend[curTex][5] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG2 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlendColorPipeNum[curTex] = 0; + imesa->TexBlendWordsUsed[curTex] = 6; + break; + + case GL_LUMINANCE_ALPHA: + case GL_RGBA: + imesa->TexBlend[curTex][0] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ADD); + imesa->TexBlend[curTex][1] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_MODULATE); + imesa->TexBlend[curTex][2] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + texel_op); + imesa->TexBlend[curTex][3] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG2 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlend[curTex][4] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + texel_op); + imesa->TexBlend[curTex][5] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG2 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlendColorPipeNum[curTex] = 0; + imesa->TexBlendWordsUsed[curTex] = 6; + break; + default: + /* Always set to passthru if something is funny */ + imesa->TexBlend[curTex][0] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][1] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][2] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlend[curTex][3] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlendColorPipeNum[curTex] = 0; + imesa->TexBlendWordsUsed[curTex] = 4; + break; + } + break; + default: + /* Always set to passthru if something is funny */ + imesa->TexBlend[curTex][0] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][1] = (STATE3D_MAP_BLEND_OP_CMD(curTex) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[curTex][2] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlend[curTex][3] = (STATE3D_MAP_BLEND_ARG_CMD(curTex) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlendColorPipeNum[curTex] = 0; + imesa->TexBlendWordsUsed[curTex] = 4; + break; + } + + if (I830_DEBUG&DEBUG_TEXTURE) + fprintf(stderr, "%s\n", __FUNCTION__); +} + +static void i830SetTexEnvCombine(i830ContextPtr imesa, + const struct gl_texture_unit *texUnit, + GLint unit) +{ + GLuint blendop; + GLuint ablendop; + GLuint args_RGB[3]; + GLuint args_A[3]; + GLuint texel_op = GetTexelOp(unit); + GLuint rgb_shift = texUnit->CombineScaleShiftRGB; + GLuint alpha_shift = texUnit->CombineScaleShiftA; + int i; + + if(I830_DEBUG&DEBUG_TEXTURE) + fprintf(stderr, "%s\n", __FUNCTION__); + + switch(texUnit->CombineModeRGB) { + case GL_REPLACE: + blendop = TEXBLENDOP_ARG1; + break; + case GL_MODULATE: + blendop = TEXBLENDOP_MODULATE; + break; + case GL_ADD: + blendop = TEXBLENDOP_ADD; + break; + case GL_ADD_SIGNED: + blendop = TEXBLENDOP_ADDSIGNED; + break; + case GL_INTERPOLATE: + blendop = TEXBLENDOP_BLEND; + break; + case GL_SUBTRACT: + blendop = TEXBLENDOP_SUBTRACT; + break; + case GL_DOT3_RGB_EXT: + case GL_DOT3_RGBA_EXT: + /* The EXT version of the DOT3 extension does not support the + * scale factor, but the ARB version (and the version in OpenGL + * 1.3) does. + */ + rgb_shift = 0; + alpha_shift = 0; + /* FALLTHROUGH */ + + case GL_DOT3_RGB: + case GL_DOT3_RGBA: + blendop = TEXBLENDOP_DOT3; + break; + default: + return; + } + + blendop |= (rgb_shift << TEXOP_SCALE_SHIFT); + + switch(texUnit->CombineModeA) { + case GL_REPLACE: + ablendop = TEXBLENDOP_ARG1; + break; + case GL_MODULATE: + ablendop = TEXBLENDOP_MODULATE; + break; + case GL_ADD: + ablendop = TEXBLENDOP_ADD; + break; + case GL_ADD_SIGNED: + ablendop = TEXBLENDOP_ADDSIGNED; + break; + case GL_INTERPOLATE: + ablendop = TEXBLENDOP_BLEND; + break; + case GL_SUBTRACT: + ablendop = TEXBLENDOP_SUBTRACT; + break; + default: + return; + } + + if ( (texUnit->CombineModeRGB == GL_DOT3_RGBA_EXT) + || (texUnit->CombineModeRGB == GL_DOT3_RGBA) ) { + ablendop = TEXBLENDOP_DOT3; + } + + ablendop |= (alpha_shift << TEXOP_SCALE_SHIFT); + + /* Handle RGB args */ + for(i = 0; i < 3; i++) { + switch(texUnit->CombineSourceRGB[i]) { + case GL_TEXTURE: + args_RGB[i] = texel_op; + break; + case GL_CONSTANT: + args_RGB[i] = TEXBLENDARG_FACTOR_N; + break; + case GL_PRIMARY_COLOR: + args_RGB[i] = TEXBLENDARG_DIFFUSE; + break; + case GL_PREVIOUS: + args_RGB[i] = TEXBLENDARG_CURRENT; + break; + default: + return; + + } + + switch(texUnit->CombineOperandRGB[i]) { + case GL_SRC_COLOR: + args_RGB[i] |= 0; + break; + case GL_ONE_MINUS_SRC_COLOR: + args_RGB[i] |= TEXBLENDARG_INV_ARG; + break; + case GL_SRC_ALPHA: + args_RGB[i] |= TEXBLENDARG_REPLICATE_ALPHA; + break; + case GL_ONE_MINUS_SRC_ALPHA: + args_RGB[i] |= (TEXBLENDARG_REPLICATE_ALPHA | + TEXBLENDARG_INV_ARG); + break; + default: + return; + } + } + + /* Handle A args */ + for(i = 0; i < 3; i++) { + switch(texUnit->CombineSourceA[i]) { + case GL_TEXTURE: + args_A[i] = texel_op; + break; + case GL_CONSTANT: + args_A[i] = TEXBLENDARG_FACTOR_N; + break; + case GL_PRIMARY_COLOR: + args_A[i] = TEXBLENDARG_DIFFUSE; + break; + case GL_PREVIOUS: + args_A[i] = TEXBLENDARG_CURRENT; + break; + default: + return; + + } + + switch(texUnit->CombineOperandA[i]) { + case GL_SRC_ALPHA: + args_A[i] |= 0; + break; + case GL_ONE_MINUS_SRC_ALPHA: + args_A[i] |= TEXBLENDARG_INV_ARG; + break; + default: + return; + } + } + + /* Native Arg1 == Arg0 in GL_EXT_texture_env_combine spec */ + /* Native Arg2 == Arg1 in GL_EXT_texture_env_combine spec */ + /* Native Arg0 == Arg2 in GL_EXT_texture_env_combine spec */ + + /* When we render we need to figure out which is the last really enabled + * tex unit, and put last stage on it + */ + + imesa->TexBlendColorPipeNum[unit] = 0; + + /* Build color pipeline */ + + imesa->TexBlend[unit][0] = (STATE3D_MAP_BLEND_OP_CMD(unit) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_MODIFY_PARMS | + blendop); + imesa->TexBlend[unit][1] = (STATE3D_MAP_BLEND_ARG_CMD(unit) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + args_RGB[0]); + imesa->TexBlend[unit][2] = (STATE3D_MAP_BLEND_ARG_CMD(unit) | + TEXPIPE_COLOR | + TEXBLEND_ARG2 | + TEXBLENDARG_MODIFY_PARMS | + args_RGB[1]); + imesa->TexBlend[unit][3] = (STATE3D_MAP_BLEND_ARG_CMD(unit) | + TEXPIPE_COLOR | + TEXBLEND_ARG0 | + TEXBLENDARG_MODIFY_PARMS | + args_RGB[2]); + + /* Build Alpha pipeline */ + imesa->TexBlend[unit][4] = (STATE3D_MAP_BLEND_OP_CMD(unit) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_MODIFY_PARMS | + ablendop); + imesa->TexBlend[unit][5] = (STATE3D_MAP_BLEND_ARG_CMD(unit) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + args_A[0]); + imesa->TexBlend[unit][6] = (STATE3D_MAP_BLEND_ARG_CMD(unit) | + TEXPIPE_ALPHA | + TEXBLEND_ARG2 | + TEXBLENDARG_MODIFY_PARMS | + args_A[1]); + imesa->TexBlend[unit][7] = (STATE3D_MAP_BLEND_ARG_CMD(unit) | + TEXPIPE_ALPHA | + TEXBLEND_ARG0 | + TEXBLENDARG_MODIFY_PARMS | + args_A[2]); + + { + GLubyte r, g, b, a; + GLfloat *fc = texUnit->EnvColor; + + FLOAT_COLOR_TO_UBYTE_COLOR(r, fc[RCOMP]); + FLOAT_COLOR_TO_UBYTE_COLOR(g, fc[GCOMP]); + FLOAT_COLOR_TO_UBYTE_COLOR(b, fc[BCOMP]); + FLOAT_COLOR_TO_UBYTE_COLOR(a, fc[ACOMP]); + + imesa->TexBlend[unit][8] = STATE3D_COLOR_FACTOR_CMD(unit); + imesa->TexBlend[unit][9] = ((a << 24) | + (r << 16) | + (g << 8) | + b); + } + imesa->TexBlendWordsUsed[unit] = 10; +} + + + + +static void i830UpdateTexEnv( GLcontext *ctx, GLuint unit ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + const struct gl_texture_object *tObj = texUnit->_Current; + i830TextureObjectPtr t = (i830TextureObjectPtr)tObj->DriverData; + GLuint col; + + imesa->TexBlendWordsUsed[unit] = 0; + + if (0) fprintf(stderr, "i830UpdateTexEnv called : %s\n", + _mesa_lookup_enum_by_nr(texUnit->EnvMode)); + + if(texUnit->EnvMode == GL_COMBINE) { + i830SetTexEnvCombine(imesa, + texUnit, + unit); + } else { + i830SetBlend_GL1_2(imesa, + unit, + texUnit->EnvMode, + t->image[0][0].internalFormat); + + /* add blend color */ + { + GLubyte r, g, b, a; + GLfloat *fc = texUnit->EnvColor; + + FLOAT_COLOR_TO_UBYTE_COLOR(r, fc[RCOMP]); + FLOAT_COLOR_TO_UBYTE_COLOR(g, fc[GCOMP]); + FLOAT_COLOR_TO_UBYTE_COLOR(b, fc[BCOMP]); + FLOAT_COLOR_TO_UBYTE_COLOR(a, fc[ACOMP]); + + col = ((a << 24) | + (r << 16) | + (g << 8) | + b); + } + + { + int i; + + i = imesa->TexBlendWordsUsed[unit]; + imesa->TexBlend[unit][i++] = STATE3D_COLOR_FACTOR_CMD(unit); + imesa->TexBlend[unit][i++] = col; + + imesa->TexBlendWordsUsed[unit] = i; + } + } + + I830_STATECHANGE( imesa, I830_UPLOAD_TEXBLEND_N(unit) ); +} + + +/* This is bogus -- can't load the same texture object on two units. + */ +static void i830TexSetUnit( i830TextureObjectPtr t, GLuint unit ) +{ + if(I830_DEBUG&DEBUG_TEXTURE) + fprintf(stderr, "%s unit(%d)\n", __FUNCTION__, unit); + + t->Setup[I830_TEXREG_TM0LI] = (STATE3D_LOAD_STATE_IMMEDIATE_2 | + (LOAD_TEXTURE_MAP0 << unit) | 4); + + I830_SET_FIELD(t->Setup[I830_TEXREG_MCS], MAP_UNIT_MASK, MAP_UNIT(unit)); + + t->current_unit = unit; + t->base.bound |= (1U << unit); +} + +#define TEXCOORDTYPE_MASK (~((1<<13)|(1<<12)|(1<<11))) + + +static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + struct gl_texture_object *tObj = texUnit->_Current; + i830TextureObjectPtr t = (i830TextureObjectPtr)tObj->DriverData; + GLuint mcs = t->Setup[I830_TEXREG_MCS] & TEXCOORDTYPE_MASK; + + /* Handle projective texturing */ + if (imesa->vertex_format & (1<<31)) { + mcs |= TEXCOORDTYPE_HOMOGENEOUS; + } else { + mcs |= TEXCOORDTYPE_CARTESIAN; + } + + /* Fallback if there's a texture border */ + if ( tObj->Image[tObj->BaseLevel]->Border > 0 ) { + return GL_FALSE; + } + + /* Upload teximages (not pipelined) + */ + if (t->base.dirty_images[0]) { + i830SetTexImages( imesa, tObj ); + if (!t->base.memBlock) { + return GL_FALSE; + } + } + + /* Update state if this is a different texture object to last + * time. + */ + if (imesa->CurrentTexObj[unit] != t || + mcs != t->Setup[I830_TEXREG_MCS]) { + + if ( imesa->CurrentTexObj[unit] != NULL ) { + /* The old texture is no longer bound to this texture unit. + * Mark it as such. + */ + + imesa->CurrentTexObj[unit]->base.bound &= ~(1U << unit); + } + + I830_STATECHANGE(imesa, (I830_UPLOAD_TEX0<<unit)); + t->Setup[I830_TEXREG_MCS] = mcs; + imesa->CurrentTexObj[unit] = t; + i830TexSetUnit(t, unit); + } + + /* Update texture environment if texture object image format or + * texture environment state has changed. + * + * KW: doesn't work -- change from tex0 only to tex0+tex1 gets + * missed (need to update last stage flag?). Call + * i830UpdateTexEnv always. + */ + if (tObj->Image[tObj->BaseLevel]->Format != + imesa->TexEnvImageFmt[unit]) { + imesa->TexEnvImageFmt[unit] = tObj->Image[tObj->BaseLevel]->Format; + } + i830UpdateTexEnv( ctx, unit ); + imesa->TexEnabledMask |= I830_TEX_UNIT_ENABLED(unit); + + return GL_TRUE; +} + +static GLboolean enable_tex_rect( GLcontext *ctx, GLuint unit ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + struct gl_texture_object *tObj = texUnit->_Current; + i830TextureObjectPtr t = (i830TextureObjectPtr)tObj->DriverData; + GLuint mcs = t->Setup[I830_TEXREG_MCS]; + + mcs &= ~TEXCOORDS_ARE_NORMAL; + mcs |= TEXCOORDS_ARE_IN_TEXELUNITS; + + if (mcs != t->Setup[I830_TEXREG_MCS]) { + I830_STATECHANGE(imesa, (I830_UPLOAD_TEX0<<unit)); + t->Setup[I830_TEXREG_MCS] = mcs; + } + + return GL_TRUE; +} + + +static GLboolean enable_tex_2d( GLcontext *ctx, GLuint unit ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + struct gl_texture_object *tObj = texUnit->_Current; + i830TextureObjectPtr t = (i830TextureObjectPtr)tObj->DriverData; + GLuint mcs = t->Setup[I830_TEXREG_MCS]; + + mcs &= ~TEXCOORDS_ARE_IN_TEXELUNITS; + mcs |= TEXCOORDS_ARE_NORMAL; + + if (mcs != t->Setup[I830_TEXREG_MCS]) { + I830_STATECHANGE(imesa, (I830_UPLOAD_TEX0<<unit)); + t->Setup[I830_TEXREG_MCS] = mcs; + } + + return GL_TRUE; +} + + +static GLboolean disable_tex0( GLcontext *ctx ) +{ + const int unit = 0; + i830ContextPtr imesa = I830_CONTEXT(ctx); + + /* This is happening too often. I need to conditionally send diffuse + * state to the card. Perhaps a diffuse dirty flag of some kind. + * Will need to change this logic if more than 2 texture units are + * used. We need to only do this up to the last unit enabled, or unit + * one if nothing is enabled. + */ + + if ( imesa->CurrentTexObj[unit] != NULL ) { + /* The old texture is no longer bound to this texture unit. + * Mark it as such. + */ + + imesa->CurrentTexObj[unit]->base.bound &= ~(1U << unit); + imesa->CurrentTexObj[unit] = NULL; + } + + imesa->TexEnvImageFmt[unit] = 0; + imesa->dirty &= ~(I830_UPLOAD_TEX_N(unit)); + + imesa->TexBlend[unit][0] = (STATE3D_MAP_BLEND_OP_CMD(unit) | + TEXPIPE_COLOR | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + DISABLE_TEX_CNTRL_STAGE | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[unit][1] = (STATE3D_MAP_BLEND_OP_CMD(unit) | + TEXPIPE_ALPHA | + ENABLE_TEXOUTPUT_WRT_SEL | + TEXOP_OUTPUT_CURRENT | + TEXOP_SCALE_1X | + TEXOP_MODIFY_PARMS | + TEXBLENDOP_ARG1); + imesa->TexBlend[unit][2] = (STATE3D_MAP_BLEND_ARG_CMD(unit) | + TEXPIPE_COLOR | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlend[unit][3] = (STATE3D_MAP_BLEND_ARG_CMD(unit) | + TEXPIPE_ALPHA | + TEXBLEND_ARG1 | + TEXBLENDARG_MODIFY_PARMS | + TEXBLENDARG_CURRENT); + imesa->TexBlendColorPipeNum[unit] = 0; + imesa->TexBlendWordsUsed[unit] = 4; + I830_STATECHANGE(imesa, (I830_UPLOAD_TEXBLEND_N(unit))); + + return GL_TRUE; +} + +static GLboolean i830UpdateTexUnit( GLcontext *ctx, GLuint unit ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + + imesa->TexEnabledMask &= ~(I830_TEX_UNIT_ENABLED(unit)); + + if (texUnit->_ReallyEnabled == TEXTURE_2D_BIT) { + return (enable_tex_common( ctx, unit ) && + enable_tex_2d( ctx, unit )); + } + else if (texUnit->_ReallyEnabled == TEXTURE_RECT_BIT) { + return (enable_tex_common( ctx, unit ) && + enable_tex_rect( ctx, unit )); + } + else if (texUnit->_ReallyEnabled) { + return GL_FALSE; + } + else if (unit == 0) { + return disable_tex0( ctx ); + } + else { + return GL_TRUE; + } +} + + +/* Called from vb code to update projective texturing properly */ +void i830UpdateTexUnitProj( GLcontext *ctx, GLuint unit, GLboolean state ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + struct gl_texture_object *tObj = texUnit->_Current; + i830TextureObjectPtr t; + GLuint mcs; + + if (!tObj) return; + + t = (i830TextureObjectPtr)tObj->DriverData; + mcs = (t->Setup[I830_TEXREG_MCS] & + TEXCOORDTYPE_MASK & + ~TEXCOORDS_ARE_NORMAL); + + /* Handle projective texturing */ + if (state) { + mcs |= TEXCOORDTYPE_HOMOGENEOUS; + } else { + mcs |= TEXCOORDTYPE_CARTESIAN; + } + + if (texUnit->_ReallyEnabled == TEXTURE_2D_BIT) { + mcs |= TEXCOORDS_ARE_NORMAL; + } + else if (texUnit->_ReallyEnabled == TEXTURE_RECT_BIT) { + mcs |= TEXCOORDS_ARE_IN_TEXELUNITS; + } + else + return; + + if (mcs != t->Setup[I830_TEXREG_MCS]) { + I830_STATECHANGE(imesa, (I830_UPLOAD_TEX0<<unit)); + t->Setup[I830_TEXREG_MCS] = mcs; + } +} + +/* Only deal with unit 0 and 1 for right now */ +void i830UpdateTextureState( GLcontext *ctx ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + int pipe_num = 0; + GLboolean ok; + + ok = (i830UpdateTexUnit( ctx, 0 ) && + i830UpdateTexUnit( ctx, 1 ) && + i830UpdateTexUnit( ctx, 2 ) && + i830UpdateTexUnit( ctx, 3 )); + + FALLBACK( imesa, I830_FALLBACK_TEXTURE, !ok ); + + + /* Make sure last stage is set correctly */ + if(imesa->TexEnabledMask & I830_TEX_UNIT_ENABLED(3)) { + pipe_num = imesa->TexBlendColorPipeNum[3]; + imesa->TexBlend[3][pipe_num] |= TEXOP_LAST_STAGE; + } else if(imesa->TexEnabledMask & I830_TEX_UNIT_ENABLED(2)) { + pipe_num = imesa->TexBlendColorPipeNum[2]; + imesa->TexBlend[2][pipe_num] |= TEXOP_LAST_STAGE; + } else if(imesa->TexEnabledMask & I830_TEX_UNIT_ENABLED(1)) { + pipe_num = imesa->TexBlendColorPipeNum[1]; + imesa->TexBlend[1][pipe_num] |= TEXOP_LAST_STAGE; + } else { + pipe_num = imesa->TexBlendColorPipeNum[0]; + imesa->TexBlend[0][pipe_num] |= TEXOP_LAST_STAGE; + } +} + + + diff --git a/src/mesa/drivers/dri/i830/i830_tris.c b/src/mesa/drivers/dri/i830/i830_tris.c new file mode 100644 index 0000000000..66720c1efc --- /dev/null +++ b/src/mesa/drivers/dri/i830/i830_tris.c @@ -0,0 +1,880 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_tris.c,v 1.4 2002/12/10 01:26:54 dawes Exp $ */ +/************************************************************************** + +Copyright 2001 VA Linux Systems Inc., Fremont, California. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Original Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Adapted for use on the I830M: + * Jeff Hartmann <jhartmann@2d3d.com> + */ + +#include "glheader.h" +#include "context.h" +#include "macros.h" +#include "enums.h" +#include "dd.h" + +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +#include "i830_screen.h" +#include "i830_dri.h" + +#include "i830_tris.h" +#include "i830_state.h" +#include "i830_vb.h" +#include "i830_ioctl.h" +#include "i830_span.h" + +static void i830RenderPrimitive( GLcontext *ctx, GLenum prim ); + +/*********************************************************************** + * Emit primitives as inline vertices * + ***********************************************************************/ + +#if defined(USE_X86_ASM) +#define COPY_DWORDS( j, vb, vertsize, v ) \ +do { \ + int __tmp; \ + __asm__ __volatile__( "rep ; movsl" \ + : "=%c" (j), "=D" (vb), "=S" (__tmp) \ + : "0" (vertsize), \ + "D" ((long)vb), \ + "S" ((long)v) ); \ +} while (0) +#else +#define COPY_DWORDS( j, vb, vertsize, v ) \ +do { \ + for ( j = 0 ; j < vertsize ; j++ ) \ + vb[j] = ((GLuint *)v)[j]; \ + vb += vertsize; \ +} while (0) +#endif + +static void __inline__ i830_draw_triangle( i830ContextPtr imesa, + i830VertexPtr v0, + i830VertexPtr v1, + i830VertexPtr v2 ) +{ + GLuint vertsize = imesa->vertex_size; + GLuint *vb = i830AllocDmaLow( imesa, 3 * 4 * vertsize ); + int j; + + COPY_DWORDS( j, vb, vertsize, v0 ); + COPY_DWORDS( j, vb, vertsize, v1 ); + COPY_DWORDS( j, vb, vertsize, v2 ); +} + + +static void __inline__ i830_draw_quad( i830ContextPtr imesa, + i830VertexPtr v0, + i830VertexPtr v1, + i830VertexPtr v2, + i830VertexPtr v3 ) +{ + GLuint vertsize = imesa->vertex_size; + GLuint *vb = i830AllocDmaLow( imesa, 6 * 4 * vertsize ); + int j; + + COPY_DWORDS( j, vb, vertsize, v0 ); + COPY_DWORDS( j, vb, vertsize, v1 ); + COPY_DWORDS( j, vb, vertsize, v3 ); + COPY_DWORDS( j, vb, vertsize, v1 ); + COPY_DWORDS( j, vb, vertsize, v2 ); + COPY_DWORDS( j, vb, vertsize, v3 ); +} + + +static __inline__ void i830_draw_point( i830ContextPtr imesa, + i830VertexPtr tmp ) +{ + GLuint vertsize = imesa->vertex_size; + GLuint *vb = i830AllocDmaLow( imesa, 4 * vertsize ); + int j; + + /* Adjust for sub pixel position */ + *(float *)&vb[0] = tmp->v.x - 0.125; + *(float *)&vb[1] = tmp->v.y - 0.125; + for (j = 2 ; j < vertsize ; j++) + vb[j] = tmp->ui[j]; +} + + +static __inline__ void i830_draw_line( i830ContextPtr imesa, + i830VertexPtr v0, + i830VertexPtr v1 ) +{ + GLuint vertsize = imesa->vertex_size; + GLuint *vb = i830AllocDmaLow( imesa, 2 * 4 * vertsize ); + int j; + + COPY_DWORDS( j, vb, vertsize, v0 ); + COPY_DWORDS( j, vb, vertsize, v1 ); +} + + + +/*********************************************************************** + * Macros for t_dd_tritmp.h to draw basic primitives * + ***********************************************************************/ + +#define TRI( a, b, c ) \ +do { \ + if (DO_FALLBACK) \ + imesa->draw_tri( imesa, a, b, c ); \ + else \ + i830_draw_triangle( imesa, a, b, c ); \ +} while (0) + +#define QUAD( a, b, c, d ) \ +do { \ + if (DO_FALLBACK) { \ + imesa->draw_tri( imesa, a, b, d ); \ + imesa->draw_tri( imesa, b, c, d ); \ + } else \ + i830_draw_quad( imesa, a, b, c, d ); \ +} while (0) + +#define LINE( v0, v1 ) \ +do { \ + if (DO_FALLBACK) \ + imesa->draw_line( imesa, v0, v1 ); \ + else \ + i830_draw_line( imesa, v0, v1 ); \ +} while (0) + +#define POINT( v0 ) \ +do { \ + if (DO_FALLBACK) \ + imesa->draw_point( imesa, v0 ); \ + else \ + i830_draw_point( imesa, v0 ); \ +} while (0) + + +/*********************************************************************** + * Build render functions from dd templates * + ***********************************************************************/ + +#define I830_OFFSET_BIT 0x01 +#define I830_TWOSIDE_BIT 0x02 +#define I830_UNFILLED_BIT 0x04 +#define I830_FALLBACK_BIT 0x08 +#define I830_MAX_TRIFUNC 0x10 + + +static struct { + points_func points; + line_func line; + triangle_func triangle; + quad_func quad; +} rast_tab[I830_MAX_TRIFUNC]; + + +#define DO_FALLBACK (IND & I830_FALLBACK_BIT) +#define DO_OFFSET (IND & I830_OFFSET_BIT) +#define DO_UNFILLED (IND & I830_UNFILLED_BIT) +#define DO_TWOSIDE (IND & I830_TWOSIDE_BIT) +#define DO_FLAT 0 +#define DO_TRI 1 +#define DO_QUAD 1 +#define DO_LINE 1 +#define DO_POINTS 1 +#define DO_FULL_QUAD 1 + +#define HAVE_RGBA 1 +#define HAVE_SPEC 1 +#define HAVE_BACK_COLORS 0 +#define HAVE_HW_FLATSHADE 1 +#define VERTEX i830Vertex +#define TAB rast_tab + +/* Only used to pull back colors into vertices (ie, we know color is + * floating point). + */ +#define I830_COLOR( dst, src ) \ +do { \ + dst[0] = src[2]; \ + dst[1] = src[1]; \ + dst[2] = src[0]; \ + dst[3] = src[3]; \ +} while (0) + +#define I830_SPEC( dst, src ) \ +do { \ + dst[0] = src[2]; \ + dst[1] = src[1]; \ + dst[2] = src[0]; \ +} while (0) + + +#define DEPTH_SCALE (imesa->depth_scale) +#define UNFILLED_TRI unfilled_tri +#define UNFILLED_QUAD unfilled_quad +#define VERT_X(_v) _v->v.x +#define VERT_Y(_v) _v->v.y +#define VERT_Z(_v) _v->v.z +#define AREA_IS_CCW( a ) (a > 0) +#define GET_VERTEX(e) (imesa->verts + (e<<imesa->vertex_stride_shift)) + +#define VERT_SET_RGBA( v, c ) I830_COLOR( v->ub4[coloroffset], c ) +#define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset] +#define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset] +#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx] + +#define VERT_SET_SPEC( v, c ) if (havespec) I830_SPEC( v->ub4[5], c ) +#define VERT_COPY_SPEC( v0, v1 ) if (havespec) COPY_3V(v0->ub4[5], v1->ub4[5]) +#define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = v[idx]->ui[5] +#define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = spec[idx] + +#define LOCAL_VARS(n) \ + i830ContextPtr imesa = I830_CONTEXT(ctx); \ + GLuint color[n], spec[n]; \ + GLuint coloroffset = (imesa->vertex_size == 4 ? 3 : 4); \ + GLboolean havespec = (imesa->vertex_size > 4); \ + (void) color; (void) spec; (void) coloroffset; (void) havespec; + + +/*********************************************************************** + * Helpers for rendering unfilled primitives * + ***********************************************************************/ + +static const GLuint hw_prim[GL_POLYGON+1] = { + PRIM3D_POINTLIST, + PRIM3D_LINELIST, + PRIM3D_LINELIST, + PRIM3D_LINELIST, + PRIM3D_TRILIST, + PRIM3D_TRILIST, + PRIM3D_TRILIST, + PRIM3D_TRILIST, + PRIM3D_TRILIST, + PRIM3D_TRILIST +}; + +#define RASTERIZE(x) if (imesa->hw_primitive != hw_prim[x]) \ + i830RasterPrimitive( ctx, x, hw_prim[x] ) +#define RENDER_PRIMITIVE imesa->render_primitive +#define TAG(x) x +#define IND I830_FALLBACK_BIT +#include "tnl_dd/t_dd_unfilled.h" +#undef IND + +/*********************************************************************** + * Generate GL render functions * + ***********************************************************************/ + +#define IND (0) +#define TAG(x) x +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I830_OFFSET_BIT) +#define TAG(x) x##_offset +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I830_TWOSIDE_BIT) +#define TAG(x) x##_twoside +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I830_TWOSIDE_BIT|I830_OFFSET_BIT) +#define TAG(x) x##_twoside_offset +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I830_UNFILLED_BIT) +#define TAG(x) x##_unfilled +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I830_OFFSET_BIT|I830_UNFILLED_BIT) +#define TAG(x) x##_offset_unfilled +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I830_TWOSIDE_BIT|I830_UNFILLED_BIT) +#define TAG(x) x##_twoside_unfilled +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I830_TWOSIDE_BIT|I830_OFFSET_BIT|I830_UNFILLED_BIT) +#define TAG(x) x##_twoside_offset_unfilled +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I830_FALLBACK_BIT) +#define TAG(x) x##_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I830_OFFSET_BIT|I830_FALLBACK_BIT) +#define TAG(x) x##_offset_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I830_TWOSIDE_BIT|I830_FALLBACK_BIT) +#define TAG(x) x##_twoside_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I830_TWOSIDE_BIT|I830_OFFSET_BIT|I830_FALLBACK_BIT) +#define TAG(x) x##_twoside_offset_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I830_UNFILLED_BIT|I830_FALLBACK_BIT) +#define TAG(x) x##_unfilled_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I830_OFFSET_BIT|I830_UNFILLED_BIT|I830_FALLBACK_BIT) +#define TAG(x) x##_offset_unfilled_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I830_TWOSIDE_BIT|I830_UNFILLED_BIT|I830_FALLBACK_BIT) +#define TAG(x) x##_twoside_unfilled_fallback +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (I830_TWOSIDE_BIT|I830_OFFSET_BIT|I830_UNFILLED_BIT| \ + I830_FALLBACK_BIT) +#define TAG(x) x##_twoside_offset_unfilled_fallback +#include "tnl_dd/t_dd_tritmp.h" + + +static void init_rast_tab( void ) +{ + init(); + init_offset(); + init_twoside(); + init_twoside_offset(); + init_unfilled(); + init_offset_unfilled(); + init_twoside_unfilled(); + init_twoside_offset_unfilled(); + init_fallback(); + init_offset_fallback(); + init_twoside_fallback(); + init_twoside_offset_fallback(); + init_unfilled_fallback(); + init_offset_unfilled_fallback(); + init_twoside_unfilled_fallback(); + init_twoside_offset_unfilled_fallback(); +} + + +/*********************************************************************** + * Rasterization fallback helpers * + ***********************************************************************/ + + +/* This code is hit only when a mix of accelerated and unaccelerated + * primitives are being drawn, and only for the unaccelerated + * primitives. + */ +static void +i830_fallback_tri( i830ContextPtr imesa, + i830Vertex *v0, + i830Vertex *v1, + i830Vertex *v2 ) +{ + GLcontext *ctx = imesa->glCtx; + SWvertex v[3]; + + if (0) + fprintf(stderr, "\n%s\n", __FUNCTION__); + + i830_translate_vertex( ctx, v0, &v[0] ); + i830_translate_vertex( ctx, v1, &v[1] ); + i830_translate_vertex( ctx, v2, &v[2] ); + i830SpanRenderStart( ctx ); + _swrast_Triangle( ctx, &v[0], &v[1], &v[2] ); + i830SpanRenderFinish( ctx ); +} + + +static void +i830_fallback_line( i830ContextPtr imesa, + i830Vertex *v0, + i830Vertex *v1 ) +{ + GLcontext *ctx = imesa->glCtx; + SWvertex v[2]; + + if (0) + fprintf(stderr, "\n%s\n", __FUNCTION__); + + i830_translate_vertex( ctx, v0, &v[0] ); + i830_translate_vertex( ctx, v1, &v[1] ); + i830SpanRenderStart( ctx ); + _swrast_Line( ctx, &v[0], &v[1] ); + i830SpanRenderFinish( ctx ); +} + + +static void +i830_fallback_point( i830ContextPtr imesa, + i830Vertex *v0 ) +{ + GLcontext *ctx = imesa->glCtx; + SWvertex v[1]; + + if (0) + fprintf(stderr, "\n%s\n", __FUNCTION__); + + i830_translate_vertex( ctx, v0, &v[0] ); + i830SpanRenderStart( ctx ); + _swrast_Point( ctx, &v[0] ); + i830SpanRenderFinish( ctx ); +} + + + +/**********************************************************************/ +/* Render unclipped begin/end objects */ +/**********************************************************************/ + +#define IND 0 +#define V(x) (i830Vertex *)(vertptr + ((x)<<vertshift)) +#define RENDER_POINTS( start, count ) \ + for ( ; start < count ; start++) POINT( V(ELT(start)) ); +#define RENDER_LINE( v0, v1 ) LINE( V(v0), V(v1) ) +#define RENDER_TRI( v0, v1, v2 ) TRI( V(v0), V(v1), V(v2) ) +#define RENDER_QUAD( v0, v1, v2, v3 ) QUAD( V(v0), V(v1), V(v2), V(v3) ) +#define INIT(x) i830RenderPrimitive( ctx, x ) +#undef LOCAL_VARS +#define LOCAL_VARS \ + i830ContextPtr imesa = I830_CONTEXT(ctx); \ + GLubyte *vertptr = (GLubyte *)imesa->verts; \ + const GLuint vertshift = imesa->vertex_stride_shift; \ + const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \ + (void) elt; +#define RESET_STIPPLE +#define RESET_OCCLUSION +#define PRESERVE_VB_DEFS +#define ELT(x) x +#define TAG(x) i830_##x##_verts +#include "tnl/t_vb_rendertmp.h" +#undef ELT +#undef TAG +#define TAG(x) i830_##x##_elts +#define ELT(x) elt[x] +#include "tnl/t_vb_rendertmp.h" + +/**********************************************************************/ +/* Render clipped primitives */ +/**********************************************************************/ + + + +static void i830RenderClippedPoly( GLcontext *ctx, const GLuint *elts, + GLuint n ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + GLuint prim = imesa->render_primitive; + + /* Render the new vertices as an unclipped polygon. + */ + { + GLuint *tmp = VB->Elts; + VB->Elts = (GLuint *)elts; + tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, + PRIM_BEGIN|PRIM_END ); + VB->Elts = tmp; + } + + /* Restore the render primitive + */ + if (prim != GL_POLYGON) + tnl->Driver.Render.PrimitiveNotify( ctx, prim ); +} + +static void i830RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + + tnl->Driver.Render.Line( ctx, ii, jj ); +} + +static void i830FastRenderClippedPoly( GLcontext *ctx, const GLuint *elts, + GLuint n ) +{ + i830ContextPtr imesa = I830_CONTEXT( ctx ); + GLuint vertsize = imesa->vertex_size; + GLuint *vb = i830AllocDmaLow( imesa, (n-2) * 3 * 4 * vertsize ); + GLubyte *vertptr = (GLubyte *)imesa->verts; + const GLuint vertshift = imesa->vertex_stride_shift; + const GLuint *start = (const GLuint *)V(elts[0]); + int i,j; + + for (i = 2 ; i < n ; i++) { + COPY_DWORDS( j, vb, vertsize, V(elts[i-1]) ); + COPY_DWORDS( j, vb, vertsize, V(elts[i]) ); + COPY_DWORDS( j, vb, vertsize, start ); + } +} + +/**********************************************************************/ +/* Choose render functions */ +/**********************************************************************/ + + + +#define _I830_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE | \ + _DD_NEW_TRI_UNFILLED | \ + _DD_NEW_TRI_LIGHT_TWOSIDE | \ + _DD_NEW_TRI_OFFSET | \ + _DD_NEW_TRI_STIPPLE | \ + _NEW_POLYGONSTIPPLE) + +#define POINT_FALLBACK (0) +#define LINE_FALLBACK (DD_LINE_STIPPLE) +#define TRI_FALLBACK (0) +#define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK|\ + DD_TRI_STIPPLE) +#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED) + +static void i830ChooseRenderState(GLcontext *ctx) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + i830ContextPtr imesa = I830_CONTEXT(ctx); + GLuint flags = ctx->_TriangleCaps; + GLuint index = 0; + + if (I830_DEBUG & DEBUG_STATE) + fprintf(stderr,"\n%s\n",__FUNCTION__); + + if (flags & (ANY_FALLBACK_FLAGS|ANY_RASTER_FLAGS)) { + if (flags & ANY_RASTER_FLAGS) { + if (flags & DD_TRI_LIGHT_TWOSIDE) index |= I830_TWOSIDE_BIT; + if (flags & DD_TRI_OFFSET) index |= I830_OFFSET_BIT; + if (flags & DD_TRI_UNFILLED) index |= I830_UNFILLED_BIT; + } + + imesa->draw_point = i830_draw_point; + imesa->draw_line = i830_draw_line; + imesa->draw_tri = i830_draw_triangle; + + /* Hook in fallbacks for specific primitives. + */ + if (flags & ANY_FALLBACK_FLAGS) + { + if (flags & POINT_FALLBACK) + imesa->draw_point = i830_fallback_point; + + if (flags & LINE_FALLBACK) + imesa->draw_line = i830_fallback_line; + + if (flags & TRI_FALLBACK) + imesa->draw_tri = i830_fallback_tri; + + if ((flags & DD_TRI_STIPPLE) && !imesa->hw_stipple) { + imesa->draw_tri = i830_fallback_tri; + } + + index |= I830_FALLBACK_BIT; + } + } + + if (imesa->RenderIndex != index) { + imesa->RenderIndex = index; + + tnl->Driver.Render.Points = rast_tab[index].points; + tnl->Driver.Render.Line = rast_tab[index].line; + tnl->Driver.Render.Triangle = rast_tab[index].triangle; + tnl->Driver.Render.Quad = rast_tab[index].quad; + + if (index == 0) { + tnl->Driver.Render.PrimTabVerts = i830_render_tab_verts; + tnl->Driver.Render.PrimTabElts = i830_render_tab_elts; + tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */ + tnl->Driver.Render.ClippedPolygon = i830FastRenderClippedPoly; + } else { + tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; + tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; + tnl->Driver.Render.ClippedLine = i830RenderClippedLine; + tnl->Driver.Render.ClippedPolygon = i830RenderClippedPoly; + } + } +} + +static const GLenum reduced_prim[GL_POLYGON+1] = { + GL_POINTS, + GL_LINES, + GL_LINES, + GL_LINES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES, + GL_TRIANGLES +}; + + +/**********************************************************************/ +/* High level hooks for t_vb_render.c */ +/**********************************************************************/ + + + +/* Determine the rasterized primitive when not drawing unfilled + * polygons. + * + * Used only for the default render stage which always decomposes + * primitives to trianges/lines/points. For the accelerated stage, + * which renders strips as strips, the equivalent calculations are + * performed in i810render.c. + */ +static void i830RenderPrimitive( GLcontext *ctx, GLenum prim ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + GLuint rprim = reduced_prim[prim]; + + imesa->render_primitive = prim; + + if (rprim == GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED)) + return; + + if (imesa->reduced_primitive != rprim || + hw_prim[prim] != imesa->hw_primitive) { + i830RasterPrimitive( ctx, rprim, hw_prim[prim] ); + } +} + +static void i830RunPipeline( GLcontext *ctx ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + + if (imesa->NewGLState) { + if (imesa->NewGLState & _NEW_TEXTURE) { + I830_FIREVERTICES( imesa ); + i830UpdateTextureState( ctx ); /* may modify imesa->NewGLState */ + } + + if (!imesa->Fallback) { + if (imesa->NewGLState & _I830_NEW_VERTEX) + i830ChooseVertexState( ctx ); + + if (imesa->NewGLState & _I830_NEW_RENDERSTATE) + i830ChooseRenderState( ctx ); + } + + imesa->NewGLState = 0; + } + + _tnl_run_pipeline( ctx ); +} + +static void i830RenderStart( GLcontext *ctx ) +{ + /* Check for projective textureing. Make sure all texcoord + * pointers point to something. (fix in mesa?) + */ + + i830CheckTexSizes( ctx ); +} + +static void i830RenderFinish( GLcontext *ctx ) +{ + if (I830_CONTEXT(ctx)->RenderIndex & I830_FALLBACK_BIT) + _swrast_flush( ctx ); +} + + + + +/* System to flush dma and emit state changes based on the rasterized + * primitive. + */ +void i830RasterPrimitive( GLcontext *ctx, + GLenum rprim, + GLuint hwprim ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + GLuint aa = imesa->Setup[I830_CTXREG_AA]; + GLuint st1 = imesa->StippleSetup[I830_STPREG_ST1]; + + aa &= ~AA_LINE_ENABLE; + + if (I830_DEBUG & DEBUG_PRIMS) { + /* Prints reduced prim, and hw prim */ + char *prim_name = "Unknown"; + + switch(hwprim) { + case PRIM3D_POINTLIST: + prim_name = "PointList"; + break; + case PRIM3D_LINELIST: + prim_name = "LineList"; + break; + case PRIM3D_LINESTRIP: + prim_name = "LineStrip"; + break; + case PRIM3D_TRILIST: + prim_name = "TriList"; + break; + case PRIM3D_TRISTRIP: + prim_name = "TriStrip"; + break; + case PRIM3D_TRIFAN: + prim_name = "TriFan"; + break; + case PRIM3D_POLY: + prim_name = "Polygons"; + break; + default: + break; + } + + fprintf(stderr, "%s : rprim(%s), hwprim(%s)\n", + __FUNCTION__, + _mesa_lookup_enum_by_nr(rprim), + prim_name); + } + + switch (rprim) { + case GL_TRIANGLES: + aa |= AA_LINE_DISABLE; + if (ctx->Polygon.StippleFlag) + st1 |= ST1_ENABLE; + else + st1 &= ~ST1_ENABLE; + break; + case GL_LINES: + st1 &= ~ST1_ENABLE; + if (ctx->Line.SmoothFlag) { + aa |= AA_LINE_ENABLE; + } else { + aa |= AA_LINE_DISABLE; + } + break; + case GL_POINTS: + st1 &= ~ST1_ENABLE; + aa |= AA_LINE_DISABLE; + break; + default: + return; + } + + imesa->reduced_primitive = rprim; + + if (aa != imesa->Setup[I830_CTXREG_AA]) { + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_AA] = aa; + } + +#if 0 + if (st1 != imesa->StippleSetup[I830_STPREG_ST1]) { + I830_STATECHANGE(imesa, I830_UPLOAD_STIPPLE); + imesa->StippleSetup[I830_STPREG_ST1] = st1; + } +#endif + + if (hwprim != imesa->hw_primitive) { + I830_STATECHANGE(imesa, 0); + imesa->hw_primitive = hwprim; + } +} + +/**********************************************************************/ +/* Transition to/from hardware rasterization. */ +/**********************************************************************/ + +static char *fallbackStrings[] = { + "Texture", + "Draw buffer", + "Read buffer", + "Color mask", + "Render mode", + "Stencil", + "Stipple", + "User disable" +}; + + +static char *getFallbackString(GLuint bit) +{ + int i = 0; + while (bit > 1) { + i++; + bit >>= 1; + } + return fallbackStrings[i]; +} + + + +void i830Fallback( i830ContextPtr imesa, GLuint bit, GLboolean mode ) +{ + GLcontext *ctx = imesa->glCtx; + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint oldfallback = imesa->Fallback; + + if (mode) { + imesa->Fallback |= bit; + if (oldfallback == 0) { + I830_FIREVERTICES(imesa); + if (I830_DEBUG & DEBUG_FALLBACKS) + fprintf(stderr, "ENTER FALLBACK %s\n", getFallbackString( bit )); + _swsetup_Wakeup( ctx ); + imesa->RenderIndex = ~0; + } + } + else { + imesa->Fallback &= ~bit; + if (oldfallback == bit) { + _swrast_flush( ctx ); + if (I830_DEBUG & DEBUG_FALLBACKS) + fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString( bit )); + tnl->Driver.Render.Start = i830RenderStart; + tnl->Driver.Render.PrimitiveNotify = i830RenderPrimitive; + tnl->Driver.Render.Finish = i830RenderFinish; + tnl->Driver.Render.BuildVertices = i830BuildVertices; + imesa->NewGLState |= (_I830_NEW_RENDERSTATE|_I830_NEW_VERTEX); + } + } +} + + + + +/**********************************************************************/ +/* Initialization. */ +/**********************************************************************/ + + +void i830InitTriFuncs( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + static int firsttime = 1; + + if (firsttime) { + init_rast_tab(); + firsttime = 0; + } + + tnl->Driver.RunPipeline = i830RunPipeline; + tnl->Driver.Render.Start = i830RenderStart; + tnl->Driver.Render.Finish = i830RenderFinish; + tnl->Driver.Render.PrimitiveNotify = i830RenderPrimitive; + tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple; + tnl->Driver.Render.BuildVertices = i830BuildVertices; +} diff --git a/src/mesa/drivers/dri/i830/i830_tris.h b/src/mesa/drivers/dri/i830/i830_tris.h new file mode 100644 index 0000000000..ae4f0a5df5 --- /dev/null +++ b/src/mesa/drivers/dri/i830/i830_tris.h @@ -0,0 +1,37 @@ +/* + * GLX Hardware Device Driver for Intel i810 + * Copyright (C) 1999 Keith Whitwell + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Adapted for use in the I830M: + * Jeff Hartmann <jhartmann@2d3d.com> + */ +/* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_tris.h,v 1.3 2002/09/09 19:18:48 dawes Exp $ */ + +#ifndef I830TRIS_INC +#define I830TRIS_INC + +#include "mtypes.h" + +extern void i830PrintRenderState( const char *msg, GLuint state ); +extern void i830InitTriFuncs( GLcontext *ctx ); +extern void i830RasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim ); + +#endif diff --git a/src/mesa/drivers/dri/i830/i830_vb.c b/src/mesa/drivers/dri/i830/i830_vb.c new file mode 100644 index 0000000000..a7ac054c23 --- /dev/null +++ b/src/mesa/drivers/dri/i830/i830_vb.c @@ -0,0 +1,592 @@ +/* + * GLX Hardware Device Driver for Intel i810 + * Copyright (C) 1999 Keith Whitwell + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Adapted for use on the I830M: + * Jeff Hartmann <jhartmann@2d3d.com> + */ +/* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_vb.c,v 1.5 2002/12/10 01:26:54 dawes Exp $ */ + +#include "glheader.h" +#include "mtypes.h" +#include "imports.h" +#include "macros.h" +#include "colormac.h" + +#include "swrast_setup/swrast_setup.h" +#include "tnl/t_context.h" + +#include "i830_screen.h" +#include "i830_dri.h" + +#include "i830_context.h" +#include "i830_vb.h" +#include "i830_ioctl.h" +#include "i830_tris.h" +#include "i830_state.h" + +#define I830_TEX1_BIT 0x1 +#define I830_TEX0_BIT 0x2 +#define I830_RGBA_BIT 0x4 +#define I830_SPEC_BIT 0x8 +#define I830_FOG_BIT 0x10 +#define I830_XYZW_BIT 0x20 +#define I830_PTEX_BIT 0x40 +#define I830_MAX_SETUP 0x80 + +static struct { + void (*emit)( GLcontext *, GLuint, GLuint, void *, GLuint ); + interp_func interp; + copy_pv_func copy_pv; + GLboolean (*check_tex_sizes)( GLcontext *ctx ); + GLuint vertex_size; + GLuint vertex_stride_shift; + GLuint vertex_format; +} setup_tab[I830_MAX_SETUP]; + +#define TINY_VERTEX_FORMAT (STATE3D_VERTEX_FORMAT_CMD | \ + VRTX_TEX_COORD_COUNT(0) | \ + VRTX_HAS_DIFFUSE | \ + VRTX_HAS_XYZ) + +#define NOTEX_VERTEX_FORMAT (STATE3D_VERTEX_FORMAT_CMD | \ + VRTX_TEX_COORD_COUNT(0) | \ + VRTX_HAS_DIFFUSE | \ + VRTX_HAS_SPEC | \ + VRTX_HAS_XYZW) + +#define TEX0_VERTEX_FORMAT (STATE3D_VERTEX_FORMAT_CMD | \ + VRTX_TEX_COORD_COUNT(1) | \ + VRTX_HAS_DIFFUSE | \ + VRTX_HAS_SPEC | \ + VRTX_HAS_XYZW) + +#define TEX1_VERTEX_FORMAT (STATE3D_VERTEX_FORMAT_CMD | \ + VRTX_TEX_COORD_COUNT(2) | \ + VRTX_HAS_DIFFUSE | \ + VRTX_HAS_SPEC | \ + VRTX_HAS_XYZW) + + +/* I'm cheating here hardcore : if bit 31 is set I know to emit + * a vf2 state == TEXCOORDFMT_3D. We never mix 2d/3d texcoords, + * so this solution works for now. + */ + +#define PROJ_TEX1_VERTEX_FORMAT ((1<<31) | \ + STATE3D_VERTEX_FORMAT_CMD | \ + VRTX_TEX_COORD_COUNT(2) | \ + VRTX_HAS_DIFFUSE | \ + VRTX_HAS_SPEC | \ + VRTX_HAS_XYZW) + +/* Might want to do these later */ +#define TEX2_VERTEX_FORMAT 0 +#define TEX3_VERTEX_FORMAT 0 +#define PROJ_TEX3_VERTEX_FORMAT 0 + +#define DO_XYZW (IND & I830_XYZW_BIT) +#define DO_RGBA (IND & I830_RGBA_BIT) +#define DO_SPEC (IND & I830_SPEC_BIT) +#define DO_FOG (IND & I830_FOG_BIT) +#define DO_TEX0 (IND & I830_TEX0_BIT) +#define DO_TEX1 (IND & I830_TEX1_BIT) +#define DO_TEX2 0 +#define DO_TEX3 0 +#define DO_PTEX (IND & I830_PTEX_BIT) + +#define VERTEX i830Vertex +#define VERTEX_COLOR i830_color_t +#define GET_VIEWPORT_MAT() I830_CONTEXT(ctx)->ViewportMatrix.m +#define GET_TEXSOURCE(n) n +#define GET_VERTEX_FORMAT() I830_CONTEXT(ctx)->vertex_format +#define GET_VERTEX_STORE() ((GLubyte *)I830_CONTEXT(ctx)->verts) +#define GET_VERTEX_STRIDE_SHIFT() I830_CONTEXT(ctx)->vertex_stride_shift +#define GET_UBYTE_COLOR_STORE() &I830_CONTEXT(ctx)->UbyteColor +#define GET_UBYTE_SPEC_COLOR_STORE() &I830_CONTEXT(ctx)->UbyteSecondaryColor +#define INVALIDATE_STORED_VERTICES() + +#define HAVE_HW_VIEWPORT 0 +#define HAVE_HW_DIVIDE 0 +#define HAVE_RGBA_COLOR 0 +#define HAVE_TINY_VERTICES 1 +#define HAVE_NOTEX_VERTICES 1 +#define HAVE_TEX0_VERTICES 1 +#define HAVE_TEX1_VERTICES 1 +#define HAVE_TEX2_VERTICES 0 +#define HAVE_TEX3_VERTICES 0 +#define HAVE_PTEX_VERTICES 1 + +#define UNVIEWPORT_VARS GLfloat h = I830_CONTEXT(ctx)->driDrawable->h +#define UNVIEWPORT_X(x) x - SUBPIXEL_X +#define UNVIEWPORT_Y(y) - y + h + SUBPIXEL_Y +#define UNVIEWPORT_Z(z) z * (float)I830_CONTEXT(ctx)->ClearDepth + +#define PTEX_FALLBACK() FALLBACK(I830_CONTEXT(ctx), I830_FALLBACK_TEXTURE, 1) + +#define IMPORT_FLOAT_COLORS i830_import_float_colors +#define IMPORT_FLOAT_SPEC_COLORS i830_import_float_spec_colors + +#define INTERP_VERTEX setup_tab[I830_CONTEXT(ctx)->SetupIndex].interp +#define COPY_PV_VERTEX setup_tab[I830_CONTEXT(ctx)->SetupIndex].copy_pv + + +/*********************************************************************** + * Generate pv-copying and translation functions * + ***********************************************************************/ + +#define TAG(x) i830_##x +#include "tnl_dd/t_dd_vb.c" + +/*********************************************************************** + * Generate vertex emit and interp functions * + ***********************************************************************/ + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT) +#define TAG(x) x##_wg +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_SPEC_BIT) +#define TAG(x) x##_wgs +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_TEX0_BIT) +#define TAG(x) x##_wgt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_TEX0_BIT|I830_TEX1_BIT) +#define TAG(x) x##_wgt0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_TEX0_BIT|I830_PTEX_BIT) +#define TAG(x) x##_wgpt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_SPEC_BIT|I830_TEX0_BIT) +#define TAG(x) x##_wgst0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_SPEC_BIT|I830_TEX0_BIT|\ + I830_TEX1_BIT) +#define TAG(x) x##_wgst0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_SPEC_BIT|I830_TEX0_BIT|\ + I830_PTEX_BIT) +#define TAG(x) x##_wgspt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_FOG_BIT) +#define TAG(x) x##_wgf +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_FOG_BIT|I830_SPEC_BIT) +#define TAG(x) x##_wgfs +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_FOG_BIT|I830_TEX0_BIT) +#define TAG(x) x##_wgft0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_FOG_BIT|I830_TEX0_BIT|\ + I830_TEX1_BIT) +#define TAG(x) x##_wgft0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_FOG_BIT|I830_TEX0_BIT|\ + I830_PTEX_BIT) +#define TAG(x) x##_wgfpt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_FOG_BIT|I830_SPEC_BIT|\ + I830_TEX0_BIT) +#define TAG(x) x##_wgfst0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_FOG_BIT|I830_SPEC_BIT|\ + I830_TEX0_BIT|I830_TEX1_BIT) +#define TAG(x) x##_wgfst0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_FOG_BIT|I830_SPEC_BIT|\ + I830_TEX0_BIT|I830_PTEX_BIT) +#define TAG(x) x##_wgfspt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_TEX0_BIT) +#define TAG(x) x##_t0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_TEX0_BIT|I830_TEX1_BIT) +#define TAG(x) x##_t0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_FOG_BIT) +#define TAG(x) x##_f +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_FOG_BIT|I830_TEX0_BIT) +#define TAG(x) x##_ft0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_FOG_BIT|I830_TEX0_BIT|I830_TEX1_BIT) +#define TAG(x) x##_ft0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_RGBA_BIT) +#define TAG(x) x##_g +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_RGBA_BIT|I830_SPEC_BIT) +#define TAG(x) x##_gs +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_RGBA_BIT|I830_TEX0_BIT) +#define TAG(x) x##_gt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_RGBA_BIT|I830_TEX0_BIT|I830_TEX1_BIT) +#define TAG(x) x##_gt0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_RGBA_BIT|I830_SPEC_BIT|I830_TEX0_BIT) +#define TAG(x) x##_gst0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_RGBA_BIT|I830_SPEC_BIT|I830_TEX0_BIT|I830_TEX1_BIT) +#define TAG(x) x##_gst0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_RGBA_BIT|I830_FOG_BIT) +#define TAG(x) x##_gf +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_RGBA_BIT|I830_FOG_BIT|I830_SPEC_BIT) +#define TAG(x) x##_gfs +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_RGBA_BIT|I830_FOG_BIT|I830_TEX0_BIT) +#define TAG(x) x##_gft0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_RGBA_BIT|I830_FOG_BIT|I830_TEX0_BIT|I830_TEX1_BIT) +#define TAG(x) x##_gft0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_RGBA_BIT|I830_FOG_BIT|I830_SPEC_BIT|I830_TEX0_BIT) +#define TAG(x) x##_gfst0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_RGBA_BIT|I830_FOG_BIT|I830_SPEC_BIT|I830_TEX0_BIT|\ + I830_TEX1_BIT) +#define TAG(x) x##_gfst0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +/* Add functions for proj texturing for t0 and t1 */ +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_TEX0_BIT|I830_TEX1_BIT|\ + I830_PTEX_BIT) +#define TAG(x) x##_wgpt0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_SPEC_BIT|I830_TEX0_BIT|\ + I830_TEX1_BIT|I830_PTEX_BIT) +#define TAG(x) x##_wgspt0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_FOG_BIT|I830_TEX0_BIT|\ + I830_TEX1_BIT|I830_PTEX_BIT) +#define TAG(x) x##_wgfpt0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (I830_XYZW_BIT|I830_RGBA_BIT|I830_FOG_BIT|I830_SPEC_BIT|\ + I830_TEX1_BIT|I830_TEX0_BIT|I830_PTEX_BIT) +#define TAG(x) x##_wgfspt0t1 +#include "tnl_dd/t_dd_vbtmp.h" + + +static void init_setup_tab( void ) +{ + init_wg(); + init_wgs(); + init_wgt0(); + init_wgt0t1(); + init_wgpt0(); + init_wgst0(); + init_wgst0t1(); + init_wgspt0(); + init_wgf(); + init_wgfs(); + init_wgft0(); + init_wgft0t1(); + init_wgfpt0(); + init_wgfst0(); + init_wgfst0t1(); + init_wgfspt0(); + init_t0(); + init_t0t1(); + init_f(); + init_ft0(); + init_ft0t1(); + init_g(); + init_gs(); + init_gt0(); + init_gt0t1(); + init_gst0(); + init_gst0t1(); + init_gf(); + init_gfs(); + init_gft0(); + init_gft0t1(); + init_gfst0(); + init_gfst0t1(); + /* Add proj texturing on t1 */ + init_wgpt0t1(); + init_wgspt0t1(); + init_wgfpt0t1(); + init_wgfspt0t1(); +} + + + +void i830PrintSetupFlags(char *msg, GLuint flags ) +{ + fprintf(stderr, "%s(%x): %s%s%s%s%s%s%s\n", + msg, + (int)flags, + (flags & I830_XYZW_BIT) ? " xyzw," : "", + (flags & I830_RGBA_BIT) ? " rgba," : "", + (flags & I830_SPEC_BIT) ? " spec," : "", + (flags & I830_FOG_BIT) ? " fog," : "", + (flags & I830_TEX0_BIT) ? " tex-0," : "", + (flags & I830_TEX1_BIT) ? " tex-1," : "", + (flags & I830_PTEX_BIT) ? " ptex," : ""); +} + +void i830CheckTexSizes( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + i830ContextPtr imesa = I830_CONTEXT( ctx ); + + if (!setup_tab[imesa->SetupIndex].check_tex_sizes(ctx)) { + int ind = imesa->SetupIndex |= I830_PTEX_BIT; + + if(setup_tab[ind].vertex_format != imesa->vertex_format) { + int vfmt = setup_tab[ind].vertex_format; + + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_VF] = ~(1<<31) & vfmt; + + if (vfmt & (1<<31)) { + /* Proj texturing */ + imesa->Setup[I830_CTXREG_VF2] = (STATE3D_VERTEX_FORMAT_2_CMD | + VRTX_TEX_SET_0_FMT(TEXCOORDFMT_3D) | + VRTX_TEX_SET_1_FMT(TEXCOORDFMT_3D) | + VRTX_TEX_SET_2_FMT(TEXCOORDFMT_3D) | + VRTX_TEX_SET_3_FMT(TEXCOORDFMT_3D)); + i830UpdateTexUnitProj( ctx, 0, GL_TRUE ); + i830UpdateTexUnitProj( ctx, 1, GL_TRUE ); + + } else { + /* Normal texturing */ + imesa->Setup[I830_CTXREG_VF2] = (STATE3D_VERTEX_FORMAT_2_CMD | + VRTX_TEX_SET_0_FMT(TEXCOORDFMT_2D) | + VRTX_TEX_SET_1_FMT(TEXCOORDFMT_2D) | + VRTX_TEX_SET_2_FMT(TEXCOORDFMT_2D) | + VRTX_TEX_SET_3_FMT(TEXCOORDFMT_2D)); + i830UpdateTexUnitProj( ctx, 0, GL_FALSE ); + i830UpdateTexUnitProj( ctx, 1, GL_FALSE ); + } + imesa->vertex_format = vfmt; + imesa->vertex_size = setup_tab[ind].vertex_size; + imesa->vertex_stride_shift = setup_tab[ind].vertex_stride_shift; + } + + if (!imesa->Fallback && + !(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) { + tnl->Driver.Render.Interp = setup_tab[imesa->SetupIndex].interp; + tnl->Driver.Render.CopyPV = setup_tab[imesa->SetupIndex].copy_pv; + } + } +} + +void i830BuildVertices( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint newinputs ) +{ + i830ContextPtr imesa = I830_CONTEXT( ctx ); + GLubyte *v = ((GLubyte *) + imesa->verts + (start<<imesa->vertex_stride_shift)); + GLuint stride = 1<<imesa->vertex_stride_shift; + + if (0) fprintf(stderr, "%s\n", __FUNCTION__); + + newinputs |= imesa->SetupNewInputs; + imesa->SetupNewInputs = 0; + + if (!newinputs) + return; + + if (newinputs & VERT_BIT_CLIP) { + setup_tab[imesa->SetupIndex].emit( ctx, start, count, v, stride ); + } else { + GLuint ind = 0; + + if (newinputs & VERT_BIT_COLOR0) + ind |= I830_RGBA_BIT; + + if (newinputs & VERT_BIT_COLOR1) + ind |= I830_SPEC_BIT; + + if (newinputs & VERT_BIT_TEX0) + ind |= I830_TEX0_BIT; + + if (newinputs & VERT_BIT_TEX1) + ind |= I830_TEX1_BIT; + + if (newinputs & VERT_BIT_FOG) + ind |= I830_FOG_BIT; + +#if 0 + if (imesa->SetupIndex & I830_PTEX_BIT) + ind = ~0; +#endif + + ind &= imesa->SetupIndex; + + if (ind) { + setup_tab[ind].emit( ctx, start, count, v, stride ); + } + } +} + +void i830ChooseVertexState( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + i830ContextPtr imesa = I830_CONTEXT( ctx ); + GLuint ind = I830_XYZW_BIT|I830_RGBA_BIT; + + if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) + ind |= I830_SPEC_BIT; + + if (ctx->Fog.Enabled) + ind |= I830_FOG_BIT; + + if (ctx->Texture._EnabledUnits & 0x2) + /* unit 1 enabled */ + ind |= I830_TEX1_BIT|I830_TEX0_BIT; + else if (ctx->Texture._EnabledUnits & 0x1) + /* unit 0 enabled */ + ind |= I830_TEX0_BIT; + + imesa->SetupIndex = ind; + + if (I830_DEBUG & (DEBUG_VERTS|DEBUG_STATE)) + i830PrintSetupFlags( __FUNCTION__, ind ); + + if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) { + tnl->Driver.Render.Interp = i830_interp_extras; + tnl->Driver.Render.CopyPV = i830_copy_pv_extras; + } else { + tnl->Driver.Render.Interp = setup_tab[ind].interp; + tnl->Driver.Render.CopyPV = setup_tab[ind].copy_pv; + } + + if (setup_tab[ind].vertex_format != imesa->vertex_format) { + int vfmt = setup_tab[ind].vertex_format; + + I830_STATECHANGE(imesa, I830_UPLOAD_CTX); + imesa->Setup[I830_CTXREG_VF] = ~(1<<31) & vfmt; + + if (vfmt & (1<<31)) { + /* Proj texturing */ + imesa->Setup[I830_CTXREG_VF2] = (STATE3D_VERTEX_FORMAT_2_CMD | + VRTX_TEX_SET_0_FMT(TEXCOORDFMT_3D) | + VRTX_TEX_SET_1_FMT(TEXCOORDFMT_3D) | + VRTX_TEX_SET_2_FMT(TEXCOORDFMT_3D) | + VRTX_TEX_SET_3_FMT(TEXCOORDFMT_3D)); + i830UpdateTexUnitProj( ctx, 0, GL_TRUE ); + i830UpdateTexUnitProj( ctx, 1, GL_TRUE ); + } else { + /* Normal texturing */ + imesa->Setup[I830_CTXREG_VF2] = (STATE3D_VERTEX_FORMAT_2_CMD | + VRTX_TEX_SET_0_FMT(TEXCOORDFMT_2D) | + VRTX_TEX_SET_1_FMT(TEXCOORDFMT_2D) | + VRTX_TEX_SET_2_FMT(TEXCOORDFMT_2D) | + VRTX_TEX_SET_3_FMT(TEXCOORDFMT_2D)); + i830UpdateTexUnitProj( ctx, 0, GL_FALSE ); + i830UpdateTexUnitProj( ctx, 1, GL_FALSE ); + } + imesa->vertex_format = vfmt; + imesa->vertex_size = setup_tab[ind].vertex_size; + imesa->vertex_stride_shift = setup_tab[ind].vertex_stride_shift; + } +} + + + +void i830_emit_contiguous_verts( GLcontext *ctx, + GLuint start, + GLuint count ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + GLuint vertex_size = imesa->vertex_size * 4; + GLuint *dest = i830AllocDmaLow( imesa, (count-start) * vertex_size); + setup_tab[imesa->SetupIndex].emit( ctx, start, count, dest, vertex_size ); +} + + + +void i830InitVB( GLcontext *ctx ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + GLuint size = TNL_CONTEXT(ctx)->vb.Size; + + imesa->verts = (char *)ALIGN_MALLOC(size * 4 * 16, 32); + + { + static int firsttime = 1; + if (firsttime) { + init_setup_tab(); + firsttime = 0; + } + } +} + + +void i830FreeVB( GLcontext *ctx ) +{ + i830ContextPtr imesa = I830_CONTEXT(ctx); + if (imesa->verts) { + ALIGN_FREE(imesa->verts); + imesa->verts = 0; + } + + if (imesa->UbyteSecondaryColor.Ptr) { + ALIGN_FREE(imesa->UbyteSecondaryColor.Ptr); + imesa->UbyteSecondaryColor.Ptr = 0; + } + + if (imesa->UbyteColor.Ptr) { + ALIGN_FREE(imesa->UbyteColor.Ptr); + imesa->UbyteColor.Ptr = 0; + } +} diff --git a/src/mesa/drivers/dri/i830/i830_vb.h b/src/mesa/drivers/dri/i830/i830_vb.h new file mode 100644 index 0000000000..523354465f --- /dev/null +++ b/src/mesa/drivers/dri/i830/i830_vb.h @@ -0,0 +1,63 @@ +/* + * GLX Hardware Device Driver for Intel i810 + * Copyright (C) 1999 Keith Whitwell + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Adapted for use in the I830M: + * Jeff Hartmann <jhartmann@2d3d.com> + */ +/* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_vb.h,v 1.1 2002/09/09 19:18:49 dawes Exp $ */ + +#ifndef I830VB_INC +#define I830VB_INC + +#include "mtypes.h" +#include "swrast/swrast.h" + +#define _I830_NEW_VERTEX (_NEW_TEXTURE | \ + _DD_NEW_SEPARATE_SPECULAR | \ + _DD_NEW_TRI_UNFILLED | \ + _DD_NEW_TRI_LIGHT_TWOSIDE | \ + _NEW_FOG) + + +extern void i830ChooseVertexState( GLcontext *ctx ); +extern void i830CheckTexSizes( GLcontext *ctx ); +extern void i830BuildVertices( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint newinputs ); + + +extern void i830_emit_contiguous_verts( GLcontext *ctx, + GLuint start, + GLuint count ); + +extern void i830_translate_vertex( GLcontext *ctx, + const i830Vertex *src, + SWvertex *dst ); + +extern void i830InitVB( GLcontext *ctx ); +extern void i830FreeVB( GLcontext *ctx ); + +extern void i830_print_vertex( GLcontext *ctx, const i830Vertex *v ); +extern void i830PrintSetupFlags(char *msg, GLuint flags ); + +#endif diff --git a/src/mesa/drivers/dri/i830/server/i830_common.h b/src/mesa/drivers/dri/i830/server/i830_common.h new file mode 100644 index 0000000000..3367bfc168 --- /dev/null +++ b/src/mesa/drivers/dri/i830/server/i830_common.h @@ -0,0 +1,288 @@ +/************************************************************************** + +Copyright 2001 VA Linux Systems Inc., Fremont, California. +Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_common.h,v 1.2 2002/12/10 01:27:05 dawes Exp $ */ + +/* Author: Jeff Hartmann <jhartmann@valinux.com> + + Converted to common header format: + Jens Owen <jens@tungstengraphics.com> + */ + +#ifndef _I830_COMMON_H_ +#define _I830_COMMON_H_ + +/* WARNING: These defines must be the same as what the Xserver uses. + * if you change them, you must change the defines in the Xserver. + */ + +#ifndef _I830_DEFINES_ +#define _I830_DEFINES_ + +#define I830_DMA_BUF_ORDER 12 +#define I830_DMA_BUF_SZ (1<<I830_DMA_BUF_ORDER) +#define I830_DMA_BUF_NR 256 +#define I830_NR_SAREA_CLIPRECTS 8 + +/* Each region is a minimum of 64k, and there are at most 64 of them. + */ +#define I830_NR_TEX_REGIONS 64 +#define I830_LOG_MIN_TEX_REGION_SIZE 16 + +/* if defining I830_ENABLE_4_TEXTURES, do it in i830_3d_reg.h, too */ +#if !defined(I830_ENABLE_4_TEXTURES) +#define I830_TEXTURE_COUNT 2 +#define I830_TEXBLEND_COUNT 2 /* always same as TEXTURE_COUNT? */ +#else /* defined(I830_ENABLE_4_TEXTURES) */ +#define I830_TEXTURE_COUNT 4 +#define I830_TEXBLEND_COUNT 4 /* always same as TEXTURE_COUNT? */ +#endif /* I830_ENABLE_4_TEXTURES */ + +#define I830_TEXBLEND_SIZE 12 /* (4 args + op) * 2 + COLOR_FACTOR */ + +#define I830_UPLOAD_CTX 0x1 +#define I830_UPLOAD_BUFFERS 0x2 +#define I830_UPLOAD_CLIPRECTS 0x4 +#define I830_UPLOAD_TEX0_IMAGE 0x100 /* handled clientside */ +#define I830_UPLOAD_TEX0_CUBE 0x200 /* handled clientside */ +#define I830_UPLOAD_TEX1_IMAGE 0x400 /* handled clientside */ +#define I830_UPLOAD_TEX1_CUBE 0x800 /* handled clientside */ +#define I830_UPLOAD_TEX2_IMAGE 0x1000 /* handled clientside */ +#define I830_UPLOAD_TEX2_CUBE 0x2000 /* handled clientside */ +#define I830_UPLOAD_TEX3_IMAGE 0x4000 /* handled clientside */ +#define I830_UPLOAD_TEX3_CUBE 0x8000 /* handled clientside */ +#define I830_UPLOAD_TEX_N_IMAGE(n) (0x100 << (n * 2)) +#define I830_UPLOAD_TEX_N_CUBE(n) (0x200 << (n * 2)) +#define I830_UPLOAD_TEXIMAGE_MASK 0xff00 +#define I830_UPLOAD_TEX0 0x10000 +#define I830_UPLOAD_TEX1 0x20000 +#define I830_UPLOAD_TEX2 0x40000 +#define I830_UPLOAD_TEX3 0x80000 +#define I830_UPLOAD_TEX_N(n) (0x10000 << (n)) +#define I830_UPLOAD_TEX_MASK 0xf0000 +#define I830_UPLOAD_TEXBLEND0 0x100000 +#define I830_UPLOAD_TEXBLEND1 0x200000 +#define I830_UPLOAD_TEXBLEND2 0x400000 +#define I830_UPLOAD_TEXBLEND3 0x800000 +#define I830_UPLOAD_TEXBLEND_N(n) (0x100000 << (n)) +#define I830_UPLOAD_TEXBLEND_MASK 0xf00000 +#define I830_UPLOAD_TEX_PALETTE_N(n) (0x1000000 << (n)) +#define I830_UPLOAD_TEX_PALETTE_SHARED 0x4000000 +#define I830_UPLOAD_STIPPLE 0x8000000 + +/* Indices into buf.Setup where various bits of state are mirrored per + * context and per buffer. These can be fired at the card as a unit, + * or in a piecewise fashion as required. + */ + +/* Destbuffer state + * - backbuffer linear offset and pitch -- invarient in the current dri + * - zbuffer linear offset and pitch -- also invarient + * - drawing origin in back and depth buffers. + * + * Keep the depth/back buffer state here to acommodate private buffers + * in the future. + */ + +#define I830_DESTREG_CBUFADDR 0 +/* Invarient */ +#define I830_DESTREG_DBUFADDR 1 +#define I830_DESTREG_DV0 2 +#define I830_DESTREG_DV1 3 +#define I830_DESTREG_SENABLE 4 +#define I830_DESTREG_SR0 5 +#define I830_DESTREG_SR1 6 +#define I830_DESTREG_SR2 7 +#define I830_DESTREG_DR0 8 +#define I830_DESTREG_DR1 9 +#define I830_DESTREG_DR2 10 +#define I830_DESTREG_DR3 11 +#define I830_DESTREG_DR4 12 +#define I830_DEST_SETUP_SIZE 13 + +/* Context state + */ +#define I830_CTXREG_STATE1 0 +#define I830_CTXREG_STATE2 1 +#define I830_CTXREG_STATE3 2 +#define I830_CTXREG_STATE4 3 +#define I830_CTXREG_STATE5 4 +#define I830_CTXREG_IALPHAB 5 +#define I830_CTXREG_STENCILTST 6 +#define I830_CTXREG_ENABLES_1 7 +#define I830_CTXREG_ENABLES_2 8 +#define I830_CTXREG_AA 9 +#define I830_CTXREG_FOGCOLOR 10 +#define I830_CTXREG_BLENDCOLR0 11 +#define I830_CTXREG_BLENDCOLR 12 /* Dword 1 of 2 dword command */ +#define I830_CTXREG_VF 13 +#define I830_CTXREG_VF2 14 +#define I830_CTXREG_MCSB0 15 +#define I830_CTXREG_MCSB1 16 +#define I830_CTX_SETUP_SIZE 17 + +/* 1.3: Stipple state + */ +#define I830_STPREG_ST0 0 +#define I830_STPREG_ST1 1 +#define I830_STP_SETUP_SIZE 2 + +/* Texture state (per tex unit) + */ +#define I830_TEXREG_MI0 0 /* GFX_OP_MAP_INFO (6 dwords) */ +#define I830_TEXREG_MI1 1 +#define I830_TEXREG_MI2 2 +#define I830_TEXREG_MI3 3 +#define I830_TEXREG_MI4 4 +#define I830_TEXREG_MI5 5 +#define I830_TEXREG_MF 6 /* GFX_OP_MAP_FILTER */ +#define I830_TEXREG_MLC 7 /* GFX_OP_MAP_LOD_CTL */ +#define I830_TEXREG_MLL 8 /* GFX_OP_MAP_LOD_LIMITS */ +#define I830_TEXREG_MCS 9 /* GFX_OP_MAP_COORD_SETS */ +#define I830_TEX_SETUP_SIZE 10 + +/* New version. Kernel auto-detects. + */ +#define I830_TEXREG_TM0LI 0 /* load immediate 2 texture map n */ +#define I830_TEXREG_TM0S0 1 +#define I830_TEXREG_TM0S1 2 +#define I830_TEXREG_TM0S2 3 +#define I830_TEXREG_TM0S3 4 +#define I830_TEXREG_TM0S4 5 +#define I830_TEXREG_NOP0 6 /* noop */ +#define I830_TEXREG_NOP1 7 /* noop */ +#define I830_TEXREG_NOP2 8 /* noop */ +#define __I830_TEXREG_MCS 9 /* GFX_OP_MAP_COORD_SETS -- shared */ +#define __I830_TEX_SETUP_SIZE 10 + + +#define I830_FRONT 0x1 +#define I830_BACK 0x2 +#define I830_DEPTH 0x4 + +/* Driver specific DRM command indices + * NOTE: these are not OS specific, but they are driver specific + */ +#define DRM_I830_INIT 0x00 +#define DRM_I830_VERTEX 0x01 +#define DRM_I830_CLEAR 0x02 +#define DRM_I830_FLUSH 0x03 +#define DRM_I830_GETAGE 0x04 +#define DRM_I830_GETBUF 0x05 +#define DRM_I830_SWAP 0x06 +#define DRM_I830_COPY 0x07 +#define DRM_I830_DOCOPY 0x08 +#define DRM_I830_FLIP 0x09 +#define DRM_I830_IRQ_EMIT 0x0a +#define DRM_I830_IRQ_WAIT 0x0b +#define DRM_I830_GETPARAM 0x0c +#define DRM_I830_SETPARAM 0x0d + +#endif /* _I830_DEFINES_ */ + +typedef struct { + enum { + I830_INIT_DMA = 0x01, + I830_CLEANUP_DMA = 0x02 + } func; + unsigned int mmio_offset; + unsigned int buffers_offset; + int sarea_priv_offset; + unsigned int ring_start; + unsigned int ring_end; + unsigned int ring_size; + unsigned int front_offset; + unsigned int back_offset; + unsigned int depth_offset; + unsigned int w; + unsigned int h; + unsigned int pitch; + unsigned int pitch_bits; + unsigned int back_pitch; + unsigned int depth_pitch; + unsigned int cpp; +} drmI830Init; + +typedef struct { + int clear_color; + int clear_depth; + int flags; + unsigned int clear_colormask; + unsigned int clear_depthmask; +} drmI830Clear; + +/* These may be placeholders if we have more cliprects than + * I830_NR_SAREA_CLIPRECTS. In that case, the client sets discard to + * false, indicating that the buffer will be dispatched again with a + * new set of cliprects. + */ +typedef struct { + int idx; /* buffer index */ + int used; /* nr bytes in use */ + int discard; /* client is finished with the buffer? */ +} drmI830Vertex; + +typedef struct { + int idx; /* buffer index */ + int used; /* nr bytes in use */ + void *address; /* Address to copy from */ +} drmI830Copy; + +typedef struct { + void *virtual; + int request_idx; + int request_size; + int granted; +} drmI830DMA; + +typedef struct drm_i830_irq_emit { + int *irq_seq; +} drmI830IrqEmit; + +typedef struct drm_i830_irq_wait { + int irq_seq; +} drmI830IrqWait; + +typedef struct drm_i830_getparam { + int param; + int *value; +} drmI830GetParam; + +#define I830_PARAM_IRQ_ACTIVE 1 + + +typedef struct drm_i830_setparam { + int param; + int value; +} drmI830SetParam; + +#define I830_SETPARAM_USE_MI_BATCHBUFFER_START 1 + + + +#endif /* _I830_DRM_H_ */ diff --git a/src/mesa/drivers/dri/i830/server/i830_dri.h b/src/mesa/drivers/dri/i830/server/i830_dri.h new file mode 100644 index 0000000000..69a4f678d2 --- /dev/null +++ b/src/mesa/drivers/dri/i830/server/i830_dri.h @@ -0,0 +1,140 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dri.h,v 1.5 2002/12/10 01:27:05 dawes Exp $ */ + +#ifndef _I830_DRI_H +#define _I830_DRI_H + +#include "xf86drm.h" +#include "i830_common.h" + +#define I830_MAX_DRAWABLES 256 + +#define I830_MAJOR_VERSION 1 +#define I830_MINOR_VERSION 3 +#define I830_PATCHLEVEL 0 + +#define I830_REG_SIZE 0x80000 + +typedef struct _I830DRIRec { + drmHandle regs; + drmSize regsSize; + drmAddress regsMap; + + drmSize backbufferSize; + drmHandle backbuffer; + + drmSize depthbufferSize; + drmHandle depthbuffer; + + drmHandle textures; + int textureSize; + + drmHandle agp_buffers; + drmSize agp_buf_size; + + int deviceID; + int width; + int height; + int mem; + int cpp; + int bitsPerPixel; + int fbOffset; + int fbStride; + + int backOffset; + int depthOffset; + + int auxPitch; + int auxPitchBits; + + int logTextureGranularity; + int textureOffset; + + /* For non-dma direct rendering. + */ + int ringOffset; + int ringSize; + + drmBufMapPtr drmBufs; + int irq; + int sarea_priv_offset; +} I830DRIRec, *I830DRIPtr; + +typedef struct { + /* Nothing here yet */ + int dummy; +} I830ConfigPrivRec, *I830ConfigPrivPtr; + +typedef struct { + /* Nothing here yet */ + int dummy; +} I830DRIContextRec, *I830DRIContextPtr; + +/* Warning: If you change the SAREA structure you must change the kernel + * structure as well */ + +typedef struct _I830SAREA { + unsigned int ContextState[I830_CTX_SETUP_SIZE]; + unsigned int BufferState[I830_DEST_SETUP_SIZE]; + unsigned int TexState[I830_TEXTURE_COUNT][I830_TEX_SETUP_SIZE]; + unsigned int TexBlendState[I830_TEXBLEND_COUNT][I830_TEXBLEND_SIZE]; + unsigned int TexBlendStateWordsUsed[I830_TEXBLEND_COUNT]; + unsigned int Palette[2][256]; + unsigned int dirty; + + unsigned int nbox; + XF86DRIClipRectRec boxes[I830_NR_SAREA_CLIPRECTS]; + + /* Maintain an LRU of contiguous regions of texture space. If + * you think you own a region of texture memory, and it has an + * age different to the one you set, then you are mistaken and + * it has been stolen by another client. If global texAge + * hasn't changed, there is no need to walk the list. + * + * These regions can be used as a proxy for the fine-grained + * texture information of other clients - by maintaining them + * in the same lru which is used to age their own textures, + * clients have an approximate lru for the whole of global + * texture space, and can make informed decisions as to which + * areas to kick out. There is no need to choose whether to + * kick out your own texture or someone else's - simply eject + * them all in LRU order. + */ + + drmTextureRegion texList[I830_NR_TEX_REGIONS + 1]; + /* Last elt is sentinal */ + int texAge; /* last time texture was uploaded */ + int last_enqueue; /* last time a buffer was enqueued */ + int last_dispatch; /* age of the most recently dispatched buffer */ + int last_quiescent; /* */ + int ctxOwner; /* last context to upload state */ + + int vertex_prim; + + int pf_enabled; /* is pageflipping allowed? */ + int pf_active; /* is pageflipping active right now? */ + int pf_current_page; /* which buffer is being displayed? */ + + int perf_boxes; /* performance boxes to be displayed */ + + /* Here's the state for texunits 2,3: + */ + unsigned int TexState2[I830_TEX_SETUP_SIZE]; + unsigned int TexBlendState2[I830_TEXBLEND_SIZE]; + unsigned int TexBlendStateWordsUsed2; + + unsigned int TexState3[I830_TEX_SETUP_SIZE]; + unsigned int TexBlendState3[I830_TEXBLEND_SIZE]; + unsigned int TexBlendStateWordsUsed3; + + unsigned int StippleState[I830_STP_SETUP_SIZE]; +} I830SAREARec, *I830SAREAPtr; + +/* Flags for perf_boxes + */ +#define I830_BOX_RING_EMPTY 0x1 /* populated by kernel */ +#define I830_BOX_FLIP 0x2 /* populated by kernel */ +#define I830_BOX_WAIT 0x4 /* populated by kernel & client */ +#define I830_BOX_TEXTURE_LOAD 0x8 /* populated by kernel */ +#define I830_BOX_LOST_CONTEXT 0x10 /* populated by client */ + +#endif |