Browse Source

add tdfx DRI driver

tags/R300_DRIVER_0
Alan Hourihane 22 years ago
parent
commit
e05ab2795b
33 changed files with 15823 additions and 0 deletions
  1. 64
    0
      src/mesa/drivers/dri/tdfx/BUGS
  2. 128
    0
      src/mesa/drivers/dri/tdfx/Makefile.X11
  3. 84
    0
      src/mesa/drivers/dri/tdfx/X86/fx_3dnow_fastpath.S
  4. 314
    0
      src/mesa/drivers/dri/tdfx/X86/fx_3dnow_fasttmp.h
  5. 63
    0
      src/mesa/drivers/dri/tdfx/dri_glide.h
  6. 897
    0
      src/mesa/drivers/dri/tdfx/tdfx_context.c
  7. 1027
    0
      src/mesa/drivers/dri/tdfx/tdfx_context.h
  8. 330
    0
      src/mesa/drivers/dri/tdfx/tdfx_dd.c
  9. 47
    0
      src/mesa/drivers/dri/tdfx/tdfx_dd.h
  10. 606
    0
      src/mesa/drivers/dri/tdfx/tdfx_glide.h
  11. 90
    0
      src/mesa/drivers/dri/tdfx/tdfx_lock.c
  12. 149
    0
      src/mesa/drivers/dri/tdfx/tdfx_lock.h
  13. 689
    0
      src/mesa/drivers/dri/tdfx/tdfx_pixels.c
  14. 80
    0
      src/mesa/drivers/dri/tdfx/tdfx_pixels.h
  15. 802
    0
      src/mesa/drivers/dri/tdfx/tdfx_render.c
  16. 54
    0
      src/mesa/drivers/dri/tdfx/tdfx_render.h
  17. 331
    0
      src/mesa/drivers/dri/tdfx/tdfx_screen.c
  18. 73
    0
      src/mesa/drivers/dri/tdfx/tdfx_screen.h
  19. 1399
    0
      src/mesa/drivers/dri/tdfx/tdfx_span.c
  20. 48
    0
      src/mesa/drivers/dri/tdfx/tdfx_span.h
  21. 1466
    0
      src/mesa/drivers/dri/tdfx/tdfx_state.c
  22. 64
    0
      src/mesa/drivers/dri/tdfx/tdfx_state.h
  23. 1473
    0
      src/mesa/drivers/dri/tdfx/tdfx_tex.c
  24. 165
    0
      src/mesa/drivers/dri/tdfx/tdfx_tex.h
  25. 970
    0
      src/mesa/drivers/dri/tdfx/tdfx_texman.c
  26. 84
    0
      src/mesa/drivers/dri/tdfx/tdfx_texman.h
  27. 2107
    0
      src/mesa/drivers/dri/tdfx/tdfx_texstate.c
  28. 44
    0
      src/mesa/drivers/dri/tdfx/tdfx_texstate.h
  29. 1258
    0
      src/mesa/drivers/dri/tdfx/tdfx_tris.c
  30. 42
    0
      src/mesa/drivers/dri/tdfx/tdfx_tris.h
  31. 365
    0
      src/mesa/drivers/dri/tdfx/tdfx_vb.c
  32. 68
    0
      src/mesa/drivers/dri/tdfx/tdfx_vb.h
  33. 442
    0
      src/mesa/drivers/dri/tdfx/tdfx_vbtmp.h

+ 64
- 0
src/mesa/drivers/dri/tdfx/BUGS View File

@@ -0,0 +1,64 @@
REMOVE THIS FILE BEFORE MERGING WITH TRUNK
------------------------------------------

OUTSTANDING BUGS

demos/reflect - reading back Z on Voodoo3, image offset to right
Fixed in latest Glide.

Q3 - some polygons drawn as vertical strips, similar to bug that was
seen in demos/fire. Voodoo3 only. May be related to glDepthMask
or glColorMask.

book/fog - not fogging
Fog in orthograph mode still not implemented. Checking with
3dfx engineers for ideas.

Q3 demo crashes after changing display settings
but the full Q3 game version seems OK.



MORE OUTSTANDING BUGS

private context was NULL! causing immediate failure of any glx prog. cant
reproduce after restarting the X server. putting it down as halluc.

texture object image was NULL, causing segmentation failure. happens with
prboom. ive put a check in tdfx_texstate.c but this isn't a fix.

prboom, wall textures near first chainsaw aren't bound properly. sideways
movements causes the wall textures to move with you. prboom busted?

16bpp mode, quake3, windowed, q3dm1, floor under rocketlauncher bands. it
looks like multitexturing gone wrong. i'll disable a tmu and test.

sof, polygons appear at wrong x,y,z positions, intermittent, have not yet
found reliable way of reproducing. culling? sometimes polys disappear.

descent3 is all black in 16bpp mode - FIXED (palette problems)

smeared pixels in quake3 - FIXED (texture memory overlapped FB)



PERFORMANCE COMPARISON (Brian / Alan)

V3/16 is Voodoo3 in 16bpp on a P3/500
V5/16 is Voodoo5 in 16bpp on a P3/600
V5/32 is Voodoo5 in 32bpp on a P3/600
V5A/16 is Voodoo5 in 16bpp on an Alpha AXP/600
V5A/32 is Voodoo5 in 32bpp on an Alpha AXP/600

tdfx-2-1-branch tdfx-3-0-0-branch
demo V3/16 V5/16 V5/32 V3/16 V5/16 V5/32 V5A/16 V5A/32
------------------------------------------------------------------------
gloss 257 183 174 320 308 177 313 167
fire 42 39 52 41
fire (no help) 98 80 50 106 113 73 124 80
tunnel 61 50 70 58
tunnel (no help) 167 142 57 138 152 113 171 122
gears 663 554 540 881 1232 776 1484 830
teapot 20 21 37 36
teapot (no help) 22 14 14 24 30 30 43 42


+ 128
- 0
src/mesa/drivers/dri/tdfx/Makefile.X11 View File

@@ -0,0 +1,128 @@

# 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/tdfx_dri.c

DRIVER_SOURCES = tdfx_context.c \
../common/mm.c \
../common/utils.c \
../common/texmem.c \
../common/vblank.c \
../common/xmlconfig.c \
tdfx_dd.c \
tdfx_lock.c \
tdfx_pixels.c \
tdfx_render.c \
tdfx_screen.c \
tdfx_span.c \
tdfx_state.c \
tdfx_tex.c \
tdfx_texman.c \
tdfx_texstate.c \
tdfx_tris.c \
tdfx_vb.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)

$(SYMLINKS):
mkdir -p server
cd server
rm -f $@ && ln -s ../../radeon/$@ $@


### 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 tdfx_dri.so

tdfx_dri.so: $(SYMLINKS) $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile.X11
rm -f $@ && gcc -o $@ -shared $(OBJECTS) $(MESA_MODULES) $(WINOBJ) $(WINLIB) -lc $(GL_LIB_DEPS)
rm -f $(TOP)/lib/tdfx_dri.so && \
install tdfx_dri.so $(TOP)/lib/tdfx_dri.so

$(TOP)/lib/tdfx_dri.so: tdfx_dri.so
rm -f $(TOP)/lib/tdfx_dri.so && \
install tdfx_dri.so $(TOP)/lib/tdfx_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
-rm -f $(SYMLINKS)


include $(TOP)/Make-config

include depend

+ 84
- 0
src/mesa/drivers/dri/tdfx/X86/fx_3dnow_fastpath.S View File

@@ -0,0 +1,84 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/tdfx/X86/fx_3dnow_fastpath.S,v 1.2 2000/09/26 15:56:51 tsi Exp $ */

#include "../../X86/assyntax.h"

#define SETUP_RGBA 0x1
#define SETUP_TMU0 0x2
#define SETUP_TMU1 0x4


/* Pack either rgba or texture into the remaining half of a 32 byte vertex.
*/
#define CLIP_R 24
#define CLIP_G 16
#define CLIP_B 20
#define CLIP_A 28 /* defined inf fxdrv.h */

#define CLIP_S0 16
#define CLIP_T0 20
#define CLIP_S1 24
#define CLIP_T1 28

#define SIZE 4
#define TYPE (0)
#define TAG(x) x
#include "fx_3dnow_fasttmp.h"

#define SIZE 8
#define TYPE (SETUP_RGBA)
#define TAG(x) x##_RGBA
#include "fx_3dnow_fasttmp.h"

#define SIZE 6
#define TYPE (SETUP_TMU0)
#define TAG(x) x##_TMU0
#include "fx_3dnow_fasttmp.h"

#define SIZE 8
#define TYPE (SETUP_TMU0|SETUP_TMU1)
#define TAG(x) x##_TMU0_TMU1
#include "fx_3dnow_fasttmp.h"

#undef CLIP_S1
#undef CLIP_T1
#define CLIP_S1 16
#define CLIP_T1 20

#define SIZE 6
#define TYPE (SETUP_TMU1)
#define TAG(x) x##_TMU1
#include "fx_3dnow_fasttmp.h"

/* These three need to use a full 64 byte clip-space vertex.
*/
#undef CLIP_S0
#undef CLIP_T0
#undef CLIP_S1
#undef CLIP_T1

#define CLIP_S0 32
#define CLIP_T0 36
#define CLIP_S1 40
#define CLIP_T1 44

#define SIZE 10
#define TYPE (SETUP_RGBA|SETUP_TMU0)
#define TAG(x) x##_RGBA_TMU0
#include "fx_3dnow_fasttmp.h"

#define SIZE 12
#define TYPE (SETUP_RGBA|SETUP_TMU0|SETUP_TMU1)
#define TAG(x) x##_RGBA_TMU0_TMU1
#include "fx_3dnow_fasttmp.h"

#undef CLIP_S1
#undef CLIP_T1
#define CLIP_S1 32
#define CLIP_T1 36

#define SIZE 10
#define TYPE (SETUP_RGBA|SETUP_TMU1)
#define TAG(x) x##_RGBA_TMU1
#include "fx_3dnow_fasttmp.h"



+ 314
- 0
src/mesa/drivers/dri/tdfx/X86/fx_3dnow_fasttmp.h View File

@@ -0,0 +1,314 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/tdfx/X86/fx_3dnow_fasttmp.h,v 1.2 2000/09/26 15:56:51 tsi Exp $ */

#if !defined(NASM_ASSEMBLER) && !defined(MASM_ASSEMBLER)
#define TAGLLBL(a) TAG(.L##a)
#else
#define TAGLLBL(a) TAG(a)
#endif

#if !GLIDE3

#define GR_VERTEX_X_OFFSET 0
#define GR_VERTEX_Y_OFFSET 4
#define GR_VERTEX_Z_OFFSET 8
#define GR_VERTEX_R_OFFSET 12
#define GR_VERTEX_G_OFFSET 16
#define GR_VERTEX_B_OFFSET 20
#define GR_VERTEX_OOZ_OFFSET 24
#define GR_VERTEX_A_OFFSET 28
#define GR_VERTEX_OOW_OFFSET 32

#else /* GLIDE3 */

#define GR_VERTEX_X_OFFSET 0
#define GR_VERTEX_Y_OFFSET 4
#define GR_VERTEX_OOZ_OFFSET 8
#define GR_VERTEX_OOW_OFFSET 12
#define GR_VERTEX_R_OFFSET 16
#define GR_VERTEX_G_OFFSET 20
#define GR_VERTEX_B_OFFSET 24
#define GR_VERTEX_A_OFFSET 28
#define GR_VERTEX_Z_OFFSET 32

#endif /* GLIDE3 */

#define GR_VERTEX_SOW_TMU0_OFFSET 36
#define GR_VERTEX_TOW_TMU0_OFFSET 40
#define GR_VERTEX_OOW_TMU0_OFFSET 44
#define GR_VERTEX_SOW_TMU1_OFFSET 48
#define GR_VERTEX_TOW_TMU1_OFFSET 52
#define GR_VERTEX_OOW_TMU1_OFFSET 56




/*#define MAT_SX 0 /* accessed by REGIND !! */
#define MAT_SY 20
#define MAT_SZ 40
#define MAT_TX 48
#define MAT_TY 52
#define MAT_TZ 56




/* Do viewport map, device scale and perspective projection.
*
* void project_verts( GLfloat *first,
* GLfloat *last,
* const GLfloat *m,
* GLuint stride )
*
*
* Rearrange fxVertices to look like grVertices.
*/

GLOBL GLNAME( TAG(fx_3dnow_project_vertices) )
GLNAME( TAG(fx_3dnow_project_vertices) ):

PUSH_L ( EBP )

MOV_L ( REGOFF(8, ESP), ECX ) /* first_vert */
MOV_L ( REGOFF(12, ESP), EDX ) /* last_vert */

CMP_L ( ECX, EDX )
JE ( TAGLLBL(FXPV_end) )

FEMMS

PREFETCH ( REGIND(ECX) ) /* fetch the first vertex */

MOV_L ( REGOFF(16, ESP), EBP ) /* matrix */
MOV_L ( REGOFF(20, ESP), EAX ) /* stride */

MOVD ( REGOFF(MAT_TX, EBP), MM6 ) /* | tx */
PUNPCKLDQ ( REGOFF(MAT_TY, EBP), MM6 ) /* ty | tx */

#if !defined(FX_V2)
MOV_L ( CONST(0x49400000), REGOFF(-8, ESP) ) /* snapper */
MOV_L ( CONST(0x49400000), REGOFF(-4, ESP) ) /* snapper */
#endif

MOVQ ( REGOFF(-8, ESP), MM4 ) /* snapper | snapper */
PFADD ( MM4, MM6 ) /* ty+snapper | tx+snapper */

MOVD ( REGIND(EBP), MM5 )
PUNPCKLDQ ( REGOFF(MAT_SY, EBP), MM5 ) /* vsy | vsx */

MOVD ( REGOFF(MAT_SZ, EBP), MM1 ) /* | vsz */


ALIGNTEXT32
TAGLLBL(FXPV_loop_start):

PREFETCH ( REGOFF(64, ECX) ) /* fetch the next-ish vertex */


MOVD ( REGOFF(12, ECX), MM0 ) /* | f[3] */
PFRCP ( MM0, MM0 ) /* oow = 1/f[3] */

MOVD ( REGOFF(12, ECX), MM7 ) /* | f[3] */
PFRCPIT1 ( MM0, MM7 )
PFRCPIT2 ( MM0, MM7 ) /* oow | oow */

PUNPCKLDQ ( MM7, MM7 )


#if (TYPE & SETUP_RGBA)
MOVD ( REGOFF(CLIP_R, ECX ), MM0 ) /* f[RCOORD] = f[CLIP_R]; */
MOVD ( MM0, REGOFF(GR_VERTEX_R_OFFSET, ECX) )
#endif

#if (TYPE & SETUP_TMU1)
MOVQ ( REGOFF(CLIP_S1, ECX), MM0 ) /* f[S1COORD] = f[CLIP_S1] * oow */
PFMUL ( MM7, MM0 ) /* f[T1COORD] = f[CLIP_T1] * oow */
MOVQ ( MM0, REGOFF(GR_VERTEX_SOW_TMU1_OFFSET, ECX) )
#endif


#if (TYPE & SETUP_TMU0)
MOVQ ( REGOFF(CLIP_S0, ECX), MM0 ) /* f[S0COORD] = f[CLIP_S0] * oow */
PFMUL ( MM7, MM0 ) /* f[T0COORD] = f[CLIP_T0] * oow */
MOVQ ( MM0, REGOFF(GR_VERTEX_SOW_TMU0_OFFSET, ECX) )
#endif





/* DO_SETUP_XYZ */

MOVQ ( REGIND(ECX), MM2 ) /* f[1] | f[0] */
PFMUL ( MM7, MM2 ) /* f[1] * oow | f[0] * oow */

MOVD ( REGOFF(8, ECX), MM3 ) /* | f[2] */
PFMUL ( MM7, MM3 ) /* | f[2] * oow */

MOVD ( REGOFF(MAT_TZ, EBP), MM0 ) /* | vtz */
PFMUL ( MM1, MM3 ) /* | f[2] *= vsz */

PFADD ( MM0, MM3 ) /* | f[2] += vtz */
PFMUL ( MM5, MM2 ) /* f[1] *= vsy | f[0] *= vsx */

PFADD ( MM6, MM2 ) /* f[1] += vty | f[0] += vtx */

#if !defined(FX_V2)
PFSUB ( MM4, MM2 ) /* f[0,1] -= snapper */
#endif

MOVQ ( MM2, REGOFF(GR_VERTEX_X_OFFSET, ECX) )
MOVD ( MM3, REGOFF(GR_VERTEX_OOZ_OFFSET, ECX) )


/* end of DO_SETUP_XYZ */

MOVD ( MM7, REGOFF(GR_VERTEX_OOW_OFFSET, ECX) ) /* f[OOWCOORD] = oow */
ADD_L ( EAX, ECX ) /* f += stride */

CMP_L ( ECX, EDX ) /* stall??? */
JA ( TAGLLBL(FXPV_loop_start) )

TAGLLBL(FXPV_end):
FEMMS
POP_L ( EBP )
RET







/* void project_verts( GLfloat *first,
* GLfloat *last,
* const GLfloat *m,
* GLuint stride,
* const GLubyte *mask )
*
*/

GLOBL GLNAME( TAG(fx_3dnow_project_clipped_vertices) )
GLNAME( TAG(fx_3dnow_project_clipped_vertices) ):

PUSH_L ( EBP )

MOV_L ( REGOFF(8, ESP), ECX ) /* first FXDRIVER(VB)->verts*/
MOV_L ( REGOFF(12, ESP), EDX ) /* last FXDRIVER(VB)->last_vert */

FEMMS

PUSH_L ( EDI )
PUSH_L ( ESI )

PREFETCH ( REGIND(ECX) ) /* fetch the first vertex */

MOV_L ( REGOFF(24, ESP), EBP ) /* mat ctx->Viewport.WindowMap.M */
MOV_L ( REGOFF(28, ESP), EAX ) /* stride */
MOV_L ( REGOFF(32, ESP), ESI ) /* VB->ClipMask */

MOVD ( REGOFF(MAT_TX, EBP), MM6 ) /* | tx */
PUNPCKLDQ ( REGOFF(MAT_TY, EBP), MM6 ) /* ty | tx */

#if !defined(FX_V2)
MOV_L ( CONST(0x49400000), REGOFF(-8, ESP) ) /* snapper */
MOV_L ( CONST(0x49400000), REGOFF(-4, ESP) ) /* snapper */
#endif

MOVQ ( REGOFF(-8, ESP), MM4 ) /* snapper | snapper */
PFADD ( MM4, MM6 ) /* ty+snapper | tx+snapper */

MOVD ( REGIND(EBP), MM5 )
PUNPCKLDQ ( REGOFF(MAT_SY, EBP), MM5 ) /* vsy | vsx */

MOVD ( REGOFF(MAT_SZ, EBP), MM1 ) /* | vsz */



ALIGNTEXT32
TAGLLBL(FXPCV_loop_start):

PREFETCH ( REGOFF(64, ECX) ) /* fetch the next-ish vertex */

CMP_B ( CONST(0), REGIND(ESI) )
JNE ( TAGLLBL(FXPCV_skip) )

MOVD ( REGOFF(12, ECX), MM0) /* | f[3] */
PFRCP ( MM0, MM0 ) /* oow = 1/f[3] */

MOVD ( REGOFF(12, ECX), MM7) /* | f[3] */
PFRCPIT1 ( MM0, MM7 )
PFRCPIT2 ( MM0, MM7 ) /* oow | oow */

PUNPCKLDQ ( MM7, MM7 )


#if (TYPE & SETUP_RGBA)
MOVD ( REGOFF(CLIP_R, ECX ), MM0 ) /* f[RCOORD] = f[CLIP_R]; */
MOVD ( MM0, REGOFF(GR_VERTEX_R_OFFSET, ECX) )
#endif

#if (TYPE & SETUP_TMU1)
MOVQ ( REGOFF(CLIP_S1, ECX), MM0 ) /* f[S1COORD] = f[CLIP_S1] * oow */
PFMUL ( MM7, MM0 ) /* f[T1COORD] = f[CLIP_T1] * oow */
MOVQ ( MM0, REGOFF(GR_VERTEX_SOW_TMU1_OFFSET, ECX) )
#endif


#if (TYPE & SETUP_TMU0)
MOVQ ( REGOFF(CLIP_S0, ECX), MM0 ) /* f[S0COORD] = f[CLIP_S0] * oow */
PFMUL ( MM7, MM0 ) /* f[T0COORD] = f[CLIP_T0] * oow */
MOVQ ( MM0, REGOFF(GR_VERTEX_SOW_TMU0_OFFSET, ECX) )
#endif




/* DO_SETUP_XYZ */

MOVQ ( REGIND(ECX), MM2 ) /* f[1] | f[0] */
PFMUL ( MM7, MM2 ) /* f[1] * oow | f[0] * oow */

MOVD ( REGOFF(8, ECX), MM3 ) /* | f[2] */
PFMUL ( MM7, MM3 ) /* | f[2] * oow */

MOVD ( REGOFF(MAT_TZ, EBP), MM0 ) /* | vtz */
PFMUL ( MM1, MM3 ) /* | f[2] *= vsz */

PFADD ( MM0, MM3 ) /* | f[2] += vtz */
PFMUL ( MM5, MM2 ) /* f[1] *= vsy | f[0] *= vsx */

PFADD ( MM6, MM2 ) /* f[1] += vty | f[0] += vtx */

#if !defined(FX_V2)
PFSUB ( MM4, MM2 ) /* f[0,1] -= snapper */
#endif

MOVQ ( MM2, REGOFF(GR_VERTEX_X_OFFSET, ECX) )
MOVD ( MM3, REGOFF(GR_VERTEX_OOZ_OFFSET, ECX) )


/* end of DO_SETUP_XYZ */

MOVD ( MM7, REGOFF(GR_VERTEX_OOW_OFFSET, ECX) ) /* f[OOWCOORD] = oow */

TAGLLBL(FXPCV_skip):
ADD_L ( EAX, ECX ) /* f += stride */

INC_L ( ESI ) /* next ClipMask */
CMP_L ( ECX, EDX )
JA ( TAGLLBL(FXPCV_loop_start) )

POP_L ( ESI )
POP_L ( EDI )

TAGLLBL(FXPCV_end):
FEMMS
POP_L ( EBP )
RET



#undef TYPE
#undef TAG
#undef SIZE


+ 63
- 0
src/mesa/drivers/dri/tdfx/dri_glide.h View File

@@ -0,0 +1,63 @@
/* -*- mode: c; c-basic-offset: 3 -*-
*
* Copyright 2000 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
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION 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/tdfx/dri_glide.h,v 1.1 2001/03/21 16:14:26 dawes Exp $ */

/*
* Original rewrite:
* Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
*
* Authors:
* Gareth Hughes <gareth@valinux.com>
*
*/

#ifndef __DRI_GLIDE_H__
#define __DRI_GLIDE_H__

#ifdef GLX_DIRECT_RENDERING

#include <glide.h>
#include "dri_mesaint.h"

/*
* This is the private interface between Glide and the DRI.
*/
extern void grDRIOpen( char *pFB, char *pRegs, int deviceID,
int width, int height,
int mem, int cpp, int stride,
int fifoOffset, int fifoSize,
int fbOffset, int backOffset, int depthOffset,
int textureOffset, int textureSize,
volatile int *fifoPtr, volatile int *fifoRead );
extern void grDRIPosition( int x, int y, int w, int h,
int numClip, XF86DRIClipRectPtr pClip );
extern void grDRILostContext( void );
extern void grDRIImportFifo( int fifoPtr, int fifoRead );
extern void grDRIInvalidateAll( void );
extern void grDRIResetSAREA( void );
extern void grDRIBufferSwap( FxU32 swapInterval );
#endif
#endif

+ 897
- 0
src/mesa/drivers/dri/tdfx/tdfx_context.c View File

@@ -0,0 +1,897 @@
/* -*- mode: c; c-basic-offset: 3 -*-
*
* Copyright 2000 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
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION 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/tdfx/tdfx_context.c,v 1.12 2003/05/08 09:25:35 herrb Exp $ */

/*
* Original rewrite:
* Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Brian Paul <brianp@valinux.com>
*
*/

#include <dlfcn.h>
#include "tdfx_context.h"
#include "tdfx_dd.h"
#include "tdfx_state.h"
#include "tdfx_vb.h"
#include "tdfx_tris.h"
#include "tdfx_render.h"
#include "tdfx_span.h"
#include "tdfx_texman.h"
#include "extensions.h"


#include "swrast/swrast.h"
#include "swrast_setup/swrast_setup.h"
#include "array_cache/acache.h"

#include "tnl/tnl.h"
#include "tnl/t_pipeline.h"


/*
* Enable/Disable the extensions for this context.
*/
static void tdfxDDInitExtensions( GLcontext *ctx )
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);

_mesa_enable_extension( ctx, "GL_HP_occlusion_test" );
_mesa_enable_extension( ctx, "GL_EXT_paletted_texture" );
_mesa_enable_extension( ctx, "GL_EXT_texture_lod_bias" );

if ( fxMesa->haveTwoTMUs ) {
_mesa_enable_extension( ctx, "GL_EXT_texture_env_add" );
_mesa_enable_extension( ctx, "GL_ARB_multitexture" );
}

if ( TDFX_IS_NAPALM( fxMesa ) ) {
#if 0
_mesa_enable_extension( ctx, "GL_ARB_texture_compression" );
_mesa_enable_extension( ctx, "GL_3DFX_texture_compression_FXT1" );
#endif
_mesa_enable_extension( ctx, "GL_EXT_texture_env_combine" );
}

#if 0
_mesa_enable_extension( ctx, "GL_ARB_texture_cube_map");
_mesa_enable_extension( ctx, "GL_NV_texture_rectangle");
#endif

if (fxMesa->haveHwStencil) {
_mesa_enable_extension( ctx, "GL_EXT_stencil_wrap" );
}
}



static const struct gl_pipeline_stage *tdfx_pipeline[] = {
&_tnl_vertex_transform_stage,
&_tnl_normal_transform_stage,
&_tnl_lighting_stage, /* REMOVE: fog coord stage */
&_tnl_texgen_stage,
&_tnl_texture_transform_stage,
/* REMOVE: point attenuation stage */
&_tnl_render_stage,
0,
};


GLboolean tdfxCreateContext( const __GLcontextModes *mesaVis,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate )
{
tdfxContextPtr fxMesa;
GLcontext *ctx, *shareCtx;
__DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
tdfxScreenPrivate *fxScreen = (tdfxScreenPrivate *) sPriv->private;
TDFXSAREAPriv *saPriv = (TDFXSAREAPriv *) ((char *) sPriv->pSAREA +
sizeof(XF86DRISAREARec));

/* Allocate tdfx context */
fxMesa = (tdfxContextPtr) CALLOC( sizeof(tdfxContextRec) );
if (!fxMesa)
return GL_FALSE;

/* Allocate the Mesa context */
if (sharedContextPrivate)
shareCtx = ((tdfxContextPtr) sharedContextPrivate)->glCtx;
else
shareCtx = NULL;

fxMesa->glCtx = _mesa_create_context(mesaVis, shareCtx, (void *) fxMesa, GL_TRUE);
if (!fxMesa->glCtx) {
FREE(fxMesa);
return GL_FALSE;
}
driContextPriv->driverPrivate = fxMesa;

/* Mirror some important DRI state
*/
fxMesa->hHWContext = driContextPriv->hHWContext;
fxMesa->driHwLock = &sPriv->pSAREA->lock;
fxMesa->driFd = sPriv->fd;

fxMesa->driScreen = sPriv;
fxMesa->driContext = driContextPriv;
fxMesa->fxScreen = fxScreen;
fxMesa->sarea = saPriv;

fxMesa->haveHwStencil = ( TDFX_IS_NAPALM( fxMesa ) &&
mesaVis->stencilBits &&
mesaVis->depthBits == 24 );

fxMesa->screen_width = fxScreen->width;
fxMesa->screen_height = fxScreen->height;

fxMesa->new_gl_state = ~0;
fxMesa->new_state = ~0;
fxMesa->dirty = ~0;

/* NOTE: This must be here before any Glide calls! */
if (!tdfxInitGlide( fxMesa )) {
FREE(fxMesa);
return GL_FALSE;
}

fxMesa->Glide.grDRIOpen( (char*) sPriv->pFB, fxScreen->regs.map, fxScreen->deviceID,
fxScreen->width, fxScreen->height, fxScreen->mem, fxScreen->cpp,
fxScreen->stride, fxScreen->fifoOffset, fxScreen->fifoSize,
fxScreen->fbOffset, fxScreen->backOffset, fxScreen->depthOffset,
fxScreen->textureOffset, fxScreen->textureSize, &saPriv->fifoPtr,
&saPriv->fifoRead );

if ( getenv( "FX_GLIDE_SWAPINTERVAL" ) ) {
fxMesa->Glide.SwapInterval = atoi( getenv( "FX_GLIDE_SWAPINTERVAL" ) );
} else {
fxMesa->Glide.SwapInterval = 0;
}
if ( getenv( "FX_MAX_PENDING_SWAPS" ) ) {
fxMesa->Glide.MaxPendingSwaps = atoi( getenv( "FX_MAX_PENDING_SWAPS" ) );
} else {
fxMesa->Glide.MaxPendingSwaps = 2;
}

fxMesa->Glide.Initialized = GL_FALSE;
fxMesa->Glide.Board = 0;


if (getenv("FX_EMULATE_SINGLE_TMU")) {
fxMesa->haveTwoTMUs = GL_FALSE;
}
else {
if ( TDFX_IS_BANSHEE( fxMesa ) ) {
fxMesa->haveTwoTMUs = GL_FALSE;
} else {
fxMesa->haveTwoTMUs = GL_TRUE;
}
}

fxMesa->stats.swapBuffer = 0;
fxMesa->stats.reqTexUpload = 0;
fxMesa->stats.texUpload = 0;
fxMesa->stats.memTexUpload = 0;

fxMesa->tmuSrc = TDFX_TMU_NONE;

ctx = fxMesa->glCtx;
if ( TDFX_IS_NAPALM( fxMesa ) ) {
ctx->Const.MaxTextureLevels = 12;
} else {
ctx->Const.MaxTextureLevels = 9;
}
ctx->Const.MaxTextureUnits = TDFX_IS_BANSHEE( fxMesa ) ? 1 : 2;

/* No wide points.
*/
ctx->Const.MinPointSize = 1.0;
ctx->Const.MinPointSizeAA = 1.0;
ctx->Const.MaxPointSize = 1.0;
ctx->Const.MaxPointSizeAA = 1.0;

/* Disable wide lines as we can't antialias them correctly in
* hardware.
*/
ctx->Const.MinLineWidth = 1.0;
ctx->Const.MinLineWidthAA = 1.0;
ctx->Const.MaxLineWidth = 1.0;
ctx->Const.MaxLineWidthAA = 1.0;
ctx->Const.LineWidthGranularity = 1.0;

/* 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, tdfx_pipeline );

/* Configure swrast to match hardware characteristics:
*/
_swrast_allow_pixel_fog( ctx, GL_TRUE );
_swrast_allow_vertex_fog( ctx, GL_FALSE );

tdfxDDInitExtensions( ctx );
tdfxDDInitDriverFuncs( ctx );
tdfxDDInitStateFuncs( ctx );
tdfxDDInitRenderFuncs( ctx );
tdfxDDInitSpanFuncs( ctx );
tdfxDDInitTriFuncs( ctx );
tdfxInitVB( ctx );
tdfxInitState( fxMesa );

return GL_TRUE;
}


static GLboolean tdfxInitVertexFormats( tdfxContextPtr fxMesa )
{
FxI32 result;
int i;

LOCK_HARDWARE( fxMesa );

fxMesa->Glide.grGet( GR_GLIDE_VERTEXLAYOUT_SIZE, sizeof(FxI32), &result );
for ( i = 0 ; i < TDFX_NUM_LAYOUTS ; i++ ) {
fxMesa->layout[i] = MALLOC( result );
if ( !fxMesa->layout[i] ) {
UNLOCK_HARDWARE( fxMesa );
return GL_FALSE;
}
}

/* Tiny vertex format - 16 bytes.
*/
fxMesa->Glide.grReset( GR_VERTEX_PARAMETER );
fxMesa->Glide.grCoordinateSpace( GR_WINDOW_COORDS );
fxMesa->Glide.grVertexLayout( GR_PARAM_XY, TDFX_XY_OFFSET, GR_PARAM_ENABLE );
fxMesa->Glide.grVertexLayout( GR_PARAM_Z, TDFX_Z_OFFSET, GR_PARAM_ENABLE );
fxMesa->Glide.grVertexLayout( GR_PARAM_PARGB, TDFX_Q_OFFSET, GR_PARAM_ENABLE );
fxMesa->Glide.grGlideGetVertexLayout( fxMesa->layout[TDFX_LAYOUT_TINY] );

/* Non textured vertex format - 24 bytes (Need w for table fog)
*/
fxMesa->Glide.grReset( GR_VERTEX_PARAMETER );
fxMesa->Glide.grCoordinateSpace( GR_WINDOW_COORDS );
fxMesa->Glide.grVertexLayout( GR_PARAM_XY, TDFX_XY_OFFSET, GR_PARAM_ENABLE );
fxMesa->Glide.grVertexLayout( GR_PARAM_Z, TDFX_Z_OFFSET, GR_PARAM_ENABLE );
fxMesa->Glide.grVertexLayout( GR_PARAM_Q, TDFX_Q_OFFSET, GR_PARAM_ENABLE );
fxMesa->Glide.grVertexLayout( GR_PARAM_PARGB, TDFX_ARGB_OFFSET, GR_PARAM_ENABLE );
fxMesa->Glide.grGlideGetVertexLayout( fxMesa->layout[TDFX_LAYOUT_NOTEX] );

/* Single textured vertex format - 32 bytes.
*/
fxMesa->Glide.grReset( GR_VERTEX_PARAMETER );
fxMesa->Glide.grCoordinateSpace( GR_WINDOW_COORDS );
fxMesa->Glide.grVertexLayout( GR_PARAM_XY, TDFX_XY_OFFSET, GR_PARAM_ENABLE );
fxMesa->Glide.grVertexLayout( GR_PARAM_Z, TDFX_Z_OFFSET, GR_PARAM_ENABLE );
fxMesa->Glide.grVertexLayout( GR_PARAM_Q, TDFX_Q_OFFSET, GR_PARAM_ENABLE );
fxMesa->Glide.grVertexLayout( GR_PARAM_PARGB, TDFX_ARGB_OFFSET, GR_PARAM_ENABLE );
fxMesa->Glide.grVertexLayout( GR_PARAM_ST0, TDFX_ST0_OFFSET, GR_PARAM_ENABLE );
/*grVertexLayout( GR_PARAM_FOG_EXT, TDFX_FOG_OFFSET, GR_PARAM_ENABLE );*/
fxMesa->Glide.grGlideGetVertexLayout( fxMesa->layout[TDFX_LAYOUT_SINGLE] );

/* Multitextured vertex format - 40 bytes.
*/
fxMesa->Glide.grReset( GR_VERTEX_PARAMETER );
fxMesa->Glide.grCoordinateSpace( GR_WINDOW_COORDS );
fxMesa->Glide.grVertexLayout( GR_PARAM_XY, TDFX_XY_OFFSET, GR_PARAM_ENABLE );
fxMesa->Glide.grVertexLayout( GR_PARAM_Z, TDFX_Z_OFFSET, GR_PARAM_ENABLE );
fxMesa->Glide.grVertexLayout( GR_PARAM_Q, TDFX_Q_OFFSET, GR_PARAM_ENABLE );
fxMesa->Glide.grVertexLayout( GR_PARAM_PARGB, TDFX_ARGB_OFFSET, GR_PARAM_ENABLE );
fxMesa->Glide.grVertexLayout( GR_PARAM_ST0, TDFX_ST0_OFFSET, GR_PARAM_ENABLE );
fxMesa->Glide.grVertexLayout( GR_PARAM_ST1, TDFX_ST1_OFFSET, GR_PARAM_ENABLE );
/*fxMesa->Glide.grVertexLayout( GR_PARAM_FOG_EXT, TDFX_FOG_OFFSET, GR_PARAM_ENABLE );*/
fxMesa->Glide.grGlideGetVertexLayout( fxMesa->layout[TDFX_LAYOUT_MULTI] );

/* Projected texture vertex format - 48 bytes.
*/
fxMesa->Glide.grReset( GR_VERTEX_PARAMETER );
fxMesa->Glide.grCoordinateSpace( GR_WINDOW_COORDS );
fxMesa->Glide.grVertexLayout( GR_PARAM_XY, TDFX_XY_OFFSET, GR_PARAM_ENABLE );
fxMesa->Glide.grVertexLayout( GR_PARAM_Z, TDFX_Z_OFFSET, GR_PARAM_ENABLE );
fxMesa->Glide.grVertexLayout( GR_PARAM_Q, TDFX_Q_OFFSET, GR_PARAM_ENABLE );
fxMesa->Glide.grVertexLayout( GR_PARAM_PARGB, TDFX_ARGB_OFFSET, GR_PARAM_ENABLE );
fxMesa->Glide.grVertexLayout( GR_PARAM_ST0, TDFX_ST0_OFFSET, GR_PARAM_ENABLE );
fxMesa->Glide.grVertexLayout( GR_PARAM_Q0, TDFX_Q0_OFFSET, GR_PARAM_ENABLE );
fxMesa->Glide.grVertexLayout( GR_PARAM_ST1, TDFX_ST1_OFFSET, GR_PARAM_ENABLE );
fxMesa->Glide.grVertexLayout( GR_PARAM_Q1, TDFX_Q1_OFFSET, GR_PARAM_ENABLE );
/*fxMesa->Glide.grVertexLayout( GR_PARAM_FOG_EXT, TDFX_FOG_OFFSET, GR_PARAM_ENABLE );*/
fxMesa->Glide.grGlideGetVertexLayout( fxMesa->layout[TDFX_LAYOUT_PROJECT] );

UNLOCK_HARDWARE( fxMesa );

return GL_TRUE;
}


/*
* Initialize the state in an tdfxContextPtr struct.
*/
static GLboolean
tdfxInitContext( __DRIdrawablePrivate *driDrawPriv, tdfxContextPtr fxMesa )
{
/* KW: Would be nice to make one of these a member of the other.
*/
FxI32 result[2];

if ( TDFX_DEBUG & DEBUG_VERBOSE_DRI ) {
fprintf( stderr, "%s( %p )\n", __FUNCTION__, fxMesa );
}

#if DEBUG_LOCKING
fprintf(stderr, "Debug locking enabled\n");
#endif

if ( fxMesa->Glide.Initialized )
return GL_TRUE;

fxMesa->width = driDrawPriv->w;
fxMesa->height = driDrawPriv->h;

/* We have to use a light lock here, because we can't do any glide
* operations yet. No use of FX_* functions in this function.
*/
DRM_LIGHT_LOCK( fxMesa->driFd, fxMesa->driHwLock, fxMesa->hHWContext );

fxMesa->Glide.grGlideInit();
fxMesa->Glide.grSstSelect( fxMesa->Glide.Board );

fxMesa->Glide.Context = fxMesa->Glide.grSstWinOpen( (FxU32) -1,
GR_RESOLUTION_NONE,
GR_REFRESH_NONE,
fxMesa->Glide.ColorFormat,
fxMesa->Glide.Origin,
2, 1 );

fxMesa->Glide.grDRIResetSAREA();

DRM_UNLOCK( fxMesa->driFd, fxMesa->driHwLock, fxMesa->hHWContext );

if ( !fxMesa->Glide.Context )
return GL_FALSE;


/* Perform the Glide-dependant part of the context initialization.
*/
FX_grColorMaskv( fxMesa->glCtx, true4 );

tdfxTMInit( fxMesa );

LOCK_HARDWARE( fxMesa );

if ( fxMesa->glCtx->Visual.depthBits > 0 ) {
fxMesa->Glide.grDepthBufferMode(GR_DEPTHBUFFER_ZBUFFER);
} else {
fxMesa->Glide.grDepthBufferMode(GR_DEPTHBUFFER_DISABLE);
}

fxMesa->Glide.grLfbWriteColorFormat( GR_COLORFORMAT_ABGR );

fxMesa->Glide.grGet( GR_TEXTURE_ALIGN, sizeof(FxI32), result );
fxMesa->Glide.TextureAlign = result[0];

fxMesa->Glide.State = NULL;
fxMesa->Glide.grGet( GR_GLIDE_STATE_SIZE, sizeof(FxI32), result );
fxMesa->Glide.State = MALLOC( result[0] );

fxMesa->Fog.Table = NULL;
fxMesa->Glide.grGet( GR_FOG_TABLE_ENTRIES, sizeof(FxI32), result );
fxMesa->Fog.Table = MALLOC( result[0] * sizeof(GrFog_t) );

UNLOCK_HARDWARE( fxMesa );

if ( !fxMesa->Glide.State || !fxMesa->Fog.Table ) {
if ( fxMesa->Glide.State )
FREE( fxMesa->Glide.State );
if ( fxMesa->Fog.Table )
FREE( fxMesa->Fog.Table );
return GL_FALSE;
}

if ( !tdfxInitVertexFormats( fxMesa ) ) {
return GL_FALSE;
}

LOCK_HARDWARE( fxMesa );

fxMesa->Glide.grGlideGetState( fxMesa->Glide.State );

if ( getenv( "FX_GLIDE_INFO" ) ) {
printf( "GR_RENDERER = %s\n", (char *) fxMesa->Glide.grGetString( GR_RENDERER ) );
printf( "GR_VERSION = %s\n", (char *) fxMesa->Glide.grGetString( GR_VERSION ) );
printf( "GR_VENDOR = %s\n", (char *) fxMesa->Glide.grGetString( GR_VENDOR ) );
printf( "GR_HARDWARE = %s\n", (char *) fxMesa->Glide.grGetString( GR_HARDWARE ) );
printf( "GR_EXTENSION = %s\n", (char *) fxMesa->Glide.grGetString( GR_EXTENSION ) );
}

UNLOCK_HARDWARE( fxMesa );

{
const char *debug = getenv("LIBGL_DEBUG");
if (debug && strstr(debug, "fallbacks")) {
fxMesa->debugFallbacks = GL_TRUE;
}
}


fxMesa->numClipRects = 0;
fxMesa->pClipRects = NULL;
fxMesa->scissoredClipRects = GL_FALSE;

fxMesa->Glide.Initialized = GL_TRUE;

return GL_TRUE;
}


void
tdfxDestroyContext( __DRIcontextPrivate *driContextPriv )
{
tdfxContextPtr fxMesa = (tdfxContextPtr) driContextPriv->driverPrivate;

if ( TDFX_DEBUG & DEBUG_VERBOSE_DRI ) {
fprintf( stderr, "%s( %p )\n", __FUNCTION__, fxMesa );
}

if ( fxMesa ) {
if (fxMesa->glCtx->Shared->RefCount == 1 && fxMesa->driDrawable) {
/* This share group is about to go away, free our private
* texture object data.
*/
struct gl_texture_object *tObj;
tObj = fxMesa->glCtx->Shared->TexObjectList;
while (tObj) {
tdfxTMFreeTexture(fxMesa, tObj);
tObj = tObj->Next;
}
}

tdfxTMClose(fxMesa); /* free texture memory */

_swsetup_DestroyContext( fxMesa->glCtx );
_tnl_DestroyContext( fxMesa->glCtx );
_ac_DestroyContext( fxMesa->glCtx );
_swrast_DestroyContext( fxMesa->glCtx );

tdfxFreeVB( fxMesa->glCtx );

/* Free Mesa context */
fxMesa->glCtx->DriverCtx = NULL;
_mesa_destroy_context(fxMesa->glCtx);

/* free the tdfx context */
XFree( fxMesa );
}
}


GLboolean
tdfxUnbindContext( __DRIcontextPrivate *driContextPriv )
{
GET_CURRENT_CONTEXT(ctx);
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);

if ( TDFX_DEBUG & DEBUG_VERBOSE_DRI ) {
fprintf( stderr, "%s( %p )\n", __FUNCTION__, driContextPriv );
}

if ( driContextPriv && (tdfxContextPtr) driContextPriv == fxMesa ) {
LOCK_HARDWARE(fxMesa);
fxMesa->Glide.grGlideGetState(fxMesa->Glide.State);
UNLOCK_HARDWARE(fxMesa);
}
return GL_TRUE;
}


GLboolean
tdfxMakeCurrent( __DRIcontextPrivate *driContextPriv,
__DRIdrawablePrivate *driDrawPriv,
__DRIdrawablePrivate *driReadPriv )
{
if ( TDFX_DEBUG & DEBUG_VERBOSE_DRI ) {
fprintf( stderr, "%s( %p )\n", __FUNCTION__, driContextPriv );
}

if ( driContextPriv ) {
tdfxContextPtr newFx = (tdfxContextPtr) driContextPriv->driverPrivate;
GLcontext *newCtx = newFx->glCtx;
GET_CURRENT_CONTEXT(curCtx);

if ( newFx->driDrawable != driDrawPriv ) {
newFx->driDrawable = driDrawPriv;
newFx->dirty = ~0;
}
else if (curCtx == newCtx) {
/* same drawable, same context -> no-op */
/* Need to call _mesa_make_current2() in order to make sure API
* dispatch is set correctly.
*/
_mesa_make_current2( newCtx,
(GLframebuffer *) driDrawPriv->driverPrivate,
(GLframebuffer *) driReadPriv->driverPrivate );
return GL_TRUE;
}

if ( !newFx->Glide.Initialized ) {
if ( !tdfxInitContext( driDrawPriv, newFx ) )
return GL_FALSE;

LOCK_HARDWARE( newFx );

/* FIXME: Force loading of window information */
newFx->width = 0;
tdfxUpdateClipping(newCtx);
tdfxUploadClipping(newFx);

UNLOCK_HARDWARE( newFx );
} else {
LOCK_HARDWARE( newFx );

newFx->Glide.grSstSelect( newFx->Glide.Board );
newFx->Glide.grGlideSetState( newFx->Glide.State );

tdfxUpdateClipping(newCtx);
tdfxUploadClipping(newFx);

UNLOCK_HARDWARE( newFx );
}

_mesa_make_current2( newCtx,
(GLframebuffer *) driDrawPriv->driverPrivate,
(GLframebuffer *) driReadPriv->driverPrivate );

if ( !newCtx->Viewport.Width ) {
_mesa_set_viewport( newCtx, 0, 0, driDrawPriv->w, driDrawPriv->h );
}
} else {
_mesa_make_current( 0, 0 );
}

return GL_TRUE;
}


/*
* Enable this to trace calls to various Glide functions.
*/
/*#define DEBUG_TRAP*/
#ifdef DEBUG_TRAP
static void (*real_grDrawTriangle)( const void *a, const void *b, const void *c );
static void (*real_grDrawPoint)( const void *a );
static void (*real_grDrawVertexArray)(FxU32 mode, FxU32 Count, void *pointers);
static void (*real_grDrawVertexArrayContiguous)(FxU32 mode, FxU32 Count,
void *pointers, FxU32 stride);
static void (*real_grClipWindow)( FxU32 minx, FxU32 miny, FxU32 maxx, FxU32 maxy );

static void (*real_grVertexLayout)(FxU32 param, FxI32 offset, FxU32 mode);
static void (*real_grGlideGetVertexLayout)( void *layout );
static void (*real_grGlideSetVertexLayout)( const void *layout );

static void (*real_grTexDownloadMipMapLevel)( GrChipID_t tmu,
FxU32 startAddress,
GrLOD_t thisLod,
GrLOD_t largeLod,
GrAspectRatio_t aspectRatio,
GrTextureFormat_t format,
FxU32 evenOdd,
void *data );


static void debug_grDrawTriangle( const void *a, const void *b, const void *c )
{
printf("%s\n", __FUNCTION__);
(*real_grDrawTriangle)(a, b, c);
}

static void debug_grDrawPoint( const void *a )
{
const float *f = (const float *) a;
printf("%s %g %g\n", __FUNCTION__, f[0], f[1]);
(*real_grDrawPoint)(a);
}

static void debug_grDrawVertexArray(FxU32 mode, FxU32 Count, void *pointers)
{
printf("%s count=%d\n", __FUNCTION__, (int) Count);
(*real_grDrawVertexArray)(mode, Count, pointers);
}

static void debug_grDrawVertexArrayContiguous(FxU32 mode, FxU32 Count,
void *pointers, FxU32 stride)
{
printf("%s mode=0x%x count=%d\n", __FUNCTION__, (int) mode, (int) Count);
(*real_grDrawVertexArrayContiguous)(mode, Count, pointers, stride);
}

static void debug_grClipWindow( FxU32 minx, FxU32 miny, FxU32 maxx, FxU32 maxy )
{
printf("%s %d,%d .. %d,%d\n", __FUNCTION__,
(int) minx, (int) miny, (int) maxx, (int) maxy);
(*real_grClipWindow)(minx, miny, maxx, maxy);
}

static void debug_grVertexLayout(FxU32 param, FxI32 offset, FxU32 mode)
{
(*real_grVertexLayout)(param, offset, mode);
}

static void debug_grGlideGetVertexLayout( void *layout )
{
(*real_grGlideGetVertexLayout)(layout);
}

static void debug_grGlideSetVertexLayout( const void *layout )
{
(*real_grGlideSetVertexLayout)(layout);
}

static void debug_grTexDownloadMipMapLevel( GrChipID_t tmu,
FxU32 startAddress,
GrLOD_t thisLod,
GrLOD_t largeLod,
GrAspectRatio_t aspectRatio,
GrTextureFormat_t format,
FxU32 evenOdd,
void *data )
{
(*real_grTexDownloadMipMapLevel)(tmu, startAddress, thisLod, largeLod,
aspectRatio, format, evenOdd, data);
}

#endif


/*
* Examine the context's deviceID to determine what kind of 3dfx hardware
* is installed. dlopen() the appropriate Glide library and initialize
* this context's Glide function pointers.
* Return: true/false = success/failure
*/
GLboolean tdfxInitGlide(tdfxContextPtr tmesa)
{
static const char *defaultGlide = "libglide3.so";
const char *libName;
void *libHandle;

/*
* XXX this code which selects a Glide library filename given the
* deviceID may need to be cleaned up a bit.
* Non-Linux systems may have different filenames, for example.
*/
switch (tmesa->fxScreen->deviceID) {
case PCI_CHIP_BANSHEE:
case PCI_CHIP_VOODOO3:
libName = "libglide3-v3.so";
break;
case PCI_CHIP_VOODOO5: /* same as PCI_CHIP_VOODOO4 */
libName = "libglide3-v5.so";
break;
default:
{
__driUtilMessage("unrecognized 3dfx deviceID: 0x%x",
tmesa->fxScreen->deviceID);
}
return GL_FALSE;
}

libHandle = dlopen(libName, RTLD_NOW);
if (!libHandle) {
/* The device-specific Glide library filename didn't work, try the
* old, generic libglide3.so library.
*/
libHandle = dlopen(defaultGlide, RTLD_NOW);
if (!libHandle) {
__driUtilMessage(
"can't find Glide library, dlopen(%s) and dlopen(%s) both failed.",
libName, defaultGlide);
__driUtilMessage("dlerror() message: %s", dlerror());
return GL_FALSE;
}
libName = defaultGlide;
}

{
const char *env = getenv("LIBGL_DEBUG");
if (env && strstr(env, "verbose")) {
fprintf(stderr, "libGL: using Glide library %s\n", libName);
}
}

#define GET_FUNCTION(PTR, NAME) \
tmesa->Glide.PTR = dlsym(libHandle, NAME); \
if (!tmesa->Glide.PTR) { \
__driUtilMessage("couldn't find Glide function %s in %s.", \
NAME, libName); \
}

GET_FUNCTION(grDrawPoint, "grDrawPoint");
GET_FUNCTION(grDrawLine, "grDrawLine");
GET_FUNCTION(grDrawTriangle, "grDrawTriangle");
GET_FUNCTION(grVertexLayout, "grVertexLayout");
GET_FUNCTION(grDrawVertexArray, "grDrawVertexArray");
GET_FUNCTION(grDrawVertexArrayContiguous, "grDrawVertexArrayContiguous");
GET_FUNCTION(grBufferClear, "grBufferClear");
/*GET_FUNCTION(grBufferSwap, "grBufferSwap");*/
GET_FUNCTION(grRenderBuffer, "grRenderBuffer");
GET_FUNCTION(grErrorSetCallback, "grErrorSetCallback");
GET_FUNCTION(grFinish, "grFinish");
GET_FUNCTION(grFlush, "grFlush");
GET_FUNCTION(grSstWinOpen, "grSstWinOpen");
GET_FUNCTION(grSstWinClose, "grSstWinClose");
#if 0
/* Not in V3 lib, and not used anyway. */
GET_FUNCTION(grSetNumPendingBuffers, "grSetNumPendingBuffers");
#endif
GET_FUNCTION(grSelectContext, "grSelectContext");
GET_FUNCTION(grSstOrigin, "grSstOrigin");
GET_FUNCTION(grSstSelect, "grSstSelect");
GET_FUNCTION(grAlphaBlendFunction, "grAlphaBlendFunction");
GET_FUNCTION(grAlphaCombine, "grAlphaCombine");
GET_FUNCTION(grAlphaControlsITRGBLighting, "grAlphaControlsITRGBLighting");
GET_FUNCTION(grAlphaTestFunction, "grAlphaTestFunction");
GET_FUNCTION(grAlphaTestReferenceValue, "grAlphaTestReferenceValue");
GET_FUNCTION(grChromakeyMode, "grChromakeyMode");
GET_FUNCTION(grChromakeyValue, "grChromakeyValue");
GET_FUNCTION(grClipWindow, "grClipWindow");
GET_FUNCTION(grColorCombine, "grColorCombine");
GET_FUNCTION(grColorMask, "grColorMask");
GET_FUNCTION(grCullMode, "grCullMode");
GET_FUNCTION(grConstantColorValue, "grConstantColorValue");
GET_FUNCTION(grDepthBiasLevel, "grDepthBiasLevel");
GET_FUNCTION(grDepthBufferFunction, "grDepthBufferFunction");
GET_FUNCTION(grDepthBufferMode, "grDepthBufferMode");
GET_FUNCTION(grDepthMask, "grDepthMask");
GET_FUNCTION(grDisableAllEffects, "grDisableAllEffects");
GET_FUNCTION(grDitherMode, "grDitherMode");
GET_FUNCTION(grFogColorValue, "grFogColorValue");
GET_FUNCTION(grFogMode, "grFogMode");
GET_FUNCTION(grFogTable, "grFogTable");
GET_FUNCTION(grLoadGammaTable, "grLoadGammaTable");
GET_FUNCTION(grSplash, "grSplash");
GET_FUNCTION(grGet, "grGet");
GET_FUNCTION(grGetString, "grGetString");
GET_FUNCTION(grQueryResolutions, "grQueryResolutions");
GET_FUNCTION(grReset, "grReset");
GET_FUNCTION(grGetProcAddress, "grGetProcAddress");
GET_FUNCTION(grEnable, "grEnable");
GET_FUNCTION(grDisable, "grDisable");
GET_FUNCTION(grCoordinateSpace, "grCoordinateSpace");
GET_FUNCTION(grDepthRange, "grDepthRange");
GET_FUNCTION(grStippleMode, "grStippleMode");
GET_FUNCTION(grStipplePattern, "grStipplePattern");
GET_FUNCTION(grViewport, "grViewport");
GET_FUNCTION(grTexCalcMemRequired, "grTexCalcMemRequired");
GET_FUNCTION(grTexTextureMemRequired, "grTexTextureMemRequired");
GET_FUNCTION(grTexMinAddress, "grTexMinAddress");
GET_FUNCTION(grTexMaxAddress, "grTexMaxAddress");
GET_FUNCTION(grTexNCCTable, "grTexNCCTable");
GET_FUNCTION(grTexSource, "grTexSource");
GET_FUNCTION(grTexClampMode, "grTexClampMode");
GET_FUNCTION(grTexCombine, "grTexCombine");
GET_FUNCTION(grTexDetailControl, "grTexDetailControl");
GET_FUNCTION(grTexFilterMode, "grTexFilterMode");
GET_FUNCTION(grTexLodBiasValue, "grTexLodBiasValue");
GET_FUNCTION(grTexDownloadMipMap, "grTexDownloadMipMap");
GET_FUNCTION(grTexDownloadMipMapLevel, "grTexDownloadMipMapLevel");
GET_FUNCTION(grTexDownloadMipMapLevelPartial, "grTexDownloadMipMapLevelPartial");
GET_FUNCTION(grTexDownloadTable, "grTexDownloadTable");
GET_FUNCTION(grTexDownloadTablePartial, "grTexDownloadTablePartial");
GET_FUNCTION(grTexMipMapMode, "grTexMipMapMode");
GET_FUNCTION(grTexMultibase, "grTexMultibase");
GET_FUNCTION(grTexMultibaseAddress, "grTexMultibaseAddress");
GET_FUNCTION(grLfbLock, "grLfbLock");
GET_FUNCTION(grLfbUnlock, "grLfbUnlock");
GET_FUNCTION(grLfbConstantAlpha, "grLfbConstantAlpha");
GET_FUNCTION(grLfbConstantDepth, "grLfbConstantDepth");
GET_FUNCTION(grLfbWriteColorSwizzle, "grLfbWriteColorSwizzle");
GET_FUNCTION(grLfbWriteColorFormat, "grLfbWriteColorFormat");
GET_FUNCTION(grLfbWriteRegion, "grLfbWriteRegion");
GET_FUNCTION(grLfbReadRegion, "grLfbReadRegion");
GET_FUNCTION(grGlideInit, "grGlideInit");
GET_FUNCTION(grGlideShutdown, "grGlideShutdown");
GET_FUNCTION(grGlideGetState, "grGlideGetState");
GET_FUNCTION(grGlideSetState, "grGlideSetState");
GET_FUNCTION(grGlideGetVertexLayout, "grGlideGetVertexLayout");
GET_FUNCTION(grGlideSetVertexLayout, "grGlideSetVertexLayout");

/* Glide utility functions */
GET_FUNCTION(guFogGenerateExp, "guFogGenerateExp");
GET_FUNCTION(guFogGenerateExp2, "guFogGenerateExp2");
GET_FUNCTION(guFogGenerateLinear, "guFogGenerateLinear");

/* DRI functions */
GET_FUNCTION(grDRIOpen, "grDRIOpen");
GET_FUNCTION(grDRIPosition, "grDRIPosition");
/*GET_FUNCTION(grDRILostContext, "grDRILostContext");*/
GET_FUNCTION(grDRIImportFifo, "grDRIImportFifo");
GET_FUNCTION(grDRIInvalidateAll, "grDRIInvalidateAll");
GET_FUNCTION(grDRIResetSAREA, "grDRIResetSAREA");
GET_FUNCTION(grDRIBufferSwap, "grDRIBufferSwap");

/*
* Extension functions:
* Just use dlysm() because we want a NULL pointer if the function is
* not found.
*/
/* PIXEXT extension */
tmesa->Glide.grStencilFunc = dlsym(libHandle, "grStencilFunc");
tmesa->Glide.grStencilMask = dlsym(libHandle, "grStencilMask");
tmesa->Glide.grStencilOp = dlsym(libHandle, "grStencilOp");
tmesa->Glide.grBufferClearExt = dlsym(libHandle, "grBufferClearExt");
tmesa->Glide.grColorMaskExt = dlsym(libHandle, "grColorMaskExt");
/* COMBINE extension */
tmesa->Glide.grColorCombineExt = dlsym(libHandle, "grColorCombineExt");
tmesa->Glide.grTexColorCombineExt = dlsym(libHandle, "grTexColorCombineExt");
tmesa->Glide.grAlphaCombineExt = dlsym(libHandle, "grAlphaCombineExt");
tmesa->Glide.grTexAlphaCombineExt = dlsym(libHandle, "grTexAlphaCombineExt");
tmesa->Glide.grAlphaBlendFunctionExt = dlsym(libHandle, "grAlphaBlendFunctionExt");
tmesa->Glide.grConstantColorValueExt = dlsym(libHandle, "grConstantColorValueExt");
/* Texus 2 */
tmesa->Glide.txImgQuantize = dlsym(libHandle, "txImgQuantize");
tmesa->Glide.txImgDequantizeFXT1 = dlsym(libHandle, "_txImgDequantizeFXT1");
tmesa->Glide.txErrorSetCallback = dlsym(libHandle, "txErrorSetCallback");
#ifdef DEBUG_TRAP
/* wrap the drawing functions so we can trap them */
real_grDrawTriangle = tmesa->Glide.grDrawTriangle;
tmesa->Glide.grDrawTriangle = debug_grDrawTriangle;

real_grDrawPoint = tmesa->Glide.grDrawPoint;
tmesa->Glide.grDrawPoint = debug_grDrawPoint;

real_grDrawVertexArray = tmesa->Glide.grDrawVertexArray;
tmesa->Glide.grDrawVertexArray = debug_grDrawVertexArray;

real_grDrawVertexArrayContiguous = tmesa->Glide.grDrawVertexArrayContiguous;
tmesa->Glide.grDrawVertexArrayContiguous = debug_grDrawVertexArrayContiguous;

real_grClipWindow = tmesa->Glide.grClipWindow;
tmesa->Glide.grClipWindow = debug_grClipWindow;

real_grVertexLayout = tmesa->Glide.grVertexLayout;
tmesa->Glide.grVertexLayout = debug_grVertexLayout;

real_grGlideGetVertexLayout = tmesa->Glide.grGlideGetVertexLayout;
tmesa->Glide.grGlideGetVertexLayout = debug_grGlideGetVertexLayout;

real_grGlideSetVertexLayout = tmesa->Glide.grGlideSetVertexLayout;
tmesa->Glide.grGlideSetVertexLayout = debug_grGlideSetVertexLayout;

real_grTexDownloadMipMapLevel = tmesa->Glide.grTexDownloadMipMapLevel;
tmesa->Glide.grTexDownloadMipMapLevel = debug_grTexDownloadMipMapLevel;

#endif
return GL_TRUE;
}

+ 1027
- 0
src/mesa/drivers/dri/tdfx/tdfx_context.h
File diff suppressed because it is too large
View File


+ 330
- 0
src/mesa/drivers/dri/tdfx/tdfx_dd.c View File

@@ -0,0 +1,330 @@
/* -*- mode: c; c-basic-offset: 3 -*-
*
* Copyright 2000 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
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION 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/tdfx/tdfx_dd.c,v 1.10 2002/10/30 12:52:00 alanh Exp $ */

/*
* Original rewrite:
* Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Brian Paul <brianp@valinux.com>
*
*/

#include "tdfx_context.h"
#include "tdfx_dd.h"
#include "tdfx_lock.h"
#include "tdfx_vb.h"
#include "tdfx_pixels.h"

#include "context.h"
#include "enums.h"
#include "swrast/swrast.h"
#if defined(USE_X86_ASM)
#include "X86/common_x86_asm.h"
#endif


#define TDFX_DATE "20021125"


/* These are used in calls to FX_grColorMaskv() */
const GLboolean false4[4] = { GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE };
const GLboolean true4[4] = { GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE };



/* KW: Put the word Mesa in the render string because quakeworld
* checks for this rather than doing a glGet(GL_MAX_TEXTURE_SIZE).
* Why?
*/
static const GLubyte *tdfxDDGetString( GLcontext *ctx, GLenum name )
{
tdfxContextPtr fxMesa = (tdfxContextPtr) ctx->DriverCtx;

switch ( name ) {
case GL_RENDERER:
{
/* The renderer string must be per-context state to handle
* multihead correctly.
*/
char *buffer = fxMesa->rendererString;
char hardware[100];

LOCK_HARDWARE(fxMesa);
strcpy( hardware, fxMesa->Glide.grGetString(GR_HARDWARE) );
UNLOCK_HARDWARE(fxMesa);

strcpy( buffer, "Mesa DRI " );
strcat( buffer, TDFX_DATE );
strcat( buffer, " " );

if ( strcmp( hardware, "Voodoo3 (tm)" ) == 0 ) {
strcat( buffer, "Voodoo3" );
}
else if ( strcmp( hardware, "Voodoo Banshee (tm)" ) == 0 ) {
strcat( buffer, "VoodooBanshee" );
}
else if ( strcmp( hardware, "Voodoo4 (tm)" ) == 0 ) {
strcat( buffer, "Voodoo4" );
}
else if ( strcmp( hardware, "Voodoo5 (tm)" ) == 0 ) {
strcat( buffer, "Voodoo5" );
}
else {
/* unexpected result: replace spaces with hyphens */
int i;
for ( i = 0 ; hardware[i] && i < 60 ; i++ ) {
if ( hardware[i] == ' ' || hardware[i] == '\t' )
hardware[i] = '-';
}
strcat( buffer, hardware );
}

/* Append any CPU-specific information.
*/
#ifdef USE_X86_ASM
if ( _mesa_x86_cpu_features ) {
strncat( buffer, " x86", 4 );
}
#endif
#ifdef USE_MMX_ASM
if ( cpu_has_mmx ) {
strncat( buffer, "/MMX", 4 );
}
#endif
#ifdef USE_3DNOW_ASM
if ( cpu_has_3dnow ) {
strncat( buffer, "/3DNow!", 7 );
}
#endif
#ifdef USE_SSE_ASM
if ( cpu_has_xmm ) {
strncat( buffer, "/SSE", 4 );
}
#endif
return (const GLubyte *) buffer;
}
case GL_VENDOR:
return (const GLubyte *)"VA Linux Systems, Inc.";
default:
return NULL;
}
}


/* Return uptodate buffer size information.
*/
static void tdfxDDGetBufferSize( GLframebuffer *buffer,
GLuint *width, GLuint *height )
{
GET_CURRENT_CONTEXT(ctx);
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);

LOCK_HARDWARE( fxMesa );
*width = fxMesa->width;
*height = fxMesa->height;
UNLOCK_HARDWARE( fxMesa );
}



/*
* Return the current value of the occlusion test flag and
* reset the flag (hardware counters) to false.
*/
static GLboolean get_occlusion_result( GLcontext *ctx )
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
GLboolean result;

LOCK_HARDWARE( fxMesa );
fxMesa->Glide.grFinish(); /* required to flush the FIFO - FB 21-01-2002 */

if (ctx->Depth.OcclusionTest) {
if (ctx->OcclusionResult) {
result = GL_TRUE; /* result of software rendering */
}
else {
FxI32 zfail, in;
fxMesa->Glide.grGet(GR_STATS_PIXELS_DEPTHFUNC_FAIL, 4, &zfail);
fxMesa->Glide.grGet(GR_STATS_PIXELS_IN, 4, &in);
/* Geometry is occluded if there is no input (in == 0) */
/* or if all pixels failed the depth test (zfail == in) */
/* The < 1 is there because I have empirically seen cases where */
/* zfail > in.... go figure. FB - 21-01-2002. */
result = ((in - zfail) < 1 || in == 0) ? GL_FALSE : GL_TRUE;
}
}
else {
result = ctx->OcclusionResultSaved;
}

/* reset results now */
fxMesa->Glide.grReset(GR_STATS_PIXELS);
ctx->OcclusionResult = GL_FALSE;
ctx->OcclusionResultSaved = GL_FALSE;

UNLOCK_HARDWARE( fxMesa );

return result;
}


/*
* We're only implementing this function to handle the
* GL_OCCLUSTION_TEST_RESULT_HP case. It's special because it
* has a side-effect: resetting the occlustion result flag.
*/
static GLboolean tdfxDDGetBooleanv( GLcontext *ctx, GLenum pname,
GLboolean *result )
{
if ( pname == GL_OCCLUSION_TEST_RESULT_HP ) {
*result = get_occlusion_result( ctx );
return GL_TRUE;
}
return GL_FALSE;
}

static GLboolean tdfxDDGetDoublev( GLcontext *ctx, GLenum pname,
GLdouble *result )
{
if ( pname == GL_OCCLUSION_TEST_RESULT_HP ) {
*result = (GLdouble) get_occlusion_result( ctx );
return GL_TRUE;
}
return GL_FALSE;
}

static GLboolean tdfxDDGetFloatv( GLcontext *ctx, GLenum pname,
GLfloat *result )
{
if ( pname == GL_OCCLUSION_TEST_RESULT_HP ) {
*result = (GLfloat) get_occlusion_result( ctx );
return GL_TRUE;
}
return GL_FALSE;
}

static GLboolean tdfxDDGetIntegerv( GLcontext *ctx, GLenum pname,
GLint *result )
{
if ( pname == GL_OCCLUSION_TEST_RESULT_HP ) {
*result = (GLint) get_occlusion_result( ctx );
return GL_TRUE;
}
return GL_FALSE;
}



#define VISUAL_EQUALS_RGBA(vis, r, g, b, a) \
((vis.redBits == r) && \
(vis.greenBits == g) && \
(vis.blueBits == b) && \
(vis.alphaBits == a))

void tdfxDDInitDriverFuncs( GLcontext *ctx )
{
if ( MESA_VERBOSE & VERBOSE_DRIVER ) {
fprintf( stderr, "tdfx: %s()\n", __FUNCTION__ );
}

ctx->Driver.GetString = tdfxDDGetString;
ctx->Driver.GetBufferSize = tdfxDDGetBufferSize;
ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
ctx->Driver.Error = NULL;

/* 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;

/* Accelerated paths
*/
if ( VISUAL_EQUALS_RGBA(ctx->Visual, 8, 8, 8, 8) )
{
ctx->Driver.DrawPixels = tdfx_drawpixels_R8G8B8A8;
ctx->Driver.ReadPixels = tdfx_readpixels_R8G8B8A8;
}
else if ( VISUAL_EQUALS_RGBA(ctx->Visual, 5, 6, 5, 0) )
{
ctx->Driver.ReadPixels = tdfx_readpixels_R5G6B5;
}

ctx->Driver.GetBooleanv = tdfxDDGetBooleanv;
ctx->Driver.GetDoublev = tdfxDDGetDoublev;
ctx->Driver.GetFloatv = tdfxDDGetFloatv;
ctx->Driver.GetIntegerv = tdfxDDGetIntegerv;
ctx->Driver.GetPointerv = NULL;
}


/*
* These are here for lack of a better place.
*/

void
FX_grColorMaskv(GLcontext *ctx, const GLboolean rgba[4])
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
LOCK_HARDWARE(fxMesa);
if (ctx->Visual.redBits == 8) {
/* 32bpp mode */
ASSERT( fxMesa->Glide.grColorMaskExt );
fxMesa->Glide.grColorMaskExt(rgba[RCOMP], rgba[GCOMP],
rgba[BCOMP], rgba[ACOMP]);
}
else {
/* 16 bpp mode */
/* we never have an alpha buffer */
fxMesa->Glide.grColorMask(rgba[RCOMP] || rgba[GCOMP] || rgba[BCOMP],
GL_FALSE);
}
UNLOCK_HARDWARE(fxMesa);
}

void
FX_grColorMaskv_NoLock(GLcontext *ctx, const GLboolean rgba[4])
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
if (ctx->Visual.redBits == 8) {
/* 32bpp mode */
ASSERT( fxMesa->Glide.grColorMaskExt );
fxMesa->Glide.grColorMaskExt(rgba[RCOMP], rgba[GCOMP],
rgba[BCOMP], rgba[ACOMP]);
}
else {
/* 16 bpp mode */
/* we never have an alpha buffer */
fxMesa->Glide.grColorMask(rgba[RCOMP] || rgba[GCOMP] || rgba[BCOMP],
GL_FALSE);
}
}

+ 47
- 0
src/mesa/drivers/dri/tdfx/tdfx_dd.h View File

@@ -0,0 +1,47 @@
/* -*- mode: c; c-basic-offset: 3 -*-
*
* Copyright 2000 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
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION 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/tdfx/tdfx_dd.h,v 1.1 2001/03/21 16:14:27 dawes Exp $ */

/*
* Original rewrite:
* Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
*
* Authors:
* Gareth Hughes <gareth@valinux.com>
*
*/

#ifndef __TDFX_DD_H__
#define __TDFX_DD_H__

#ifdef GLX_DIRECT_RENDERING

#include "context.h"

extern void tdfxDDInitDriverFuncs( GLcontext *ctx );

#endif
#endif

+ 606
- 0
src/mesa/drivers/dri/tdfx/tdfx_glide.h View File

@@ -0,0 +1,606 @@
/*
* This file defines macros and types necessary for accessing glide3.
*/

/* $XFree86: xc/lib/GL/mesa/src/drv/tdfx/tdfx_glide.h,v 1.1 2002/02/22 21:45:03 dawes Exp $ */

#ifndef NEWGLIDE_H
#define NEWGLIDE_H

#define FX_CALL

typedef unsigned char FxU8;
typedef signed char FxI8;
typedef unsigned short FxU16;
typedef signed short FxI16;
#if defined(__alpha__) || defined (__LP64__)
typedef signed int FxI32;
typedef unsigned int FxU32;
#else
typedef signed long FxI32;
typedef unsigned long FxU32;
#endif
typedef unsigned long AnyPtr;
typedef int FxBool;
typedef float FxFloat;
typedef double FxDouble;

typedef unsigned long FxColor_t;
typedef struct
{
float r, g, b, a;
}
FxColor4;

typedef FxU32 GrColor_t;
typedef FxU8 GrAlpha_t;
typedef FxU32 GrMipMapId_t;
typedef FxU32 GrStipplePattern_t;
typedef FxU8 GrFog_t;
typedef FxU32 GrContext_t;
typedef int (FX_CALL * GrProc) (void);

#define FXTRUE 1
#define FXFALSE 0

#define FXBIT(i) (1L << (i))

#define GR_NULL_MIPMAP_HANDLE ((GrMipMapId_t) -1)

#define GR_MIPMAPLEVELMASK_EVEN FXBIT(0)
#define GR_MIPMAPLEVELMASK_ODD FXBIT(1)
#define GR_MIPMAPLEVELMASK_BOTH (GR_MIPMAPLEVELMASK_EVEN | GR_MIPMAPLEVELMASK_ODD )

typedef FxI32 GrChipID_t;
#define GR_TMU0 0x0
#define GR_TMU1 0x1
#define GR_TMU2 0x2

#define GR_FBI 0x0

typedef FxI32 GrCombineFunction_t;
#define GR_COMBINE_FUNCTION_ZERO 0x0
#define GR_COMBINE_FUNCTION_NONE GR_COMBINE_FUNCTION_ZERO
#define GR_COMBINE_FUNCTION_LOCAL 0x1
#define GR_COMBINE_FUNCTION_LOCAL_ALPHA 0x2
#define GR_COMBINE_FUNCTION_SCALE_OTHER 0x3
#define GR_COMBINE_FUNCTION_BLEND_OTHER GR_COMBINE_FUNCTION_SCALE_OTHER
#define GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL 0x4
#define GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL_ALPHA 0x5
#define GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL 0x6
#define GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL 0x7
#define GR_COMBINE_FUNCTION_BLEND GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL
#define GR_COMBINE_FUNCTION_SCALE_OTHER_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x8
#define GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL 0x9
#define GR_COMBINE_FUNCTION_BLEND_LOCAL GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL
#define GR_COMBINE_FUNCTION_SCALE_MINUS_LOCAL_ADD_LOCAL_ALPHA 0x10

typedef FxI32 GrCombineFactor_t;
#define GR_COMBINE_FACTOR_ZERO 0x0
#define GR_COMBINE_FACTOR_NONE GR_COMBINE_FACTOR_ZERO
#define GR_COMBINE_FACTOR_LOCAL 0x1
#define GR_COMBINE_FACTOR_OTHER_ALPHA 0x2
#define GR_COMBINE_FACTOR_LOCAL_ALPHA 0x3
#define GR_COMBINE_FACTOR_TEXTURE_ALPHA 0x4
#define GR_COMBINE_FACTOR_TEXTURE_RGB 0x5
#define GR_COMBINE_FACTOR_DETAIL_FACTOR GR_COMBINE_FACTOR_TEXTURE_ALPHA
#define GR_COMBINE_FACTOR_LOD_FRACTION 0x5
#define GR_COMBINE_FACTOR_ONE 0x8
#define GR_COMBINE_FACTOR_ONE_MINUS_LOCAL 0x9
#define GR_COMBINE_FACTOR_ONE_MINUS_OTHER_ALPHA 0xa
#define GR_COMBINE_FACTOR_ONE_MINUS_LOCAL_ALPHA 0xb
#define GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA 0xc
#define GR_COMBINE_FACTOR_ONE_MINUS_DETAIL_FACTOR GR_COMBINE_FACTOR_ONE_MINUS_TEXTURE_ALPHA
#define GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION 0xd

typedef FxI32 GrCombineLocal_t;
#define GR_COMBINE_LOCAL_ITERATED 0x0
#define GR_COMBINE_LOCAL_CONSTANT 0x1
#define GR_COMBINE_LOCAL_NONE GR_COMBINE_LOCAL_CONSTANT
#define GR_COMBINE_LOCAL_DEPTH 0x2

typedef FxI32 GrCombineOther_t;
#define GR_COMBINE_OTHER_ITERATED 0x0
#define GR_COMBINE_OTHER_TEXTURE 0x1
#define GR_COMBINE_OTHER_CONSTANT 0x2
#define GR_COMBINE_OTHER_NONE GR_COMBINE_OTHER_CONSTANT

typedef FxI32 GrAlphaSource_t;
#define GR_ALPHASOURCE_CC_ALPHA 0x0
#define GR_ALPHASOURCE_ITERATED_ALPHA 0x1
#define GR_ALPHASOURCE_TEXTURE_ALPHA 0x2
#define GR_ALPHASOURCE_TEXTURE_ALPHA_TIMES_ITERATED_ALPHA 0x3

typedef FxI32 GrColorCombineFnc_t;
#define GR_COLORCOMBINE_ZERO 0x0
#define GR_COLORCOMBINE_CCRGB 0x1
#define GR_COLORCOMBINE_ITRGB 0x2
#define GR_COLORCOMBINE_ITRGB_DELTA0 0x3
#define GR_COLORCOMBINE_DECAL_TEXTURE 0x4
#define GR_COLORCOMBINE_TEXTURE_TIMES_CCRGB 0x5
#define GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB 0x6
#define GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB_DELTA0 0x7
#define GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB_ADD_ALPHA 0x8
#define GR_COLORCOMBINE_TEXTURE_TIMES_ALPHA 0x9
#define GR_COLORCOMBINE_TEXTURE_TIMES_ALPHA_ADD_ITRGB 0xa
#define GR_COLORCOMBINE_TEXTURE_ADD_ITRGB 0xb
#define GR_COLORCOMBINE_TEXTURE_SUB_ITRGB 0xc
#define GR_COLORCOMBINE_CCRGB_BLEND_ITRGB_ON_TEXALPHA 0xd
#define GR_COLORCOMBINE_DIFF_SPEC_A 0xe
#define GR_COLORCOMBINE_DIFF_SPEC_B 0xf
#define GR_COLORCOMBINE_ONE 0x10

typedef FxI32 GrAlphaBlendFnc_t;
#define GR_BLEND_ZERO 0x0
#define GR_BLEND_SRC_ALPHA 0x1
#define GR_BLEND_SRC_COLOR 0x2
#define GR_BLEND_DST_COLOR GR_BLEND_SRC_COLOR
#define GR_BLEND_DST_ALPHA 0x3
#define GR_BLEND_ONE 0x4
#define GR_BLEND_ONE_MINUS_SRC_ALPHA 0x5
#define GR_BLEND_ONE_MINUS_SRC_COLOR 0x6
#define GR_BLEND_ONE_MINUS_DST_COLOR GR_BLEND_ONE_MINUS_SRC_COLOR
#define GR_BLEND_ONE_MINUS_DST_ALPHA 0x7
#define GR_BLEND_RESERVED_8 0x8
#define GR_BLEND_RESERVED_9 0x9
#define GR_BLEND_RESERVED_A 0xa
#define GR_BLEND_RESERVED_B 0xb
#define GR_BLEND_RESERVED_C 0xc
#define GR_BLEND_RESERVED_D 0xd
#define GR_BLEND_RESERVED_E 0xe
#define GR_BLEND_ALPHA_SATURATE 0xf
#define GR_BLEND_PREFOG_COLOR GR_BLEND_ALPHA_SATURATE
#define GR_BLEND_SAME_COLOR_EXT 0x08
#define GR_BLEND_ONE_MINUS_SAME_COLOR_EXT 0x09

typedef FxI32 GrAspectRatio_t;
#define GR_ASPECT_LOG2_8x1 3
#define GR_ASPECT_LOG2_4x1 2
#define GR_ASPECT_LOG2_2x1 1
#define GR_ASPECT_LOG2_1x1 0
#define GR_ASPECT_LOG2_1x2 -1
#define GR_ASPECT_LOG2_1x4 -2
#define GR_ASPECT_LOG2_1x8 -3

typedef FxI32 GrBuffer_t;
#define GR_BUFFER_FRONTBUFFER 0x0
#define GR_BUFFER_BACKBUFFER 0x1
#define GR_BUFFER_AUXBUFFER 0x2
#define GR_BUFFER_DEPTHBUFFER 0x3
#define GR_BUFFER_ALPHABUFFER 0x4
#define GR_BUFFER_TRIPLEBUFFER 0x5

typedef FxI32 GrChromakeyMode_t;
#define GR_CHROMAKEY_DISABLE 0x0
#define GR_CHROMAKEY_ENABLE 0x1

typedef FxI32 GrChromaRangeMode_t;
#define GR_CHROMARANGE_RGB_ALL_EXT 0x0

#define GR_CHROMARANGE_DISABLE_EXT 0x00
#define GR_CHROMARANGE_ENABLE_EXT 0x01

typedef FxI32 GrTexChromakeyMode_t;
#define GR_TEXCHROMA_DISABLE_EXT 0x0
#define GR_TEXCHROMA_ENABLE_EXT 0x1

#define GR_TEXCHROMARANGE_RGB_ALL_EXT 0x0

typedef FxI32 GrCmpFnc_t;
#define GR_CMP_NEVER 0x0
#define GR_CMP_LESS 0x1
#define GR_CMP_EQUAL 0x2
#define GR_CMP_LEQUAL 0x3
#define GR_CMP_GREATER 0x4
#define GR_CMP_NOTEQUAL 0x5
#define GR_CMP_GEQUAL 0x6
#define GR_CMP_ALWAYS 0x7

typedef FxI32 GrColorFormat_t;
#define GR_COLORFORMAT_ARGB 0x0
#define GR_COLORFORMAT_ABGR 0x1

#define GR_COLORFORMAT_RGBA 0x2
#define GR_COLORFORMAT_BGRA 0x3

typedef FxI32 GrCullMode_t;
#define GR_CULL_DISABLE 0x0
#define GR_CULL_NEGATIVE 0x1
#define GR_CULL_POSITIVE 0x2

typedef FxI32 GrDepthBufferMode_t;
#define GR_DEPTHBUFFER_DISABLE 0x0
#define GR_DEPTHBUFFER_ZBUFFER 0x1
#define GR_DEPTHBUFFER_WBUFFER 0x2
#define GR_DEPTHBUFFER_ZBUFFER_COMPARE_TO_BIAS 0x3
#define GR_DEPTHBUFFER_WBUFFER_COMPARE_TO_BIAS 0x4

typedef FxI32 GrDitherMode_t;
#define GR_DITHER_DISABLE 0x0
#define GR_DITHER_2x2 0x1
#define GR_DITHER_4x4 0x2

typedef FxI32 GrStippleMode_t;
#define GR_STIPPLE_DISABLE 0x0
#define GR_STIPPLE_PATTERN 0x1
#define GR_STIPPLE_ROTATE 0x2

typedef FxI32 GrFogMode_t;
#define GR_FOG_DISABLE 0x0
#define GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT 0x1
#define GR_FOG_WITH_TABLE_ON_Q 0x2
#define GR_FOG_WITH_TABLE_ON_W GR_FOG_WITH_TABLE_ON_Q
#define GR_FOG_WITH_ITERATED_Z 0x3
#define GR_FOG_WITH_ITERATED_ALPHA_EXT 0x4
#define GR_FOG_MULT2 0x100
#define GR_FOG_ADD2 0x200

typedef FxU32 GrLock_t;
#define GR_LFB_READ_ONLY 0x00
#define GR_LFB_WRITE_ONLY 0x01
#define GR_LFB_IDLE 0x00
#define GR_LFB_NOIDLE 0x10

typedef FxI32 GrLfbBypassMode_t;
#define GR_LFBBYPASS_DISABLE 0x0
#define GR_LFBBYPASS_ENABLE 0x1

typedef FxI32 GrLfbWriteMode_t;
#define GR_LFBWRITEMODE_565 0x0
#define GR_LFBWRITEMODE_555 0x1
#define GR_LFBWRITEMODE_1555 0x2
#define GR_LFBWRITEMODE_RESERVED1 0x3
#define GR_LFBWRITEMODE_888 0x4
#define GR_LFBWRITEMODE_8888 0x5
#define GR_LFBWRITEMODE_RESERVED2 0x6
#define GR_LFBWRITEMODE_RESERVED3 0x7
#define GR_LFBWRITEMODE_RESERVED4 0x8
#define GR_LFBWRITEMODE_RESERVED5 0x9
#define GR_LFBWRITEMODE_RESERVED6 0xa
#define GR_LFBWRITEMODE_RESERVED7 0xb
#define GR_LFBWRITEMODE_565_DEPTH 0xc
#define GR_LFBWRITEMODE_555_DEPTH 0xd
#define GR_LFBWRITEMODE_1555_DEPTH 0xe
#define GR_LFBWRITEMODE_ZA16 0xf
#define GR_LFBWRITEMODE_ANY 0xFF

typedef FxI32 GrOriginLocation_t;
#define GR_ORIGIN_UPPER_LEFT 0x0
#define GR_ORIGIN_LOWER_LEFT 0x1
#define GR_ORIGIN_ANY 0xFF

typedef struct
{
int size;
void *lfbPtr;
FxU32 strideInBytes;
GrLfbWriteMode_t writeMode;
GrOriginLocation_t origin;
}
GrLfbInfo_t;

typedef FxI32 GrLOD_t;
#define GR_LOD_LOG2_2048 0xb
#define GR_LOD_LOG2_1024 0xa
#define GR_LOD_LOG2_512 0x9
#define GR_LOD_LOG2_256 0x8
#define GR_LOD_LOG2_128 0x7
#define GR_LOD_LOG2_64 0x6
#define GR_LOD_LOG2_32 0x5
#define GR_LOD_LOG2_16 0x4
#define GR_LOD_LOG2_8 0x3
#define GR_LOD_LOG2_4 0x2
#define GR_LOD_LOG2_2 0x1
#define GR_LOD_LOG2_1 0x0

typedef FxI32 GrMipMapMode_t;
#define GR_MIPMAP_DISABLE 0x0
#define GR_MIPMAP_NEAREST 0x1
#define GR_MIPMAP_NEAREST_DITHER 0x2

typedef FxI32 GrSmoothingMode_t;
#define GR_SMOOTHING_DISABLE 0x0
#define GR_SMOOTHING_ENABLE 0x1

typedef FxI32 GrTextureClampMode_t;
#define GR_TEXTURECLAMP_WRAP 0x0
#define GR_TEXTURECLAMP_CLAMP 0x1
#define GR_TEXTURECLAMP_MIRROR_EXT 0x2

typedef FxI32 GrTextureCombineFnc_t;
#define GR_TEXTURECOMBINE_ZERO 0x0
#define GR_TEXTURECOMBINE_DECAL 0x1
#define GR_TEXTURECOMBINE_OTHER 0x2
#define GR_TEXTURECOMBINE_ADD 0x3
#define GR_TEXTURECOMBINE_MULTIPLY 0x4
#define GR_TEXTURECOMBINE_SUBTRACT 0x5
#define GR_TEXTURECOMBINE_DETAIL 0x6
#define GR_TEXTURECOMBINE_DETAIL_OTHER 0x7
#define GR_TEXTURECOMBINE_TRILINEAR_ODD 0x8
#define GR_TEXTURECOMBINE_TRILINEAR_EVEN 0x9
#define GR_TEXTURECOMBINE_ONE 0xa

typedef FxI32 GrTextureFilterMode_t;
#define GR_TEXTUREFILTER_POINT_SAMPLED 0x0
#define GR_TEXTUREFILTER_BILINEAR 0x1

typedef FxI32 GrTextureFormat_t;
#define GR_TEXFMT_8BIT 0x0
#define GR_TEXFMT_RGB_332 GR_TEXFMT_8BIT
#define GR_TEXFMT_YIQ_422 0x1
#define GR_TEXFMT_ALPHA_8 0x2
#define GR_TEXFMT_INTENSITY_8 0x3
#define GR_TEXFMT_ALPHA_INTENSITY_44 0x4
#define GR_TEXFMT_P_8 0x5
#define GR_TEXFMT_RSVD0 0x6
#define GR_TEXFMT_RSVD1 0x7
#define GR_TEXFMT_16BIT 0x8
#define GR_TEXFMT_ARGB_8332 GR_TEXFMT_16BIT
#define GR_TEXFMT_AYIQ_8422 0x9
#define GR_TEXFMT_RGB_565 0xa
#define GR_TEXFMT_ARGB_1555 0xb
#define GR_TEXFMT_ARGB_4444 0xc
#define GR_TEXFMT_ALPHA_INTENSITY_88 0xd
#define GR_TEXFMT_AP_88 0xe
#define GR_TEXFMT_RSVD2 0xf
#define GR_TEXFMT_ARGB_CMP_FXT1 0x11
#define GR_TEXFMT_ARGB_8888 0x12
#define GR_TEXFMT_YUYV_422 0x13
#define GR_TEXFMT_UYVY_422 0x14
#define GR_TEXFMT_AYUV_444 0x15
#define GR_TEXFMT_ARGB_CMP_DXT1 0x16
#define GR_TEXFMT_ARGB_CMP_DXT2 0x17
#define GR_TEXFMT_ARGB_CMP_DXT3 0x18
#define GR_TEXFMT_ARGB_CMP_DXT4 0x19
#define GR_TEXFMT_ARGB_CMP_DXT5 0x1A

typedef FxU32 GrTexTable_t;
#define GR_TEXTABLE_NCC0 0x0
#define GR_TEXTABLE_NCC1 0x1
#define GR_TEXTABLE_PALETTE 0x2
#define GR_TEXTABLE_PALETTE_6666_EXT 0x3

typedef FxU32 GrNCCTable_t;
#define GR_NCCTABLE_NCC0 0x0
#define GR_NCCTABLE_NCC1 0x1

typedef FxU32 GrTexBaseRange_t;
#define GR_TEXBASE_256 0x3
#define GR_TEXBASE_128 0x2
#define GR_TEXBASE_64 0x1
#define GR_TEXBASE_32_TO_1 0x0
#define GR_TEXBASE_2048 0x7
#define GR_TEXBASE_1024 0x6
#define GR_TEXBASE_512 0x5
#define GR_TEXBASE_256_TO_1 0x4

typedef FxU32 GrEnableMode_t;
#define GR_MODE_DISABLE 0x0
#define GR_MODE_ENABLE 0x1

#define GR_AA_ORDERED 0x01
#define GR_ALLOW_MIPMAP_DITHER 0x02
#define GR_PASSTHRU 0x03
#define GR_SHAMELESS_PLUG 0x04
#define GR_VIDEO_SMOOTHING 0x05

typedef FxU32 GrCoordinateSpaceMode_t;
#define GR_WINDOW_COORDS 0x00
#define GR_CLIP_COORDS 0x01

/* Parameters for strips */
#define GR_PARAM_XY 0x01
#define GR_PARAM_Z 0x02
#define GR_PARAM_W 0x03
#define GR_PARAM_Q 0x04
#define GR_PARAM_FOG_EXT 0x05

#define GR_PARAM_A 0x10

#define GR_PARAM_RGB 0x20

#define GR_PARAM_PARGB 0x30

#define GR_PARAM_ST0 0x40
#define GR_PARAM_ST1 GR_PARAM_ST0+1
#define GR_PARAM_ST2 GR_PARAM_ST0+2

#define GR_PARAM_Q0 0x50
#define GR_PARAM_Q1 GR_PARAM_Q0+1
#define GR_PARAM_Q2 GR_PARAM_Q0+2

#define GR_PARAM_DISABLE 0x00
#define GR_PARAM_ENABLE 0x01

/* grDrawVertexArray/grDrawVertexArrayContiguous */
#define GR_POINTS 0
#define GR_LINE_STRIP 1
#define GR_LINES 2
#define GR_POLYGON 3
#define GR_TRIANGLE_STRIP 4
#define GR_TRIANGLE_FAN 5
#define GR_TRIANGLES 6
#define GR_TRIANGLE_STRIP_CONTINUE 7
#define GR_TRIANGLE_FAN_CONTINUE 8

/* grGet/grReset */
#define GR_BITS_DEPTH 0x01
#define GR_BITS_RGBA 0x02
#define GR_FIFO_FULLNESS 0x03
#define GR_FOG_TABLE_ENTRIES 0x04
#define GR_GAMMA_TABLE_ENTRIES 0x05
#define GR_GLIDE_STATE_SIZE 0x06
#define GR_GLIDE_VERTEXLAYOUT_SIZE 0x07
#define GR_IS_BUSY 0x08
#define GR_LFB_PIXEL_PIPE 0x09
#define GR_MAX_TEXTURE_SIZE 0x0a
#define GR_MAX_TEXTURE_ASPECT_RATIO 0x0b
#define GR_MEMORY_FB 0x0c
#define GR_MEMORY_TMU 0x0d
#define GR_MEMORY_UMA 0x0e
#define GR_NUM_BOARDS 0x0f
#define GR_NON_POWER_OF_TWO_TEXTURES 0x10
#define GR_NUM_FB 0x11
#define GR_NUM_SWAP_HISTORY_BUFFER 0x12
#define GR_NUM_TMU 0x13
#define GR_PENDING_BUFFERSWAPS 0x14
#define GR_REVISION_FB 0x15
#define GR_REVISION_TMU 0x16
#define GR_STATS_LINES 0x17
#define GR_STATS_PIXELS_AFUNC_FAIL 0x18
#define GR_STATS_PIXELS_CHROMA_FAIL 0x19
#define GR_STATS_PIXELS_DEPTHFUNC_FAIL 0x1a
#define GR_STATS_PIXELS_IN 0x1b
#define GR_STATS_PIXELS_OUT 0x1c
#define GR_STATS_PIXELS 0x1d
#define GR_STATS_POINTS 0x1e
#define GR_STATS_TRIANGLES_IN 0x1f
#define GR_STATS_TRIANGLES_OUT 0x20
#define GR_STATS_TRIANGLES 0x21
#define GR_SWAP_HISTORY 0x22
#define GR_SUPPORTS_PASSTHRU 0x23
#define GR_TEXTURE_ALIGN 0x24
#define GR_VIDEO_POSITION 0x25
#define GR_VIEWPORT 0x26
#define GR_WDEPTH_MIN_MAX 0x27
#define GR_ZDEPTH_MIN_MAX 0x28
#define GR_VERTEX_PARAMETER 0x29
#define GR_BITS_GAMMA 0x2a
#define GR_GET_RESERVED_1 0x1000

/* grGetString types */
#define GR_EXTENSION 0xa0
#define GR_HARDWARE 0xa1
#define GR_RENDERER 0xa2
#define GR_VENDOR 0xa3
#define GR_VERSION 0xa4

typedef FxI32 GrScreenRefresh_t;
#define GR_REFRESH_NONE 0xff

typedef FxI32 GrScreenResolution_t;
#define GR_RESOLUTION_NONE 0xff

typedef struct
{
GrLOD_t smallLodLog2;
GrLOD_t largeLodLog2;
GrAspectRatio_t aspectRatioLog2;
GrTextureFormat_t format;
void *data;
}
GrTexInfo;

typedef struct GrSstPerfStats_s
{
FxU32 pixelsIn;
FxU32 chromaFail;
FxU32 zFuncFail;
FxU32 aFuncFail;
FxU32 pixelsOut;
}
GrSstPerfStats_t;

typedef struct
{
GrScreenResolution_t resolution;
GrScreenRefresh_t refresh;
int numColorBuffers;
int numAuxBuffers;
}
GrResolution;

typedef GrResolution GlideResolution;
#define GR_QUERY_ANY ((FxU32)(~0))

typedef FxU32 GrLfbSrcFmt_t;
#define GR_LFB_SRC_FMT_565 0x00
#define GR_LFB_SRC_FMT_555 0x01
#define GR_LFB_SRC_FMT_1555 0x02
#define GR_LFB_SRC_FMT_888 0x04
#define GR_LFB_SRC_FMT_8888 0x05
#define GR_LFB_SRC_FMT_565_DEPTH 0x0c
#define GR_LFB_SRC_FMT_555_DEPTH 0x0d
#define GR_LFB_SRC_FMT_1555_DEPTH 0x0e
#define GR_LFB_SRC_FMT_ZA16 0x0f
#define GR_LFB_SRC_FMT_RLE16 0x80

typedef FxU32 GrPixelFormat_t;
#define GR_PIXFMT_I_8 0x0001
#define GR_PIXFMT_AI_88 0x0002
#define GR_PIXFMT_RGB_565 0x0003
#define GR_PIXFMT_ARGB_1555 0x0004
#define GR_PIXFMT_ARGB_8888 0x0005
#define GR_PIXFMT_AA_2_RGB_565 0x0006
#define GR_PIXFMT_AA_2_ARGB_1555 0x0007
#define GR_PIXFMT_AA_2_ARGB_8888 0x0008
#define GR_PIXFMT_AA_4_RGB_565 0x0009
#define GR_PIXFMT_AA_4_ARGB_1555 0x000a
#define GR_PIXFMT_AA_4_ARGB_8888 0x000b

#define GR_LFBWRITEMODE_Z32 0x0008

typedef FxU32 GrAAMode_t;
#define GR_AA_NONE 0x0000
#define GR_AA_4SAMPLES 0x0001

typedef FxU8 GrStencil_t;

typedef FxU32 GrStencilOp_t;
#define GR_STENCILOP_KEEP 0x00
#define GR_STENCILOP_ZERO 0x01
#define GR_STENCILOP_REPLACE 0x02
#define GR_STENCILOP_INCR_CLAMP 0x03
#define GR_STENCILOP_DECR_CLAMP 0x04
#define GR_STENCILOP_INVERT 0x05
#define GR_STENCILOP_INCR_WRAP 0x06
#define GR_STENCILOP_DECR_WRAP 0x07

#define GR_TEXTURE_UMA_EXT 0x06
#define GR_STENCIL_MODE_EXT 0x07
#define GR_OPENGL_MODE_EXT 0x08

typedef FxU32 GrCCUColor_t;
typedef FxU32 GrACUColor_t;
typedef FxU32 GrTCCUColor_t;
typedef FxU32 GrTACUColor_t;
#define GR_CMBX_ZERO 0x00
#define GR_CMBX_TEXTURE_ALPHA 0x01
#define GR_CMBX_ALOCAL 0x02
#define GR_CMBX_AOTHER 0x03
#define GR_CMBX_B 0x04
#define GR_CMBX_CONSTANT_ALPHA 0x05
#define GR_CMBX_CONSTANT_COLOR 0x06
#define GR_CMBX_DETAIL_FACTOR 0x07
#define GR_CMBX_ITALPHA 0x08
#define GR_CMBX_ITRGB 0x09
#define GR_CMBX_LOCAL_TEXTURE_ALPHA 0x0a
#define GR_CMBX_LOCAL_TEXTURE_RGB 0x0b
#define GR_CMBX_LOD_FRAC 0x0c
#define GR_CMBX_OTHER_TEXTURE_ALPHA 0x0d
#define GR_CMBX_OTHER_TEXTURE_RGB 0x0e
#define GR_CMBX_TEXTURE_RGB 0x0f
#define GR_CMBX_TMU_CALPHA 0x10
#define GR_CMBX_TMU_CCOLOR 0x11

typedef FxU32 GrCombineMode_t;
#define GR_FUNC_MODE_ZERO 0x00
#define GR_FUNC_MODE_X 0x01
#define GR_FUNC_MODE_ONE_MINUS_X 0x02
#define GR_FUNC_MODE_NEGATIVE_X 0x03
#define GR_FUNC_MODE_X_MINUS_HALF 0x04

typedef FxU32 GrAlphaBlendOp_t;
#define GR_BLEND_OP_ADD 0x00
#define GR_BLEND_OP_SUB 0x01
#define GR_BLEND_OP_REVSUB 0x02

typedef struct
{
FxU32 data[256];
}
GuTexPalette;

typedef void (*GrErrorCallbackFnc_t) (const char *string, FxBool fatal);

#endif

+ 90
- 0
src/mesa/drivers/dri/tdfx/tdfx_lock.c View File

@@ -0,0 +1,90 @@
/* -*- mode: c; c-basic-offset: 3 -*-
*
* Copyright 2000 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
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION 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/tdfx/tdfx_lock.c,v 1.5 2002/12/16 16:19:00 dawes Exp $ */

/*
* Original rewrite:
* Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
*
* Authors:
* Gareth Hughes <gareth@valinux.com>
*
*/

#include "tdfx_context.h"
#include "tdfx_lock.h"
#include "tdfx_state.h"
#include "tdfx_render.h"
#include "tdfx_texman.h"
#include "tdfx_tris.h"


void tdfxGetLock( tdfxContextPtr fxMesa )
{
__DRIcontextPrivate *cPriv = fxMesa->driContext;
__DRIdrawablePrivate *dPriv = cPriv->driDrawablePriv;
__DRIscreenPrivate *sPriv = dPriv->driScreenPriv;
TDFXSAREAPriv *saPriv = (TDFXSAREAPriv *) (((char *) sPriv->pSAREA) +
fxMesa->fxScreen->sarea_priv_offset);
unsigned int stamp = dPriv->lastStamp;

drmGetLock( fxMesa->driFd, fxMesa->hHWContext, 0 );

/* This macro will update dPriv's cliprects if needed */
DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv );

if ( saPriv->fifoOwner != fxMesa->hHWContext ) {
fxMesa->Glide.grDRIImportFifo( saPriv->fifoPtr, saPriv->fifoRead );
}

if ( saPriv->ctxOwner != fxMesa->hHWContext ) {
/* This sequence looks a little odd. Glide mirrors the state, and
* when you get the state you are forcing the mirror to be up to
* date, and then getting a copy from the mirror. You can then force
* that state onto the hardware when you set the state.
*/
void *state;
FxI32 stateSize;
fxMesa->Glide.grGet(GR_GLIDE_STATE_SIZE, 4, &stateSize);
state = malloc(stateSize);
fxMesa->Glide.grGlideGetState( state );
fxMesa->Glide.grGlideSetState( state );
free( state );
}

#if 0
if ( saPriv->texOwner != fxMesa->hHWContext ) {
tdfxTMRestoreTextures_NoLock( fxMesa );
}
#endif

if ( *dPriv->pStamp != stamp || saPriv->ctxOwner != fxMesa->hHWContext ) {
tdfxUpdateClipping(fxMesa->glCtx);
tdfxUploadClipping(fxMesa);
}

DEBUG_LOCK();
}

+ 149
- 0
src/mesa/drivers/dri/tdfx/tdfx_lock.h View File

@@ -0,0 +1,149 @@
/* -*- mode: c; c-basic-offset: 3 -*-
*
* Copyright 2000 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
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION 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/tdfx/tdfx_lock.h,v 1.3 2002/02/22 21:45:03 dawes Exp $ */

/*
* Original rewrite:
* Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
*
* Authors:
* Gareth Hughes <gareth@valinux.com>
*
*/

#ifndef __TDFX_LOCK_H__
#define __TDFX_LOCK_H__

#ifdef GLX_DIRECT_RENDERING

/* You can turn this on to find locking conflicts.
*/
#define DEBUG_LOCKING 0

#if DEBUG_LOCKING
extern char *prevLockFile;
extern int prevLockLine;

#define DEBUG_LOCK() \
do { \
prevLockFile = (__FILE__); \
prevLockLine = (__LINE__); \
} while (0)

#define DEBUG_RESET() \
do { \
prevLockFile = 0; \
prevLockLine = 0; \
} while (0)

#define DEBUG_CHECK_LOCK() \
do { \
if ( prevLockFile ) { \
fprintf( stderr, \
"LOCK SET!\n\tPrevious %s:%d\n\tCurrent: %s:%d\n", \
prevLockFile, prevLockLine, __FILE__, __LINE__ ); \
exit( 1 ); \
} \
} while (0)

#else

#define DEBUG_LOCK()
#define DEBUG_RESET()
#define DEBUG_CHECK_LOCK()

#endif /* DEBUG_LOCKING */


extern void tdfxGetLock( tdfxContextPtr fxMesa );


/* !!! We may want to separate locks from locks with validation.
This could be used to improve performance for those things
commands that do not do any drawing !!! */

#define DRM_LIGHT_LOCK_RETURN(fd,lock,context,__ret) \
do { \
DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret); \
if (__ret) drmGetLock(fd,context,0); \
} while(0)

#define LOCK_HARDWARE( fxMesa ) \
do { \
char __ret = 0; \
\
DEBUG_CHECK_LOCK(); \
DRM_CAS( fxMesa->driHwLock, fxMesa->hHWContext, \
DRM_LOCK_HELD | fxMesa->hHWContext, __ret ); \
if ( __ret ) { \
tdfxGetLock( fxMesa ); \
} \
DEBUG_LOCK(); \
} while (0)

/* Unlock the hardware using the global current context */
#define UNLOCK_HARDWARE( fxMesa ) \
do { \
DRM_UNLOCK( fxMesa->driFd, fxMesa->driHwLock, fxMesa->hHWContext ); \
DEBUG_RESET(); \
} while (0)

/*
* This pair of macros makes a loop over the drawing operations
* so it is not self contained and doesn't have the nice single
* statement semantics of most macros.
*/
#define BEGIN_CLIP_LOOP(fxMesa) \
do { \
LOCK_HARDWARE( fxMesa ); \
BEGIN_CLIP_LOOP_LOCKED( fxMesa )

#define BEGIN_CLIP_LOOP_LOCKED(fxMesa) \
do { \
int _nc = fxMesa->numClipRects; \
while (_nc--) { \
if (fxMesa->numClipRects > 1) { \
int _height = fxMesa->screen_height; \
fxMesa->Glide.grClipWindow(fxMesa->pClipRects[_nc].x1, \
_height - fxMesa->pClipRects[_nc].y2, \
fxMesa->pClipRects[_nc].x2, \
_height - fxMesa->pClipRects[_nc].y1); \
}


#define END_CLIP_LOOP_LOCKED( fxMesa ) \
} \
} while (0)

#define END_CLIP_LOOP( fxMesa ) \
END_CLIP_LOOP_LOCKED( fxMesa ); \
UNLOCK_HARDWARE( fxMesa ); \
} while (0)


#endif /* GLX_DIRECT_RENDERING */

#endif /* __TDFX_LOCK_H__ */

+ 689
- 0
src/mesa/drivers/dri/tdfx/tdfx_pixels.c View File

@@ -0,0 +1,689 @@
/* -*- mode: c; c-basic-offset: 3 -*-
*
* Copyright 2000 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
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION 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/tdfx/tdfx_pixels.c,v 1.4 2002/02/22 21:45:03 dawes Exp $ */

/*
* Original rewrite:
* Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Brian Paul <brianp@valinux.com>
* Nathan Hand <nhand@valinux.com>
*
*/

#include "tdfx_context.h"
#include "tdfx_dd.h"
#include "tdfx_lock.h"
#include "tdfx_vb.h"
#include "tdfx_pixels.h"
#include "tdfx_render.h"

#include "swrast/swrast.h"

#include "image.h"


#define FX_grLfbWriteRegion(fxMesa,dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data) \
do { \
LOCK_HARDWARE(fxMesa); \
fxMesa->Glide.grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,FXFALSE,src_stride,src_data); \
UNLOCK_HARDWARE(fxMesa); \
} while(0)


#define FX_grLfbReadRegion(fxMesa,src_buffer,src_x,src_y,src_width,src_height,dst_stride,dst_data) \
do { \
LOCK_HARDWARE(fxMesa); \
fxMesa->Glide.grLfbReadRegion(src_buffer,src_x,src_y,src_width,src_height,dst_stride,dst_data); \
UNLOCK_HARDWARE(fxMesa); \
} while (0);


#if 0
static FxBool
FX_grLfbLock(tdfxContextPtr fxMesa, GrLock_t type, GrBuffer_t buffer,
GrLfbWriteMode_t writeMode, GrOriginLocation_t origin,
FxBool pixelPipeline, GrLfbInfo_t * info)
{
FxBool result;

LOCK_HARDWARE(fxMesa);
result = fxMesa->Glide.grLfbLock(type, buffer, writeMode, origin, pixelPipeline, info);
UNLOCK_HARDWARE(fxMesa);
return result;
}
#endif


#define FX_grLfbUnlock(fxMesa, t, b) \
do { \
LOCK_HARDWARE(fxMesa); \
fxMesa->Glide.grLfbUnlock(t, b); \
UNLOCK_HARDWARE(fxMesa); \
} while (0)



#if 0
/* test if window coord (px,py) is visible */
static GLboolean
inClipRects(tdfxContextPtr fxMesa, int px, int py)
{
int i;
for (i = 0; i < fxMesa->numClipRects; i++) {
if ((px >= fxMesa->pClipRects[i].x1) &&
(px < fxMesa->pClipRects[i].x2) &&
(py >= fxMesa->pClipRects[i].y1) &&
(py < fxMesa->pClipRects[i].y2)) return GL_TRUE;
}
return GL_FALSE;
}
#endif

/* test if rectangle of pixels (px,py) (px+width,py+height) is visible */
static GLboolean
inClipRects_Region(tdfxContextPtr fxMesa, int x, int y, int width, int height)
{
int i;
int x1, y1, x2, y2;
int xmin, xmax, ymin, ymax, pixelsleft;

y1 = y - height + 1; y2 = y;
x1 = x; x2 = x + width - 1;
pixelsleft = width * height;

for (i = 0; i < fxMesa->numClipRects; i++)
{
/* algorithm requires x1 < x2 and y1 < y2 */
if ((fxMesa->pClipRects[i].x1 < fxMesa->pClipRects[i].x2)) {
xmin = fxMesa->pClipRects[i].x1;
xmax = fxMesa->pClipRects[i].x2-1;
} else {
xmin = fxMesa->pClipRects[i].x2;
xmax = fxMesa->pClipRects[i].x1-1;
}
if ((fxMesa->pClipRects[i].y1 < fxMesa->pClipRects[i].y2)) {
ymin = fxMesa->pClipRects[i].y1;
ymax = fxMesa->pClipRects[i].y2-1;
} else {
ymin = fxMesa->pClipRects[i].y2;
ymax = fxMesa->pClipRects[i].y1-1;
}

/* reject trivial cases */
if (xmax < x1) continue;
if (ymax < y1) continue;
if (xmin > x2) continue;
if (ymin > y2) continue;

/* find the intersection */
if (xmin < x1) xmin = x1;
if (ymin < y1) ymin = y1;
if (xmax > x2) xmax = x2;
if (ymax > y2) ymax = y2;

pixelsleft -= (xmax-xmin+1) * (ymax-ymin+1);
}

return pixelsleft == 0;
}

#if 0
GLboolean
tdfx_bitmap_R5G6B5(GLcontext * ctx, GLint px, GLint py,
GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte * bitmap)
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
GrLfbInfo_t info;
TdfxU16 color;
const struct gl_pixelstore_attrib *finalUnpack;
struct gl_pixelstore_attrib scissoredUnpack;

/* check if there's any raster operations enabled which we can't handle */
if (ctx->RasterMask & (ALPHATEST_BIT |
BLEND_BIT |
DEPTH_BIT |
FOG_BIT |
LOGIC_OP_BIT |
SCISSOR_BIT |
STENCIL_BIT |
MASKING_BIT |
ALPHABUF_BIT | MULTI_DRAW_BIT)) return GL_FALSE;

if (ctx->Scissor.Enabled) {
/* This is a bit tricky, but by carefully adjusting the px, py,
* width, height, skipPixels and skipRows values we can do
* scissoring without special code in the rendering loop.
*/

/* we'll construct a new pixelstore struct */
finalUnpack = &scissoredUnpack;
scissoredUnpack = *unpack;
if (scissoredUnpack.RowLength == 0)
scissoredUnpack.RowLength = width;

/* clip left */
if (px < ctx->Scissor.X) {
scissoredUnpack.SkipPixels += (ctx->Scissor.X - px);
width -= (ctx->Scissor.X - px);
px = ctx->Scissor.X;
}
/* clip right */
if (px + width >= ctx->Scissor.X + ctx->Scissor.Width) {
width -= (px + width - (ctx->Scissor.X + ctx->Scissor.Width));
}
/* clip bottom */
if (py < ctx->Scissor.Y) {
scissoredUnpack.SkipRows += (ctx->Scissor.Y - py);
height -= (ctx->Scissor.Y - py);
py = ctx->Scissor.Y;
}
/* clip top */
if (py + height >= ctx->Scissor.Y + ctx->Scissor.Height) {
height -= (py + height - (ctx->Scissor.Y + ctx->Scissor.Height));
}

if (width <= 0 || height <= 0)
return GL_TRUE; /* totally scissored away */
}
else {
finalUnpack = unpack;
}

/* compute pixel value */
{
GLint r = (GLint) (ctx->Current.RasterColor[0] * 255.0f);
GLint g = (GLint) (ctx->Current.RasterColor[1] * 255.0f);
GLint b = (GLint) (ctx->Current.RasterColor[2] * 255.0f);
/*GLint a = (GLint)(ctx->Current.RasterColor[3]*255.0f); */
if (fxMesa->bgrOrder) {
color = (TdfxU16)
(((TdfxU16) 0xf8 & b) << (11 - 3)) |
(((TdfxU16) 0xfc & g) << (5 - 3 + 1)) |
(((TdfxU16) 0xf8 & r) >> 3);
}
else
color = (TdfxU16)
(((TdfxU16) 0xf8 & r) << (11 - 3)) |
(((TdfxU16) 0xfc & g) << (5 - 3 + 1)) |
(((TdfxU16) 0xf8 & b) >> 3);
}

info.size = sizeof(info);
if (!TDFX_grLfbLock(fxMesa,
GR_LFB_WRITE_ONLY,
fxMesa->currentFB,
GR_LFBWRITEMODE_565,
GR_ORIGIN_UPPER_LEFT, FXFALSE, &info)) {
#ifndef TDFX_SILENT
fprintf(stderr, "tdfx Driver: error locking the linear frame buffer\n");
#endif
return GL_TRUE;
}

{
const GLint winX = fxMesa->x_offset;
const GLint winY = fxMesa->y_offset + fxMesa->height - 1;
/* The dest stride depends on the hardware and whether we're drawing
* to the front or back buffer. This compile-time test seems to do
* the job for now.
*/
const GLint dstStride = (fxMesa->glCtx->Color.DrawBuffer == GL_FRONT)
? (fxMesa->screen_width) : (info.strideInBytes / 2);
GLint row;
/* compute dest address of bottom-left pixel in bitmap */
GLushort *dst = (GLushort *) info.lfbPtr
+ (winY - py) * dstStride + (winX + px);

for (row = 0; row < height; row++) {
const GLubyte *src =
(const GLubyte *) _mesa_image_address(finalUnpack,
bitmap, width, height,
GL_COLOR_INDEX,
GL_BITMAP, 0, row, 0);
if (finalUnpack->LsbFirst) {
/* least significan bit first */
GLubyte mask = 1U << (finalUnpack->SkipPixels & 0x7);
GLint col;
for (col = 0; col < width; col++) {
if (*src & mask) {
if (inClipRects(fxMesa, winX + px + col, winY - py - row))
dst[col] = color;
}
if (mask == 128U) {
src++;
mask = 1U;
}
else {
mask = mask << 1;
}
}
if (mask != 1)
src++;
}
else {
/* most significan bit first */
GLubyte mask = 128U >> (finalUnpack->SkipPixels & 0x7);
GLint col;
for (col = 0; col < width; col++) {
if (*src & mask) {
if (inClipRects(fxMesa, winX + px + col, winY - py - row))
dst[col] = color;
}
if (mask == 1U) {
src++;
mask = 128U;
}
else {
mask = mask >> 1;
}
}
if (mask != 128)
src++;
}
dst -= dstStride;
}
}

TDFX_grLfbUnlock(fxMesa, GR_LFB_WRITE_ONLY, fxMesa->currentFB);
return GL_TRUE;
}
#endif

#if 0
GLboolean
tdfx_bitmap_R8G8B8A8(GLcontext * ctx, GLint px, GLint py,
GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte * bitmap)
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
GrLfbInfo_t info;
GLuint color;
const struct gl_pixelstore_attrib *finalUnpack;
struct gl_pixelstore_attrib scissoredUnpack;

/* check if there's any raster operations enabled which we can't handle */
if (ctx->RasterMask & (ALPHATEST_BIT |
BLEND_BIT |
DEPTH_BIT |
FOG_BIT |
LOGIC_OP_BIT |
SCISSOR_BIT |
STENCIL_BIT |
MASKING_BIT |
ALPHABUF_BIT | MULTI_DRAW_BIT)) return GL_FALSE;

if (ctx->Scissor.Enabled) {
/* This is a bit tricky, but by carefully adjusting the px, py,
* width, height, skipPixels and skipRows values we can do
* scissoring without special code in the rendering loop.
*/

/* we'll construct a new pixelstore struct */
finalUnpack = &scissoredUnpack;
scissoredUnpack = *unpack;
if (scissoredUnpack.RowLength == 0)
scissoredUnpack.RowLength = width;

/* clip left */
if (px < ctx->Scissor.X) {
scissoredUnpack.SkipPixels += (ctx->Scissor.X - px);
width -= (ctx->Scissor.X - px);
px = ctx->Scissor.X;
}
/* clip right */
if (px + width >= ctx->Scissor.X + ctx->Scissor.Width) {
width -= (px + width - (ctx->Scissor.X + ctx->Scissor.Width));
}
/* clip bottom */
if (py < ctx->Scissor.Y) {
scissoredUnpack.SkipRows += (ctx->Scissor.Y - py);
height -= (ctx->Scissor.Y - py);
py = ctx->Scissor.Y;
}
/* clip top */
if (py + height >= ctx->Scissor.Y + ctx->Scissor.Height) {
height -= (py + height - (ctx->Scissor.Y + ctx->Scissor.Height));
}

if (width <= 0 || height <= 0)
return GL_TRUE; /* totally scissored away */
}
else {
finalUnpack = unpack;
}

/* compute pixel value */
{
GLint r = (GLint) (ctx->Current.RasterColor[0] * 255.0f);
GLint g = (GLint) (ctx->Current.RasterColor[1] * 255.0f);
GLint b = (GLint) (ctx->Current.RasterColor[2] * 255.0f);
GLint a = (GLint) (ctx->Current.RasterColor[3] * 255.0f);
color = PACK_BGRA32(r, g, b, a);
}

info.size = sizeof(info);
if (!TDFX_grLfbLock(fxMesa, GR_LFB_WRITE_ONLY,
fxMesa->currentFB, GR_LFBWRITEMODE_8888,
GR_ORIGIN_UPPER_LEFT, FXFALSE, &info)) {
#ifndef TDFX_SILENT
fprintf(stderr, "tdfx Driver: error locking the linear frame buffer\n");
#endif
return GL_TRUE;
}

{
const GLint winX = fxMesa->x_offset;
const GLint winY = fxMesa->y_offset + fxMesa->height - 1;
GLint dstStride;
GLuint *dst;
GLint row;

if (fxMesa->glCtx->Color.DrawBuffer == GL_FRONT) {
dstStride = fxMesa->screen_width;
dst =
(GLuint *) info.lfbPtr + (winY - py) * dstStride + (winX +
px);
}
else {
dstStride = info.strideInBytes / 4;
dst =
(GLuint *) info.lfbPtr + (winY - py) * dstStride + (winX +
px);
}

/* compute dest address of bottom-left pixel in bitmap */
for (row = 0; row < height; row++) {
const GLubyte *src =
(const GLubyte *) _mesa_image_address(finalUnpack,
bitmap, width, height,
GL_COLOR_INDEX,
GL_BITMAP, 0, row, 0);
if (finalUnpack->LsbFirst) {
/* least significan bit first */
GLubyte mask = 1U << (finalUnpack->SkipPixels & 0x7);
GLint col;
for (col = 0; col < width; col++) {
if (*src & mask) {
if (inClipRects(fxMesa, winX + px + col, winY - py - row))
dst[col] = color;
}
if (mask == 128U) {
src++;
mask = 1U;
}
else {
mask = mask << 1;
}
}
if (mask != 1)
src++;
}
else {
/* most significan bit first */
GLubyte mask = 128U >> (finalUnpack->SkipPixels & 0x7);
GLint col;
for (col = 0; col < width; col++) {
if (*src & mask) {
if (inClipRects(fxMesa, winX + px + col, winY - py - row))
dst[col] = color;
}
if (mask == 1U) {
src++;
mask = 128U;
}
else {
mask = mask >> 1;
}
}
if (mask != 128)
src++;
}
dst -= dstStride;
}
}

TDFX_grLfbUnlock(fxMesa, GR_LFB_WRITE_ONLY, fxMesa->currentFB);
return GL_TRUE;
}
#endif

void
tdfx_readpixels_R5G6B5(GLcontext * ctx, GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *packing,
GLvoid * dstImage)
{
if (format != GL_RGB ||
type != GL_UNSIGNED_SHORT_5_6_5 ||
(ctx->_ImageTransferState & (IMAGE_SCALE_BIAS_BIT|
IMAGE_MAP_COLOR_BIT)))
{
_swrast_ReadPixels( ctx, x, y, width, height, format, type, packing,
dstImage );
return;
}

{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
GrLfbInfo_t info;

const GLint winX = fxMesa->x_offset;
const GLint winY = fxMesa->y_offset + fxMesa->height - 1;
const GLint scrX = winX + x;
const GLint scrY = winY - y;

LOCK_HARDWARE( fxMesa );
info.size = sizeof(info);
if (fxMesa->Glide.grLfbLock(GR_LFB_READ_ONLY,
fxMesa->ReadBuffer,
GR_LFBWRITEMODE_ANY,
GR_ORIGIN_UPPER_LEFT, FXFALSE, &info)) {
const GLint srcStride = (fxMesa->glCtx->Color.DrawBuffer ==
GL_FRONT) ? (fxMesa->screen_width) : (info.strideInBytes / 2);
const GLushort *src = (const GLushort *) info.lfbPtr
+ scrY * srcStride + scrX;
GLubyte *dst = (GLubyte *) _mesa_image_address(packing,
dstImage, width, height, format, type, 0, 0, 0);
const GLint dstStride = _mesa_image_row_stride(packing,
width, format, type);

/* directly memcpy 5R6G5B pixels into client's buffer */
const GLint widthInBytes = width * 2;
GLint row;
for (row = 0; row < height; row++) {
MEMCPY(dst, src, widthInBytes);
dst += dstStride;
src -= srcStride;
}

fxMesa->Glide.grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->ReadBuffer);
}
UNLOCK_HARDWARE( fxMesa );
return;
}
}

void
tdfx_readpixels_R8G8B8A8(GLcontext * ctx, GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *packing,
GLvoid * dstImage)
{
if ((!(format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8) &&
!(format == GL_BGRA && type == GL_UNSIGNED_BYTE)) ||
(ctx->_ImageTransferState & (IMAGE_SCALE_BIAS_BIT|
IMAGE_MAP_COLOR_BIT)))
{
_swrast_ReadPixels( ctx, x, y, width, height, format, type, packing,
dstImage );
return;
}


{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
GrLfbInfo_t info;

const GLint winX = fxMesa->x_offset;
const GLint winY = fxMesa->y_offset + fxMesa->height - 1;
const GLint scrX = winX + x;
const GLint scrY = winY - y;

LOCK_HARDWARE(fxMesa);
info.size = sizeof(info);
if (fxMesa->Glide.grLfbLock(GR_LFB_READ_ONLY,
fxMesa->ReadBuffer,
GR_LFBWRITEMODE_ANY,
GR_ORIGIN_UPPER_LEFT, FXFALSE, &info))
{
const GLint srcStride = (fxMesa->glCtx->Color.DrawBuffer == GL_FRONT)
? (fxMesa->screen_width) : (info.strideInBytes / 4);
const GLuint *src = (const GLuint *) info.lfbPtr
+ scrY * srcStride + scrX;
const GLint dstStride =
_mesa_image_row_stride(packing, width, format, type);
GLubyte *dst = (GLubyte *) _mesa_image_address(packing,
dstImage, width, height, format, type, 0, 0, 0);
const GLint widthInBytes = width * 4;

{
GLint row;
for (row = 0; row < height; row++) {
MEMCPY(dst, src, widthInBytes);
dst += dstStride;
src -= srcStride;
}
}

fxMesa->Glide.grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->ReadBuffer);
}
UNLOCK_HARDWARE(fxMesa);
}
}

void
tdfx_drawpixels_R8G8B8A8(GLcontext * ctx, GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid * pixels)
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);

if ((!(format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8) &&
!(format == GL_BGRA && type == GL_UNSIGNED_BYTE)) ||
ctx->Pixel.ZoomX != 1.0F ||
ctx->Pixel.ZoomY != 1.0F ||
(ctx->_ImageTransferState & (IMAGE_SCALE_BIAS_BIT|
IMAGE_MAP_COLOR_BIT)) ||
ctx->Color.AlphaEnabled ||
ctx->Depth.Test ||
ctx->Fog.Enabled ||
ctx->Scissor.Enabled ||
ctx->Stencil.Enabled ||
!ctx->Color.ColorMask[0] ||
!ctx->Color.ColorMask[1] ||
!ctx->Color.ColorMask[2] ||
!ctx->Color.ColorMask[3] ||
ctx->Color.ColorLogicOpEnabled ||
ctx->Texture._EnabledUnits ||
ctx->Depth.OcclusionTest ||
fxMesa->Fallback)
{
_swrast_DrawPixels( ctx, x, y, width, height, format, type,
unpack, pixels );
return;
}

{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
GrLfbInfo_t info;
GLboolean result = GL_FALSE;

const GLint winX = fxMesa->x_offset;
const GLint winY = fxMesa->y_offset + fxMesa->height - 1;
const GLint scrX = winX + x;
const GLint scrY = winY - y;

/* lock early to make sure cliprects are right */
LOCK_HARDWARE(fxMesa);

/* make sure hardware has latest blend funcs */
if (ctx->Color.BlendEnabled) {
fxMesa->dirty |= TDFX_UPLOAD_BLEND_FUNC;
tdfxEmitHwStateLocked( fxMesa );
}

/* look for clipmasks, giveup if region obscured */
if (fxMesa->glCtx->Color.DrawBuffer == GL_FRONT) {
if (!inClipRects_Region(fxMesa, scrX, scrY, width, height)) {
UNLOCK_HARDWARE(fxMesa);
_swrast_DrawPixels( ctx, x, y, width, height, format, type,
unpack, pixels );
return;
}
}

info.size = sizeof(info);
if (fxMesa->Glide.grLfbLock(GR_LFB_WRITE_ONLY,
fxMesa->DrawBuffer,
GR_LFBWRITEMODE_8888,
GR_ORIGIN_UPPER_LEFT, FXTRUE, &info))
{
const GLint dstStride = (fxMesa->glCtx->Color.DrawBuffer == GL_FRONT)
? (fxMesa->screen_width * 4) : (info.strideInBytes);
GLubyte *dst = (GLubyte *) info.lfbPtr
+ scrY * dstStride + scrX * 4;
const GLint srcStride =
_mesa_image_row_stride(unpack, width, format, type);
const GLubyte *src = (GLubyte *) _mesa_image_address(unpack,
pixels, width, height, format, type, 0, 0, 0);
const GLint widthInBytes = width * 4;

if ((format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8) ||
(format == GL_BGRA && type == GL_UNSIGNED_BYTE)) {
GLint row;
for (row = 0; row < height; row++) {
MEMCPY(dst, src, widthInBytes);
dst -= dstStride;
src += srcStride;
}
result = GL_TRUE;
}

fxMesa->Glide.grLfbUnlock(GR_LFB_WRITE_ONLY, fxMesa->DrawBuffer);
}
UNLOCK_HARDWARE(fxMesa);
}
}

+ 80
- 0
src/mesa/drivers/dri/tdfx/tdfx_pixels.h View File

@@ -0,0 +1,80 @@
/* -*- mode: c; c-basic-offset: 3 -*-
*
* Copyright 2000 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
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION 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/tdfx/tdfx_pixels.h,v 1.2 2002/02/22 21:45:03 dawes Exp $ */

/*
* Original rewrite:
* Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Brian Paul <brianp@valinux.com>
* Nathan Hand <nhand@valinux.com>
*
*/

#ifndef __TDFX_PIXELS_H__
#define __TDFX_PIXELS_H__

#ifdef GLX_DIRECT_RENDERING

#include "context.h"

extern void
tdfx_bitmap_R5G6B5( GLcontext *ctx, GLint px, GLint py,
GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte *bitmap );

extern void
tdfx_bitmap_R8G8B8A8( GLcontext *ctx, GLint px, GLint py,
GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte *bitmap );

extern void
tdfx_readpixels_R5G6B5( GLcontext *ctx, GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *packing,
GLvoid *dstImage );

extern void
tdfx_readpixels_R8G8B8A8( GLcontext *ctx, GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *packing,
GLvoid *dstImage );

extern void
tdfx_drawpixels_R8G8B8A8( GLcontext *ctx, GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels );

#endif
#endif

+ 802
- 0
src/mesa/drivers/dri/tdfx/tdfx_render.c View File

@@ -0,0 +1,802 @@
/* -*- mode: c; c-basic-offset: 3 -*-
*
* Copyright 2000 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
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION 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/tdfx/tdfx_render.c,v 1.4 2002/02/22 21:45:03 dawes Exp $ */

/*
* Original rewrite:
* Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Brian Paul <brianp@valinux.com>
*
*/

#include "tdfx_context.h"
#include "tdfx_render.h"
#include "tdfx_state.h"
#include "tdfx_texman.h"
#include "swrast/swrast.h"

/* Clear the color and/or depth buffers.
*/
static void tdfxDDClear( GLcontext *ctx,
GLbitfield mask, GLboolean all,
GLint x, GLint y, GLint width, GLint height )
{
tdfxContextPtr fxMesa = (tdfxContextPtr) ctx->DriverCtx;
GLbitfield softwareMask = mask & (DD_ACCUM_BIT);
const GLuint stencil_size =
fxMesa->haveHwStencil ? fxMesa->glCtx->Visual.stencilBits : 0;

if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) {
fprintf( stderr, "%s( %d, %d, %d, %d )\n",
__FUNCTION__, (int) x, (int) y, (int) width, (int) height );
}

/* Need this check to respond to glScissor and clipping updates */
if ((fxMesa->new_state & (TDFX_NEW_CLIP | TDFX_NEW_DEPTH)) ||
(fxMesa->dirty & TDFX_UPLOAD_COLOR_MASK)) {
tdfxDDUpdateHwState(ctx);
}

/* we can't clear accum buffers */
mask &= ~(DD_ACCUM_BIT);

if (mask & DD_STENCIL_BIT) {
if (!fxMesa->haveHwStencil || ctx->Stencil.WriteMask[0] != 0xff) {
/* Napalm seems to have trouble with stencil write masks != 0xff */
/* do stencil clear in software */
mask &= ~(DD_STENCIL_BIT);
softwareMask |= DD_STENCIL_BIT;
}
}

if (fxMesa->glCtx->Visual.redBits != 8) {
/* can only do color masking if running in 24/32bpp on Napalm */
if (ctx->Color.ColorMask[RCOMP] != ctx->Color.ColorMask[GCOMP] ||
ctx->Color.ColorMask[GCOMP] != ctx->Color.ColorMask[BCOMP]) {
softwareMask |= (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT));
mask &= ~(DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT);
}
}

if (fxMesa->haveHwStencil) {
/*
* If we want to clear stencil, it must be enabled
* in the HW, even if the stencil test is not enabled
* in the OGL state.
*/
LOCK_HARDWARE(fxMesa);
if (mask & DD_STENCIL_BIT) {
fxMesa->Glide.grStencilMask(/*ctx->Stencil.WriteMask*/ 0xff);
/* set stencil ref value = desired clear value */
fxMesa->Glide.grStencilFunc(GR_CMP_ALWAYS,
ctx->Stencil.Clear, 0xff);
fxMesa->Glide.grStencilOp(GR_STENCILOP_REPLACE,
GR_STENCILOP_REPLACE, GR_STENCILOP_REPLACE);
fxMesa->Glide.grEnable(GR_STENCIL_MODE_EXT);
}
else {
fxMesa->Glide.grDisable(GR_STENCIL_MODE_EXT);
}
UNLOCK_HARDWARE(fxMesa);
}

/*
* This may be ugly, but it's needed in order to work around a number
* of Glide bugs.
*/
BEGIN_CLIP_LOOP(fxMesa);
{
/*
* This could probably be done fancier but doing each possible case
* explicitly is less error prone.
*/
switch (mask & ~DD_STENCIL_BIT) {
case DD_BACK_LEFT_BIT | DD_DEPTH_BIT:
/* back buffer & depth */
FX_grColorMaskv_NoLock(ctx, true4); /* work around Voodoo3 bug */
fxMesa->Glide.grDepthMask(FXTRUE);
fxMesa->Glide.grRenderBuffer(GR_BUFFER_BACKBUFFER);
if (stencil_size > 0) {
fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear,
(FxU32) ctx->Stencil.Clear);
}
else
fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear);
if (!ctx->Depth.Mask || !ctx->Depth.Test) {
fxMesa->Glide.grDepthMask(FXFALSE);
}
break;
case DD_FRONT_LEFT_BIT | DD_DEPTH_BIT:
/* XXX it appears that the depth buffer isn't cleared when
* glRenderBuffer(GR_BUFFER_FRONTBUFFER) is set.
* This is a work-around/
*/
/* clear depth */
fxMesa->Glide.grDepthMask(FXTRUE);
fxMesa->Glide.grRenderBuffer(GR_BUFFER_BACKBUFFER);
FX_grColorMaskv_NoLock(ctx, false4);
if (stencil_size > 0)
fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear,
(FxU32) ctx->Stencil.Clear);
else
fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear);
/* clear front */
FX_grColorMaskv_NoLock(ctx, true4);
fxMesa->Glide.grRenderBuffer(GR_BUFFER_FRONTBUFFER);
if (stencil_size > 0)
fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear,
(FxU32) ctx->Stencil.Clear);
else
fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear);
if (!ctx->Depth.Mask || !ctx->Depth.Test) {
fxMesa->Glide.grDepthMask(FXFALSE);
}
break;
case DD_BACK_LEFT_BIT:
/* back buffer only */
fxMesa->Glide.grDepthMask(FXFALSE);
fxMesa->Glide.grRenderBuffer(GR_BUFFER_BACKBUFFER);
if (stencil_size > 0)
fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear,
(FxU32) ctx->Stencil.Clear);
else
fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear);
if (ctx->Depth.Mask && ctx->Depth.Test) {
fxMesa->Glide.grDepthMask(FXTRUE);
}
break;
case DD_FRONT_LEFT_BIT:
/* front buffer only */
fxMesa->Glide.grDepthMask(FXFALSE);
fxMesa->Glide.grRenderBuffer(GR_BUFFER_FRONTBUFFER);
if (stencil_size > 0)
fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear,
(FxU32) ctx->Stencil.Clear);
else
fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear);
if (ctx->Depth.Mask && ctx->Depth.Test) {
fxMesa->Glide.grDepthMask(FXTRUE);
}
break;
case DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT:
/* front and back */
fxMesa->Glide.grDepthMask(FXFALSE);
fxMesa->Glide.grRenderBuffer(GR_BUFFER_BACKBUFFER);
if (stencil_size > 0)
fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear,
(FxU32) ctx->Stencil.Clear);
else
fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear);
fxMesa->Glide.grRenderBuffer(GR_BUFFER_FRONTBUFFER);
if (stencil_size > 0)
fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear,
(FxU32) ctx->Stencil.Clear);
else
fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear);
if (ctx->Depth.Mask && ctx->Depth.Test) {
fxMesa->Glide.grDepthMask(FXTRUE);
}
break;
case DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT | DD_DEPTH_BIT:
/* clear front */
fxMesa->Glide.grDepthMask(FXFALSE);
fxMesa->Glide.grRenderBuffer(GR_BUFFER_FRONTBUFFER);
if (stencil_size > 0)
fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear,
(FxU32) ctx->Stencil.Clear);
else
fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear);
/* clear back and depth */
fxMesa->Glide.grDepthMask(FXTRUE);
fxMesa->Glide.grRenderBuffer(GR_BUFFER_BACKBUFFER);
if (stencil_size > 0)
fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear,
(FxU32) ctx->Stencil.Clear);
else
fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear);
if (!ctx->Depth.Mask || !ctx->Depth.Mask) {
fxMesa->Glide.grDepthMask(FXFALSE);
}
break;
case DD_DEPTH_BIT:
/* just the depth buffer */
fxMesa->Glide.grRenderBuffer(GR_BUFFER_BACKBUFFER);
FX_grColorMaskv_NoLock(ctx, false4);
fxMesa->Glide.grDepthMask(FXTRUE);
if (stencil_size > 0)
fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear,
(FxU32) ctx->Stencil.Clear);
else
fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear);
FX_grColorMaskv_NoLock(ctx, true4);
if (ctx->Color._DrawDestMask & FRONT_LEFT_BIT)
fxMesa->Glide.grRenderBuffer(GR_BUFFER_FRONTBUFFER);
if (!ctx->Depth.Test || !ctx->Depth.Mask)
fxMesa->Glide.grDepthMask(FXFALSE);
break;
default:
/* clear no color buffers or depth buffer but might clear stencil */
if (stencil_size > 0 && (mask & DD_STENCIL_BIT)) {
/* XXX need this RenderBuffer call to work around Glide bug */
fxMesa->Glide.grRenderBuffer(GR_BUFFER_BACKBUFFER);
fxMesa->Glide.grDepthMask(FXFALSE);
FX_grColorMaskv_NoLock(ctx, false4);
fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear,
(FxU32) ctx->Stencil.Clear);
if (ctx->Depth.Mask && ctx->Depth.Test) {
fxMesa->Glide.grDepthMask(FXTRUE);
}
FX_grColorMaskv_NoLock(ctx, true4);
if (ctx->Color._DrawDestMask & FRONT_LEFT_BIT)
fxMesa->Glide.grRenderBuffer(GR_BUFFER_FRONTBUFFER);
}
}
}
END_CLIP_LOOP(fxMesa);

if (fxMesa->haveHwStencil && (mask & DD_STENCIL_BIT)) {
/* We changed the stencil state above. Signal that we need to
* upload it again.
*/
fxMesa->dirty |= TDFX_UPLOAD_STENCIL;
}

if (softwareMask)
_swrast_Clear( ctx, softwareMask, all, x, y, width, height );
}



static void tdfxDDFinish( GLcontext *ctx )
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);

FLUSH_BATCH( fxMesa );

LOCK_HARDWARE( fxMesa );
fxMesa->Glide.grFinish();
UNLOCK_HARDWARE( fxMesa );
}

static void tdfxDDFlush( GLcontext *ctx )
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);

FLUSH_BATCH( fxMesa );

LOCK_HARDWARE( fxMesa );
fxMesa->Glide.grFlush();
UNLOCK_HARDWARE( fxMesa );
}


#if 0
static const char *texSource(int k)
{
switch (k) {
case GR_CMBX_ZERO:
return "GR_CMBX_ZERO";
case GR_CMBX_TEXTURE_ALPHA:
return "GR_CMBX_TEXTURE_ALPHA";
case GR_CMBX_ALOCAL:
return "GR_CMBX_ALOCAL";
case GR_CMBX_AOTHER:
return "GR_CMBX_AOTHER";
case GR_CMBX_B:
return "GR_CMBX_B";
case GR_CMBX_CONSTANT_ALPHA:
return "GR_CMBX_CONSTANT_ALPHA";
case GR_CMBX_CONSTANT_COLOR:
return "GR_CMBX_CONSTANT_COLOR";
case GR_CMBX_DETAIL_FACTOR:
return "GR_CMBX_DETAIL_FACTOR";
case GR_CMBX_ITALPHA:
return "GR_CMBX_ITALPHA";
case GR_CMBX_ITRGB:
return "GR_CMBX_ITRGB";
case GR_CMBX_LOCAL_TEXTURE_ALPHA:
return "GR_CMBX_LOCAL_TEXTURE_ALPHA";
case GR_CMBX_LOCAL_TEXTURE_RGB:
return "GR_CMBX_LOCAL_TEXTURE_RGB";
case GR_CMBX_LOD_FRAC:
return "GR_CMBX_LOD_FRAC";
case GR_CMBX_OTHER_TEXTURE_ALPHA:
return "GR_CMBX_OTHER_TEXTURE_ALPHA";
case GR_CMBX_OTHER_TEXTURE_RGB:
return "GR_CMBX_OTHER_TEXTURE_RGB";
case GR_CMBX_TEXTURE_RGB:
return "GR_CMBX_TEXTURE_RGB";
case GR_CMBX_TMU_CALPHA:
return "GR_CMBX_TMU_CALPHA";
case GR_CMBX_TMU_CCOLOR:
return "GR_CMBX_TMU_CCOLOR";
default:
return "";
}
}
#endif

#if 0
static const char *texMode(int k)
{
switch (k) {
case GR_FUNC_MODE_ZERO:
return "GR_FUNC_MODE_ZERO";
case GR_FUNC_MODE_X:
return "GR_FUNC_MODE_X";
case GR_FUNC_MODE_ONE_MINUS_X:
return "GR_FUNC_MODE_ONE_MINUS_X";
case GR_FUNC_MODE_NEGATIVE_X:
return "GR_FUNC_MODE_NEGATIVE_X";
case GR_FUNC_MODE_X_MINUS_HALF:
return "GR_FUNC_MODE_X_MINUS_HALF";
default:
return "";
}
}
#endif

#if 0
static const char *texInvert(int k)
{
return k ? "FXTRUE" : "FXFALSE";
}
#endif

static void uploadTextureEnv( tdfxContextPtr fxMesa )
{
if (TDFX_IS_NAPALM(fxMesa)) {
int unit;
for (unit = 0; unit < TDFX_NUM_TMU; unit++) {
#if 0
printf("upload env %d\n", unit);
printf(" cSourceA = %s\t", texSource(fxMesa->TexCombineExt[unit].Color.SourceA));
printf(" cModeA = %s\n", texMode(fxMesa->TexCombineExt[unit].Color.ModeA));
printf(" cSourceB = %s\t", texSource(fxMesa->TexCombineExt[unit].Color.SourceB));
printf(" cModeB = %s\n", texMode(fxMesa->TexCombineExt[unit].Color.ModeB));
printf(" cSourceC = %s\t", texSource(fxMesa->TexCombineExt[unit].Color.SourceC));
printf(" cInvertC = %s\n", texInvert(fxMesa->TexCombineExt[unit].Color.InvertC));
printf(" cSourceD = %s\t", texSource(fxMesa->TexCombineExt[unit].Color.SourceD));
printf(" cInvertD = %s\n", texInvert(fxMesa->TexCombineExt[unit].Color.InvertD));
printf(" cShift = %d\t", fxMesa->TexCombineExt[unit].Color.Shift);
printf(" cInvert = %d\n", fxMesa->TexCombineExt[unit].Color.Invert);
printf(" aSourceA = %s\t", texSource(fxMesa->TexCombineExt[unit].Alpha.SourceA));
printf(" aModeA = %s\n", texMode(fxMesa->TexCombineExt[unit].Alpha.ModeA));
printf(" aSourceB = %s\t", texSource(fxMesa->TexCombineExt[unit].Alpha.SourceB));
printf(" aModeB = %s\n", texMode(fxMesa->TexCombineExt[unit].Alpha.ModeB));
printf(" aSourceC = %s\t", texSource(fxMesa->TexCombineExt[unit].Alpha.SourceC));
printf(" aInvertC = %s\n", texInvert(fxMesa->TexCombineExt[unit].Alpha.InvertC));
printf(" aSourceD = %s\t", texSource(fxMesa->TexCombineExt[unit].Alpha.SourceD));
printf(" aInvertD = %s\n", texInvert(fxMesa->TexCombineExt[unit].Alpha.InvertD));
printf(" aShift = %d\t", fxMesa->TexCombineExt[unit].Alpha.Shift);
printf(" aInvert = %d\n", fxMesa->TexCombineExt[unit].Alpha.Invert);
printf(" Color = 0x%08x\n", fxMesa->TexCombineExt[unit].EnvColor);
#endif
fxMesa->Glide.grTexColorCombineExt(TDFX_TMU0 + unit,
fxMesa->TexCombineExt[unit].Color.SourceA,
fxMesa->TexCombineExt[unit].Color.ModeA,
fxMesa->TexCombineExt[unit].Color.SourceB,
fxMesa->TexCombineExt[unit].Color.ModeB,
fxMesa->TexCombineExt[unit].Color.SourceC,
fxMesa->TexCombineExt[unit].Color.InvertC,
fxMesa->TexCombineExt[unit].Color.SourceD,
fxMesa->TexCombineExt[unit].Color.InvertD,
fxMesa->TexCombineExt[unit].Color.Shift,
fxMesa->TexCombineExt[unit].Color.Invert);
fxMesa->Glide.grTexAlphaCombineExt(TDFX_TMU0 + unit,
fxMesa->TexCombineExt[unit].Alpha.SourceA,
fxMesa->TexCombineExt[unit].Alpha.ModeA,
fxMesa->TexCombineExt[unit].Alpha.SourceB,
fxMesa->TexCombineExt[unit].Alpha.ModeB,
fxMesa->TexCombineExt[unit].Alpha.SourceC,
fxMesa->TexCombineExt[unit].Alpha.InvertC,
fxMesa->TexCombineExt[unit].Alpha.SourceD,
fxMesa->TexCombineExt[unit].Alpha.InvertD,
fxMesa->TexCombineExt[unit].Alpha.Shift,
fxMesa->TexCombineExt[unit].Alpha.Invert);
fxMesa->Glide.grConstantColorValueExt(TDFX_TMU0 + unit,
fxMesa->TexCombineExt[unit].EnvColor);
}
}
else {
/* Voodoo3 */
int unit;
for (unit = 0; unit < TDFX_NUM_TMU; unit++) {
struct tdfx_texcombine *comb = &fxMesa->TexCombine[unit];
fxMesa->Glide.grTexCombine(TDFX_TMU0 + unit,
comb->FunctionRGB,
comb->FactorRGB,
comb->FunctionAlpha,
comb->FactorAlpha,
comb->InvertRGB,
comb->InvertAlpha);
}
}
}


static void uploadTextureParams( tdfxContextPtr fxMesa )
{
int unit;
for (unit = 0; unit < TDFX_NUM_TMU; unit++) {
const struct tdfx_texparams *p = &fxMesa->TexParams[unit];
/*
printf("upload params %d\n", unit);
printf(" clamp %x %x\n", env->sClamp, env->tClamp);
printf(" filter %x %x\n", env->minFilt, env->magFilt);
printf(" mipmap %x %x\n", env->mmMode, env->LODblend);
printf(" lod bias %f\n", env->LodBias);
*/
fxMesa->Glide.grTexClampMode(GR_TMU0 + unit, p->sClamp, p->tClamp);
fxMesa->Glide.grTexFilterMode(GR_TMU0 + unit, p->minFilt, p->magFilt);
fxMesa->Glide.grTexMipMapMode(GR_TMU0 + unit, p->mmMode, p->LODblend);
fxMesa->Glide.grTexLodBiasValue(GR_TMU0 + unit, p->LodBias);
}
}


static void uploadTextureSource( tdfxContextPtr fxMesa )
{
int unit;
for (unit = 0; unit < TDFX_NUM_TMU; unit++) {
const struct tdfx_texsource *src = &fxMesa->TexSource[unit];
/*
printf("upload source %d @ %d %p\n", unit, src->StartAddress, src->Info);
*/
if (src->Info) {
/*
printf(" smallLodLog2=%d largeLodLog2=%d ar=%d format=%d data=%p\n",
src->Info->smallLodLog2, src->Info->largeLodLog2,
src->Info->aspectRatioLog2, src->Info->format,
src->Info->data);
*/
fxMesa->Glide.grTexSource(GR_TMU0 + unit,
src->StartAddress,
src->EvenOdd,
src->Info);
}
}
}


static void uploadTextureImages( tdfxContextPtr fxMesa )
{
GLcontext *ctx = fxMesa->glCtx;
int unit;
for (unit = 0; unit < TDFX_NUM_TMU; unit++) {
if (ctx->Texture.Unit[unit]._ReallyEnabled == TEXTURE_2D_BIT) {
struct gl_texture_object *tObj = ctx->Texture.Unit[unit].Current2D;
tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj);
if (ti && ti->reloadImages && ti->whichTMU != TDFX_TMU_NONE) {
/*
printf("download texture image on unit %d\n", unit);
*/
tdfxTMDownloadTexture(fxMesa, tObj);
ti->reloadImages = GL_FALSE;
}
}
}
}



/*
* If scissoring is enabled, compute intersection of scissor region
* with all X clip rects, resulting in new cliprect list.
* If number of cliprects is zero or one, call grClipWindow to setup
* the clip region. Otherwise we'll call grClipWindow inside the
* BEGIN_CLIP_LOOP macro.
*/
void tdfxUploadClipping( tdfxContextPtr fxMesa )
{
__DRIdrawablePrivate *dPriv = fxMesa->driDrawable;

assert(dPriv);

if (fxMesa->numClipRects == 0) {
/* all drawing clipped away */
fxMesa->Glide.grClipWindow(0, 0, 0, 0);
}
else if (fxMesa->numClipRects == 1) {
fxMesa->Glide.grClipWindow(fxMesa->pClipRects[0].x1,
fxMesa->screen_height - fxMesa->pClipRects[0].y2,
fxMesa->pClipRects[0].x2,
fxMesa->screen_height - fxMesa->pClipRects[0].y1);
}
/* else, we'll do a cliprect loop around all drawing */

fxMesa->Glide.grDRIPosition( dPriv->x, dPriv->y, dPriv->w, dPriv->h,
fxMesa->numClipRects, fxMesa->pClipRects );
}


void tdfxEmitHwStateLocked( tdfxContextPtr fxMesa )
{
if ( !fxMesa->dirty )
return;

if ( fxMesa->dirty & TDFX_UPLOAD_COLOR_COMBINE ) {
if (TDFX_IS_NAPALM(fxMesa)) {
fxMesa->Glide.grColorCombineExt(fxMesa->ColorCombineExt.SourceA,
fxMesa->ColorCombineExt.ModeA,
fxMesa->ColorCombineExt.SourceB,
fxMesa->ColorCombineExt.ModeB,
fxMesa->ColorCombineExt.SourceC,
fxMesa->ColorCombineExt.InvertC,
fxMesa->ColorCombineExt.SourceD,
fxMesa->ColorCombineExt.InvertD,
fxMesa->ColorCombineExt.Shift,
fxMesa->ColorCombineExt.Invert);
}
else {
/* Voodoo 3 */
fxMesa->Glide.grColorCombine( fxMesa->ColorCombine.Function,
fxMesa->ColorCombine.Factor,
fxMesa->ColorCombine.Local,
fxMesa->ColorCombine.Other,
fxMesa->ColorCombine.Invert );
}
fxMesa->dirty &= ~TDFX_UPLOAD_COLOR_COMBINE;
}
if ( fxMesa->dirty & TDFX_UPLOAD_ALPHA_COMBINE ) {
if (TDFX_IS_NAPALM(fxMesa)) {
fxMesa->Glide.grAlphaCombineExt(fxMesa->AlphaCombineExt.SourceA,
fxMesa->AlphaCombineExt.ModeA,
fxMesa->AlphaCombineExt.SourceB,
fxMesa->AlphaCombineExt.ModeB,
fxMesa->AlphaCombineExt.SourceC,
fxMesa->AlphaCombineExt.InvertC,
fxMesa->AlphaCombineExt.SourceD,
fxMesa->AlphaCombineExt.InvertD,
fxMesa->AlphaCombineExt.Shift,
fxMesa->AlphaCombineExt.Invert);
}
else {
/* Voodoo 3 */
fxMesa->Glide.grAlphaCombine( fxMesa->AlphaCombine.Function,
fxMesa->AlphaCombine.Factor,
fxMesa->AlphaCombine.Local,
fxMesa->AlphaCombine.Other,
fxMesa->AlphaCombine.Invert );
}
fxMesa->dirty &= ~TDFX_UPLOAD_ALPHA_COMBINE;
}

if ( fxMesa->dirty & TDFX_UPLOAD_RENDER_BUFFER ) {
fxMesa->Glide.grRenderBuffer( fxMesa->DrawBuffer );
fxMesa->dirty &= ~TDFX_UPLOAD_RENDER_BUFFER;
}

if ( fxMesa->dirty & TDFX_UPLOAD_STIPPLE) {
fxMesa->Glide.grStipplePattern( fxMesa->Stipple.Pattern );
fxMesa->Glide.grStippleMode( fxMesa->Stipple.Mode );
fxMesa->dirty &= ~TDFX_UPLOAD_STIPPLE;
}

if ( fxMesa->dirty & TDFX_UPLOAD_ALPHA_TEST ) {
fxMesa->Glide.grAlphaTestFunction( fxMesa->Color.AlphaFunc );
fxMesa->dirty &= ~TDFX_UPLOAD_ALPHA_TEST;
}
if ( fxMesa->dirty & TDFX_UPLOAD_ALPHA_REF ) {
fxMesa->Glide.grAlphaTestReferenceValue( fxMesa->Color.AlphaRef );
fxMesa->dirty &= ~TDFX_UPLOAD_ALPHA_REF;
}
if ( fxMesa->dirty & TDFX_UPLOAD_BLEND_FUNC ) {
if (fxMesa->Glide.grAlphaBlendFunctionExt) {
fxMesa->Glide.grAlphaBlendFunctionExt( fxMesa->Color.BlendSrcRGB,
fxMesa->Color.BlendDstRGB,
GR_BLEND_OP_ADD,
fxMesa->Color.BlendSrcA,
fxMesa->Color.BlendDstA,
GR_BLEND_OP_ADD );
}
else {
fxMesa->Glide.grAlphaBlendFunction( fxMesa->Color.BlendSrcRGB,
fxMesa->Color.BlendDstRGB,
fxMesa->Color.BlendSrcA,
fxMesa->Color.BlendDstA );
}
fxMesa->dirty &= ~TDFX_UPLOAD_BLEND_FUNC;
}

if ( fxMesa->dirty & TDFX_UPLOAD_DEPTH_MODE ) {
fxMesa->Glide.grDepthBufferMode( fxMesa->Depth.Mode );
fxMesa->dirty &= ~TDFX_UPLOAD_DEPTH_MODE;
}
if ( fxMesa->dirty & TDFX_UPLOAD_DEPTH_BIAS ) {
fxMesa->Glide.grDepthBiasLevel( fxMesa->Depth.Bias );
fxMesa->dirty &= ~TDFX_UPLOAD_DEPTH_BIAS;
}
if ( fxMesa->dirty & TDFX_UPLOAD_DEPTH_FUNC ) {
fxMesa->Glide.grDepthBufferFunction( fxMesa->Depth.Func );
fxMesa->dirty &= ~TDFX_UPLOAD_DEPTH_FUNC;
}
if ( fxMesa->dirty & TDFX_UPLOAD_DEPTH_MASK ) {
fxMesa->Glide.grDepthMask( fxMesa->Depth.Mask );
fxMesa->dirty &= ~TDFX_UPLOAD_DEPTH_MASK;
}

if ( fxMesa->dirty & TDFX_UPLOAD_DITHER) {
fxMesa->Glide.grDitherMode( fxMesa->Color.Dither );
}

if ( fxMesa->dirty & TDFX_UPLOAD_FOG_MODE ) {
fxMesa->Glide.grFogMode( fxMesa->Fog.Mode );
fxMesa->dirty &= ~TDFX_UPLOAD_FOG_MODE;
}
if ( fxMesa->dirty & TDFX_UPLOAD_FOG_COLOR ) {
fxMesa->Glide.grFogColorValue( fxMesa->Fog.Color );
fxMesa->dirty &= ~TDFX_UPLOAD_FOG_COLOR;
}
if ( fxMesa->dirty & TDFX_UPLOAD_FOG_TABLE ) {
fxMesa->Glide.grFogTable( fxMesa->Fog.Table );
fxMesa->dirty &= ~TDFX_UPLOAD_FOG_TABLE;
}

if ( fxMesa->dirty & TDFX_UPLOAD_CULL ) {
fxMesa->Glide.grCullMode( fxMesa->CullMode );
fxMesa->dirty &= ~TDFX_UPLOAD_CULL;
}

if ( fxMesa->dirty & TDFX_UPLOAD_CLIP ) {
tdfxUploadClipping( fxMesa );
fxMesa->dirty &= ~TDFX_UPLOAD_CLIP;
}

if ( fxMesa->dirty & TDFX_UPLOAD_COLOR_MASK ) {
if ( fxMesa->Glide.grColorMaskExt
&& fxMesa->glCtx->Visual.redBits == 8) {
fxMesa->Glide.grColorMaskExt( fxMesa->Color.ColorMask[RCOMP],
fxMesa->Color.ColorMask[GCOMP],
fxMesa->Color.ColorMask[BCOMP],
fxMesa->Color.ColorMask[ACOMP] );
} else {
fxMesa->Glide.grColorMask( fxMesa->Color.ColorMask[RCOMP] ||
fxMesa->Color.ColorMask[GCOMP] ||
fxMesa->Color.ColorMask[BCOMP],
fxMesa->Color.ColorMask[ACOMP] );
}
fxMesa->dirty &= ~TDFX_UPLOAD_COLOR_MASK;
}

/* if ( fxMesa->dirty & TDFX_UPLOAD_CONSTANT_COLOR ) { */
/* grConstantColorValue( fxMesa->Color.MonoColor ); */
/* fxMesa->dirty &= ~TDFX_UPLOAD_CONSTANT_COLOR; */
/* } */

if ( fxMesa->dirty & TDFX_UPLOAD_LINE ) {
if (fxMesa->glCtx->Line.SmoothFlag && fxMesa->glCtx->Line.Width == 1.0)
fxMesa->Glide.grEnable(GR_AA_ORDERED);
else
fxMesa->Glide.grDisable(GR_AA_ORDERED);
fxMesa->dirty &= ~TDFX_UPLOAD_LINE;
}

if ( fxMesa->dirty & TDFX_UPLOAD_STENCIL ) {
if (fxMesa->glCtx->Stencil.Enabled) {
fxMesa->Glide.grEnable(GR_STENCIL_MODE_EXT);
fxMesa->Glide.grStencilOp(fxMesa->Stencil.FailFunc,
fxMesa->Stencil.ZFailFunc,
fxMesa->Stencil.ZPassFunc);
fxMesa->Glide.grStencilFunc(fxMesa->Stencil.Function,
fxMesa->Stencil.RefValue,
fxMesa->Stencil.ValueMask);
fxMesa->Glide.grStencilMask(fxMesa->Stencil.WriteMask);
}
else {
fxMesa->Glide.grDisable(GR_STENCIL_MODE_EXT);
}
fxMesa->dirty &= ~TDFX_UPLOAD_STENCIL;
}

if ( fxMesa->dirty & TDFX_UPLOAD_VERTEX_LAYOUT ) {
fxMesa->Glide.grGlideSetVertexLayout( fxMesa->layout[fxMesa->vertexFormat] );
fxMesa->dirty &= ~TDFX_UPLOAD_VERTEX_LAYOUT;
}

if ( fxMesa->dirty & TDFX_UPLOAD_TEXTURE_ENV ) {
uploadTextureEnv(fxMesa);
fxMesa->dirty &= ~TDFX_UPLOAD_TEXTURE_ENV;
}

if ( fxMesa->dirty & TDFX_UPLOAD_TEXTURE_PARAMS ) {
uploadTextureParams(fxMesa);
fxMesa->dirty &= ~TDFX_UPLOAD_TEXTURE_PARAMS;
}

if ( fxMesa->dirty & TDFX_UPLOAD_TEXTURE_PALETTE ) {
if (fxMesa->TexPalette.Data) {
fxMesa->Glide.grTexDownloadTable(fxMesa->TexPalette.Type, fxMesa->TexPalette.Data);
}
fxMesa->dirty &= ~TDFX_UPLOAD_TEXTURE_PALETTE;
}

if ( fxMesa->dirty & TDFX_UPLOAD_TEXTURE_SOURCE ) {
uploadTextureSource(fxMesa);
fxMesa->dirty &= ~TDFX_UPLOAD_TEXTURE_SOURCE;
}

if ( fxMesa->dirty & TDFX_UPLOAD_TEXTURE_IMAGES ) {
uploadTextureImages(fxMesa);
fxMesa->dirty &= ~TDFX_UPLOAD_TEXTURE_IMAGES;
}

fxMesa->dirty = 0;
}



void tdfxDDInitRenderFuncs( GLcontext *ctx )
{
ctx->Driver.Clear = tdfxDDClear;
ctx->Driver.Finish = tdfxDDFinish;
ctx->Driver.Flush = tdfxDDFlush;
}

+ 54
- 0
src/mesa/drivers/dri/tdfx/tdfx_render.h View File

@@ -0,0 +1,54 @@
/* -*- mode: c; c-basic-offset: 3 -*-
*
* Copyright 2000 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
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION 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/tdfx/tdfx_render.h,v 1.1 2001/03/21 16:14:28 dawes Exp $ */

/*
* Original rewrite:
* Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
*
* Authors:
* Gareth Hughes <gareth@valinux.com>
*
*/

#ifndef __TDFX_RENDER_H__
#define __TDFX_RENDER_H__

#ifdef GLX_DIRECT_RENDERING

#include "tdfx_context.h"

extern void tdfxDDInitRenderFuncs( GLcontext *ctx );

extern void tdfxEmitHwStateLocked( tdfxContextPtr fxMesa );

extern void tdfxUploadClipping( tdfxContextPtr fxMesa );

#define FLUSH_BATCH( fxMesa )


#endif
#endif

+ 331
- 0
src/mesa/drivers/dri/tdfx/tdfx_screen.c View File

@@ -0,0 +1,331 @@
/* -*- mode: c; c-basic-offset: 3 -*-
*
* Copyright 2000 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
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION 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/tdfx/tdfx_screen.c,v 1.3 2002/02/22 21:45:03 dawes Exp $ */

/*
* Original rewrite:
* Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
*
* Authors:
* Gareth Hughes <gareth@valinux.com>
*
*/

#include "tdfx_dri.h"
#include "tdfx_context.h"
#include "tdfx_lock.h"
#include "tdfx_vb.h"
#include "tdfx_tris.h"


#ifdef DEBUG_LOCKING
char *prevLockFile = 0;
int prevLockLine = 0;
#endif

#ifndef TDFX_DEBUG
int TDFX_DEBUG = (0
/* | DEBUG_ALWAYS_SYNC */
/* | DEBUG_VERBOSE_API */
/* | DEBUG_VERBOSE_MSG */
/* | DEBUG_VERBOSE_LRU */
/* | DEBUG_VERBOSE_DRI */
/* | DEBUG_VERBOSE_IOCTL */
/* | DEBUG_VERBOSE_2D */
);
#endif



static GLboolean
tdfxCreateScreen( __DRIscreenPrivate *sPriv )
{
tdfxScreenPrivate *fxScreen;
TDFXDRIPtr fxDRIPriv = (TDFXDRIPtr) sPriv->pDevPriv;

/* Allocate the private area */
fxScreen = (tdfxScreenPrivate *) Xmalloc( sizeof(tdfxScreenPrivate) );
if ( !fxScreen )
return GL_FALSE;

fxScreen->driScrnPriv = sPriv;
sPriv->private = (void *) fxScreen;

fxScreen->regs.handle = fxDRIPriv->regs;
fxScreen->regs.size = fxDRIPriv->regsSize;
fxScreen->deviceID = fxDRIPriv->deviceID;
fxScreen->width = fxDRIPriv->width;
fxScreen->height = fxDRIPriv->height;
fxScreen->mem = fxDRIPriv->mem;
fxScreen->cpp = fxDRIPriv->cpp;
fxScreen->stride = fxDRIPriv->stride;
fxScreen->fifoOffset = fxDRIPriv->fifoOffset;
fxScreen->fifoSize = fxDRIPriv->fifoSize;
fxScreen->fbOffset = fxDRIPriv->fbOffset;
fxScreen->backOffset = fxDRIPriv->backOffset;
fxScreen->depthOffset = fxDRIPriv->depthOffset;
fxScreen->textureOffset = fxDRIPriv->textureOffset;
fxScreen->textureSize = fxDRIPriv->textureSize;
fxScreen->sarea_priv_offset = fxDRIPriv->sarea_priv_offset;

if ( drmMap( sPriv->fd, fxScreen->regs.handle,
fxScreen->regs.size, &fxScreen->regs.map ) ) {
return GL_FALSE;
}

return GL_TRUE;
}


static void
tdfxDestroyScreen( __DRIscreenPrivate *sPriv )
{
tdfxScreenPrivate *fxScreen = (tdfxScreenPrivate *) sPriv->private;

if ( fxScreen ) {
drmUnmap( fxScreen->regs.map, fxScreen->regs.size );

Xfree( fxScreen );
sPriv->private = NULL;
}
}


static GLboolean
tdfxInitDriver( __DRIscreenPrivate *sPriv )
{
if ( TDFX_DEBUG & DEBUG_VERBOSE_DRI ) {
fprintf( stderr, "%s( %p )\n", __FUNCTION__, sPriv );
}

/* Check the DRI externsion version */
if ( sPriv->driMajor != 4 || sPriv->driMinor < 0 ) {
__driUtilMessage( "tdfx 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(
"3dfx 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 < 0 ) {
__driUtilMessage(
"3dfx DRI driver expected DRM driver version 1.0.x "
"but got version %d.%d.%d",
sPriv->drmMajor, sPriv->drmMinor, sPriv->drmPatch );
return GL_FALSE;
}

if ( !tdfxCreateScreen( sPriv ) ) {
tdfxDestroyScreen( sPriv );
return GL_FALSE;
}

return GL_TRUE;
}


static GLboolean
tdfxCreateBuffer( __DRIscreenPrivate *driScrnPriv,
__DRIdrawablePrivate *driDrawPriv,
const __GLcontextModes *mesaVis,
GLboolean isPixmap )
{
if (isPixmap) {
return GL_FALSE; /* not implemented */
}
else {
driDrawPriv->driverPrivate = (void *)
_mesa_create_framebuffer( mesaVis,
GL_FALSE, /* software depth buffer? */
mesaVis->stencilBits > 0,
mesaVis->accumRedBits > 0,
GL_FALSE /* software alpha channel? */ );
return (driDrawPriv->driverPrivate != NULL);
}
}


static void
tdfxDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
{
_mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
}


static void
tdfxSwapBuffers( __DRIdrawablePrivate *driDrawPriv )

{
GET_CURRENT_CONTEXT(ctx);
tdfxContextPtr fxMesa = 0;
GLframebuffer *mesaBuffer;

if ( TDFX_DEBUG & DEBUG_VERBOSE_DRI ) {
fprintf( stderr, "%s( %p )\n", __FUNCTION__, driDrawPriv );
}

mesaBuffer = (GLframebuffer *) driDrawPriv->driverPrivate;
if ( !mesaBuffer->Visual.doubleBufferMode )
return; /* can't swap a single-buffered window */

/* If the current context's drawable matches the given drawable
* we have to do a glFinish (per the GLX spec).
*/
if ( ctx ) {
__DRIdrawablePrivate *curDrawPriv;
fxMesa = TDFX_CONTEXT(ctx);
curDrawPriv = fxMesa->driContext->driDrawablePriv;

if ( curDrawPriv == driDrawPriv ) {
/* swapping window bound to current context, flush first */
_mesa_notifySwapBuffers( ctx );
LOCK_HARDWARE( fxMesa );
}
else {
/* find the fxMesa context previously bound to the window */
fxMesa = (tdfxContextPtr) driDrawPriv->driContextPriv->driverPrivate;
if (!fxMesa)
return;
LOCK_HARDWARE( fxMesa );
fxMesa->Glide.grSstSelect( fxMesa->Glide.Board );
printf("SwapBuf SetState 1\n");
fxMesa->Glide.grGlideSetState(fxMesa->Glide.State );
}
}

#ifdef STATS
{
int stalls;
static int prevStalls = 0;

stalls = fxMesa->Glide.grFifoGetStalls();

fprintf( stderr, "%s:\n", __FUNCTION__ );
if ( stalls != prevStalls ) {
fprintf( stderr, " %d stalls occurred\n",
stalls - prevStalls );
prevStalls = stalls;
}
if ( fxMesa && fxMesa->texSwaps ) {
fprintf( stderr, " %d texture swaps occurred\n",
fxMesa->texSwaps );
fxMesa->texSwaps = 0;
}
}
#endif

if (fxMesa->scissoredClipRects) {
/* restore clip rects without scissor box */
fxMesa->Glide.grDRIPosition( driDrawPriv->x, driDrawPriv->y,
driDrawPriv->w, driDrawPriv->h,
driDrawPriv->numClipRects,
driDrawPriv->pClipRects );
}

fxMesa->Glide.grDRIBufferSwap( fxMesa->Glide.SwapInterval );

if (fxMesa->scissoredClipRects) {
/* restore clip rects WITH scissor box */
fxMesa->Glide.grDRIPosition( driDrawPriv->x, driDrawPriv->y,
driDrawPriv->w, driDrawPriv->h,
fxMesa->numClipRects, fxMesa->pClipRects );
}


#if 0
{
FxI32 result;
do {
FxI32 result;
fxMesa->Glide.grGet(GR_PENDING_BUFFERSWAPS, 4, &result);
} while ( result > fxMesa->maxPendingSwapBuffers );
}
#endif

fxMesa->stats.swapBuffer++;

if (ctx) {
if (ctx->DriverCtx != fxMesa) {
fxMesa = TDFX_CONTEXT(ctx);
fxMesa->Glide.grSstSelect( fxMesa->Glide.Board );
printf("SwapBuf SetState 2\n");
fxMesa->Glide.grGlideSetState(fxMesa->Glide.State );
}
UNLOCK_HARDWARE( fxMesa );
}
}


static GLboolean
tdfxOpenCloseFullScreen(__DRIcontextPrivate *driContextPriv)
{
return GL_TRUE;
}


static const struct __DriverAPIRec tdfxAPI = {
.InitDriver = tdfxInitDriver,
.DestroyScreen = tdfxDestroyScreen,
.CreateContext = tdfxCreateContext,
.DestroyContext = tdfxDestroyContext,
.CreateBuffer = tdfxCreateBuffer,
.DestroyBuffer = tdfxDestroyBuffer,
.SwapBuffers = tdfxSwapBuffers,
.MakeCurrent = tdfxMakeCurrent,
.UnbindContext = tdfxUnbindContext,
.OpenFullScreen = tdfxOpenCloseFullScreen,
.CloseFullScreen = tdfxOpenCloseFullScreen,
.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.
*/
void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
int numConfigs, __GLXvisualConfig *config)
{
__DRIscreenPrivate *psp;
psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &tdfxAPI);
return (void *) psp;
}

+ 73
- 0
src/mesa/drivers/dri/tdfx/tdfx_screen.h View File

@@ -0,0 +1,73 @@
/* -*- mode: c; c-basic-offset: 3 -*-
*
* Copyright 2000 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
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION 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/tdfx/tdfx_screen.h,v 1.2 2002/02/22 21:45:03 dawes Exp $ */

/*
* Original rewrite:
* Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
*
* Authors:
* Gareth Hughes <gareth@valinux.com>
*
*/

#ifndef __TDFX_SCREEN_H__
#define __TDFX_SCREEN_H__

#ifdef GLX_DIRECT_RENDERING

typedef struct {
drmHandle handle;
drmSize size;
drmAddress map;
} tdfxRegion, *tdfxRegionPtr;

typedef struct {
tdfxRegion regs;

int deviceID;
int width;
int height;
int mem;
int cpp;
int stride;

int fifoOffset;
int fifoSize;

int fbOffset;
int backOffset;
int depthOffset;
int textureOffset;
int textureSize;

__DRIscreenPrivate *driScrnPriv;
unsigned int sarea_priv_offset;
} tdfxScreenPrivate;


#endif
#endif

+ 1399
- 0
src/mesa/drivers/dri/tdfx/tdfx_span.c
File diff suppressed because it is too large
View File


+ 48
- 0
src/mesa/drivers/dri/tdfx/tdfx_span.h View File

@@ -0,0 +1,48 @@
/* -*- mode: c; c-basic-offset: 3 -*-
*
* Copyright 2000 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
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION 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/tdfx/tdfx_span.h,v 1.1 2001/03/21 16:14:28 dawes Exp $ */

/*
* Original rewrite:
* Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Brian Paul <brianp@valinux.com>
*
*/

#ifndef __TDFX_SPAN_H__
#define __TDFX_SPAN_H__

#ifdef GLX_DIRECT_RENDERING

#include "context.h"

extern void tdfxDDInitSpanFuncs( GLcontext *ctx );

#endif
#endif

+ 1466
- 0
src/mesa/drivers/dri/tdfx/tdfx_state.c
File diff suppressed because it is too large
View File


+ 64
- 0
src/mesa/drivers/dri/tdfx/tdfx_state.h View File

@@ -0,0 +1,64 @@
/* -*- mode: c; c-basic-offset: 3 -*-
*
* Copyright 2000 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
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION 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/tdfx/tdfx_state.h,v 1.2 2002/02/22 21:45:04 dawes Exp $ */

/*
* Original rewrite:
* Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Brian Paul <brianp@valinux.com>
*
*/

#ifndef __TDFX_STATE_H__
#define __TDFX_STATE_H__

#ifdef GLX_DIRECT_RENDERING

#include "context.h"
#include "tdfx_context.h"

extern void tdfxDDInitStateFuncs( GLcontext *ctx );

extern void tdfxDDUpdateHwState( GLcontext *ctx );

extern void tdfxInitState( tdfxContextPtr fxMesa );

extern void tdfxUpdateClipping( GLcontext *ctx );


extern void tdfxFallback( GLcontext *ctx, GLuint bit, GLboolean mode );
#define FALLBACK( rmesa, bit, mode ) tdfxFallback( rmesa->glCtx, bit, mode )

extern void tdfxUpdateCull( GLcontext *ctx );
extern void tdfxUpdateStipple( GLcontext *ctx );
extern void tdfxUpdateViewport( GLcontext *ctx );


#endif
#endif

+ 1473
- 0
src/mesa/drivers/dri/tdfx/tdfx_tex.c
File diff suppressed because it is too large
View File


+ 165
- 0
src/mesa/drivers/dri/tdfx/tdfx_tex.h View File

@@ -0,0 +1,165 @@
/* -*- mode: c; c-basic-offset: 3 -*-
*
* Copyright 2000 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
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION 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/tdfx/tdfx_tex.h,v 1.2 2002/02/22 21:45:04 dawes Exp $ */

/*
* Original rewrite:
* Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Brian Paul <brianp@valinux.com>
*
*/

#ifndef _TDFX_TEX_H_
#define _TDFX_TEX_H_


#include "texutil.h"


#define tdfxDDIsCompressedFormatMacro(internalFormat) \
(((internalFormat) == GL_COMPRESSED_RGB_FXT1_3DFX) || \
((internalFormat) == GL_COMPRESSED_RGBA_FXT1_3DFX))
#define tdfxDDIsCompressedGlideFormatMacro(internalFormat) \
((internalFormat) == GR_TEXFMT_ARGB_CMP_FXT1)



extern void
tdfxTexValidate(GLcontext * ctx, struct gl_texture_object *tObj);

extern void
tdfxDDBindTexture(GLcontext * ctx, GLenum target,
struct gl_texture_object *tObj);

extern void
tdfxDDDeleteTexture(GLcontext * ctx, struct gl_texture_object *tObj);

extern GLboolean
tdfxDDIsTextureResident(GLcontext *ctx, struct gl_texture_object *tObj);

extern void
tdfxDDTexturePalette(GLcontext * ctx, struct gl_texture_object *tObj);

#if 000 /* DEAD? */
extern void
fxDDTexUseGlobalPalette(GLcontext * ctx, GLboolean state);
#endif

extern void
tdfxDDTexEnv(GLcontext * ctx, GLenum target, GLenum pname,
const GLfloat * param);

extern void
tdfxDDTexParameter(GLcontext * ctx, GLenum target,
struct gl_texture_object *tObj,
GLenum pname, const GLfloat * params);

extern const struct gl_texture_format *
tdfxDDChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
GLenum srcFormat, GLenum srcType );

extern void
tdfxDDTexImage2D(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);

extern void
tdfxDDTexSubImage2D(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 );

#if 000
extern GLboolean
tdfxDDCompressedTexImage2D( GLcontext *ctx, GLenum target,
GLint level, GLsizei imageSize,
const GLvoid *data,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage,
GLboolean *retainInternalCopy);

extern GLboolean
tdfxDDCompressedTexSubImage2D( GLcontext *ctx, GLenum target,
GLint level, GLint xoffset,
GLint yoffset, GLsizei width,
GLint height, GLenum format,
GLsizei imageSize, const GLvoid *data,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage );
#endif

extern GLboolean
tdfxDDTestProxyTexImage(GLcontext *ctx, GLenum target,
GLint level, GLint internalFormat,
GLenum format, GLenum type,
GLint width, GLint height,
GLint depth, GLint border);

extern GLvoid *
tdfxDDGetTexImage(GLcontext * ctx, GLenum target, GLint level,
const struct gl_texture_object *texObj,
GLenum * formatOut, GLenum * typeOut,
GLboolean * freeImageOut);

extern void
tdfxDDGetCompressedTexImage( GLcontext *ctx, GLenum target,
GLint lod, void *image,
const struct gl_texture_object *texObj,
struct gl_texture_image *texImage );

extern GLint
tdfxDDSpecificCompressedTexFormat(GLcontext *ctx,
GLint internalFormat,
GLint numDimensions);

extern GLint
tdfxDDBaseCompressedTexFormat(GLcontext *ctx,
GLint internalFormat);

extern GLboolean
tdfxDDIsCompressedFormat(GLcontext *ctx, GLint internalFormat);

extern GLsizei
tdfxDDCompressedImageSize(GLcontext *ctx,
GLenum intFormat,
GLuint numDimensions,
GLuint width,
GLuint height,
GLuint depth);


#endif

+ 970
- 0
src/mesa/drivers/dri/tdfx/tdfx_texman.c View File

@@ -0,0 +1,970 @@
/* -*- mode: c; c-basic-offset: 3 -*-
*
* Copyright 2000 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
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION 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/tdfx/tdfx_texman.c,v 1.5 2002/02/22 21:45:04 dawes Exp $ */

/*
* Original rewrite:
* Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Brian Paul <brianp@valinux.com>
*
*/

#include "tdfx_context.h"
#include "tdfx_tex.h"
#include "tdfx_texman.h"


#define BAD_ADDRESS ((FxU32) -1)


#if 0 /* DEBUG use */
/*
* Verify the consistancy of the texture memory manager.
* This involves:
* Traversing all texture objects and computing total memory used.
* Traverse the free block list and computing total memory free.
* Compare the total free and total used amounts to the total memory size.
* Make various assertions about the results.
*/
static void
VerifyFreeList(tdfxContextPtr fxMesa, FxU32 tmu)
{
struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
tdfxMemRange *block;
int prevStart = -1, prevEnd = -1;
int totalFree = 0;
int numObj = 0, numRes = 0;
int totalUsed = 0;

for (block = shared->tmFree[tmu]; block; block = block->next) {
assert( block->endAddr > 0 );
assert( block->startAddr <= shared->totalTexMem[tmu] );
assert( block->endAddr <= shared->totalTexMem[tmu] );
assert( (int) block->startAddr > prevStart );
assert( (int) block->startAddr >= prevEnd );
prevStart = (int) block->startAddr;
prevEnd = (int) block->endAddr;
totalFree += (block->endAddr - block->startAddr);
}
assert(totalFree == shared->freeTexMem[tmu]);

{
struct gl_texture_object *obj;
for (obj = mesaShared->TexObjectList; obj; obj = obj->Next) {
tdfxTexInfo *ti = TDFX_TEXTURE_DATA(obj);
numObj++;
if (ti) {
if (ti->isInTM) {
numRes++;
assert(ti->tm[0]);
if (ti->tm[tmu])
totalUsed += (ti->tm[tmu]->endAddr - ti->tm[tmu]->startAddr);
}
else {
assert(!ti->tm[0]);
}
}
}
}

printf("totalFree: %d totalUsed: %d totalMem: %d #objs=%d #res=%d\n",
shared->freeTexMem[tmu], totalUsed, shared->totalTexMem[tmu],
numObj, numRes);

assert(totalUsed + totalFree == shared->totalTexMem[tmu]);
}


static void
dump_texmem(tdfxContextPtr fxMesa)
{
struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
struct gl_texture_object *oldestObj, *obj, *lowestPriorityObj;
tdfxMemRange *r;
FxU32 prev;

printf("DUMP Objects:\n");
for (obj = mesaShared->TexObjectList; obj; obj = obj->Next) {
tdfxTexInfo *info = TDFX_TEXTURE_DATA(obj);

if (info && info->isInTM) {
printf("Obj %8p: %4d info = %p\n", obj, obj->Name, info);

printf(" isInTM=%d whichTMU=%d lastTimeUsed=%d\n",
info->isInTM, info->whichTMU, info->lastTimeUsed);
printf(" tm[0] = %p", info->tm[0]);
assert(info->tm[0]);
if (info->tm[0]) {
printf(" tm startAddr = %d endAddr = %d",
info->tm[0]->startAddr,
info->tm[0]->endAddr);
}
printf("\n");
printf(" tm[1] = %p", info->tm[1]);
if (info->tm[1]) {
printf(" tm startAddr = %d endAddr = %d",
info->tm[1]->startAddr,
info->tm[1]->endAddr);
}
printf("\n");
}
}

VerifyFreeList(fxMesa, 0);
VerifyFreeList(fxMesa, 1);

printf("Free memory unit 0: %d bytes\n", shared->freeTexMem[0]);
prev = 0;
for (r = shared->tmFree[0]; r; r = r->next) {
printf("%8p: start %8d end %8d size %8d gap %8d\n", r, r->startAddr, r->endAddr, r->endAddr - r->startAddr, r->startAddr - prev);
prev = r->endAddr;
}

printf("Free memory unit 1: %d bytes\n", shared->freeTexMem[1]);
prev = 0;
for (r = shared->tmFree[1]; r; r = r->next) {
printf("%8p: start %8d end %8d size %8d gap %8d\n", r, r->startAddr, r->endAddr, r->endAddr - r->startAddr, r->startAddr - prev);
prev = r->endAddr;
}

}
#endif



#ifdef TEXSANITY
static void
fubar(void)
{
}

/*
* Sanity Check
*/
static void
sanity(tdfxContextPtr fxMesa)
{
tdfxMemRange *tmp, *prev, *pos;

prev = 0;
tmp = fxMesa->tmFree[0];
while (tmp) {
if (!tmp->startAddr && !tmp->endAddr) {
fprintf(stderr, "Textures fubar\n");
fubar();
}
if (tmp->startAddr >= tmp->endAddr) {
fprintf(stderr, "Node fubar\n");
fubar();
}
if (prev && (prev->startAddr >= tmp->startAddr ||
prev->endAddr > tmp->startAddr)) {
fprintf(stderr, "Sorting fubar\n");
fubar();
}
prev = tmp;
tmp = tmp->next;
}
prev = 0;
tmp = fxMesa->tmFree[1];
while (tmp) {
if (!tmp->startAddr && !tmp->endAddr) {
fprintf(stderr, "Textures fubar\n");
fubar();
}
if (tmp->startAddr >= tmp->endAddr) {
fprintf(stderr, "Node fubar\n");
fubar();
}
if (prev && (prev->startAddr >= tmp->startAddr ||
prev->endAddr > tmp->startAddr)) {
fprintf(stderr, "Sorting fubar\n");
fubar();
}
prev = tmp;
tmp = tmp->next;
}
}
#endif





/*
* Allocate and initialize a new MemRange struct.
* Try to allocate it from the pool of free MemRange nodes rather than malloc.
*/
static tdfxMemRange *
NewRangeNode(tdfxContextPtr fxMesa, FxU32 start, FxU32 end)
{
struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
tdfxMemRange *result;

_glthread_LOCK_MUTEX(mesaShared->Mutex);
if (shared && shared->tmPool) {
result = shared->tmPool;
shared->tmPool = shared->tmPool->next;
}
else {
result = MALLOC(sizeof(tdfxMemRange));

}
_glthread_UNLOCK_MUTEX(mesaShared->Mutex);

if (!result) {
/*fprintf(stderr, "fxDriver: out of memory!\n");*/
return NULL;
}

result->startAddr = start;
result->endAddr = end;
result->next = NULL;

return result;
}


/*
* Initialize texture memory.
* We take care of one or both TMU's here.
*/
void
tdfxTMInit(tdfxContextPtr fxMesa)
{
if (!fxMesa->glCtx->Shared->DriverData) {
const char *extensions;
struct tdfxSharedState *shared = CALLOC_STRUCT(tdfxSharedState);
if (!shared)
return;

LOCK_HARDWARE(fxMesa);
extensions = fxMesa->Glide.grGetString(GR_EXTENSION);
UNLOCK_HARDWARE(fxMesa);
if (strstr(extensions, "TEXUMA")) {
FxU32 start, end;
shared->umaTexMemory = GL_TRUE;
LOCK_HARDWARE(fxMesa);
fxMesa->Glide.grEnable(GR_TEXTURE_UMA_EXT);
start = fxMesa->Glide.grTexMinAddress(0);
end = fxMesa->Glide.grTexMaxAddress(0);
UNLOCK_HARDWARE(fxMesa);
shared->totalTexMem[0] = end - start;
shared->totalTexMem[1] = 0;
shared->freeTexMem[0] = end - start;
shared->freeTexMem[1] = 0;
shared->tmFree[0] = NewRangeNode(fxMesa, start, end);
shared->tmFree[1] = NULL;
/*printf("UMA tex memory: %d\n", (int) (end - start));*/
}
else {
const int numTMUs = fxMesa->haveTwoTMUs ? 2 : 1;
int tmu;
shared->umaTexMemory = GL_FALSE;
LOCK_HARDWARE(fxMesa);
for (tmu = 0; tmu < numTMUs; tmu++) {
FxU32 start = fxMesa->Glide.grTexMinAddress(tmu);
FxU32 end = fxMesa->Glide.grTexMaxAddress(tmu);
shared->totalTexMem[tmu] = end - start;
shared->freeTexMem[tmu] = end - start;
shared->tmFree[tmu] = NewRangeNode(fxMesa, start, end);
/*printf("Split tex memory: %d\n", (int) (end - start));*/
}
UNLOCK_HARDWARE(fxMesa);
}

shared->tmPool = NULL;
fxMesa->glCtx->Shared->DriverData = shared;
/*printf("Texture memory init UMA: %d\n", shared->umaTexMemory);*/
}
}


/*
* Clean-up texture memory before destroying context.
*/
void
tdfxTMClose(tdfxContextPtr fxMesa)
{
if (fxMesa->glCtx->Shared->RefCount == 1 && fxMesa->driDrawable) {
/* refcount will soon go to zero, free our 3dfx stuff */
struct tdfxSharedState *shared = (struct tdfxSharedState *) fxMesa->glCtx->Shared->DriverData;

const int numTMUs = fxMesa->haveTwoTMUs ? 2 : 1;
int tmu;
tdfxMemRange *tmp, *next;

/* Deallocate the pool of free tdfxMemRange nodes */
tmp = shared->tmPool;
while (tmp) {
next = tmp->next;
FREE(tmp);
tmp = next;
}

/* Delete the texture memory block tdfxMemRange nodes */
for (tmu = 0; tmu < numTMUs; tmu++) {
tmp = shared->tmFree[tmu];
while (tmp) {
next = tmp->next;
FREE(tmp);
tmp = next;
}
}

FREE(shared);
fxMesa->glCtx->Shared->DriverData = NULL;
}
}



/*
* Delete a tdfxMemRange struct.
* We keep a linked list of free/available tdfxMemRange structs to
* avoid extra malloc/free calls.
*/
#if 0
static void
DeleteRangeNode_NoLock(struct TdfxSharedState *shared, tdfxMemRange *range)
{
/* insert at head of list */
range->next = shared->tmPool;
shared->tmPool = range;
}
#endif

#define DELETE_RANGE_NODE(shared, range) \
(range)->next = (shared)->tmPool; \
(shared)->tmPool = (range)



/*
* When we've run out of texture memory we have to throw out an
* existing texture to make room for the new one. This function
* determins the texture to throw out.
*/
static struct gl_texture_object *
FindOldestObject(tdfxContextPtr fxMesa, FxU32 tmu)
{
const GLuint bindnumber = fxMesa->texBindNumber;
struct gl_texture_object *oldestObj, *obj, *lowestPriorityObj;
GLfloat lowestPriority;
GLuint oldestAge;

oldestObj = NULL;
oldestAge = 0;

lowestPriority = 1.0F;
lowestPriorityObj = NULL;

for (obj = fxMesa->glCtx->Shared->TexObjectList; obj; obj = obj->Next) {
tdfxTexInfo *info = TDFX_TEXTURE_DATA(obj);

if (info && info->isInTM &&
((info->whichTMU == tmu) || (info->whichTMU == TDFX_TMU_BOTH) ||
(info->whichTMU == TDFX_TMU_SPLIT))) {
GLuint age, lasttime;

assert(info->tm[0]);
lasttime = info->lastTimeUsed;

if (lasttime > bindnumber)
age = bindnumber + (UINT_MAX - lasttime + 1); /* TO DO: check wrap around */
else
age = bindnumber - lasttime;

if (age >= oldestAge) {
oldestAge = age;
oldestObj = obj;
}

/* examine priority */
if (obj->Priority < lowestPriority) {
lowestPriority = obj->Priority;
lowestPriorityObj = obj;
}
}
}

if (lowestPriority < 1.0) {
ASSERT(lowestPriorityObj);
/*
printf("discard %d pri=%f\n", lowestPriorityObj->Name, lowestPriority);
*/
return lowestPriorityObj;
}
else {
/*
printf("discard %d age=%d\n", oldestObj->Name, oldestAge);
*/
return oldestObj;
}
}


#if 0
static void
FlushTexMemory(tdfxContextPtr fxMesa)
{
struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
struct gl_texture_object *obj;

for (obj = mesaShared->TexObjectList; obj; obj = obj->Next) {
if (obj->RefCount < 2) {
/* don't flush currently bound textures */
tdfxTMMoveOutTM_NoLock(fxMesa, obj);
}
}
}
#endif


/*
* Find the address (offset?) at which we can store a new texture.
* <tmu> is the texture unit.
* <size> is the texture size in bytes.
*/
static FxU32
FindStartAddr(tdfxContextPtr fxMesa, FxU32 tmu, FxU32 size)
{
struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
tdfxMemRange *prev, *block;
FxU32 result;
#if 0
int discardedCount = 0;
#define MAX_DISCARDS 10
#endif

if (shared->umaTexMemory) {
assert(tmu == TDFX_TMU0);
}

_glthread_LOCK_MUTEX(mesaShared->Mutex);
while (1) {
prev = NULL;
block = shared->tmFree[tmu];
while (block) {
if (block->endAddr - block->startAddr >= size) {
/* The texture will fit here */
result = block->startAddr;
block->startAddr += size;
if (block->startAddr == block->endAddr) {
/* Remove this node since it's empty */
if (prev) {
prev->next = block->next;
}
else {
shared->tmFree[tmu] = block->next;
}
DELETE_RANGE_NODE(shared, block);
}
shared->freeTexMem[tmu] -= size;
_glthread_UNLOCK_MUTEX(mesaShared->Mutex);
return result;
}
prev = block;
block = block->next;
}
/* We failed to find a block large enough to accomodate <size> bytes.
* Find the oldest texObject and free it.
*/
#if 0
discardedCount++;
if (discardedCount > MAX_DISCARDS + 1) {
_mesa_problem(NULL, "%s: extreme texmem fragmentation", __FUNCTION__);
_glthread_UNLOCK_MUTEX(mesaShared->Mutex);
return BAD_ADDRESS;
}
else if (discardedCount > MAX_DISCARDS) {
/* texture memory is probably really fragmented, flush it */
FlushTexMemory(fxMesa);
}
else
#endif
{
struct gl_texture_object *obj = FindOldestObject(fxMesa, tmu);
if (obj) {
tdfxTMMoveOutTM_NoLock(fxMesa, obj);
fxMesa->stats.texSwaps++;
}
else {
_mesa_problem(NULL, "%s: extreme texmem fragmentation", __FUNCTION__);
_glthread_UNLOCK_MUTEX(mesaShared->Mutex);
return BAD_ADDRESS;
}
}
}

/* never get here, but play it safe */
_glthread_UNLOCK_MUTEX(mesaShared->Mutex);
return BAD_ADDRESS;
}


/*
* Remove the given tdfxMemRange node from hardware texture memory.
*/
static void
RemoveRange_NoLock(tdfxContextPtr fxMesa, FxU32 tmu, tdfxMemRange *range)
{
struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
tdfxMemRange *block, *prev;

if (shared->umaTexMemory) {
assert(tmu == TDFX_TMU0);
}

if (!range)
return;

if (range->startAddr == range->endAddr) {
DELETE_RANGE_NODE(shared, range);
return;
}
shared->freeTexMem[tmu] += range->endAddr - range->startAddr;

/* find position in linked list to insert this tdfxMemRange node */
prev = NULL;
block = shared->tmFree[tmu];
while (block) {
assert(range->startAddr != block->startAddr);
if (range->startAddr > block->startAddr) {
prev = block;
block = block->next;
}
else {
break;
}
}

/* Insert the free block, combine with adjacent blocks when possible */
range->next = block;
if (block) {
if (range->endAddr == block->startAddr) {
/* Combine */
block->startAddr = range->startAddr;
DELETE_RANGE_NODE(shared, range);
range = block;
}
}
if (prev) {
if (prev->endAddr == range->startAddr) {
/* Combine */
prev->endAddr = range->endAddr;
prev->next = range->next;
DELETE_RANGE_NODE(shared, range);
}
else {
prev->next = range;
}
}
else {
shared->tmFree[tmu] = range;
}
}


#if 0 /* NOT USED */
static void
RemoveRange(tdfxContextPtr fxMesa, FxU32 tmu, tdfxMemRange *range)
{
struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
_glthread_LOCK_MUTEX(mesaShared->Mutex);
RemoveRange_NoLock(fxMesa, tmu, range);
_glthread_UNLOCK_MUTEX(mesaShared->Mutex);
}
#endif


/*
* Allocate space for a texture image.
* <tmu> is the texture unit
* <texmemsize> is the number of bytes to allocate
*/
static tdfxMemRange *
AllocTexMem(tdfxContextPtr fxMesa, FxU32 tmu, FxU32 texmemsize)
{
FxU32 startAddr;
startAddr = FindStartAddr(fxMesa, tmu, texmemsize);
if (startAddr == BAD_ADDRESS) {
_mesa_problem(fxMesa->glCtx, "%s returned NULL! tmu=%d texmemsize=%d",
__FUNCTION__, (int) tmu, (int) texmemsize);
return NULL;
}
else {
tdfxMemRange *range;
range = NewRangeNode(fxMesa, startAddr, startAddr + texmemsize);
return range;
}
}


/*
* Download (copy) the given texture data (all mipmap levels) into the
* Voodoo's texture memory.
* The texture memory must have already been allocated.
*/
void
tdfxTMDownloadTexture(tdfxContextPtr fxMesa, struct gl_texture_object *tObj)
{
tdfxTexInfo *ti;
GLint l;
FxU32 targetTMU;

assert(tObj);
ti = TDFX_TEXTURE_DATA(tObj);
assert(ti);
targetTMU = ti->whichTMU;

switch (targetTMU) {
case TDFX_TMU0:
case TDFX_TMU1:
if (ti->tm[targetTMU]) {
for (l = ti->minLevel; l <= ti->maxLevel
&& tObj->Image[l]->Data; l++) {
GrLOD_t glideLod = ti->info.largeLodLog2 - l + tObj->BaseLevel;
fxMesa->Glide.grTexDownloadMipMapLevel(targetTMU,
ti->tm[targetTMU]->startAddr,
glideLod,
ti->info.largeLodLog2,
ti->info.aspectRatioLog2,
ti->info.format,
GR_MIPMAPLEVELMASK_BOTH,
tObj->Image[l]->Data);
}
}
break;
case TDFX_TMU_SPLIT:
if (ti->tm[TDFX_TMU0] && ti->tm[TDFX_TMU1]) {
for (l = ti->minLevel; l <= ti->maxLevel
&& tObj->Image[l]->Data; l++) {
GrLOD_t glideLod = ti->info.largeLodLog2 - l + tObj->BaseLevel;
fxMesa->Glide.grTexDownloadMipMapLevel(GR_TMU0,
ti->tm[TDFX_TMU0]->startAddr,
glideLod,
ti->info.largeLodLog2,
ti->info.aspectRatioLog2,
ti->info.format,
GR_MIPMAPLEVELMASK_ODD,
tObj->Image[l]->Data);

fxMesa->Glide.grTexDownloadMipMapLevel(GR_TMU1,
ti->tm[TDFX_TMU1]->startAddr,
glideLod,
ti->info.largeLodLog2,
ti->info.aspectRatioLog2,
ti->info.format,
GR_MIPMAPLEVELMASK_EVEN,
tObj->Image[l]->Data);
}
}
break;
case TDFX_TMU_BOTH:
if (ti->tm[TDFX_TMU0] && ti->tm[TDFX_TMU1]) {
for (l = ti->minLevel; l <= ti->maxLevel
&& tObj->Image[l]->Data; l++) {
GrLOD_t glideLod = ti->info.largeLodLog2 - l + tObj->BaseLevel;
fxMesa->Glide.grTexDownloadMipMapLevel(GR_TMU0,
ti->tm[TDFX_TMU0]->startAddr,
glideLod,
ti->info.largeLodLog2,
ti->info.aspectRatioLog2,
ti->info.format,
GR_MIPMAPLEVELMASK_BOTH,
tObj->Image[l]->Data);

fxMesa->Glide.grTexDownloadMipMapLevel(GR_TMU1,
ti->tm[TDFX_TMU1]->startAddr,
glideLod,
ti->info.largeLodLog2,
ti->info.aspectRatioLog2,
ti->info.format,
GR_MIPMAPLEVELMASK_BOTH,
tObj->Image[l]->Data);
}
}
break;
default:
_mesa_problem(NULL, "%s: bad tmu (%d)", __FUNCTION__, (int)targetTMU);
return;
}
}


void
tdfxTMReloadMipMapLevel(GLcontext *ctx, struct gl_texture_object *tObj,
GLint level)
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj);
GrLOD_t glideLod;
FxU32 tmu;

tmu = ti->whichTMU;
glideLod = ti->info.largeLodLog2 - level + tObj->BaseLevel;
ASSERT(ti->isInTM);

LOCK_HARDWARE(fxMesa);

switch (tmu) {
case TDFX_TMU0:
case TDFX_TMU1:
fxMesa->Glide.grTexDownloadMipMapLevel(tmu,
ti->tm[tmu]->startAddr,
glideLod,
ti->info.largeLodLog2,
ti->info.aspectRatioLog2,
ti->info.format,
GR_MIPMAPLEVELMASK_BOTH,
tObj->Image[level]->Data);
break;
case TDFX_TMU_SPLIT:
fxMesa->Glide.grTexDownloadMipMapLevel(GR_TMU0,
ti->tm[GR_TMU0]->startAddr,
glideLod,
ti->info.largeLodLog2,
ti->info.aspectRatioLog2,
ti->info.format,
GR_MIPMAPLEVELMASK_ODD,
tObj->Image[level]->Data);

fxMesa->Glide.grTexDownloadMipMapLevel(GR_TMU1,
ti->tm[GR_TMU1]->startAddr,
glideLod,
ti->info.largeLodLog2,
ti->info.aspectRatioLog2,
ti->info.format,
GR_MIPMAPLEVELMASK_EVEN,
tObj->Image[level]->Data);
break;
case TDFX_TMU_BOTH:
fxMesa->Glide.grTexDownloadMipMapLevel(GR_TMU0,
ti->tm[GR_TMU0]->startAddr,
glideLod,
ti->info.largeLodLog2,
ti->info.aspectRatioLog2,
ti->info.format,
GR_MIPMAPLEVELMASK_BOTH,
tObj->Image[level]->Data);

fxMesa->Glide.grTexDownloadMipMapLevel(GR_TMU1,
ti->tm[GR_TMU1]->startAddr,
glideLod,
ti->info.largeLodLog2,
ti->info.aspectRatioLog2,
ti->info.format,
GR_MIPMAPLEVELMASK_BOTH,
tObj->Image[level]->Data);
break;

default:
_mesa_problem(ctx, "%s: bad tmu (%d)", __FUNCTION__, (int)tmu);
break;
}
UNLOCK_HARDWARE(fxMesa);
}


/*
* Allocate space for the given texture in texture memory then
* download (copy) it into that space.
*/
void
tdfxTMMoveInTM_NoLock( tdfxContextPtr fxMesa, struct gl_texture_object *tObj,
FxU32 targetTMU )
{
tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj);
FxU32 texmemsize;

fxMesa->stats.reqTexUpload++;

if (ti->isInTM) {
if (ti->whichTMU == targetTMU)
return;
if (targetTMU == TDFX_TMU_SPLIT || ti->whichTMU == TDFX_TMU_SPLIT) {
tdfxTMMoveOutTM_NoLock(fxMesa, tObj);
}
else {
if (ti->whichTMU == TDFX_TMU_BOTH)
return;
targetTMU = TDFX_TMU_BOTH;
}
}

ti->whichTMU = targetTMU;

switch (targetTMU) {
case TDFX_TMU0:
case TDFX_TMU1:
texmemsize = fxMesa->Glide.grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH,
&(ti->info));
ti->tm[targetTMU] = AllocTexMem(fxMesa, targetTMU, texmemsize);
break;
case TDFX_TMU_SPLIT:
texmemsize = fxMesa->Glide.grTexTextureMemRequired(GR_MIPMAPLEVELMASK_ODD,
&(ti->info));
ti->tm[TDFX_TMU0] = AllocTexMem(fxMesa, TDFX_TMU0, texmemsize);
if (ti->tm[TDFX_TMU0])
fxMesa->stats.memTexUpload += texmemsize;

texmemsize = fxMesa->Glide.grTexTextureMemRequired(GR_MIPMAPLEVELMASK_EVEN,
&(ti->info));
ti->tm[TDFX_TMU1] = AllocTexMem(fxMesa, TDFX_TMU1, texmemsize);
break;
case TDFX_TMU_BOTH:
texmemsize = fxMesa->Glide.grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH,
&(ti->info));
ti->tm[TDFX_TMU0] = AllocTexMem(fxMesa, TDFX_TMU0, texmemsize);
if (ti->tm[TDFX_TMU0])
fxMesa->stats.memTexUpload += texmemsize;

texmemsize = fxMesa->Glide.grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH,
&(ti->info));
ti->tm[TDFX_TMU1] = AllocTexMem(fxMesa, TDFX_TMU1, texmemsize);
break;
default:
_mesa_problem(NULL, "%s: bad tmu (%d)", __FUNCTION__, (int)targetTMU);
return;
}

ti->reloadImages = GL_TRUE;
ti->isInTM = GL_TRUE;

fxMesa->stats.texUpload++;
}


/*
* Move the given texture out of hardware texture memory.
* This deallocates the texture's memory space.
*/
void
tdfxTMMoveOutTM_NoLock( tdfxContextPtr fxMesa, struct gl_texture_object *tObj )
{
struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj);

if (MESA_VERBOSE & VERBOSE_DRIVER) {
fprintf(stderr, "fxmesa: %s(%p (%d))\n", __FUNCTION__, tObj, tObj->Name);
}

/*
VerifyFreeList(fxMesa, 0);
VerifyFreeList(fxMesa, 1);
*/

if (!ti || !ti->isInTM)
return;

switch (ti->whichTMU) {
case TDFX_TMU0:
case TDFX_TMU1:
RemoveRange_NoLock(fxMesa, ti->whichTMU, ti->tm[ti->whichTMU]);
break;
case TDFX_TMU_SPLIT:
case TDFX_TMU_BOTH:
assert(!shared->umaTexMemory);
RemoveRange_NoLock(fxMesa, TDFX_TMU0, ti->tm[TDFX_TMU0]);
RemoveRange_NoLock(fxMesa, TDFX_TMU1, ti->tm[TDFX_TMU1]);
break;
default:
_mesa_problem(NULL, "%s: bad tmu (%d)", __FUNCTION__, (int)ti->whichTMU);
return;
}

ti->isInTM = GL_FALSE;
ti->tm[0] = NULL;
ti->tm[1] = NULL;
ti->whichTMU = TDFX_TMU_NONE;

/*
VerifyFreeList(fxMesa, 0);
VerifyFreeList(fxMesa, 1);
*/
}


/*
* Called via glDeleteTexture to delete a texture object.
*/
void
tdfxTMFreeTexture(tdfxContextPtr fxMesa, struct gl_texture_object *tObj)
{
tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj);
if (ti) {
tdfxTMMoveOutTM(fxMesa, tObj);
FREE(ti);
tObj->DriverData = NULL;
}
/*
VerifyFreeList(fxMesa, 0);
VerifyFreeList(fxMesa, 1);
*/
}



/*
* After a context switch this function will be called to restore
* texture memory for the new context.
*/
void tdfxTMRestoreTextures_NoLock( tdfxContextPtr fxMesa )
{
GLcontext *ctx = fxMesa->glCtx;
struct gl_texture_object *tObj;
int i;

for ( tObj = ctx->Shared->TexObjectList ; tObj ; tObj = tObj->Next ) {
tdfxTexInfo *ti = TDFX_TEXTURE_DATA( tObj );
if ( ti && ti->isInTM ) {
for ( i = 0 ; i < MAX_TEXTURE_UNITS ; i++ ) {
if ( ctx->Texture.Unit[i]._Current == tObj ) {
tdfxTMDownloadTexture( fxMesa, tObj );
break;
}
}
if ( i == MAX_TEXTURE_UNITS ) {
tdfxTMMoveOutTM_NoLock( fxMesa, tObj );
}
}
}
/*
VerifyFreeList(fxMesa, 0);
VerifyFreeList(fxMesa, 1);
*/
}

+ 84
- 0
src/mesa/drivers/dri/tdfx/tdfx_texman.h View File

@@ -0,0 +1,84 @@
/* -*- mode: c; c-basic-offset: 3 -*-
*
* Copyright 2000 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
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION 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/tdfx/tdfx_texman.h,v 1.2 2002/02/22 21:45:04 dawes Exp $ */

/*
* Original rewrite:
* Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Brian Paul <brianp@valinux.com>
*
*/

#ifndef __TDFX_TEXMAN_H__
#define __TDFX_TEXMAN_H__


#include "tdfx_lock.h"


extern void tdfxTMInit( tdfxContextPtr fxMesa );

extern void tdfxTMClose( tdfxContextPtr fxMesa );

extern void tdfxTMDownloadTexture(tdfxContextPtr fxMesa,
struct gl_texture_object *tObj);

extern void tdfxTMReloadMipMapLevel( GLcontext *ctx,
struct gl_texture_object *tObj,
GLint level );

extern void tdfxTMMoveInTM_NoLock( tdfxContextPtr fxMesa,
struct gl_texture_object *tObj,
FxU32 targetTMU );

extern void tdfxTMMoveOutTM_NoLock( tdfxContextPtr fxMesa,
struct gl_texture_object *tObj );

extern void tdfxTMFreeTexture( tdfxContextPtr fxMesa,
struct gl_texture_object *tObj );

extern void tdfxTMRestoreTextures_NoLock( tdfxContextPtr fxMesa );


#define tdfxTMMoveInTM( fxMesa, tObj, targetTMU ) \
do { \
LOCK_HARDWARE( fxMesa ); \
tdfxTMMoveInTM_NoLock( fxMesa, tObj, targetTMU ); \
UNLOCK_HARDWARE( fxMesa ); \
} while (0)

#define tdfxTMMoveOutTM( fxMesa, tObj ) \
do { \
LOCK_HARDWARE( fxMesa ); \
tdfxTMMoveOutTM_NoLock( fxMesa, tObj ); \
UNLOCK_HARDWARE( fxMesa ); \
} while (0)


#endif

+ 2107
- 0
src/mesa/drivers/dri/tdfx/tdfx_texstate.c
File diff suppressed because it is too large
View File


+ 44
- 0
src/mesa/drivers/dri/tdfx/tdfx_texstate.h View File

@@ -0,0 +1,44 @@
/* -*- mode: c; c-basic-offset: 3 -*-
*
* Copyright 2000 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
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION 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/tdfx/tdfx_texstate.h,v 1.1 2002/02/22 21:45:04 dawes Exp $ */

/*
* Original rewrite:
* Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Brian Paul <brianp@valinux.com>
*
*/

#ifndef __TDFX_TEXSTATE_H__
#define __TDFX_TEXSTATE_H__

extern void tdfxUpdateTextureState( GLcontext *ctx );
extern void tdfxUpdateTextureBinding( GLcontext *ctx );

#endif

+ 1258
- 0
src/mesa/drivers/dri/tdfx/tdfx_tris.c
File diff suppressed because it is too large
View File


+ 42
- 0
src/mesa/drivers/dri/tdfx/tdfx_tris.h View File

@@ -0,0 +1,42 @@
/* -*- mode: c; c-basic-offset: 3 -*-
*
* Copyright 2000 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
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION 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>
*
*/
/* $XFree86: xc/lib/GL/mesa/src/drv/tdfx/tdfx_tris.h,v 1.5 2002/10/30 12:52:01 alanh Exp $ */

#ifndef TDFX_TRIS_INC
#define TDFX_TRIS_INC

#include "mtypes.h"

extern void tdfxDDInitTriFuncs( GLcontext *ctx );


#endif

+ 365
- 0
src/mesa/drivers/dri/tdfx/tdfx_vb.c View File

@@ -0,0 +1,365 @@
/*
* 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.
*
*
*/
/* $XFree86: xc/lib/GL/mesa/src/drv/tdfx/tdfx_vb.c,v 1.3 2002/10/30 12:52:01 alanh Exp $ */
#include "glheader.h"
#include "mtypes.h"
#include "imports.h"
#include "macros.h"
#include "colormac.h"

#include "math/m_translate.h"
#include "swrast_setup/swrast_setup.h"

#include "tdfx_context.h"
#include "tdfx_vb.h"
#include "tdfx_tris.h"
#include "tdfx_state.h"
#include "tdfx_render.h"

static void copy_pv_rgba4( GLcontext *ctx, GLuint edst, GLuint esrc )
{
tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
GLubyte *tdfxverts = (GLubyte *)fxMesa->verts;
GLuint shift = fxMesa->vertex_stride_shift;
tdfxVertex *dst = (tdfxVertex *)(tdfxverts + (edst << shift));
tdfxVertex *src = (tdfxVertex *)(tdfxverts + (esrc << shift));
dst->ui[4] = src->ui[4];
}

static void copy_pv_rgba3( GLcontext *ctx, GLuint edst, GLuint esrc )
{
tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
GLubyte *tdfxverts = (GLubyte *)fxMesa->verts;
GLuint shift = fxMesa->vertex_stride_shift;
tdfxVertex *dst = (tdfxVertex *)(tdfxverts + (edst << shift));
tdfxVertex *src = (tdfxVertex *)(tdfxverts + (esrc << shift));
dst->ui[3] = src->ui[3];
}

typedef void (*emit_func)( GLcontext *, GLuint, GLuint, void *, GLuint );

static struct {
emit_func emit;
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[TDFX_MAX_SETUP];


static void import_float_colors( GLcontext *ctx )
{
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
struct gl_client_array *from = VB->ColorPtr[0];
struct gl_client_array *to = &TDFX_CONTEXT(ctx)->UbyteColor;
GLuint count = VB->Count;

if (!to->Ptr) {
to->Ptr = ALIGN_MALLOC( VB->Size * 4 * sizeof(GLubyte), 32 );
to->Type = GL_UNSIGNED_BYTE;
}

/* No need to transform the same value 3000 times.
*/
if (!from->StrideB) {
to->StrideB = 0;
count = 1;
}
else
to->StrideB = 4 * sizeof(GLubyte);
_math_trans_4ub( (GLubyte (*)[4]) to->Ptr,
from->Ptr,
from->StrideB,
from->Type,
from->Size,
0,
count);

VB->ColorPtr[0] = to;
}


#define GET_COLOR(ptr, idx) (((GLchan (*)[4])((ptr)->Ptr))[idx])


static void interp_extras( GLcontext *ctx,
GLfloat t,
GLuint dst, GLuint out, GLuint in,
GLboolean force_boundary )
{
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;

/*fprintf(stderr, "%s\n", __FUNCTION__);*/

if (VB->ColorPtr[1]) {
INTERP_4CHAN( t,
GET_COLOR(VB->ColorPtr[1], dst),
GET_COLOR(VB->ColorPtr[1], out),
GET_COLOR(VB->ColorPtr[1], in) );
}

if (VB->EdgeFlag) {
VB->EdgeFlag[dst] = VB->EdgeFlag[out] || force_boundary;
}

setup_tab[TDFX_CONTEXT(ctx)->SetupIndex].interp(ctx, t, dst, out, in,
force_boundary);
}

static void copy_pv_extras( GLcontext *ctx, GLuint dst, GLuint src )
{
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;

if (VB->ColorPtr[1]) {
COPY_CHAN4( GET_COLOR(VB->ColorPtr[1], dst),
GET_COLOR(VB->ColorPtr[1], src) );
}

setup_tab[TDFX_CONTEXT(ctx)->SetupIndex].copy_pv(ctx, dst, src);
}



#define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT)
#define TAG(x) x##_wg
#include "tdfx_vbtmp.h"

/* Special for tdfx: fog requires w
*/
#define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT)
#define TAG(x) x##_wg_fog
#include "tdfx_vbtmp.h"

#define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_TEX0_BIT)
#define TAG(x) x##_wgt0
#include "tdfx_vbtmp.h"

#define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT)
#define TAG(x) x##_wgt0t1
#include "tdfx_vbtmp.h"

#define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_TEX0_BIT|TDFX_PTEX_BIT)
#define TAG(x) x##_wgpt0
#include "tdfx_vbtmp.h"

#define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT|\
TDFX_PTEX_BIT)
#define TAG(x) x##_wgpt0t1
#include "tdfx_vbtmp.h"

#define IND (TDFX_RGBA_BIT)
#define TAG(x) x##_g
#include "tdfx_vbtmp.h"

#define IND (TDFX_TEX0_BIT)
#define TAG(x) x##_t0
#include "tdfx_vbtmp.h"

#define IND (TDFX_TEX0_BIT|TDFX_TEX1_BIT)
#define TAG(x) x##_t0t1
#include "tdfx_vbtmp.h"

#define IND (TDFX_RGBA_BIT|TDFX_TEX0_BIT)
#define TAG(x) x##_gt0
#include "tdfx_vbtmp.h"

#define IND (TDFX_RGBA_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT)
#define TAG(x) x##_gt0t1
#include "tdfx_vbtmp.h"



static void init_setup_tab( void )
{
init_wg();
init_wg_fog();
init_wgt0();
init_wgt0t1();
init_wgpt0();
init_wgpt0t1();

init_g();
init_t0();
init_t0t1();
init_gt0();
init_gt0t1();
}


void tdfxPrintSetupFlags(char *msg, GLuint flags )
{
fprintf(stderr, "%s(%x): %s%s%s%s%s\n",
msg,
(int)flags,
(flags & TDFX_XYZ_BIT) ? " xyz," : "",
(flags & TDFX_W_BIT) ? " w," : "",
(flags & TDFX_RGBA_BIT) ? " rgba," : "",
(flags & TDFX_TEX0_BIT) ? " tex-0," : "",
(flags & TDFX_TEX1_BIT) ? " tex-1," : "");
}



void tdfxCheckTexSizes( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );

if (!setup_tab[fxMesa->SetupIndex].check_tex_sizes(ctx)) {
GLuint ind = fxMesa->SetupIndex |= (TDFX_PTEX_BIT|TDFX_RGBA_BIT);

/* Tdfx handles projective textures nicely; just have to change
* up to the new vertex format.
*/
if (setup_tab[ind].vertex_format != fxMesa->vertexFormat) {
FLUSH_BATCH(fxMesa);
fxMesa->dirty |= TDFX_UPLOAD_VERTEX_LAYOUT;
fxMesa->vertexFormat = setup_tab[ind].vertex_format;
fxMesa->vertex_stride_shift = setup_tab[ind].vertex_stride_shift;

/* This is required as we have just changed the vertex
* format, so the interp and copy routines must also change.
* In the unfilled and twosided cases we are using the
* swrast_setup ones anyway, so leave them in place.
*/
if (!(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
tnl->Driver.Render.Interp = setup_tab[fxMesa->SetupIndex].interp;
tnl->Driver.Render.CopyPV = setup_tab[fxMesa->SetupIndex].copy_pv;
}
}
}
}


void tdfxBuildVertices( GLcontext *ctx, GLuint start, GLuint count,
GLuint newinputs )
{
tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
GLubyte *v = (fxMesa->verts + (start<<fxMesa->vertex_stride_shift));
GLuint stride = 1<<fxMesa->vertex_stride_shift;

newinputs |= fxMesa->SetupNewInputs;
fxMesa->SetupNewInputs = 0;

if (!newinputs)
return;

if (newinputs & VERT_BIT_CLIP) {
setup_tab[fxMesa->SetupIndex].emit( ctx, start, count, v, stride );
} else {
GLuint ind = 0;

if (newinputs & VERT_BIT_COLOR0)
ind |= TDFX_RGBA_BIT;
if (newinputs & VERT_BIT_TEX0)
ind |= TDFX_TEX0_BIT;

if (newinputs & VERT_BIT_TEX1)
ind |= TDFX_TEX0_BIT|TDFX_TEX1_BIT;

if (fxMesa->SetupIndex & TDFX_PTEX_BIT)
ind = ~0;

ind &= fxMesa->SetupIndex;

if (ind) {
setup_tab[ind].emit( ctx, start, count, v, stride );
}
}
}


void tdfxChooseVertexState( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
GLuint ind = TDFX_XYZ_BIT|TDFX_RGBA_BIT;

if (ctx->Texture._EnabledUnits & 0x2)
/* unit 1 enabled */
ind |= TDFX_W_BIT|TDFX_TEX1_BIT|TDFX_TEX0_BIT;
else if (ctx->Texture._EnabledUnits & 0x1)
/* unit 0 enabled */
ind |= TDFX_W_BIT|TDFX_TEX0_BIT;
else if (ctx->Fog.Enabled)
ind |= TDFX_W_BIT;
fxMesa->SetupIndex = ind;

if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) {
tnl->Driver.Render.Interp = interp_extras;
tnl->Driver.Render.CopyPV = 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 != fxMesa->vertexFormat) {
FLUSH_BATCH(fxMesa);
fxMesa->dirty |= TDFX_UPLOAD_VERTEX_LAYOUT;
fxMesa->vertexFormat = setup_tab[ind].vertex_format;
fxMesa->vertex_stride_shift = setup_tab[ind].vertex_stride_shift;
}
}



void tdfxInitVB( GLcontext *ctx )
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
GLuint size = TNL_CONTEXT(ctx)->vb.Size;
static int firsttime = 1;
if (firsttime) {
init_setup_tab();
firsttime = 0;
}

fxMesa->verts = (GLubyte *)ALIGN_MALLOC(size * sizeof(tdfxVertex), 32);
fxMesa->vertexFormat = setup_tab[TDFX_XYZ_BIT|TDFX_RGBA_BIT].vertex_format;
fxMesa->vertex_stride_shift = setup_tab[(TDFX_XYZ_BIT|
TDFX_RGBA_BIT)].vertex_stride_shift;
fxMesa->SetupIndex = TDFX_XYZ_BIT|TDFX_RGBA_BIT;
}


void tdfxFreeVB( GLcontext *ctx )
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
if (fxMesa->verts) {
ALIGN_FREE(fxMesa->verts);
fxMesa->verts = 0;
}

if (fxMesa->UbyteColor.Ptr) {
ALIGN_FREE(fxMesa->UbyteColor.Ptr);
fxMesa->UbyteColor.Ptr = 0;
}

}

+ 68
- 0
src/mesa/drivers/dri/tdfx/tdfx_vb.h View File

@@ -0,0 +1,68 @@
/*
* GLX Hardware Device Driver for Intel tdfx
* 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.
*
*
*/
/* $XFree86: xc/lib/GL/mesa/src/drv/tdfx/tdfx_vb.h,v 1.2 2002/02/22 21:45:04 dawes Exp $ */

#ifndef TDFXVB_INC
#define TDFXVB_INC

#include "mtypes.h"

#include "tnl/tnl.h"
#include "tnl/t_context.h"
#include "math/m_xform.h"

#define TDFX_XYZ_BIT 0x1
#define TDFX_W_BIT 0x2
#define TDFX_RGBA_BIT 0x4
#define TDFX_TEX1_BIT 0x8
#define TDFX_TEX0_BIT 0x10
#define TDFX_PTEX_BIT 0x20
#define TDFX_MAX_SETUP 0x40

#define _TDFX_NEW_RASTERSETUP (_NEW_TEXTURE | \
_DD_NEW_SEPARATE_SPECULAR | \
_DD_NEW_TRI_UNFILLED | \
_DD_NEW_TRI_LIGHT_TWOSIDE | \
_NEW_FOG)


extern void tdfxValidateBuildProjVerts(GLcontext *ctx,
GLuint start, GLuint count,
GLuint newinputs );

extern void tdfxPrintSetupFlags(char *msg, GLuint flags );

extern void tdfxInitVB( GLcontext *ctx );

extern void tdfxFreeVB( GLcontext *ctx );

extern void tdfxCheckTexSizes( GLcontext *ctx );

extern void tdfxChooseVertexState( GLcontext *ctx );

extern void tdfxBuildVertices( GLcontext *ctx, GLuint start, GLuint count,
GLuint newinputs );

#endif

+ 442
- 0
src/mesa/drivers/dri/tdfx/tdfx_vbtmp.h View File

@@ -0,0 +1,442 @@

#if (IND & (TDFX_W_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT))

static void TAG(emit)( GLcontext *ctx,
GLuint start, GLuint end,
void *dest,
GLuint stride )
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
GLfloat (*tc0)[4], (*tc1)[4];
GLubyte (*col)[4];
GLuint tc0_stride, tc1_stride, col_stride;
GLuint tc0_size, tc1_size;
GLfloat (*proj)[4] = VB->NdcPtr->data;
GLuint proj_stride = VB->NdcPtr->stride;
tdfxVertex *v = (tdfxVertex *)dest;
GLfloat u0scale,v0scale,u1scale,v1scale;
const GLubyte *mask = VB->ClipMask;
const GLfloat *s = fxMesa->hw_viewport;
int i;

/* fprintf(stderr, "%s\n", __FUNCTION__); */
ASSERT(stride > 16);


if (IND & TDFX_TEX0_BIT) {
tc0_stride = VB->TexCoordPtr[0]->stride;
tc0 = VB->TexCoordPtr[0]->data;
u0scale = fxMesa->sScale0;
v0scale = fxMesa->tScale0;
if (IND & TDFX_PTEX_BIT)
tc0_size = VB->TexCoordPtr[0]->size;
}

if (IND & TDFX_TEX1_BIT) {
tc1 = VB->TexCoordPtr[1]->data;
tc1_stride = VB->TexCoordPtr[1]->stride;
u1scale = fxMesa->sScale1;
v1scale = fxMesa->tScale1;
if (IND & TDFX_PTEX_BIT)
tc1_size = VB->TexCoordPtr[1]->size;
}
if (IND & TDFX_RGBA_BIT) {
if (VB->ColorPtr[0]->Type != GL_UNSIGNED_BYTE)
import_float_colors( ctx );
col = VB->ColorPtr[0]->Ptr;
col_stride = VB->ColorPtr[0]->StrideB;
}

if (VB->importable_data) {
/* May have nonstandard strides:
*/
if (start) {
proj = (GLfloat (*)[4])((GLubyte *)proj + start * proj_stride);
if (IND & TDFX_TEX0_BIT)
tc0 = (GLfloat (*)[4])((GLubyte *)tc0 + start * tc0_stride);
if (IND & TDFX_TEX1_BIT)
tc1 = (GLfloat (*)[4])((GLubyte *)tc1 + start * tc1_stride);
if (IND & TDFX_RGBA_BIT)
STRIDE_4UB(col, start * col_stride);
}

for (i=start; i < end; i++, v = (tdfxVertex *)((GLubyte *)v + stride)) {
if (IND & TDFX_XYZ_BIT) {
if (mask[i] == 0) {
/* unclipped */
v->v.x = s[0] * proj[0][0] + s[12];
v->v.y = s[5] * proj[0][1] + s[13];
v->v.z = s[10] * proj[0][2] + s[14];
v->v.rhw = proj[0][3];
} else {
/* clipped */
v->v.rhw = 1.0;
}
proj = (GLfloat (*)[4])((GLubyte *)proj + proj_stride);
}
if (IND & TDFX_RGBA_BIT) {
#if 0
*(GLuint *)&v->v.color = *(GLuint *)col;
#else
GLubyte *b = (GLubyte *) &v->v.color;
b[0] = col[0][2];
b[1] = col[0][1];
b[2] = col[0][0];
b[3] = col[0][3];

#endif
STRIDE_4UB(col, col_stride);
}
if (IND & TDFX_TEX0_BIT) {
GLfloat w = v->v.rhw;
if (IND & TDFX_PTEX_BIT) {
v->pv.tu0 = tc0[0][0] * u0scale * w;
v->pv.tv0 = tc0[0][1] * v0scale * w;
v->pv.tq0 = w;
if (tc0_size == 4)
v->pv.tq0 = tc0[0][3] * w;
}
else {
v->v.tu0 = tc0[0][0] * u0scale * w;
v->v.tv0 = tc0[0][1] * v0scale * w;
}
tc0 = (GLfloat (*)[4])((GLubyte *)tc0 + tc0_stride);
}
if (IND & TDFX_TEX1_BIT) {
GLfloat w = v->v.rhw;
if (IND & TDFX_PTEX_BIT) {
v->pv.tu1 = tc1[0][0] * u1scale * w;
v->pv.tv1 = tc1[0][1] * v1scale * w;
v->pv.tq1 = w;
if (tc1_size == 4)
v->pv.tq1 = tc1[0][3] * w;
}
else {
v->v.tu1 = tc1[0][0] * u1scale * w;
v->v.tv1 = tc1[0][1] * v1scale * w;
}
tc1 = (GLfloat (*)[4])((GLubyte *)tc1 + tc1_stride);
}
}
}
else {
for (i=start; i < end; i++, v = (tdfxVertex *)((GLubyte *)v + stride)) {
if (IND & TDFX_XYZ_BIT) {
if (mask[i] == 0) {
v->v.x = s[0] * proj[i][0] + s[12];
v->v.y = s[5] * proj[i][1] + s[13];
v->v.z = s[10] * proj[i][2] + s[14];
v->v.rhw = proj[i][3];
} else {
v->v.rhw = 1.0;
}
}
if (IND & TDFX_RGBA_BIT) {
#if 0
*(GLuint *)&v->v.color = *(GLuint *)&col[i];
#else
GLubyte *b = (GLubyte *) &v->v.color;
b[0] = col[i][2];
b[1] = col[i][1];
b[2] = col[i][0];
b[3] = col[i][3];

#endif
}
if (IND & TDFX_TEX0_BIT) {
GLfloat w = v->v.rhw;
if (IND & TDFX_PTEX_BIT) {
v->pv.tu0 = tc0[i][0] * u0scale * w;
v->pv.tv0 = tc0[i][1] * v0scale * w;
v->pv.tq0 = w;
if (tc0_size == 4)
v->pv.tq0 = tc0[i][3] * w;
}
else {
v->v.tu0 = tc0[i][0] * u0scale * w;
v->v.tv0 = tc0[i][1] * v0scale * w;
}
}
if (IND & TDFX_TEX1_BIT) {
GLfloat w = v->v.rhw;
if (IND & TDFX_PTEX_BIT) {
v->pv.tu1 = tc1[i][0] * u1scale * w;
v->pv.tv1 = tc1[i][1] * v1scale * w;
v->pv.tq1 = w;
if (tc1_size == 4)
v->pv.tq1 = tc1[i][3] * w;
}
else {
v->v.tu1 = tc1[i][0] * u1scale * w;
v->v.tv1 = tc1[i][1] * v1scale * w;
}
}
}
}
}
#else
#if (IND & TDFX_XYZ_BIT)
static void TAG(emit)( GLcontext *ctx, GLuint start, GLuint end,
void *dest, GLuint stride )
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
GLubyte (*col)[4];
GLuint col_stride;
GLfloat (*proj)[4] = VB->NdcPtr->data;
GLuint proj_stride = VB->NdcPtr->stride;
GLfloat *v = (GLfloat *)dest;
const GLubyte *mask = VB->ClipMask;
const GLfloat *s = fxMesa->hw_viewport;
int i;

/* fprintf(stderr, "%s %d..%d dest %p stride %d\n", __FUNCTION__, */
/* start, end, dest, stride); */

ASSERT(fxMesa->SetupIndex == (TDFX_XYZ_BIT|TDFX_RGBA_BIT));
ASSERT(stride == 16);

if (VB->ColorPtr[0]->Type != GL_UNSIGNED_BYTE)
import_float_colors( ctx );

col = (GLubyte (*)[4])VB->ColorPtr[0]->Ptr;
col_stride = VB->ColorPtr[0]->StrideB;
ASSERT(VB->ColorPtr[0]->Type == GL_UNSIGNED_BYTE);

/* Pack what's left into a 4-dword vertex. Color is in a different
* place, and there is no 'w' coordinate.
*/
if (VB->importable_data) {
if (start) {
proj = (GLfloat (*)[4])((GLubyte *)proj + start * proj_stride);
STRIDE_4UB(col, start * col_stride);
}

for (i=start; i < end; i++, v+=4) {
if (mask[i] == 0) {
v[0] = s[0] * proj[0][0] + s[12];
v[1] = s[5] * proj[0][1] + s[13];
v[2] = s[10] * proj[0][2] + s[14];
}
proj = (GLfloat (*)[4])((GLubyte *)proj + proj_stride);
{
GLubyte *b = (GLubyte *)&v[3];
b[0] = col[0][2];
b[1] = col[0][1];
b[2] = col[0][0];
b[3] = col[0][3];
STRIDE_4UB(col, col_stride);
}
}
}
else {
for (i=start; i < end; i++, v+=4) {
if (mask[i] == 0) {
v[0] = s[0] * proj[i][0] + s[12];
v[1] = s[5] * proj[i][1] + s[13];
v[2] = s[10] * proj[i][2] + s[14];
}
{
GLubyte *b = (GLubyte *)&v[3];
b[0] = col[i][2];
b[1] = col[i][1];
b[2] = col[i][0];
b[3] = col[i][3];
}
}
}
}
#else
static void TAG(emit)( GLcontext *ctx, GLuint start, GLuint end,
void *dest, GLuint stride )
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
GLubyte (*col)[4];
GLuint col_stride;
GLfloat *v = (GLfloat *)dest;
int i;

if (VB->ColorPtr[0]->Type != GL_UNSIGNED_BYTE)
import_float_colors( ctx );

col = VB->ColorPtr[0]->Ptr;
col_stride = VB->ColorPtr[0]->StrideB;

if (start)
STRIDE_4UB(col, col_stride * start);

/* Need to figure out where color is:
*/
if (fxMesa->SetupIndex & TDFX_W_BIT )
v += 4;
else
v += 3;

for (i=start; i < end; i++, STRIDE_F(v, stride)) {
GLubyte *b = (GLubyte *)v;
b[0] = col[0][2];
b[1] = col[0][1];
b[2] = col[0][0];
b[3] = col[0][3];
STRIDE_4UB( col, col_stride );
}
}
#endif
#endif

#if (IND & TDFX_XYZ_BIT) && (IND & TDFX_RGBA_BIT)

static GLboolean TAG(check_tex_sizes)( GLcontext *ctx )
{
/* fprintf(stderr, "%s\n", __FUNCTION__); */

if (IND & TDFX_PTEX_BIT)
return GL_TRUE;
if (IND & TDFX_TEX0_BIT) {
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;

if (IND & TDFX_TEX1_BIT) {
if (VB->TexCoordPtr[0] == 0)
VB->TexCoordPtr[0] = VB->TexCoordPtr[1];
if (VB->TexCoordPtr[1]->size == 4)
return GL_FALSE;
}

if (VB->TexCoordPtr[0]->size == 4)
return GL_FALSE;
}

return GL_TRUE;
}

static void TAG(interp)( GLcontext *ctx,
GLfloat t,
GLuint edst, GLuint eout, GLuint ein,
GLboolean force_boundary )
{
tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
const GLuint shift = fxMesa->vertex_stride_shift;
const GLfloat *dstclip = VB->ClipPtr->data[edst];
const GLfloat oow = (dstclip[3] == 0.0F) ? 1.0F : (1.0F / dstclip[3]);
const GLfloat *s = fxMesa->hw_viewport;
GLubyte *tdfxverts = (GLubyte *)fxMesa->verts;
tdfxVertex *dst = (tdfxVertex *) (tdfxverts + (edst << shift));
const tdfxVertex *out = (const tdfxVertex *) (tdfxverts + (eout << shift));
const tdfxVertex *in = (const tdfxVertex *) (tdfxverts + (ein << shift));
const GLfloat wout = 1.0F / out->v.rhw;
const GLfloat win = 1.0F / in->v.rhw;

dst->v.x = s[0] * dstclip[0] * oow + s[12];
dst->v.y = s[5] * dstclip[1] * oow + s[13];
dst->v.z = s[10] * dstclip[2] * oow + s[14];

if (IND & (TDFX_W_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT)) {
dst->v.rhw = oow;
INTERP_UB( t, dst->ub4[4][0], out->ub4[4][0], in->ub4[4][0] );
INTERP_UB( t, dst->ub4[4][1], out->ub4[4][1], in->ub4[4][1] );
INTERP_UB( t, dst->ub4[4][2], out->ub4[4][2], in->ub4[4][2] );
INTERP_UB( t, dst->ub4[4][3], out->ub4[4][3], in->ub4[4][3] );

if (IND & TDFX_TEX0_BIT) {
if (IND & TDFX_PTEX_BIT) {
INTERP_F( t, dst->pv.tu0, out->pv.tu0 * wout, in->pv.tu0 * win );
INTERP_F( t, dst->pv.tv0, out->pv.tv0 * wout, in->pv.tv0 * win );
INTERP_F( t, dst->pv.tq0, out->pv.tq0 * wout, in->pv.tq0 * win );
dst->pv.tu0 *= oow;
dst->pv.tv0 *= oow;
dst->pv.tq0 *= oow;
} else {
INTERP_F( t, dst->v.tu0, out->v.tu0 * wout, in->v.tu0 * win );
INTERP_F( t, dst->v.tv0, out->v.tv0 * wout, in->v.tv0 * win );
dst->v.tu0 *= oow;
dst->v.tv0 *= oow;
}
}
if (IND & TDFX_TEX1_BIT) {
if (IND & TDFX_PTEX_BIT) {
INTERP_F( t, dst->pv.tu1, out->pv.tu1 * wout, in->pv.tu1 * win );
INTERP_F( t, dst->pv.tv1, out->pv.tv1 * wout, in->pv.tv1 * win );
INTERP_F( t, dst->pv.tq1, out->pv.tq1 * wout, in->pv.tq1 * win );
dst->pv.tu1 *= oow;
dst->pv.tv1 *= oow;
dst->pv.tq1 *= oow;
} else {
INTERP_F( t, dst->v.tu1, out->v.tu1 * wout, in->v.tu1 * win );
INTERP_F( t, dst->v.tv1, out->v.tv1 * wout, in->v.tv1 * win );
dst->v.tu1 *= oow;
dst->v.tv1 *= oow;
}
}
} else {
/* 4-dword vertex. Color is in v[3] and there is no oow coordinate.
*/
INTERP_UB( t, dst->ub4[3][0], out->ub4[3][0], in->ub4[3][0] );
INTERP_UB( t, dst->ub4[3][1], out->ub4[3][1], in->ub4[3][1] );
INTERP_UB( t, dst->ub4[3][2], out->ub4[3][2], in->ub4[3][2] );
INTERP_UB( t, dst->ub4[3][3], out->ub4[3][3], in->ub4[3][3] );
}
}
#endif


static void TAG(init)( void )
{
/* fprintf(stderr, "%s\n", __FUNCTION__); */

setup_tab[IND].emit = TAG(emit);
#if ((IND & TDFX_XYZ_BIT) && (IND & TDFX_RGBA_BIT))
setup_tab[IND].check_tex_sizes = TAG(check_tex_sizes);
setup_tab[IND].interp = TAG(interp);
if (IND & (TDFX_W_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT))
setup_tab[IND].copy_pv = copy_pv_rgba4;
else
setup_tab[IND].copy_pv = copy_pv_rgba3;


if (IND & TDFX_TEX1_BIT) {
if (IND & TDFX_PTEX_BIT) {
setup_tab[IND].vertex_format = TDFX_LAYOUT_PROJECT;
setup_tab[IND].vertex_size = 12;
setup_tab[IND].vertex_stride_shift = 6;
}
else {
setup_tab[IND].vertex_format = TDFX_LAYOUT_MULTI;
setup_tab[IND].vertex_size = 10;
setup_tab[IND].vertex_stride_shift = 6;
}
}
else if (IND & TDFX_TEX0_BIT) {
if (IND & TDFX_PTEX_BIT) {
setup_tab[IND].vertex_format = TDFX_LAYOUT_PROJECT;
setup_tab[IND].vertex_size = 12;
setup_tab[IND].vertex_stride_shift = 6;
} else {
setup_tab[IND].vertex_format = TDFX_LAYOUT_SINGLE;
setup_tab[IND].vertex_size = 8;
setup_tab[IND].vertex_stride_shift = 5;
}
}
else if (IND & TDFX_W_BIT) {
setup_tab[IND].vertex_format = TDFX_LAYOUT_NOTEX;
setup_tab[IND].vertex_size = 6;
setup_tab[IND].vertex_stride_shift = 5;
} else {
setup_tab[IND].vertex_format = TDFX_LAYOUT_TINY;
setup_tab[IND].vertex_size = 4;
setup_tab[IND].vertex_stride_shift = 4;
}
#endif
}


#undef IND
#undef TAG

Loading…
Cancel
Save