diff options
Diffstat (limited to 'xc/lib/GL/mesa/src/drv/radeon')
35 files changed, 11515 insertions, 2078 deletions
diff --git a/xc/lib/GL/mesa/src/drv/radeon/Imakefile b/xc/lib/GL/mesa/src/drv/radeon/Imakefile index 2a0922ccf..7cb34f1c3 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/Imakefile +++ b/xc/lib/GL/mesa/src/drv/radeon/Imakefile @@ -1,4 +1,4 @@ -XCOMM $XFree86: xc/lib/GL/mesa/src/drv/radeon/Imakefile,v 1.9 2002/02/23 00:45:50 dawes Exp $ +XCOMM $XFree86: xc/lib/GL/mesa/src/drv/radeon/Imakefile,v 1.11 2002/11/25 14:04:51 eich Exp $ #include <Threads.tmpl> @@ -25,7 +25,7 @@ XCOMM $XFree86: xc/lib/GL/mesa/src/drv/radeon/Imakefile,v 1.9 2002/02/23 00:45:5 #include "../../tnl/Imakefile.inc" #include "../../tnl_dd/Imakefile.inc" #include "../../Imakefile.inc" -#ifdef i386Architecture +#if defined(i386Architecture) && MesaUseX86Asm #include "../../X86/Imakefile.inc" #endif #ifdef SparcArchitecture @@ -40,8 +40,7 @@ XCOMM $XFree86: xc/lib/GL/mesa/src/drv/radeon/Imakefile,v 1.9 2002/02/23 00:45:5 DRMOBJS = $(GLXLIBSRC)/dri/drm/xf86drm.o \ $(GLXLIBSRC)/dri/drm/xf86drmHash.o \ $(GLXLIBSRC)/dri/drm/xf86drmRandom.o \ - $(GLXLIBSRC)/dri/drm/xf86drmSL.o \ - $(GLXLIBSRC)/dri/drm/xf86drmRadeon.o + $(GLXLIBSRC)/dri/drm/xf86drmSL.o #ifdef GlxSoProf LOSRCS = ../../../../lowpc.c @@ -55,7 +54,7 @@ XCOMM $XFree86: xc/lib/GL/mesa/src/drv/radeon/Imakefile,v 1.9 2002/02/23 00:45:5 OBJS = $(LOOBJS) $(DRIOBJS) $(DRMOBJS) $(COREMESAOBJS) \ $(MESA_ASM_OBJS) $(COMMONOBJS) $(RADEONOBJS) $(HIOBJS) -REQUIREDLIBS = MathLibrary $(LDPRELIB) $(GLXLIB) +REQUIREDLIBS = MathLibrary $(LDPRELIB) $(GLXLIB) $(XONLYLIB) #include <Library.tmpl> diff --git a/xc/lib/GL/mesa/src/drv/radeon/Imakefile.inc b/xc/lib/GL/mesa/src/drv/radeon/Imakefile.inc index e564cf074..175a3e3bf 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/Imakefile.inc +++ b/xc/lib/GL/mesa/src/drv/radeon/Imakefile.inc @@ -1,4 +1,4 @@ -XCOMM $XFree86: xc/lib/GL/mesa/src/drv/radeon/Imakefile.inc,v 1.3 2002/02/22 21:45:00 dawes Exp $ +XCOMM $XFree86: xc/lib/GL/mesa/src/drv/radeon/Imakefile.inc,v 1.4 2002/10/30 12:51:54 alanh Exp $ #ifndef MesaDrvSrcDir #define MesaDrvSrcDir $(GLXLIBSRC)/mesa/src/drv @@ -26,7 +26,8 @@ ALLOC_DEFINES = -DMALLOC_0_RETURNS_NULL -I$(XF86DRIVERSRC)/ati \ -I$(XF86COMSRC) \ -I$(GLXLIBSRC)/dri/drm \ - -I$(GLXLIBSRC)/include + -I$(GLXLIBSRC)/include \ + -I$(XTOP)/include #endif MESA_INCLUDES = -I$(MESASRCDIR)/src \ @@ -35,81 +36,141 @@ MESA_INCLUDES = -I$(MESASRCDIR)/src \ X_INCLUDES = -I$(XINCLUDESRC) -I$(EXTINCSRC) RADEONSRCS = $(MESADRVRADEONBUILDDIR)radeon_context.c \ + $(MESADRVRADEONBUILDDIR)radeon_compat.c \ $(MESADRVRADEONBUILDDIR)radeon_ioctl.c \ $(MESADRVRADEONBUILDDIR)radeon_lock.c \ - $(MESADRVRADEONBUILDDIR)radeon_render.c \ + $(MESADRVRADEONBUILDDIR)radeon_maos.c \ + $(MESADRVRADEONBUILDDIR)radeon_sanity.c \ $(MESADRVRADEONBUILDDIR)radeon_screen.c \ $(MESADRVRADEONBUILDDIR)radeon_span.c \ $(MESADRVRADEONBUILDDIR)radeon_state.c \ + $(MESADRVRADEONBUILDDIR)radeon_state_init.c \ + $(MESADRVRADEONBUILDDIR)radeon_swtcl.c \ + $(MESADRVRADEONBUILDDIR)radeon_tcl.c \ $(MESADRVRADEONBUILDDIR)radeon_tex.c \ $(MESADRVRADEONBUILDDIR)radeon_texmem.c \ $(MESADRVRADEONBUILDDIR)radeon_texstate.c \ - $(MESADRVRADEONBUILDDIR)radeon_tris.c \ - $(MESADRVRADEONBUILDDIR)radeon_vb.c + $(MESADRVRADEONBUILDDIR)radeon_vtxfmt.c \ + $(MESADRVRADEONBUILDDIR)radeon_vtxfmt_x86.c \ + $(MESADRVRADEONBUILDDIR)radeon_vtxtmp_x86.S \ + $(MESADRVRADEONBUILDDIR)radeon_vtxfmt_sse.c \ + $(MESADRVRADEONBUILDDIR)radeon_vtxfmt_c.c RADEONOBJS = $(MESADRVRADEONBUILDDIR)radeon_context.o \ + $(MESADRVRADEONBUILDDIR)radeon_compat.o \ $(MESADRVRADEONBUILDDIR)radeon_ioctl.o \ $(MESADRVRADEONBUILDDIR)radeon_lock.o \ - $(MESADRVRADEONBUILDDIR)radeon_render.o \ + $(MESADRVRADEONBUILDDIR)radeon_maos.o \ + $(MESADRVRADEONBUILDDIR)radeon_sanity.o \ $(MESADRVRADEONBUILDDIR)radeon_screen.o \ $(MESADRVRADEONBUILDDIR)radeon_span.o \ $(MESADRVRADEONBUILDDIR)radeon_state.o \ + $(MESADRVRADEONBUILDDIR)radeon_state_init.o \ + $(MESADRVRADEONBUILDDIR)radeon_swtcl.o \ + $(MESADRVRADEONBUILDDIR)radeon_tcl.o \ $(MESADRVRADEONBUILDDIR)radeon_tex.o \ $(MESADRVRADEONBUILDDIR)radeon_texmem.o \ $(MESADRVRADEONBUILDDIR)radeon_texstate.o \ - $(MESADRVRADEONBUILDDIR)radeon_tris.o \ - $(MESADRVRADEONBUILDDIR)radeon_vb.o + $(MESADRVRADEONBUILDDIR)radeon_vtxfmt.o \ + $(MESADRVRADEONBUILDDIR)radeon_vtxfmt_c.o + +#ifdef i386Architecture + RADEONOBJS += $(MESADRVRADEONBUILDDIR)radeon_vtxfmt_x86.o \ + $(MESADRVRADEONBUILDDIR)radeon_vtxtmp_x86.o \ + $(MESADRVRADEONBUILDDIR)radeon_vtxfmt_sse.o +#endif RADEONUOBJS = $(MESADRVRADEONBUILDDIR)unshared/radeon_context.o \ + $(MESADRVRADEONBUILDDIR)unshared/radeon_compat.o \ $(MESADRVRADEONBUILDDIR)unshared/radeon_ioctl.o \ $(MESADRVRADEONBUILDDIR)unshared/radeon_lock.o \ - $(MESADRVRADEONBUILDDIR)unshared/radeon_render.o \ + $(MESADRVRADEONBUILDDIR)unshared/radeon_maos.o \ + $(MESADRVRADEONBUILDDIR)unshared/radeon_sanity.o \ $(MESADRVRADEONBUILDDIR)unshared/radeon_screen.o \ $(MESADRVRADEONBUILDDIR)unshared/radeon_span.o \ $(MESADRVRADEONBUILDDIR)unshared/radeon_state.o \ + $(MESADRVRADEONBUILDDIR)unshared/radeon_state_init.o \ + $(MESADRVRADEONBUILDDIR)unshared/radeon_swtcl.o \ + $(MESADRVRADEONBUILDDIR)unshared/radeon_tcl.o \ $(MESADRVRADEONBUILDDIR)unshared/radeon_tex.o \ $(MESADRVRADEONBUILDDIR)unshared/radeon_texmem.o \ $(MESADRVRADEONBUILDDIR)unshared/radeon_texstate.o \ - $(MESADRVRADEONBUILDDIR)unshared/radeon_tris.o \ - $(MESADRVRADEONBUILDDIR)unshared/radeon_vb.o + $(MESADRVRADEONBUILDDIR)unshared/radeon_vtxfmt.o \ + $(MESADRVRADEONBUILDDIR)unshared/radeon_vtxfmt_c.o + +#ifdef i386Architecture + RADEONUOBJS += $(MESADRVRADEONBUILDDIR)unshared/radeon_vtxfmt_x86.o \ + $(MESADRVRADEONBUILDDIR)unshared/radeon_vtxtmp_x86.o \ + $(MESADRVRADEONBUILDDIR)unshared/radeon_vtxfmt_sse.o +#endif RADEONDOBJS = $(MESADRVRADEONBUILDDIR)debugger/radeon_context.o \ + $(MESADRVRADEONBUILDDIR)debugger/radeon_compat.o \ $(MESADRVRADEONBUILDDIR)debugger/radeon_ioctl.o \ $(MESADRVRADEONBUILDDIR)debugger/radeon_lock.o \ - $(MESADRVRADEONBUILDDIR)debugger/radeon_render.o \ + $(MESADRVRADEONBUILDDIR)debugger/radeon_maos.o \ + $(MESADRVRADEONBUILDDIR)debugger/radeon_sanity.o \ $(MESADRVRADEONBUILDDIR)debugger/radeon_screen.o \ $(MESADRVRADEONBUILDDIR)debugger/radeon_span.o \ $(MESADRVRADEONBUILDDIR)debugger/radeon_state.o \ + $(MESADRVRADEONBUILDDIR)debugger/radeon_state_init.o \ + $(MESADRVRADEONBUILDDIR)debugger/radeon_swtcl.o \ + $(MESADRVRADEONBUILDDIR)debugger/radeon_tcl.o \ $(MESADRVRADEONBUILDDIR)debugger/radeon_tex.o \ $(MESADRVRADEONBUILDDIR)debugger/radeon_texmem.o \ $(MESADRVRADEONBUILDDIR)debugger/radeon_texstate.o \ - $(MESADRVRADEONBUILDDIR)debugger/radeon_tris.o \ - $(MESADRVRADEONBUILDDIR)debugger/radeon_vb.o + $(MESADRVRADEONBUILDDIR)debugger/radeon_vtxfmt.o \ + $(MESADRVRADEONBUILDDIR)debugger/radeon_vtxfmt_c.o + +#ifdef i386Architecture + RADEONDOBJS += $(MESADRVRADEONBUILDDIR)debugger/radeon_vtxfmt_x86.o \ + $(MESADRVRADEONBUILDDIR)debugger/radeon_vtxtmp_x86.o \ + $(MESADRVRADEONBUILDDIR)debugger/radeon_vtxfmt_sse.o +#endif RADEONPOBJS = $(MESADRVRADEONBUILDDIR)profiled/radeon_context.o \ + $(MESADRVRADEONBUILDDIR)profiled/radeon_compat.o \ $(MESADRVRADEONBUILDDIR)profiled/radeon_ioctl.o \ $(MESADRVRADEONBUILDDIR)profiled/radeon_lock.o \ - $(MESADRVRADEONBUILDDIR)profiled/radeon_render.o \ + $(MESADRVRADEONBUILDDIR)profiled/radeon_maos.o \ + $(MESADRVRADEONBUILDDIR)profiled/radeon_sanity.o \ $(MESADRVRADEONBUILDDIR)profiled/radeon_screen.o \ $(MESADRVRADEONBUILDDIR)profiled/radeon_span.o \ $(MESADRVRADEONBUILDDIR)profiled/radeon_state.o \ + $(MESADRVRADEONBUILDDIR)profiled/radeon_state_init.o \ + $(MESADRVRADEONBUILDDIR)profiled/radeon_swtcl.o \ + $(MESADRVRADEONBUILDDIR)profiled/radeon_tcl.o \ $(MESADRVRADEONBUILDDIR)profiled/radeon_tex.o \ $(MESADRVRADEONBUILDDIR)profiled/radeon_texmem.o \ $(MESADRVRADEONBUILDDIR)profiled/radeon_texstate.o \ - $(MESADRVRADEONBUILDDIR)profiled/radeon_tris.o \ - $(MESADRVRADEONBUILDDIR)profiled/radeon_vb.o + $(MESADRVRADEONBUILDDIR)profiled/radeon_vtxfmt.o \ + $(MESADRVRADEONBUILDDIR)profiled/radeon_vtxfmt_c.o + +#ifdef i386Architecture + RADEONPOBJS += $(MESADRVRADEONBUILDDIR)profiled/radeon_vtxfmt_x86.o \ + $(MESADRVRADEONBUILDDIR)profiled/radeon_vtxtmp_x86.o \ + $(MESADRVRADEONBUILDDIR)profiled/radeon_vtxfmt_sse.o +#endif #ifdef NeedToLinkMesaSrc LinkSourceFile(radeon_context.c, $(MESADRVSRCDIR)/radeon) +LinkSourceFile(radeon_compat.c, $(MESADRVSRCDIR)/radeon) LinkSourceFile(radeon_ioctl.c, $(MESADRVSRCDIR)/radeon) LinkSourceFile(radeon_lock.c, $(MESADRVSRCDIR)/radeon) -LinkSourceFile(radeon_render.c, $(MESADRVSRCDIR)/radeon) +LinkSourceFile(radeon_maos.c, $(MESADRVSRCDIR)/radeon) +LinkSourceFile(radeon_sanity.c, $(MESADRVSRCDIR)/radeon) LinkSourceFile(radeon_screen.c, $(MESADRVSRCDIR)/radeon) LinkSourceFile(radeon_span.c, $(MESADRVSRCDIR)/radeon) LinkSourceFile(radeon_state.c, $(MESADRVSRCDIR)/radeon) +LinkSourceFile(radeon_state_init.c, $(MESADRVSRCDIR)/radeon) +LinkSourceFile(radeon_swtcl.c, $(MESADRVSRCDIR)/radeon) +LinkSourceFile(radeon_tcl.c, $(MESADRVSRCDIR)/radeon) LinkSourceFile(radeon_tex.c, $(MESADRVSRCDIR)/radeon) LinkSourceFile(radeon_texmem.c, $(MESADRVSRCDIR)/radeon) LinkSourceFile(radeon_texstate.c, $(MESADRVSRCDIR)/radeon) -LinkSourceFile(radeon_tris.c, $(MESADRVSRCDIR)/radeon) -LinkSourceFile(radeon_vb.c, $(MESADRVSRCDIR)/radeon) +LinkSourceFile(radeon_vtxfmt.c, $(MESADRVSRCDIR)/radeon) +LinkSourceFile(radeon_vtxfmt_c.c, $(MESADRVSRCDIR)/radeon) +LinkSourceFile(radeon_vtxfmt_x86.c, $(MESADRVSRCDIR)/radeon) +LinkSourceFile(radeon_vtxtmp_x86.S, $(MESADRVSRCDIR)/radeon) +LinkSourceFile(radeon_vtxfmt_sse.c, $(MESADRVSRCDIR)/radeon) #endif diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_compat.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_compat.c new file mode 100644 index 000000000..5737c4d85 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_compat.c @@ -0,0 +1,301 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_compat.c,v 1.1 2002/10/30 12:51:54 alanh Exp $ */ +/************************************************************************** + +Copyright 2002 ATI Technologies Inc., Ontario, Canada, and + Tungsten Graphics Inc., Austin, Texas. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * + */ + +#include "radeon_context.h" +#include "radeon_state.h" +#include "radeon_ioctl.h" +#include "mem.h" + +static struct { + int start; + int len; + const char *name; +} packet[RADEON_MAX_STATE_PACKETS] = { + { RADEON_PP_MISC,7,"RADEON_PP_MISC" }, + { RADEON_PP_CNTL,3,"RADEON_PP_CNTL" }, + { RADEON_RB3D_COLORPITCH,1,"RADEON_RB3D_COLORPITCH" }, + { RADEON_RE_LINE_PATTERN,2,"RADEON_RE_LINE_PATTERN" }, + { RADEON_SE_LINE_WIDTH,1,"RADEON_SE_LINE_WIDTH" }, + { RADEON_PP_LUM_MATRIX,1,"RADEON_PP_LUM_MATRIX" }, + { RADEON_PP_ROT_MATRIX_0,2,"RADEON_PP_ROT_MATRIX_0" }, + { RADEON_RB3D_STENCILREFMASK,3,"RADEON_RB3D_STENCILREFMASK" }, + { RADEON_SE_VPORT_XSCALE,6,"RADEON_SE_VPORT_XSCALE" }, + { RADEON_SE_CNTL,2,"RADEON_SE_CNTL" }, + { RADEON_SE_CNTL_STATUS,1,"RADEON_SE_CNTL_STATUS" }, + { RADEON_RE_MISC,1,"RADEON_RE_MISC" }, + { RADEON_PP_TXFILTER_0,6,"RADEON_PP_TXFILTER_0" }, + { RADEON_PP_BORDER_COLOR_0,1,"RADEON_PP_BORDER_COLOR_0" }, + { RADEON_PP_TXFILTER_1,6,"RADEON_PP_TXFILTER_1" }, + { RADEON_PP_BORDER_COLOR_1,1,"RADEON_PP_BORDER_COLOR_1" }, + { RADEON_PP_TXFILTER_2,6,"RADEON_PP_TXFILTER_2" }, + { RADEON_PP_BORDER_COLOR_2,1,"RADEON_PP_BORDER_COLOR_2" }, + { RADEON_SE_ZBIAS_FACTOR,2,"RADEON_SE_ZBIAS_FACTOR" }, + { RADEON_SE_TCL_OUTPUT_VTX_FMT,11,"RADEON_SE_TCL_OUTPUT_VTX_FMT" }, + { RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED,17,"RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED" }, +}; + + +static void radeonCompatEmitPacket( radeonContextPtr rmesa, + struct radeon_state_atom *state ) +{ + RADEONSAREAPrivPtr sarea = rmesa->sarea; + radeon_context_regs_t *ctx = &sarea->ContextState; + radeon_texture_regs_t *tex0 = &sarea->TexState[0]; + radeon_texture_regs_t *tex1 = &sarea->TexState[1]; + int i; + int *buf = state->cmd; + + for ( i = 0 ; i < state->cmd_size ; ) { + drmRadeonCmdHeader *header = (drmRadeonCmdHeader *)&buf[i++]; + + if (RADEON_DEBUG & DEBUG_STATE) + fprintf(stderr, "%s %d: %s\n", __FUNCTION__, header->packet.packet_id, + packet[(int)header->packet.packet_id].name); + + switch (header->packet.packet_id) { + case RADEON_EMIT_PP_MISC: + ctx->pp_misc = buf[i++]; + ctx->pp_fog_color = buf[i++]; + ctx->re_solid_color = buf[i++]; + ctx->rb3d_blendcntl = buf[i++]; + ctx->rb3d_depthoffset = buf[i++]; + ctx->rb3d_depthpitch = buf[i++]; + ctx->rb3d_zstencilcntl = buf[i++]; + sarea->dirty |= RADEON_UPLOAD_CONTEXT; + break; + case RADEON_EMIT_PP_CNTL: + ctx->pp_cntl = buf[i++]; + ctx->rb3d_cntl = buf[i++]; + ctx->rb3d_coloroffset = buf[i++]; + sarea->dirty |= RADEON_UPLOAD_CONTEXT; + break; + case RADEON_EMIT_RB3D_COLORPITCH: + ctx->rb3d_colorpitch = buf[i++]; + sarea->dirty |= RADEON_UPLOAD_CONTEXT; + break; + case RADEON_EMIT_RE_LINE_PATTERN: + ctx->re_line_pattern = buf[i++]; + ctx->re_line_state = buf[i++]; + sarea->dirty |= RADEON_UPLOAD_LINE; + break; + case RADEON_EMIT_SE_LINE_WIDTH: + ctx->se_line_width = buf[i++]; + sarea->dirty |= RADEON_UPLOAD_LINE; + break; + case RADEON_EMIT_PP_LUM_MATRIX: + ctx->pp_lum_matrix = buf[i++]; + sarea->dirty |= RADEON_UPLOAD_BUMPMAP; + break; + case RADEON_EMIT_PP_ROT_MATRIX_0: + ctx->pp_rot_matrix_0 = buf[i++]; + ctx->pp_rot_matrix_1 = buf[i++]; + sarea->dirty |= RADEON_UPLOAD_BUMPMAP; + break; + case RADEON_EMIT_RB3D_STENCILREFMASK: + ctx->rb3d_stencilrefmask = buf[i++]; + ctx->rb3d_ropcntl = buf[i++]; + ctx->rb3d_planemask = buf[i++]; + sarea->dirty |= RADEON_UPLOAD_MASKS; + break; + case RADEON_EMIT_SE_VPORT_XSCALE: + ctx->se_vport_xscale = buf[i++]; + ctx->se_vport_xoffset = buf[i++]; + ctx->se_vport_yscale = buf[i++]; + ctx->se_vport_yoffset = buf[i++]; + ctx->se_vport_zscale = buf[i++]; + ctx->se_vport_zoffset = buf[i++]; + sarea->dirty |= RADEON_UPLOAD_VIEWPORT; + break; + case RADEON_EMIT_SE_CNTL: + ctx->se_cntl = buf[i++]; + ctx->se_coord_fmt = buf[i++]; + sarea->dirty |= RADEON_UPLOAD_CONTEXT | RADEON_UPLOAD_VERTFMT; + break; + case RADEON_EMIT_SE_CNTL_STATUS: + ctx->se_cntl_status = buf[i++]; + sarea->dirty |= RADEON_UPLOAD_SETUP; + break; + case RADEON_EMIT_RE_MISC: + ctx->re_misc = buf[i++]; + sarea->dirty |= RADEON_UPLOAD_MISC; + break; + case RADEON_EMIT_PP_TXFILTER_0: + tex0->pp_txfilter = buf[i++]; + tex0->pp_txformat = buf[i++]; + tex0->pp_txoffset = buf[i++]; + tex0->pp_txcblend = buf[i++]; + tex0->pp_txablend = buf[i++]; + tex0->pp_tfactor = buf[i++]; + sarea->dirty |= RADEON_UPLOAD_TEX0; + break; + case RADEON_EMIT_PP_BORDER_COLOR_0: + tex0->pp_border_color = buf[i++]; + sarea->dirty |= RADEON_UPLOAD_TEX0; + break; + case RADEON_EMIT_PP_TXFILTER_1: + tex1->pp_txfilter = buf[i++]; + tex1->pp_txformat = buf[i++]; + tex1->pp_txoffset = buf[i++]; + tex1->pp_txcblend = buf[i++]; + tex1->pp_txablend = buf[i++]; + tex1->pp_tfactor = buf[i++]; + sarea->dirty |= RADEON_UPLOAD_TEX1; + break; + case RADEON_EMIT_PP_BORDER_COLOR_1: + tex1->pp_border_color = buf[i++]; + sarea->dirty |= RADEON_UPLOAD_TEX1; + break; + + case RADEON_EMIT_SE_ZBIAS_FACTOR: + i++; + i++; + break; + + case RADEON_EMIT_PP_TXFILTER_2: + case RADEON_EMIT_PP_BORDER_COLOR_2: + case RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT: + case RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED: + default: + /* These states aren't understood by radeon drm 1.1 */ + fprintf(stderr, "Tried to emit unsupported state\n"); + return; + } + } +} + + + +static void radeonCompatEmitStateLocked( radeonContextPtr rmesa ) +{ + struct radeon_state_atom *state, *tmp; + + if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS)) + fprintf(stderr, "%s\n", __FUNCTION__); + + if (rmesa->lost_context) { + if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS|DEBUG_IOCTL)) + fprintf(stderr, "%s - lost context\n", __FUNCTION__); + + foreach_s( state, tmp, &(rmesa->hw.clean) ) + move_to_tail(&(rmesa->hw.dirty), state ); + + rmesa->lost_context = 0; + } + + foreach_s( state, tmp, &(rmesa->hw.dirty) ) { + if (!state->is_tcl) + radeonCompatEmitPacket( rmesa, state ); + move_to_head( &(rmesa->hw.clean), state ); + } +} + + + +static void radeonCompatEmitPrimitiveLocked( radeonContextPtr rmesa, + GLuint hw_primitive, + GLuint nverts, + XF86DRIClipRectPtr pbox, + GLuint nbox ) +{ + int i; + + for ( i = 0 ; i < nbox ; ) { + int nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, nbox ); + XF86DRIClipRectPtr b = rmesa->sarea->boxes; + drmRadeonVertex vtx; + + rmesa->sarea->dirty |= RADEON_UPLOAD_CLIPRECTS; + rmesa->sarea->nbox = nr - i; + + for ( ; i < nr ; i++) + *b++ = pbox[i]; + + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, + "RadeonFlushVertexBuffer: prim %x buf %d verts %d " + "disc %d nbox %d\n", + hw_primitive, + rmesa->dma.current.buf->buf->idx, + nverts, + nr == nbox, + rmesa->sarea->nbox ); + + vtx.prim = hw_primitive; + vtx.idx = rmesa->dma.current.buf->buf->idx; + vtx.count = nverts; + vtx.discard = (nr == nbox); + + drmCommandWrite( rmesa->dri.fd, + DRM_RADEON_VERTEX, + &vtx, sizeof(vtx)); + } +} + + + +/* No 'start' for 1.1 vertices ioctl: only one vertex prim/buffer! + */ +void radeonCompatEmitPrimitive( radeonContextPtr rmesa, + GLuint vertex_format, + GLuint hw_primitive, + GLuint nrverts ) +{ + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s\n", __FUNCTION__); + + LOCK_HARDWARE( rmesa ); + + radeonCompatEmitStateLocked( rmesa ); + rmesa->sarea->vc_format = vertex_format; + + if (rmesa->state.scissor.enabled) { + radeonCompatEmitPrimitiveLocked( rmesa, + hw_primitive, + nrverts, + rmesa->state.scissor.pClipRects, + rmesa->state.scissor.numClipRects ); + } + else { + radeonCompatEmitPrimitiveLocked( rmesa, + hw_primitive, + nrverts, + rmesa->pClipRects, + rmesa->numClipRects ); + } + + + UNLOCK_HARDWARE( rmesa ); +} + diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_context.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_context.c index 690e30af4..15e62e161 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_context.c +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_context.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_context.c,v 1.4 2002/09/10 00:39:39 dawes Exp $ */ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_context.c,v 1.7 2003/02/08 21:26:45 dawes Exp $ */ /************************************************************************** Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and @@ -31,18 +31,20 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. * Authors: * Kevin E. Martin <martin@valinux.com> * Gareth Hughes <gareth@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> * */ -#include <stdlib.h> #include "radeon_context.h" #include "radeon_ioctl.h" #include "radeon_state.h" #include "radeon_span.h" #include "radeon_tex.h" -#include "radeon_tris.h" -#include "radeon_vb.h" +#include "radeon_swtcl.h" +#include "radeon_tcl.h" +#include "radeon_vtxfmt.h" +#include "radeon_maos.h" #include "swrast/swrast.h" #include "swrast_setup/swrast_setup.h" @@ -51,6 +53,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "tnl/tnl.h" #include "tnl/t_pipeline.h" +#include "api_arrayelt.h" #include "context.h" #include "simple_list.h" #include "mem.h" @@ -60,27 +63,18 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "X86/common_x86_asm.h" #endif -#define RADEON_DATE "20020221" +#define RADEON_DATE "20020611" #ifndef RADEON_DEBUG -int RADEON_DEBUG = (0 -/* | DEBUG_ALWAYS_SYNC */ -/* | DEBUG_VERBOSE_API */ -/* | DEBUG_VERBOSE_MSG */ -/* | DEBUG_VERBOSE_LRU */ -/* | DEBUG_VERBOSE_DRI */ -/* | DEBUG_VERBOSE_IOCTL */ -/* | DEBUG_VERBOSE_2D */ -/* | DEBUG_VERBOSE_TEXTURE */ - ); +int RADEON_DEBUG = (0); #endif -/* Return the width and height of the current color buffer. +/* Return the width and height of the given buffer. */ static void radeonGetBufferSize( GLframebuffer *buffer, - GLuint *width, GLuint *height ) + GLuint *width, GLuint *height ) { GET_CURRENT_CONTEXT(ctx); radeonContextPtr rmesa = RADEON_CONTEXT(ctx); @@ -100,10 +94,10 @@ static const GLubyte *radeonGetString( GLcontext *ctx, GLenum name ) switch ( name ) { case GL_VENDOR: - return (GLubyte *)"VA Linux Systems, Inc."; + return (GLubyte *)"Tungsten Graphics, Inc."; case GL_RENDERER: - sprintf( buffer, "Mesa DRI Radeon " RADEON_DATE ); + sprintf( buffer, "Mesa DRI Radeon " RADEON_DATE); /* Append any chipset-specific information. None yet. */ @@ -144,6 +138,18 @@ static const GLubyte *radeonGetString( GLcontext *ctx, GLenum name ) } #endif #endif + + if ( rmesa->dri.drmMinor < 3 ) { + strncat( buffer, " DRM-COMPAT", 11 ); + } + + if ( !(rmesa->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE) ) { + strncat( buffer, " TCL", 4 ); + } + else { + strncat( buffer, " NO-TCL", 7 ); + } + return (GLubyte *)buffer; default: @@ -151,76 +157,80 @@ static const GLubyte *radeonGetString( GLcontext *ctx, GLenum name ) } } -/* Send all commands to the hardware. If vertex buffers or indirect - * buffers are in use, then we need to make sure they are sent to the - * hardware. All commands that are normally sent to the ring are - * already considered `flushed'. - */ -static void radeonFlush( GLcontext *ctx ) -{ - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - RADEON_FIREVERTICES( rmesa ); - - if ( rmesa->boxes ) { - LOCK_HARDWARE( rmesa ); - radeonPerformanceBoxesLocked( rmesa ); - UNLOCK_HARDWARE( rmesa ); - } - - /* Log the performance counters if necessary */ - radeonPerformanceCounters( rmesa ); -} - -/* Make sure all commands have been sent to the hardware and have - * completed processing. +/* Extension strings exported by the R100 driver. */ -static void radeonFinish( GLcontext *ctx ) +static const char * const radeon_extensions[] = { - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - - /* Bump the performance counter */ - rmesa->c_drawWaits++; - radeonFlush( ctx ); - LOCK_HARDWARE( rmesa ); - radeonWaitForIdleLocked( rmesa ); - UNLOCK_HARDWARE( rmesa ); -} - + "GL_ARB_multisample", + "GL_ARB_multitexture", + "GL_ARB_texture_border_clamp", + "GL_ARB_texture_compression", + "GL_ARB_texture_env_add", + "GL_ARB_texture_env_combine", + "GL_ARB_texture_env_dot3", + "GL_ARB_texture_mirrored_repeat", + "GL_EXT_blend_logic_op", + "GL_EXT_blend_subtract", +/* "GL_EXT_fog_coord", */ + "GL_EXT_secondary_color", + "GL_EXT_texture_env_add", + "GL_EXT_texture_env_combine", + "GL_EXT_texture_env_dot3", + "GL_EXT_texture_filter_anisotropic", + "GL_EXT_texture_lod_bias", + "GL_ATI_texture_mirror_once", + "GL_IBM_texture_mirrored_repeat", + "GL_NV_blend_square", + "GL_SGIS_generate_mipmap", + "GL_SGIS_texture_border_clamp", + NULL +}; /* Initialize the extensions supported by this driver. */ static void radeonInitExtensions( GLcontext *ctx ) { + unsigned i; _mesa_enable_imaging_extensions( ctx ); - _mesa_enable_extension( ctx, "GL_ARB_multitexture" ); - _mesa_enable_extension( ctx, "GL_ARB_texture_env_add" ); - - _mesa_enable_extension( ctx, "GL_EXT_blend_logic_op" ); - _mesa_enable_extension( ctx, "GL_EXT_texture_env_add" ); - _mesa_enable_extension( ctx, "GL_EXT_texture_env_combine" ); - _mesa_enable_extension( ctx, "GL_EXT_texture_env_dot3" ); - _mesa_enable_extension( ctx, "GL_EXT_texture_filter_anisotropic" ); - _mesa_enable_extension( ctx, "GL_EXT_texture_lod_bias" ); - + for ( i = 0 ; radeon_extensions[i] != NULL ; i++ ) { + _mesa_enable_extension( ctx, radeon_extensions[i] ); + } } extern const struct gl_pipeline_stage _radeon_render_stage; -extern const struct gl_pipeline_stage _radeon_tcl_render_stage; +extern const struct gl_pipeline_stage _radeon_tcl_stage; static const struct gl_pipeline_stage *radeon_pipeline[] = { + + /* Try and go straight to t&l + */ + &_radeon_tcl_stage, + + /* Catch any t&l fallbacks + */ &_tnl_vertex_transform_stage, &_tnl_normal_transform_stage, &_tnl_lighting_stage, &_tnl_fog_coordinate_stage, &_tnl_texgen_stage, &_tnl_texture_transform_stage, - /* REMOVE: point attenuation stage */ -#if 1 - &_radeon_render_stage, /* ADD: unclipped rastersetup-to-dma */ -#endif - &_tnl_render_stage, + + /* Try again to go to tcl? + * - no good for asymmetric-twoside (do with multipass) + * - no good for asymmetric-unfilled (do with multipass) + * - good for material + * - good for texgen + * - need to manipulate a bit of state + * + * - worth it/not worth it? + */ + + /* Else do them here. + */ + &_radeon_render_stage, + &_tnl_render_stage, /* FALLBACK: */ 0, }; @@ -231,9 +241,8 @@ static const struct gl_pipeline_stage *radeon_pipeline[] = { static void radeonInitDriverFuncs( GLcontext *ctx ) { ctx->Driver.GetBufferSize = radeonGetBufferSize; + ctx->Driver.ResizeBuffers = _swrast_alloc_buffers; ctx->Driver.GetString = radeonGetString; - ctx->Driver.Finish = radeonFinish; - ctx->Driver.Flush = radeonFlush; ctx->Driver.Error = NULL; ctx->Driver.DrawPixels = NULL; @@ -286,11 +295,20 @@ radeonCreateContext( Display *dpy, const __GLcontextModes *glVisual, rmesa->dri.hwLock = &sPriv->pSAREA->lock; rmesa->dri.fd = sPriv->fd; + /* If we don't have 1.3, fallback to the 1.1 interfaces. + */ + if (getenv("RADEON_COMPAT") || sPriv->drmMinor < 3 ) + rmesa->dri.drmMinor = 1; + else + rmesa->dri.drmMinor = sPriv->drmMinor; + rmesa->radeonScreen = radeonScreen; rmesa->sarea = (RADEONSAREAPrivPtr)((GLubyte *)sPriv->pSAREA + radeonScreen->sarea_priv_offset); + rmesa->dma.buf0_address = rmesa->radeonScreen->buffers->list[0].address; + for ( i = 0 ; i < radeonScreen->numTexHeaps ; i++ ) { make_empty_list( &rmesa->texture.objects[i] ); rmesa->texture.heap[i] = mmInit( 0, radeonScreen->texSize[i] ); @@ -299,9 +317,8 @@ radeonCreateContext( Display *dpy, const __GLcontextModes *glVisual, rmesa->texture.numHeaps = radeonScreen->numTexHeaps; make_empty_list( &rmesa->texture.swapped ); - rmesa->RenderIndex = ~0; - rmesa->state.hw.dirty = RADEON_UPLOAD_CONTEXT_ALL; - rmesa->upload_cliprects = 1; + rmesa->swtcl.RenderIndex = ~0; + rmesa->lost_context = 1; /* KW: Set the maximum texture size small enough that we can * guarentee that both texture units can bind a maximal texture @@ -338,17 +355,20 @@ radeonCreateContext( Display *dpy, const __GLcontextModes *glVisual, ctx->Const.MaxLineWidthAA = 10.0; ctx->Const.LineWidthGranularity = 0.0625; + /* Set maxlocksize (and hence vb size) small enough to avoid + * fallbacks in radeon_tcl.c. ie. guarentee that all vertices can + * fit in a single dma buffer for indexed rendering of quad strips, + * etc. + */ + ctx->Const.MaxArrayLockSize = + MIN2( ctx->Const.MaxArrayLockSize, + RADEON_BUFFER_SIZE / RADEON_MAX_TCL_VERTSIZE ); + if (getenv("LIBGL_PERFORMANCE_BOXES")) rmesa->boxes = 1; else rmesa->boxes = 0; - { - const char *debug = getenv("LIBGL_DEBUG"); - if (debug && strstr(debug, "fallbacks")) { - rmesa->debugFallbacks = GL_TRUE; - } - } /* Initialize the software rasterizer and helper modules. */ @@ -356,29 +376,150 @@ radeonCreateContext( Display *dpy, const __GLcontextModes *glVisual, _ac_CreateContext( ctx ); _tnl_CreateContext( ctx ); _swsetup_CreateContext( ctx ); - + _ae_create_context( ctx ); /* Install the customized pipeline: */ _tnl_destroy_pipeline( ctx ); _tnl_install_pipeline( ctx, radeon_pipeline ); + /* Try and keep materials and vertices separate: + */ + _tnl_isolate_materials( ctx, GL_TRUE ); + + +/* _mesa_allow_light_in_model( ctx, GL_FALSE ); */ + /* Configure swrast to match hardware characteristics: */ _swrast_allow_pixel_fog( ctx, GL_FALSE ); _swrast_allow_vertex_fog( ctx, GL_TRUE ); - radeonInitVB( ctx ); + + _math_matrix_ctr( &rmesa->TexGenMatrix[0] ); + _math_matrix_ctr( &rmesa->TexGenMatrix[1] ); + _math_matrix_ctr( &rmesa->tmpmat ); + _math_matrix_set_identity( &rmesa->TexGenMatrix[0] ); + _math_matrix_set_identity( &rmesa->TexGenMatrix[1] ); + _math_matrix_set_identity( &rmesa->tmpmat ); + radeonInitExtensions( ctx ); radeonInitDriverFuncs( ctx ); radeonInitIoctlFuncs( ctx ); radeonInitStateFuncs( ctx ); radeonInitSpanFuncs( ctx ); radeonInitTextureFuncs( ctx ); - radeonInitTriFuncs( ctx ); - radeonInitState( rmesa ); + radeonInitSwtcl( ctx ); + + rmesa->do_irqs = (rmesa->radeonScreen->irq && !getenv("RADEON_NO_IRQS")); + rmesa->irqsEmitted = 0; + rmesa->iw.irq_seq = -1; + + rmesa->do_usleeps = !getenv("RADEON_NO_USLEEPS"); + +#if DO_DEBUG + if (getenv("RADEON_DEBUG_FALLBACKS")) + RADEON_DEBUG |= DEBUG_FALLBACKS; + + if (getenv("RADEON_DEBUG_TEXTURE")) + RADEON_DEBUG |= DEBUG_TEXTURE; + + if (getenv("RADEON_DEBUG_IOCTL")) + RADEON_DEBUG |= DEBUG_IOCTL; + + if (getenv("RADEON_DEBUG_PRIMS")) + RADEON_DEBUG |= DEBUG_PRIMS; + + if (getenv("RADEON_DEBUG_VERTS")) + RADEON_DEBUG |= DEBUG_VERTS; + + if (getenv("RADEON_DEBUG_STATE")) + RADEON_DEBUG |= DEBUG_STATE; + + if (getenv("RADEON_DEBUG_CODEGEN")) + RADEON_DEBUG |= DEBUG_CODEGEN; + + if (getenv("RADEON_DEBUG_VTXFMT")) + RADEON_DEBUG |= DEBUG_VFMT; + + if (getenv("RADEON_DEBUG_VERBOSE")) + RADEON_DEBUG |= DEBUG_VERBOSE; + + if (getenv("RADEON_DEBUG_DRI")) + RADEON_DEBUG |= DEBUG_DRI; + + if (getenv("RADEON_DEBUG_DMA")) + RADEON_DEBUG |= DEBUG_DMA; + if (getenv("RADEON_DEBUG_SANITY")) + RADEON_DEBUG |= DEBUG_SANITY; + + if (getenv("RADEON_DEBUG")) + { + const char *debug = getenv("RADEON_DEBUG"); + if (strstr(debug, "fall")) + RADEON_DEBUG |= DEBUG_FALLBACKS; + + if (strstr(debug, "tex")) + RADEON_DEBUG |= DEBUG_TEXTURE; + + if (strstr(debug, "ioctl")) + RADEON_DEBUG |= DEBUG_IOCTL; + + if (strstr(debug, "prim")) + RADEON_DEBUG |= DEBUG_PRIMS; + + if (strstr(debug, "vert")) + RADEON_DEBUG |= DEBUG_VERTS; + + if (strstr(debug, "state")) + RADEON_DEBUG |= DEBUG_STATE; + + if (strstr(debug, "code")) + RADEON_DEBUG |= DEBUG_CODEGEN; + + if (strstr(debug, "vfmt") || strstr(debug, "vtxf")) + RADEON_DEBUG |= DEBUG_VFMT; + + if (strstr(debug, "verb")) + RADEON_DEBUG |= DEBUG_VERBOSE; + + if (strstr(debug, "dri")) + RADEON_DEBUG |= DEBUG_DRI; + + if (strstr(debug, "dma")) + RADEON_DEBUG |= DEBUG_DMA; + + if (strstr(debug, "san")) + RADEON_DEBUG |= DEBUG_SANITY; + } + + +#endif + + if (getenv("RADEON_NO_RAST")) { + fprintf(stderr, "disabling 3D acceleration\n"); + FALLBACK(rmesa, RADEON_FALLBACK_DISABLE, 1); + } + else if (getenv("RADEON_TCL_FORCE_ENABLE")) { + fprintf(stderr, "Enabling TCL support... this will probably crash\n"); + fprintf(stderr, " your card if it isn't capable of TCL!\n"); + rmesa->radeonScreen->chipset |= RADEON_CHIPSET_TCL; + } else if (getenv("RADEON_TCL_FORCE_DISABLE") || + rmesa->dri.drmMinor < 3 || + !(rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL)) { + rmesa->radeonScreen->chipset &= ~RADEON_CHIPSET_TCL; + fprintf(stderr, "disabling TCL support\n"); + TCL_FALLBACK(rmesa->glCtx, RADEON_TCL_FALLBACK_TCL_DISABLE, 1); + } + + if (rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL) { + if (!getenv("RADEON_NO_VTXFMT")) + radeonVtxfmtInit( ctx ); + + _tnl_need_dlist_norm_lengths( ctx, GL_FALSE ); + } return GL_TRUE; } @@ -396,6 +537,7 @@ radeonDestroyContext( __DRIcontextPrivate *driContextPriv ) /* check if we're deleting the currently bound context */ if (rmesa == current) { + RADEON_FIREVERTICES( rmesa ); _mesa_make_current2(NULL, NULL, NULL); } @@ -414,6 +556,7 @@ radeonDestroyContext( __DRIcontextPrivate *driContextPriv ) radeonDestroyTexObj( rmesa, t ); } mmDestroy( rmesa->texture.heap[i] ); + rmesa->texture.heap[i] = NULL; } foreach_s ( t, next_t, &rmesa->texture.swapped ) { @@ -426,12 +569,27 @@ radeonDestroyContext( __DRIcontextPrivate *driContextPriv ) _ac_DestroyContext( rmesa->glCtx ); _swrast_DestroyContext( rmesa->glCtx ); - radeonFreeVB( rmesa->glCtx ); + radeonDestroySwtcl( rmesa->glCtx ); + + radeonReleaseArrays( rmesa->glCtx, ~0 ); + if (rmesa->dma.current.buf) { + radeonReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ ); + radeonFlushCmdBuf( rmesa, __FUNCTION__ ); + } + + if (!rmesa->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE) + if (!getenv("RADEON_NO_VTXFMT")) + radeonVtxfmtDestroy( rmesa->glCtx ); /* free the Mesa context */ rmesa->glCtx->DriverCtx = NULL; _mesa_destroy_context( rmesa->glCtx ); + if (rmesa->state.scissor.pClipRects) { + FREE(rmesa->state.scissor.pClipRects); + rmesa->state.scissor.pClipRects = 0; + } + FREE( rmesa ); } @@ -508,6 +666,7 @@ radeonSwapBuffers(Display *dpy, void *drawablePrivate) ctx = rmesa->glCtx; if (ctx->Visual.doubleBufferMode) { _mesa_swapbuffers( ctx ); /* flush pending rendering comands */ + if ( rmesa->doPageFlip ) { radeonPageFlip( dPriv ); } @@ -532,21 +691,14 @@ radeonMakeCurrent( __DRIcontextPrivate *driContextPriv, __DRIdrawablePrivate *driReadPriv ) { if ( driContextPriv ) { - GET_CURRENT_CONTEXT(ctx); - radeonContextPtr oldRadeonCtx = ctx ? RADEON_CONTEXT(ctx) : NULL; - radeonContextPtr newRadeonCtx = (radeonContextPtr) driContextPriv->driverPrivate; - - if ( newRadeonCtx != oldRadeonCtx ) { - newRadeonCtx->state.hw.dirty = RADEON_UPLOAD_CONTEXT_ALL; - if ( newRadeonCtx->state.texture.unit[0].texobj ) - newRadeonCtx->state.hw.dirty |= RADEON_UPLOAD_TEX0; - if ( newRadeonCtx->state.texture.unit[1].texobj ) - newRadeonCtx->state.hw.dirty |= RADEON_UPLOAD_TEX1; - } + radeonContextPtr newRadeonCtx = + (radeonContextPtr) driContextPriv->driverPrivate; + + if (RADEON_DEBUG & DEBUG_DRI) + fprintf(stderr, "%s ctx %p\n", __FUNCTION__, newRadeonCtx->glCtx); if ( newRadeonCtx->dri.drawable != driDrawPriv ) { newRadeonCtx->dri.drawable = driDrawPriv; - newRadeonCtx->upload_cliprects = 1; radeonUpdateWindow( newRadeonCtx->glCtx ); radeonUpdateViewportOffset( newRadeonCtx->glCtx ); } @@ -559,10 +711,18 @@ radeonMakeCurrent( __DRIcontextPrivate *driContextPriv, _mesa_set_viewport( newRadeonCtx->glCtx, 0, 0, driDrawPriv->w, driDrawPriv->h ); } + + if (newRadeonCtx->vb.enabled) + radeonVtxfmtMakeCurrent( newRadeonCtx->glCtx ); + } else { + if (RADEON_DEBUG & DEBUG_DRI) + fprintf(stderr, "%s ctx %p\n", __FUNCTION__, NULL); _mesa_make_current( 0, 0 ); } + if (RADEON_DEBUG & DEBUG_DRI) + fprintf(stderr, "End %s\n", __FUNCTION__); return GL_TRUE; } @@ -571,61 +731,30 @@ radeonMakeCurrent( __DRIcontextPrivate *driContextPriv, static GLboolean radeonUnbindContext( __DRIcontextPrivate *driContextPriv ) { - return GL_TRUE; -} - -/* Initialize the fullscreen mode. - */ -static GLboolean -radeonOpenFullScreen( __DRIcontextPrivate *driContextPriv ) -{ -#if 0 - radeonContextPtr rmesa = (radeonContextPtr)driContextPriv->driverPrivate; - GLint ret; - - /* FIXME: Do we need to check this? - */ - if ( !rmesa->glCtx->Visual.doubleBufferMode ) - return GL_TRUE; - - LOCK_HARDWARE( rmesa ); - radeonWaitForIdleLocked( rmesa ); - - /* Ignore errors. If this fails, we simply don't do page flipping. - */ - ret = drmRadeonFullScreen( rmesa->driFd, GL_TRUE ); + radeonContextPtr rmesa = (radeonContextPtr) driContextPriv->driverPrivate; - UNLOCK_HARDWARE( rmesa ); + if (RADEON_DEBUG & DEBUG_DRI) + fprintf(stderr, "%s ctx %p\n", __FUNCTION__, rmesa->glCtx); - rmesa->doPageFlip = ( ret == 0 ); -#endif + radeonVtxfmtUnbindContext( rmesa->glCtx ); return GL_TRUE; } -/* Shut down the fullscreen mode. +/* Fullscreen mode isn't used for much -- could be a way to shrink + * front/back buffers & get more texture memory if the client has + * changed the video resolution. + * + * Pageflipping is now done automatically whenever there is a single + * 3d client. */ static GLboolean -radeonCloseFullScreen( __DRIcontextPrivate *driContextPriv ) +radeonOpenCloseFullScreen( __DRIcontextPrivate *driContextPriv ) { -#if 0 - radeonContextPtr rmesa = (radeonContextPtr)driContextPriv->driverPrivate; - - LOCK_HARDWARE( rmesa ); - radeonWaitForIdleLocked( rmesa ); - - /* Don't care if this fails, we're not page flipping anymore. - */ - drmRadeonFullScreen( rmesa->driFd, GL_FALSE ); - - UNLOCK_HARDWARE( rmesa ); - - rmesa->doPageFlip = GL_FALSE; - rmesa->currentPage = 0; -#endif return GL_TRUE; } + /* This function is called by libGL.so as soon as libGL.so is loaded. * This is where we'd register new extension functions with the dispatcher. */ @@ -646,8 +775,8 @@ static struct __DriverAPIRec radeonAPI = { radeonSwapBuffers, radeonMakeCurrent, radeonUnbindContext, - radeonOpenFullScreen, - radeonCloseFullScreen + radeonOpenCloseFullScreen, + radeonOpenCloseFullScreen }; diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_context.h b/xc/lib/GL/mesa/src/drv/radeon/radeon_context.h index 736f4c654..051bbbcf5 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_context.h +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_context.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_context.h,v 1.4 2002/09/10 00:39:39 dawes Exp $ */ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_context.h,v 1.6 2002/12/16 16:18:58 dawes Exp $ */ /************************************************************************** Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and @@ -31,7 +31,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. * Authors: * Kevin E. Martin <martin@valinux.com> * Gareth Hughes <gareth@valinux.com> - * Keith Whitwell <keith_whitwell@yahoo.com> + * Keith Whitwell <keith@tungstengraphics.com> */ #ifndef __RADEON_CONTEXT_H__ @@ -39,34 +39,24 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #ifdef GLX_DIRECT_RENDERING -#include <X11/Xlibint.h> - -#include "dri_util.h" - -#include "xf86drm.h" -#include "xf86drmRadeon.h" - -#include "macros.h" -#include "mtypes.h" - -#include "radeon_reg.h" - struct radeon_context; typedef struct radeon_context radeonContextRec; typedef struct radeon_context *radeonContextPtr; +#include "mtypes.h" #include "radeon_lock.h" #include "radeon_screen.h" #include "mm.h" /* Flags for software fallback cases */ -/* See correponding strings in radeon_tris.c */ +/* See correponding strings in radeon_swtcl.c */ #define RADEON_FALLBACK_TEXTURE 0x0001 #define RADEON_FALLBACK_DRAW_BUFFER 0x0002 #define RADEON_FALLBACK_STENCIL 0x0004 #define RADEON_FALLBACK_RENDER_MODE 0x0008 #define RADEON_FALLBACK_BLEND_EQ 0x0010 #define RADEON_FALLBACK_BLEND_FUNC 0x0020 +#define RADEON_FALLBACK_DISABLE 0x0040 /* Use the templated vertex format: */ @@ -87,12 +77,9 @@ typedef void (*radeon_line_func)( radeonContextPtr, typedef void (*radeon_point_func)( radeonContextPtr, radeonVertex * ); -typedef void (*radeon_prim_func)( GLcontext *ctx ); - struct radeon_colorbuffer_state { GLuint clear; - GLint drawOffset, drawPitch; }; @@ -109,6 +96,10 @@ struct radeon_pixel_state { struct radeon_scissor_state { XF86DRIClipRectRec rect; GLboolean enabled; + + GLuint numClipRects; /* Cliprects active */ + GLuint numAllocedClipRects; /* Cliprects available */ + XF86DRIClipRectPtr pClipRects; }; struct radeon_stencilbuffer_state { @@ -122,8 +113,9 @@ struct radeon_stipple_state { -#define TEX_0 1 -#define TEX_1 2 +#define TEX_0 0x1 +#define TEX_1 0x2 +#define TEX_ALL 0x3 typedef struct radeon_tex_obj radeonTexObj, *radeonTexObjPtr; @@ -142,7 +134,13 @@ struct radeon_tex_obj { images need to be uploaded to local or AGP texture space */ - GLint bound; /* Texture unit currently bound to */ + GLuint dirty_state; /* Flags (1 per texunit) for + whether or not this texobj + has dirty hardware state + (pp_*) that needs to be + brought into the + texunit. */ + GLint heap; /* Texture heap currently stored in */ drmRadeonTexImage image[RADEON_MAX_TEXTURE_LEVELS]; @@ -173,10 +171,253 @@ struct radeon_texture_state { struct radeon_texture_env_state unit[RADEON_MAX_TEXTURE_UNITS]; }; -struct radeon_state { - drmRadeonState hw; + +struct radeon_state_atom { + struct radeon_state_atom *next, *prev; + const char *name; /* for debug */ + int cmd_size; /* size in bytes */ + GLuint is_tcl; + int *cmd; /* one or more cmd's */ + int *lastcmd; /* one or more cmd's */ + GLboolean (*check)( GLcontext * ); /* is this state active? */ +}; + + + +/* Trying to keep these relatively short as the variables are becoming + * extravagently long. Drop the RADEON_ off the front of everything - + * I think we know we're in the radeon driver by now, and keep the + * prefix to 3 letters unless absolutely impossible. + */ + +#define CTX_CMD_0 0 +#define CTX_PP_MISC 1 +#define CTX_PP_FOG_COLOR 2 +#define CTX_RE_SOLID_COLOR 3 +#define CTX_RB3D_BLENDCNTL 4 +#define CTX_RB3D_DEPTHOFFSET 5 +#define CTX_RB3D_DEPTHPITCH 6 +#define CTX_RB3D_ZSTENCILCNTL 7 +#define CTX_CMD_1 8 +#define CTX_PP_CNTL 9 +#define CTX_RB3D_CNTL 10 +#define CTX_RB3D_COLOROFFSET 11 +#define CTX_CMD_2 12 +#define CTX_RB3D_COLORPITCH 13 +#define CTX_STATE_SIZE 14 + +#define SET_CMD_0 0 +#define SET_SE_CNTL 1 +#define SET_SE_COORDFMT 2 +#define SET_CMD_1 3 +#define SET_SE_CNTL_STATUS 4 +#define SET_STATE_SIZE 5 + +#define LIN_CMD_0 0 +#define LIN_RE_LINE_PATTERN 1 +#define LIN_RE_LINE_STATE 2 +#define LIN_CMD_1 3 +#define LIN_SE_LINE_WIDTH 4 +#define LIN_STATE_SIZE 5 + +#define MSK_CMD_0 0 +#define MSK_RB3D_STENCILREFMASK 1 +#define MSK_RB3D_ROPCNTL 2 +#define MSK_RB3D_PLANEMASK 3 +#define MSK_STATE_SIZE 4 + +#define VPT_CMD_0 0 +#define VPT_SE_VPORT_XSCALE 1 +#define VPT_SE_VPORT_XOFFSET 2 +#define VPT_SE_VPORT_YSCALE 3 +#define VPT_SE_VPORT_YOFFSET 4 +#define VPT_SE_VPORT_ZSCALE 5 +#define VPT_SE_VPORT_ZOFFSET 6 +#define VPT_STATE_SIZE 7 + +#define MSC_CMD_0 0 +#define MSC_RE_MISC 1 +#define MSC_STATE_SIZE 2 + +#define TEX_CMD_0 0 +#define TEX_PP_TXFILTER 1 +#define TEX_PP_TXFORMAT 2 +#define TEX_PP_TXOFFSET 3 +#define TEX_PP_TXCBLEND 4 +#define TEX_PP_TXABLEND 5 +#define TEX_PP_TFACTOR 6 +#define TEX_CMD_1 7 +#define TEX_PP_BORDER_COLOR 8 +#define TEX_STATE_SIZE 9 + +#define ZBS_CMD_0 0 +#define ZBS_SE_ZBIAS_FACTOR 1 +#define ZBS_SE_ZBIAS_CONSTANT 2 +#define ZBS_STATE_SIZE 3 + +#define TCL_CMD_0 0 +#define TCL_OUTPUT_VTXFMT 1 +#define TCL_OUTPUT_VTXSEL 2 +#define TCL_MATRIX_SELECT_0 3 +#define TCL_MATRIX_SELECT_1 4 +#define TCL_UCP_VERT_BLEND_CTL 5 +#define TCL_TEXTURE_PROC_CTL 6 +#define TCL_LIGHT_MODEL_CTL 7 +#define TCL_PER_LIGHT_CTL_0 8 +#define TCL_PER_LIGHT_CTL_1 9 +#define TCL_PER_LIGHT_CTL_2 10 +#define TCL_PER_LIGHT_CTL_3 11 +#define TCL_STATE_SIZE 12 + +#define MTL_CMD_0 0 +#define MTL_EMMISSIVE_RED 1 +#define MTL_EMMISSIVE_GREEN 2 +#define MTL_EMMISSIVE_BLUE 3 +#define MTL_EMMISSIVE_ALPHA 4 +#define MTL_AMBIENT_RED 5 +#define MTL_AMBIENT_GREEN 6 +#define MTL_AMBIENT_BLUE 7 +#define MTL_AMBIENT_ALPHA 8 +#define MTL_DIFFUSE_RED 9 +#define MTL_DIFFUSE_GREEN 10 +#define MTL_DIFFUSE_BLUE 11 +#define MTL_DIFFUSE_ALPHA 12 +#define MTL_SPECULAR_RED 13 +#define MTL_SPECULAR_GREEN 14 +#define MTL_SPECULAR_BLUE 15 +#define MTL_SPECULAR_ALPHA 16 +#define MTL_SHININESS 17 +#define MTL_STATE_SIZE 18 + +#define VTX_CMD_0 0 +#define VTX_SE_COORD_FMT 1 +#define VTX_STATE_SIZE 2 + +#define MAT_CMD_0 0 +#define MAT_ELT_0 1 +#define MAT_STATE_SIZE 17 + +#define GRD_CMD_0 0 +#define GRD_VERT_GUARD_CLIP_ADJ 1 +#define GRD_VERT_GUARD_DISCARD_ADJ 2 +#define GRD_HORZ_GUARD_CLIP_ADJ 3 +#define GRD_HORZ_GUARD_DISCARD_ADJ 4 +#define GRD_STATE_SIZE 5 + +/* position changes frequently when lighting in modelpos - separate + * out to new state item? + */ +#define LIT_CMD_0 0 +#define LIT_AMBIENT_RED 1 +#define LIT_AMBIENT_GREEN 2 +#define LIT_AMBIENT_BLUE 3 +#define LIT_AMBIENT_ALPHA 4 +#define LIT_DIFFUSE_RED 5 +#define LIT_DIFFUSE_GREEN 6 +#define LIT_DIFFUSE_BLUE 7 +#define LIT_DIFFUSE_ALPHA 8 +#define LIT_SPECULAR_RED 9 +#define LIT_SPECULAR_GREEN 10 +#define LIT_SPECULAR_BLUE 11 +#define LIT_SPECULAR_ALPHA 12 +#define LIT_POSITION_X 13 +#define LIT_POSITION_Y 14 +#define LIT_POSITION_Z 15 +#define LIT_POSITION_W 16 +#define LIT_DIRECTION_X 17 +#define LIT_DIRECTION_Y 18 +#define LIT_DIRECTION_Z 19 +#define LIT_DIRECTION_W 20 +#define LIT_ATTEN_CONST 21 +#define LIT_ATTEN_LINEAR 22 +#define LIT_ATTEN_QUADRATIC 23 +#define LIT_ATTEN_XXX 24 +#define LIT_CMD_1 25 +#define LIT_SPOT_DCD 26 +#define LIT_SPOT_EXPONENT 27 +#define LIT_SPOT_CUTOFF 28 +#define LIT_SPECULAR_THRESH 29 +#define LIT_RANGE_CUTOFF 30 /* ? */ +#define LIT_RANGE_ATTEN 31 /* ? */ +#define LIT_STATE_SIZE 32 + +/* Fog + */ +#define FOG_CMD_0 0 +#define FOG_R 1 +#define FOG_C 2 +#define FOG_D 3 +#define FOG_PAD 4 +#define FOG_STATE_SIZE 5 + +/* UCP + */ +#define UCP_CMD_0 0 +#define UCP_X 1 +#define UCP_Y 2 +#define UCP_Z 3 +#define UCP_W 4 +#define UCP_STATE_SIZE 5 + +/* GLT - Global ambient + */ +#define GLT_CMD_0 0 +#define GLT_RED 1 +#define GLT_GREEN 2 +#define GLT_BLUE 3 +#define GLT_ALPHA 4 +#define GLT_STATE_SIZE 5 + +/* EYE + */ +#define EYE_CMD_0 0 +#define EYE_X 1 +#define EYE_Y 2 +#define EYE_Z 3 +#define EYE_RESCALE_FACTOR 4 +#define EYE_STATE_SIZE 5 + +#define SHN_CMD_0 0 +#define SHN_SHININESS 1 +#define SHN_STATE_SIZE 2 + + + +struct radeon_hw_state { + /* All state should be on one of these lists: + */ + struct radeon_state_atom dirty; /* dirty list head placeholder */ + struct radeon_state_atom clean; /* clean list head placeholder */ + + /* Hardware state, stored as cmdbuf commands: + * -- Need to doublebuffer for + * - reviving state after loss of context + * - eliding noop statechange loops? (except line stipple count) + */ + struct radeon_state_atom ctx; + struct radeon_state_atom set; + struct radeon_state_atom lin; + struct radeon_state_atom msk; + struct radeon_state_atom vpt; + struct radeon_state_atom tcl; + struct radeon_state_atom msc; + struct radeon_state_atom tex[2]; + struct radeon_state_atom zbs; + struct radeon_state_atom mtl; + struct radeon_state_atom mat[5]; + struct radeon_state_atom lit[8]; /* includes vec, scl commands */ + struct radeon_state_atom ucp[6]; + struct radeon_state_atom eye; /* eye pos */ + struct radeon_state_atom grd; /* guard band clipping */ + struct radeon_state_atom fog; + struct radeon_state_atom glt; +}; + +struct radeon_state { + /* Derived state for internal purposes: + */ struct radeon_colorbuffer_state color; struct radeon_depthbuffer_state depth; struct radeon_pixel_state pixel; @@ -196,13 +437,40 @@ struct radeon_texture { GLint numHeaps; }; +/* Need refcounting on dma buffers: + */ +struct radeon_dma_buffer { + int refcount; /* the number of retained regions in buf */ + drmBufPtr buf; +}; + +#define GET_START(rvb) (rmesa->radeonScreen->agp_buffer_offset + \ + (rvb)->address - rmesa->dma.buf0_address + \ + (rvb)->start) + +/* A retained region, eg vertices for indexed vertices. + */ +struct radeon_dma_region { + struct radeon_dma_buffer *buf; + char *address; /* == buf->address */ + int start, end, ptr; /* offsets from start of buf */ + int aos_start; + int aos_stride; + int aos_size; +}; + struct radeon_dma { - drmBufPtr buffer; - drmBufPtr retained; - GLubyte *address; - GLuint low, high, last; - GLuint offset; + /* Active dma region. Allocations for vertices and retained + * regions come from here. Also used for emitting random vertices, + * these may be flushed by calling flush_current(); + */ + struct radeon_dma_region current; + + void (*flush)( radeonContextPtr ); + + char *buf0_address; /* start of buf[0], for index calcs */ + GLuint nr_released_bufs; /* flush after so many buffers released */ }; struct radeon_dri_mirror { @@ -215,14 +483,205 @@ struct radeon_dri_mirror { drmContext hwContext; drmLock *hwLock; int fd; + int drmMinor; }; + +#define RADEON_CMD_BUF_SZ (8*1024) + struct radeon_store { - radeonTexObjPtr texture[2][RADEON_MAX_STATES]; - drmRadeonState state[RADEON_MAX_STATES]; - drmRadeonPrim prim[RADEON_MAX_PRIMS]; GLuint statenr; GLuint primnr; + char cmd_buf[RADEON_CMD_BUF_SZ]; + int cmd_used; + int elts_start; +}; + + +/* radeon_tcl.c + */ +struct radeon_tcl_info { + GLuint vertex_format; + GLint last_offset; + GLuint hw_primitive; + + struct radeon_dma_region *aos_components[8]; + GLuint nr_aos_components; + + GLuint *Elts; + + struct radeon_dma_region indexed_verts; + struct radeon_dma_region obj; + struct radeon_dma_region rgba; + struct radeon_dma_region spec; + struct radeon_dma_region fog; + struct radeon_dma_region tex[RADEON_MAX_TEXTURE_UNITS]; + struct radeon_dma_region norm; +}; + + +/* radeon_swtcl.c + */ +struct radeon_swtcl_info { + GLuint SetupIndex; + GLuint SetupNewInputs; + GLuint RenderIndex; + GLuint vertex_size; + GLuint vertex_stride_shift; + GLuint vertex_format; + char *verts; + + /* Fallback rasterization functions + */ + radeon_point_func draw_point; + radeon_line_func draw_line; + radeon_tri_func draw_tri; + + GLuint hw_primitive; + GLenum render_primitive; + GLuint numverts; + + struct radeon_dma_region indexed_verts; +}; + + +struct radeon_ioctl { + GLuint vertex_offset; + GLuint vertex_size; +}; + + + +#define RADEON_MAX_PRIMS 64 + + +/* Want to keep a cache of these around. Each is parameterized by + * only a single value which has only a small range. Only expect a + * few, so just rescan the list each time? + */ +struct dynfn { + struct dynfn *next, *prev; + int key; + char *code; +}; + +struct dfn_lists { + struct dynfn Vertex2f; + struct dynfn Vertex2fv; + struct dynfn Vertex3f; + struct dynfn Vertex3fv; + struct dynfn Color4ub; + struct dynfn Color4ubv; + struct dynfn Color3ub; + struct dynfn Color3ubv; + struct dynfn Color4f; + struct dynfn Color4fv; + struct dynfn Color3f; + struct dynfn Color3fv; + struct dynfn SecondaryColor3ubEXT; + struct dynfn SecondaryColor3ubvEXT; + struct dynfn SecondaryColor3fEXT; + struct dynfn SecondaryColor3fvEXT; + struct dynfn Normal3f; + struct dynfn Normal3fv; + struct dynfn TexCoord2f; + struct dynfn TexCoord2fv; + struct dynfn TexCoord1f; + struct dynfn TexCoord1fv; + struct dynfn MultiTexCoord2fARB; + struct dynfn MultiTexCoord2fvARB; + struct dynfn MultiTexCoord1fARB; + struct dynfn MultiTexCoord1fvARB; +}; + +struct _vb; + +struct dfn_generators { + struct dynfn *(*Vertex2f)( GLcontext *, int ); + struct dynfn *(*Vertex2fv)( GLcontext *, int ); + struct dynfn *(*Vertex3f)( GLcontext *, int ); + struct dynfn *(*Vertex3fv)( GLcontext *, int ); + struct dynfn *(*Color4ub)( GLcontext *, int ); + struct dynfn *(*Color4ubv)( GLcontext *, int ); + struct dynfn *(*Color3ub)( GLcontext *, int ); + struct dynfn *(*Color3ubv)( GLcontext *, int ); + struct dynfn *(*Color4f)( GLcontext *, int ); + struct dynfn *(*Color4fv)( GLcontext *, int ); + struct dynfn *(*Color3f)( GLcontext *, int ); + struct dynfn *(*Color3fv)( GLcontext *, int ); + struct dynfn *(*SecondaryColor3ubEXT)( GLcontext *, int ); + struct dynfn *(*SecondaryColor3ubvEXT)( GLcontext *, int ); + struct dynfn *(*SecondaryColor3fEXT)( GLcontext *, int ); + struct dynfn *(*SecondaryColor3fvEXT)( GLcontext *, int ); + struct dynfn *(*Normal3f)( GLcontext *, int ); + struct dynfn *(*Normal3fv)( GLcontext *, int ); + struct dynfn *(*TexCoord2f)( GLcontext *, int ); + struct dynfn *(*TexCoord2fv)( GLcontext *, int ); + struct dynfn *(*TexCoord1f)( GLcontext *, int ); + struct dynfn *(*TexCoord1fv)( GLcontext *, int ); + struct dynfn *(*MultiTexCoord2fARB)( GLcontext *, int ); + struct dynfn *(*MultiTexCoord2fvARB)( GLcontext *, int ); + struct dynfn *(*MultiTexCoord1fARB)( GLcontext *, int ); + struct dynfn *(*MultiTexCoord1fvARB)( GLcontext *, int ); +}; + + +struct radeon_vb { + /* Keep these first: referenced from codegen templates: + */ + GLint counter, initial_counter; + GLint *dmaptr; + void (*notify)( void ); + GLint vertex_size; + + /* A maximum total of 15 elements per vertex: 3 floats for position, 3 + * floats for normal, 4 floats for color, 4 bytes for secondary color, + * 2 floats for each texture unit (4 floats total). + * + * As soon as the 3rd TMU is supported or cube maps (or 3D textures) are + * supported, this value will grow. + * + * The position data is never actually stored here, so 3 elements could be + * trimmed out of the buffer. + */ + union { float f; int i; radeon_color_t color; } vertex[15]; + + GLfloat *normalptr; + GLfloat *floatcolorptr; + radeon_color_t *colorptr; + GLfloat *floatspecptr; + radeon_color_t *specptr; + GLfloat *texcoordptr[2]; + + GLcontext *context; /* current context : Single thread only! */ +}; + +struct radeon_prim { + GLuint start; + GLuint end; + GLuint prim; +}; + +struct radeon_vbinfo { + GLenum *prim; /* &ctx->Driver.CurrentExecPrimitive */ + GLuint primflags; + GLboolean enabled; /* RADEON_NO_VTXFMT//RADEON_NO_TCL env vars */ + GLboolean installed; + GLboolean fell_back; + GLboolean recheck; + GLint initial_counter; + GLint nrverts; + GLuint vertex_format; + + GLuint installed_vertex_format; + GLuint installed_color_3f_sz; + + struct radeon_prim primlist[RADEON_MAX_PRIMS]; + int nrprims; + + struct dfn_lists dfn_cache; + struct dfn_generators codegen; + GLvertexformat vtxfmt; }; @@ -233,31 +692,20 @@ struct radeon_context { /* Driver and hardware state management */ + struct radeon_hw_state hw; struct radeon_state state; /* Texture object bookkeeping */ struct radeon_texture texture; - /* Fallback rasterization functions - */ - radeon_point_func draw_point; - radeon_line_func draw_line; - radeon_tri_func draw_tri; /* Rasterization and vertex state: */ - GLuint NewGLState; + GLuint TclFallback; GLuint Fallback; - GLuint SetupIndex; - GLuint SetupNewInputs; - GLuint RenderIndex; + GLuint NewGLState; - GLuint vertex_size; - GLuint vertex_stride_shift; - GLuint vertex_format; - GLuint num_verts; - char *verts; /* Temporaries for translating away float colors: */ @@ -266,34 +714,61 @@ struct radeon_context { /* Vertex buffers */ + struct radeon_ioctl ioctl; struct radeon_dma dma; - struct radeon_store store; - GLboolean upload_cliprects; - - GLuint hw_primitive; - GLenum render_primitive; /* Page flipping */ GLuint doPageFlip; - GLuint currentPage; + + /* Busy waiting + */ + GLuint do_usleeps; + GLuint do_irqs; + GLuint irqsEmitted; + drmRadeonIrqWait iw; /* Drawable, cliprect and scissor information */ GLuint numClipRects; /* Cliprects for the draw buffer */ XF86DRIClipRectPtr pClipRects; - GLuint lastStamp; + unsigned int lastStamp; + GLboolean lost_context; + radeonScreenPtr radeonScreen; /* Screen private DRI data */ + RADEONSAREAPrivPtr sarea; /* Private SAREA data */ - /* Mirrors of some DRI state + /* TCL stuff */ - struct radeon_dri_mirror dri; + GLmatrix TexGenMatrix[RADEON_MAX_TEXTURE_UNITS]; + GLboolean recheck_texgen[RADEON_MAX_TEXTURE_UNITS]; + GLboolean TexGenNeedNormals[RADEON_MAX_TEXTURE_UNITS]; + GLuint TexMatEnabled; + GLuint TexGenEnabled; + GLmatrix tmpmat; + GLuint last_ReallyEnabled; + + /* VBI + */ + GLuint vbl_seq; - radeonScreenPtr radeonScreen; /* Screen private DRI data */ - RADEONSAREAPrivPtr sarea; /* Private SAREA data */ + /* radeon_tcl.c + */ + struct radeon_tcl_info tcl; + + /* radeon_swtcl.c + */ + struct radeon_swtcl_info swtcl; + + /* radeon_vtxfmt.c + */ + struct radeon_vbinfo vb; - GLboolean debugFallbacks; + /* Mirrors of some DRI state + */ + struct radeon_dri_mirror dri; + /* Performance counters */ GLuint boxes; /* Draw performance boxes */ @@ -322,11 +797,12 @@ static __inline GLuint radeonPackColor( GLuint cpp, } } +#define RADEON_OLD_PACKETS 1 /* ================================================================ * Debugging: */ -#define DO_DEBUG 0 +#define DO_DEBUG 1 #if DO_DEBUG extern int RADEON_DEBUG; @@ -334,14 +810,18 @@ extern int RADEON_DEBUG; #define RADEON_DEBUG 0 #endif -#define DEBUG_ALWAYS_SYNC 0x01 -#define DEBUG_VERBOSE_API 0x02 -#define DEBUG_VERBOSE_MSG 0x04 -#define DEBUG_VERBOSE_LRU 0x08 -#define DEBUG_VERBOSE_DRI 0x10 -#define DEBUG_VERBOSE_IOCTL 0x20 -#define DEBUG_VERBOSE_2D 0x40 -#define DEBUG_VERBOSE_TEXTURE 0x80 +#define DEBUG_TEXTURE 0x001 +#define DEBUG_STATE 0x002 +#define DEBUG_IOCTL 0x004 +#define DEBUG_PRIMS 0x008 +#define DEBUG_VERTS 0x010 +#define DEBUG_FALLBACKS 0x020 +#define DEBUG_VFMT 0x040 +#define DEBUG_CODEGEN 0x080 +#define DEBUG_VERBOSE 0x100 +#define DEBUG_DRI 0x200 +#define DEBUG_DMA 0x400 +#define DEBUG_SANITY 0x800 #endif #endif /* __RADEON_CONTEXT_H__ */ diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c index 223301ccb..9f0c5065b 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c,v 1.7 2002/09/16 18:05:19 eich Exp $ */ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c,v 1.11 2003/01/29 22:04:59 dawes Exp $ */ /************************************************************************** Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and @@ -31,480 +31,704 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. * Authors: * Kevin E. Martin <martin@valinux.com> * Gareth Hughes <gareth@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> * */ #include "radeon_context.h" #include "radeon_state.h" #include "radeon_ioctl.h" +#include "radeon_tcl.h" +#include "radeon_sanity.h" + +#include "radeon_macros.h" /* for INREG() */ #include "mem.h" #include "macros.h" #include "swrast/swrast.h" +#include "simple_list.h" #define RADEON_TIMEOUT 512 +#define RADEON_IDLE_RETRY 16 + +#include <unistd.h> /* for usleep() */ + +static void do_usleep( int nr, const char *caller ) +{ + if (0) fprintf(stderr, "usleep %d in %s\n", nr, caller ); + if (1) usleep( nr ); +} +static void radeonWaitForIdle( radeonContextPtr rmesa ); /* ============================================================= - * Hardware vertex buffer handling + * Kernel command buffer handling */ -/* Get a new VB from the pool of vertex buffers in AGP space. - */ -drmBufPtr radeonGetBufferLocked( radeonContextPtr rmesa ) +static void print_state_atom( struct radeon_state_atom *state ) { - int fd = rmesa->dri.fd; - int index = 0; - int size = 0; - drmDMAReq dma; - drmBufPtr buf = NULL; - int to = 0; - int ret; + int i; - dma.context = rmesa->dri.hwContext; - dma.send_count = 0; - dma.send_list = NULL; - dma.send_sizes = NULL; - dma.flags = 0; - dma.request_count = 1; - dma.request_size = RADEON_BUFFER_SIZE; - dma.request_list = &index; - dma.request_sizes = &size; - dma.granted_count = 0; + fprintf(stderr, "emit %s/%d\n", state->name, state->cmd_size); - while ( !buf && ( to++ < RADEON_TIMEOUT ) ) { - ret = drmDMA( fd, &dma ); + if (RADEON_DEBUG & DEBUG_VERBOSE) + for (i = 0 ; i < state->cmd_size ; i++) + fprintf(stderr, "\t%s[%d]: %x\n", state->name, i, state->cmd[i]); + +} + +static void radeon_emit_state_list( radeonContextPtr rmesa, + struct radeon_state_atom *list ) +{ + struct radeon_state_atom *state, *tmp; + char *dest; + + /* From Felix Kuhling: similar to some other lockups, glaxium will + * lock with what we believe to be a normal command stream, but + * sprinkling some magic waits arounds allows it to run + * uninterrupted. This has a slight effect on q3 framerates, but + * it might now be possible to remove the zbs hack, below. + * + * Felix reports that this can be narrowed down to just + * tcl,tex0,tex1 state, but that's pretty much every statechange, + * so let's just put the wait in always (unless Felix wants to + * narrow it down further...) + */ + if (1) { + drmRadeonCmdHeader *cmd; + cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, sizeof(*cmd), + __FUNCTION__ ); + cmd->wait.cmd_type = RADEON_CMD_WAIT; + cmd->wait.flags = RADEON_WAIT_3D; + } - if ( ret == 0 ) { - buf = &rmesa->radeonScreen->buffers->list[index]; - buf->used = 0; - /* Bump the performance counter */ - rmesa->c_vertexBuffers++; - return buf; + foreach_s( state, tmp, list ) { + if (state->check( rmesa->glCtx )) { + dest = radeonAllocCmdBuf( rmesa, state->cmd_size * 4, __FUNCTION__); + memcpy( dest, state->cmd, state->cmd_size * 4); + move_to_head( &(rmesa->hw.clean), state ); + if (RADEON_DEBUG & DEBUG_STATE) + print_state_atom( state ); } + else if (RADEON_DEBUG & DEBUG_STATE) + fprintf(stderr, "skip state %s\n", state->name); } +} - if ( !buf ) { - UNLOCK_HARDWARE( rmesa ); - fprintf( stderr, "Error: Could not get new VB... exiting\n" ); - exit( -1 ); + +void radeonEmitState( radeonContextPtr rmesa ) +{ + struct radeon_state_atom *state, *tmp; + + if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS)) + fprintf(stderr, "%s\n", __FUNCTION__); + + /* Somewhat overkill: + */ + if (rmesa->lost_context) { + if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS|DEBUG_IOCTL)) + fprintf(stderr, "%s - lost context\n", __FUNCTION__); + + foreach_s( state, tmp, &(rmesa->hw.clean) ) + move_to_tail(&(rmesa->hw.dirty), state ); + + rmesa->lost_context = 0; + } + else if (1) { + /* This is a darstardly kludge to work around a lockup that I + * haven't otherwise figured out. + */ + move_to_tail(&(rmesa->hw.dirty), &(rmesa->hw.zbs) ); } - return buf; + if (!(rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL)) { + foreach_s( state, tmp, &(rmesa->hw.dirty) ) { + if (state->is_tcl) { + move_to_head( &(rmesa->hw.clean), state ); + } + } + } + + radeon_emit_state_list( rmesa, &rmesa->hw.dirty ); } -static GLboolean intersect_rect( XF86DRIClipRectPtr out, - XF86DRIClipRectPtr a, - XF86DRIClipRectPtr b ) + +/* Fire a section of the retained (indexed_verts) buffer as a regular + * primtive. + */ +extern void radeonEmitVbufPrim( radeonContextPtr rmesa, + GLuint vertex_format, + GLuint primitive, + GLuint vertex_nr ) { - *out = *a; - if ( b->x1 > out->x1 ) out->x1 = b->x1; - if ( b->y1 > out->y1 ) out->y1 = b->y1; - if ( b->x2 < out->x2 ) out->x2 = b->x2; - if ( b->y2 < out->y2 ) out->y2 = b->y2; - if ( out->x1 >= out->x2 ) return GL_FALSE; - if ( out->y1 >= out->y2 ) return GL_FALSE; - return GL_TRUE; + drmRadeonCmdHeader *cmd; + + + assert(rmesa->dri.drmMinor >= 3); + assert(!(primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND)); + + radeonEmitState( rmesa ); + + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s cmd_used/4: %d\n", __FUNCTION__, + rmesa->store.cmd_used/4); + +#if RADEON_OLD_PACKETS + cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, 6 * sizeof(*cmd), + __FUNCTION__ ); + cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP; + cmd[1].i = RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM | (3 << 16); + cmd[2].i = rmesa->ioctl.vertex_offset; + cmd[3].i = vertex_nr; + cmd[4].i = vertex_format; + cmd[5].i = (primitive | + RADEON_CP_VC_CNTL_PRIM_WALK_LIST | + RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA | + RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE | + (vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT)); + + if (RADEON_DEBUG & DEBUG_PRIMS) + fprintf(stderr, "%s: header 0x%x offt 0x%x vfmt 0x%x vfcntl %x \n", + __FUNCTION__, + cmd[1].i, cmd[2].i, cmd[4].i, cmd[5].i); +#else + cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, 4 * sizeof(*cmd), + __FUNCTION__ ); + cmd[0].i = 0; + cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP; + cmd[1].i = RADEON_CP_PACKET3_3D_DRAW_VBUF | (1 << 16); + cmd[2].i = vertex_format; + cmd[3].i = (primitive | + RADEON_CP_VC_CNTL_PRIM_WALK_LIST | + RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA | + RADEON_CP_VC_CNTL_MAOS_ENABLE | + RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE | + (vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT)); + + + if (RADEON_DEBUG & DEBUG_PRIMS) + fprintf(stderr, "%s: header 0x%x vfmt 0x%x vfcntl %x \n", + __FUNCTION__, + cmd[1].i, cmd[2].i, cmd[3].i); +#endif } -static void emit_state( radeonContextPtr rmesa, - drmRadeonState *dest, - int dirty ) -{ - struct radeon_state *state = &rmesa->state; - if ( dirty & RADEON_UPLOAD_CONTEXT ) - memcpy( &dest->context, &state->hw.context, sizeof(dest->context) ); +void radeonFlushElts( radeonContextPtr rmesa ) +{ + int *cmd = (int *)(rmesa->store.cmd_buf + rmesa->store.elts_start); + int dwords; +#if RADEON_OLD_PACKETS + int nr = (rmesa->store.cmd_used - (rmesa->store.elts_start + 24)) / 2; +#else + int nr = (rmesa->store.cmd_used - (rmesa->store.elts_start + 16)) / 2; +#endif - if ( dirty & RADEON_UPLOAD_VERTFMT ) - memcpy( &dest->vertex, &state->hw.vertex, sizeof(dest->vertex) ); + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s\n", __FUNCTION__); - if ( dirty & RADEON_UPLOAD_LINE ) - memcpy( &dest->line, &state->hw.line, sizeof(dest->line) ); + assert( rmesa->dma.flush == radeonFlushElts ); + rmesa->dma.flush = 0; - if ( dirty & RADEON_UPLOAD_BUMPMAP ) - memcpy( &dest->bumpmap, &state->hw.bumpmap, sizeof(dest->bumpmap) ); + /* Cope with odd number of elts: + */ + rmesa->store.cmd_used = (rmesa->store.cmd_used + 2) & ~2; + dwords = (rmesa->store.cmd_used - rmesa->store.elts_start) / 4; + +#if RADEON_OLD_PACKETS + cmd[1] |= (dwords - 3) << 16; + cmd[5] |= nr << RADEON_CP_VC_CNTL_NUM_SHIFT; +#else + cmd[1] |= (dwords - 3) << 16; + cmd[3] |= nr << RADEON_CP_VC_CNTL_NUM_SHIFT; +#endif +} - if ( dirty & RADEON_UPLOAD_MASKS ) - memcpy( &dest->mask, &state->hw.mask, sizeof(dest->mask) ); - if ( dirty & RADEON_UPLOAD_VIEWPORT ) - memcpy( &dest->viewport, &state->hw.viewport, sizeof(dest->viewport) ); +GLushort *radeonAllocEltsOpenEnded( radeonContextPtr rmesa, + GLuint vertex_format, + GLuint primitive, + GLuint min_nr ) +{ + drmRadeonCmdHeader *cmd; + GLushort *retval; + + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s %d\n", __FUNCTION__, min_nr); + + assert(rmesa->dri.drmMinor >= 3); + assert((primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND)); + + radeonEmitState( rmesa ); + +#if RADEON_OLD_PACKETS + cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, + 24 + min_nr*2, + __FUNCTION__ ); + cmd[0].i = 0; + cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP; + cmd[1].i = RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM; + cmd[2].i = rmesa->ioctl.vertex_offset; + cmd[3].i = 0xffff; + cmd[4].i = vertex_format; + cmd[5].i = (primitive | + RADEON_CP_VC_CNTL_PRIM_WALK_IND | + RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA | + RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE); + + retval = (GLushort *)(cmd+6); +#else + cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, + 16 + min_nr*2, + __FUNCTION__ ); + cmd[0].i = 0; + cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP; + cmd[1].i = RADEON_CP_PACKET3_3D_DRAW_INDX; + cmd[2].i = vertex_format; + cmd[3].i = (primitive | + RADEON_CP_VC_CNTL_PRIM_WALK_IND | + RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA | + RADEON_CP_VC_CNTL_MAOS_ENABLE | + RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE); + + retval = (GLushort *)(cmd+4); +#endif - if ( dirty & RADEON_UPLOAD_SETUP ) { - memcpy( &dest->setup1, &state->hw.setup1, sizeof(dest->setup1) ); - memcpy( &dest->setup2, &state->hw.setup2, sizeof(dest->setup2) ); - } + if (RADEON_DEBUG & DEBUG_PRIMS) + fprintf(stderr, "%s: header 0x%x vfmt 0x%x prim %x \n", + __FUNCTION__, + cmd[1].i, vertex_format, primitive); - if ( dirty & RADEON_UPLOAD_MISC ) - memcpy( &dest->misc, &state->hw.misc, sizeof(dest->misc) ); + assert(!rmesa->dma.flush); + rmesa->dma.flush = radeonFlushElts; - if ( dirty & RADEON_UPLOAD_ZBIAS ) - memcpy( &dest->zbias, &state->hw.zbias, sizeof(dest->zbias) ); + rmesa->store.elts_start = ((char *)cmd) - rmesa->store.cmd_buf; - /* Assemble the texture state, combining the texture object and - * texture environment state into the hardware texture unit state. - */ - if ( dirty & RADEON_UPLOAD_TEX0 ) { - radeonTexObjPtr t0 = state->texture.unit[0].texobj; + return retval; +} - dest->texture[0].pp_txfilter = t0->pp_txfilter | state->hw.texture[0].pp_txfilter; - dest->texture[0].pp_txformat = t0->pp_txformat | RADEON_TXFORMAT_ST_ROUTE_STQ0; - dest->texture[0].pp_txoffset = t0->pp_txoffset; - dest->texture[0].pp_border_color = t0->pp_border_color; - dest->texture[0].pp_txcblend = state->hw.texture[0].pp_txcblend; - dest->texture[0].pp_txablend = state->hw.texture[0].pp_txablend; - dest->texture[0].pp_tfactor = state->hw.texture[0].pp_tfactor; - } - if ( dirty & RADEON_UPLOAD_TEX1 ) { - radeonTexObjPtr t1 = state->texture.unit[1].texobj; - dest->texture[1].pp_txfilter = t1->pp_txfilter | state->hw.texture[1].pp_txfilter; - dest->texture[1].pp_txformat = t1->pp_txformat | RADEON_TXFORMAT_ST_ROUTE_STQ1; - dest->texture[1].pp_txoffset = t1->pp_txoffset; - dest->texture[1].pp_border_color = t1->pp_border_color; - dest->texture[1].pp_txcblend = state->hw.texture[1].pp_txcblend; - dest->texture[1].pp_txablend = state->hw.texture[1].pp_txablend; - dest->texture[1].pp_tfactor = state->hw.texture[1].pp_tfactor; - } +void radeonEmitVertexAOS( radeonContextPtr rmesa, + GLuint vertex_size, + GLuint offset ) +{ +#if RADEON_OLD_PACKETS + rmesa->ioctl.vertex_size = vertex_size; + rmesa->ioctl.vertex_offset = offset; +#else + drmRadeonCmdHeader *cmd; + assert(rmesa->dri.drmMinor >= 3); + + if (RADEON_DEBUG & (DEBUG_PRIMS|DEBUG_IOCTL)) + fprintf(stderr, "%s: vertex_size 0x%x offset 0x%x \n", + __FUNCTION__, vertex_size, offset); + + cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, 5 * sizeof(int), + __FUNCTION__ ); + + cmd[0].i = 0; + cmd[0].header.cmd_type = RADEON_CMD_PACKET3; + cmd[1].i = RADEON_CP_PACKET3_3D_LOAD_VBPNTR | (2 << 16); + cmd[2].i = 1; + cmd[3].i = vertex_size | (vertex_size << 8); + cmd[4].i = offset; +#endif } + -#if 0 -static void print_values( const char *name, const void *vals, int sz ) +void radeonEmitAOS( radeonContextPtr rmesa, + struct radeon_dma_region **component, + GLuint nr, + GLuint offset ) { - const int *ivals = (const int *)vals; +#if RADEON_OLD_PACKETS + assert( nr == 1 ); + assert( component[0]->aos_size == component[0]->aos_stride ); + rmesa->ioctl.vertex_size = component[0]->aos_size; + rmesa->ioctl.vertex_offset = + (component[0]->aos_start + offset * component[0]->aos_stride * 4); +#else + drmRadeonCmdHeader *cmd; + int sz = 3 + (nr/2 * 3) + (nr & 1) * 2; int i; + int *tmp; + + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s\n", __FUNCTION__); + + assert(rmesa->dri.drmMinor >= 3); + + cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, sz * sizeof(int), + __FUNCTION__ ); + cmd[0].i = 0; + cmd[0].header.cmd_type = RADEON_CMD_PACKET3; + cmd[1].i = RADEON_CP_PACKET3_3D_LOAD_VBPNTR | ((sz-3) << 16); + cmd[2].i = nr; + tmp = &cmd[0].i; + cmd += 3; + + for (i = 0 ; i < nr ; i++) { + if (i & 1) { + cmd[0].i |= ((component[i]->aos_stride << 24) | + (component[i]->aos_size << 16)); + cmd[2].i = (component[i]->aos_start + + offset * component[i]->aos_stride * 4); + cmd += 3; + } + else { + cmd[0].i = ((component[i]->aos_stride << 8) | + (component[i]->aos_size << 0)); + cmd[1].i = (component[i]->aos_start + + offset * component[i]->aos_stride * 4); + } + } - for (i = 0; i < sz/4 ; i++) - fprintf(stderr, "%s %d: 0x%x\n", name, i, ivals[i]); -} + if (RADEON_DEBUG & DEBUG_VERTS) { + fprintf(stderr, "%s:\n", __FUNCTION__); + for (i = 0 ; i < sz ; i++) + fprintf(stderr, " %d: %x\n", i, tmp[i]); + } #endif -/* -static void print_state( drmRadeonState *state ) -{ - int dirty = state->dirty; +} - if ( dirty & RADEON_UPLOAD_CONTEXT ) - print_values( "CONTEXT", &state->context, sizeof(state->context) ); - if ( dirty & RADEON_UPLOAD_VERTFMT ) - print_values( "VERTFMT", &state->vertex, sizeof(state->vertex) ); +static int radeonFlushCmdBufLocked( radeonContextPtr rmesa, + const char * caller ) +{ + int ret, i; + drmRadeonCmdBuffer cmd; - if ( dirty & RADEON_UPLOAD_LINE ) - print_values( "LINE", &state->line, sizeof(state->line) ); + if (RADEON_DEBUG & DEBUG_IOCTL) { + fprintf(stderr, "%s from %s\n", __FUNCTION__, caller); - if ( dirty & RADEON_UPLOAD_BUMPMAP ) - print_values( "BUMPMAP", &state->bumpmap, sizeof(state->bumpmap) ); + if (RADEON_DEBUG & DEBUG_VERBOSE) + for (i = 0 ; i < rmesa->store.cmd_used ; i += 4 ) + fprintf(stderr, "%d: %x\n", i/4, + *(int *)(&rmesa->store.cmd_buf[i])); + } - if ( dirty & RADEON_UPLOAD_MASKS ) - print_values( "MASKS", &state->mask, sizeof(state->mask) ); + if (RADEON_DEBUG & DEBUG_DMA) + fprintf(stderr, "%s: Releasing %d buffers\n", __FUNCTION__, + rmesa->dma.nr_released_bufs); - if ( dirty & RADEON_UPLOAD_VIEWPORT ) - print_values( "VIEWPORT", &state->viewport, sizeof(state->viewport) ); - if ( dirty & RADEON_UPLOAD_SETUP ) { - print_values( "SETUP", &state->setup1, sizeof(state->setup1) ); - print_values( "SETUP2", &state->setup2, sizeof(state->setup2) ); + if (RADEON_DEBUG & DEBUG_SANITY) { + if (rmesa->state.scissor.enabled) + ret = radeonSanityCmdBuffer( rmesa, + rmesa->state.scissor.numClipRects, + rmesa->state.scissor.pClipRects); + else + ret = radeonSanityCmdBuffer( rmesa, + rmesa->numClipRects, + rmesa->pClipRects); } - if ( dirty & RADEON_UPLOAD_MISC ) - print_values( "MISC", &state->misc, sizeof(state->misc) ); + cmd.bufsz = rmesa->store.cmd_used; + cmd.buf = rmesa->store.cmd_buf; - if ( dirty & RADEON_UPLOAD_ZBIAS ) - print_values( "ZBIAS", &state->zbias, sizeof(state->zbias) ); + if (rmesa->state.scissor.enabled) { + cmd.nbox = rmesa->state.scissor.numClipRects; + cmd.boxes = (drmClipRect *)rmesa->state.scissor.pClipRects; + } else { + cmd.nbox = rmesa->numClipRects; + cmd.boxes = (drmClipRect *)rmesa->pClipRects; + } - if ( dirty & RADEON_UPLOAD_TEX0 ) - print_values( "TEX0", &state->texture[0], sizeof(state->texture[0]) ); + ret = drmCommandWrite( rmesa->dri.fd, + DRM_RADEON_CMDBUF, + &cmd, sizeof(cmd) ); - if ( dirty & RADEON_UPLOAD_TEX1 ) - print_values( "TEX1", &state->texture[1], sizeof(state->texture[1]) ); + rmesa->store.primnr = 0; + rmesa->store.statenr = 0; + rmesa->store.cmd_used = 0; + rmesa->dma.nr_released_bufs = 0; + rmesa->lost_context = 1; + return ret; } -*/ -static void emit_prim( radeonContextPtr rmesa ) -{ - GLuint prim = rmesa->store.primnr++; - GLuint dirty = rmesa->state.hw.dirty; - rmesa->store.prim[prim].prim = rmesa->hw_primitive; - rmesa->store.prim[prim].start = rmesa->dma.last; - rmesa->store.prim[prim].finish = rmesa->dma.low; - rmesa->store.prim[prim].vc_format = rmesa->vertex_format; - - if (rmesa->hw_primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND) - rmesa->store.prim[prim].numverts = rmesa->dma.offset / 64; - else - rmesa->store.prim[prim].numverts = rmesa->num_verts; +/* Note: does not emit any commands to avoid recursion on + * radeonAllocCmdBuf. + */ +void radeonFlushCmdBuf( radeonContextPtr rmesa, const char *caller ) +{ + int ret; - rmesa->num_verts = 0; - rmesa->dma.last = rmesa->dma.low; + + assert (rmesa->dri.drmMinor >= 3); + LOCK_HARDWARE( rmesa ); + ret = radeonFlushCmdBufLocked( rmesa, caller ); + UNLOCK_HARDWARE( rmesa ); - /* Make sure we keep a copy of the initial state. - */ - if (prim == 0) { - dirty = RADEON_UPLOAD_CONTEXT_ALL; - if (rmesa->state.texture.unit[0].texobj) dirty |= RADEON_UPLOAD_TEX0; - if (rmesa->state.texture.unit[1].texobj) dirty |= RADEON_UPLOAD_TEX1; + if (ret) { + fprintf(stderr, "drmRadeonCmdBuffer: %d\n", ret); + exit(ret); } +} - if (dirty) - { - GLuint state = rmesa->store.statenr++; - - emit_state( rmesa, &rmesa->store.state[state], dirty ); -/* fprintf(stderr, "emit state %d, dirty %x rmesa->dirty %x\n", */ -/* state, dirty, rmesa->state.hw.dirty ); */ - rmesa->store.state[state].dirty = rmesa->state.hw.dirty; /* override */ - rmesa->store.texture[0][state] = rmesa->state.texture.unit[0].texobj; - rmesa->store.texture[1][state] = rmesa->state.texture.unit[1].texobj; - rmesa->state.hw.dirty = 0; -/* print_state( &rmesa->store.state[state] ); */ - } - - rmesa->store.prim[prim].stateidx = rmesa->store.statenr - 1; - -/* fprintf(stderr, "emit_prim %d hwprim 0x%x vfmt 0x%x %d..%d %d verts stateidx %x\n", */ -/* prim, */ -/* rmesa->store.prim[prim].prim, */ -/* rmesa->store.prim[prim].vc_format, */ -/* rmesa->store.prim[prim].start, */ -/* rmesa->store.prim[prim].finish, */ -/* rmesa->store.prim[prim].numverts, */ -/* rmesa->store.prim[prim].stateidx); */ -} +/* ============================================================= + * Hardware vertex buffer handling + */ -void radeonFlushPrimsLocked( radeonContextPtr rmesa ) +void radeonRefillCurrentDmaRegion( radeonContextPtr rmesa ) { - XF86DRIClipRectPtr pbox = (XF86DRIClipRectPtr)rmesa->pClipRects; - int nbox = rmesa->numClipRects; - drmBufPtr buffer = rmesa->dma.buffer; - RADEONSAREAPrivPtr sarea = rmesa->sarea; + struct radeon_dma_buffer *dmabuf; int fd = rmesa->dri.fd; - int discard_sz = rmesa->dma.high - rmesa->dma.low < 4096; - int discard = (rmesa->dma.retained != rmesa->dma.buffer && - discard_sz); - int i; + int index = 0; + int size = 0; + drmDMAReq dma; + int ret; - if ( !nbox ) - rmesa->store.primnr = 0; - else if ( nbox >= RADEON_NR_SAREA_CLIPRECTS ) { - rmesa->upload_cliprects = 1; - for ( i = 0 ; i < rmesa->store.statenr ; i++ ) - rmesa->store.state[0].dirty |= rmesa->store.state[i].dirty; - if ( !rmesa->store.texture[0][0] ) - rmesa->store.state[0].dirty &= ~RADEON_UPLOAD_TEX0; - if ( !rmesa->store.texture[1][0] ) - rmesa->store.state[0].dirty &= ~RADEON_UPLOAD_TEX1; + if (RADEON_DEBUG & (DEBUG_IOCTL|DEBUG_DMA)) + fprintf(stderr, "%s\n", __FUNCTION__); + + if (rmesa->dma.flush) { + rmesa->dma.flush( rmesa ); } + if (rmesa->dma.current.buf) + radeonReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ ); -/* fprintf(stderr, "%s: boxes: %d prims: %d states: %d vertexstore: 0x%x\n", */ -/* __FUNCTION__, */ -/* sarea->nbox, rmesa->store.primnr, rmesa->store.statenr, */ -/* rmesa->dma.low - rmesa->store.prim[0].start); */ + if (rmesa->dma.nr_released_bufs > 4) + radeonFlushCmdBuf( rmesa, __FUNCTION__ ); - if ( !rmesa->upload_cliprects || !rmesa->store.primnr ) - { - if ( nbox == 1 ) { - sarea->nbox = 0; - } else { - sarea->nbox = nbox; - } + dma.context = rmesa->dri.hwContext; + dma.send_count = 0; + dma.send_list = NULL; + dma.send_sizes = NULL; + dma.flags = 0; + dma.request_count = 1; + dma.request_size = RADEON_BUFFER_SIZE; + dma.request_list = &index; + dma.request_sizes = &size; + dma.granted_count = 0; -/* fprintf(stderr, "case a %d boxes %d prims %d states\n", */ -/* sarea->nbox, rmesa->store.primnr, rmesa->store.statenr); */ - if (discard || rmesa->store.primnr) - drmRadeonFlushPrims( fd, - buffer->idx, - discard, - rmesa->store.statenr, - rmesa->store.state, - rmesa->store.primnr, - rmesa->store.prim); - } - else - { - for ( i = 0 ; i < nbox ; ) { - int nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, nbox ); - XF86DRIClipRectPtr b = sarea->boxes; - int discard_now = 0; - - /* TODO: Precalculate this intersection: - */ - if ( rmesa->state.scissor.enabled ) { - sarea->nbox = 0; - - for ( ; i < nr ; i++ ) { - *b = pbox[i]; - if ( intersect_rect( b, b, &rmesa->state.scissor.rect ) ) { - sarea->nbox++; - b++; - } - } - - /* Culled? - */ - if ( !sarea->nbox ) { - if ( nr < nbox ) continue; - rmesa->store.primnr = 0; - } - } else { - sarea->nbox = nr - i; - for ( ; i < nr ; i++) { - *b++ = pbox[i]; - } - } + LOCK_HARDWARE(rmesa); /* no need to validate */ - /* Finished with the buffer? - */ - if ( nr == nbox ) { - discard_now = discard; - } + ret = drmDMA( fd, &dma ); + + if (ret != 0) { + /* Free some up this way? + */ + if (rmesa->dma.nr_released_bufs) { + radeonFlushCmdBufLocked( rmesa, __FUNCTION__ ); + } + + if (RADEON_DEBUG & DEBUG_DMA) + fprintf(stderr, "Waiting for buffers\n"); + + radeonWaitForIdleLocked( rmesa ); + ret = drmDMA( fd, &dma ); -/* fprintf(stderr, "case a %d boxes %d prims %d states, discard: %d\n", */ -/* sarea->nbox, rmesa->store.primnr, rmesa->store.statenr, discard); */ - drmRadeonFlushPrims( fd, - buffer->idx, - discard_now, - rmesa->store.statenr, - rmesa->store.state, - rmesa->store.primnr, - rmesa->store.prim); + if ( ret != 0 ) { + UNLOCK_HARDWARE( rmesa ); + fprintf( stderr, "Error: Could not get dma buffer... exiting\n" ); + exit( -1 ); } } - if (discard_sz) { - rmesa->dma.buffer = 0; - rmesa->dma.address = 0; - rmesa->dma.low = 0; - rmesa->dma.high = 0; - } - else { - rmesa->dma.low = (rmesa->dma.low + 0x7) & ~0x7; /* alignment */ - } - rmesa->dma.last = rmesa->dma.low; - rmesa->store.primnr = 0; - rmesa->store.statenr = 0; - rmesa->upload_cliprects = 0; - rmesa->num_verts = 0; -} + UNLOCK_HARDWARE(rmesa); -void radeonFlushPrimsGetBuffer( radeonContextPtr rmesa ) -{ - if (rmesa->dma.low != rmesa->dma.last) - emit_prim( rmesa ); + if (RADEON_DEBUG & DEBUG_DMA) + fprintf(stderr, "Allocated buffer %d\n", index); - LOCK_HARDWARE(rmesa); + dmabuf = CALLOC_STRUCT( radeon_dma_buffer ); + dmabuf->buf = &rmesa->radeonScreen->buffers->list[index]; + dmabuf->refcount = 1; - if (rmesa->dma.buffer) { - rmesa->dma.low = rmesa->dma.high; /* force discard */ - rmesa->dma.last = rmesa->dma.low; - radeonFlushPrimsLocked( rmesa ); - } + rmesa->dma.current.buf = dmabuf; + rmesa->dma.current.address = dmabuf->buf->address; + rmesa->dma.current.end = dmabuf->buf->total; + rmesa->dma.current.start = 0; + rmesa->dma.current.ptr = 0; - rmesa->dma.buffer = radeonGetBufferLocked( rmesa ); - rmesa->dma.high = rmesa->dma.buffer->total; - rmesa->dma.address = (GLubyte *)rmesa->dma.buffer->address; - rmesa->dma.low = 0; - rmesa->num_verts = 0; - rmesa->dma.last = rmesa->dma.low; - UNLOCK_HARDWARE(rmesa); + rmesa->c_vertexBuffers++; } - -void radeonFlushPrims( radeonContextPtr rmesa ) +void radeonReleaseDmaRegion( radeonContextPtr rmesa, + struct radeon_dma_region *region, + const char *caller ) { - if (rmesa->dma.buffer) { - if (rmesa->dma.low != rmesa->dma.last) - emit_prim( rmesa ); + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s from %s\n", __FUNCTION__, caller); + + if (!region->buf) + return; - LOCK_HARDWARE( rmesa ); - radeonFlushPrimsLocked( rmesa ); - UNLOCK_HARDWARE( rmesa ); + if (rmesa->dma.flush) + rmesa->dma.flush( rmesa ); + + if (--region->buf->refcount == 0) { + drmRadeonCmdHeader *cmd; + + if (RADEON_DEBUG & (DEBUG_IOCTL|DEBUG_DMA)) + fprintf(stderr, "%s -- DISCARD BUF %d\n", __FUNCTION__, + region->buf->buf->idx); + + cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, sizeof(*cmd), + __FUNCTION__ ); + cmd->dma.cmd_type = RADEON_CMD_DMA_DISCARD; + cmd->dma.buf_idx = region->buf->buf->idx; + FREE(region->buf); + rmesa->dma.nr_released_bufs++; } + + region->buf = 0; + region->start = 0; } -void radeonEmitPrim( radeonContextPtr rmesa ) +/* Allocates a region from rmesa->dma.current. If there isn't enough + * space in current, grab a new buffer (and discard what was left of current) + */ +void radeonAllocDmaRegion( radeonContextPtr rmesa, + struct radeon_dma_region *region, + int bytes, + int alignment ) { - ASSERT(rmesa->dma.buffer); - emit_prim( rmesa ); + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s %d\n", __FUNCTION__, bytes); - if (rmesa->store.primnr == RADEON_MAX_PRIMS || - rmesa->store.statenr == RADEON_MAX_STATES) { - LOCK_HARDWARE(rmesa); - radeonFlushPrimsLocked(rmesa); - UNLOCK_HARDWARE(rmesa); - } - else { - rmesa->dma.low = (rmesa->dma.low + 0x7) & ~0x7; /* alignment */ - rmesa->dma.last = rmesa->dma.low; - rmesa->num_verts = 0; - } + if (rmesa->dma.flush) + rmesa->dma.flush( rmesa ); + + if (region->buf) + radeonReleaseDmaRegion( rmesa, region, __FUNCTION__ ); + + alignment--; + rmesa->dma.current.start = rmesa->dma.current.ptr = + (rmesa->dma.current.ptr + alignment) & ~alignment; + + if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end ) + radeonRefillCurrentDmaRegion( rmesa ); + + region->start = rmesa->dma.current.start; + region->ptr = rmesa->dma.current.start; + region->end = rmesa->dma.current.start + bytes; + region->address = rmesa->dma.current.address; + region->buf = rmesa->dma.current.buf; + region->buf->refcount++; + + rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */ + rmesa->dma.current.start = + rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7; + + if ( rmesa->dri.drmMinor < 3 ) + radeonRefillCurrentDmaRegion( rmesa ); } +void radeonAllocDmaRegionVerts( radeonContextPtr rmesa, + struct radeon_dma_region *region, + int numverts, + int vertsize, + int alignment ) +{ + radeonAllocDmaRegion( rmesa, region, vertsize * numverts, alignment ); +} /* ================================================================ - * Texture uploads + * SwapBuffers with client-side throttling */ -void radeonFireBlitLocked( radeonContextPtr rmesa, drmBufPtr buffer, - GLint offset, GLint pitch, GLint format, - GLint x, GLint y, GLint width, GLint height ) +static CARD32 radeonGetLastFrame (radeonContextPtr rmesa) { -#if 0 - GLint ret; + unsigned char *RADEONMMIO = rmesa->radeonScreen->mmio.map; + int ret; + CARD32 frame; + + if (rmesa->dri.screen->drmMinor >= 4) { + drmRadeonGetParam gp; - ret = drmRadeonTextureBlit( rmesa->dri.fd, buffer->idx, - offset, pitch, format, - x, y, width, height ); + gp.param = RADEON_PARAM_LAST_FRAME; + gp.value = (int *)&frame; + ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_GETPARAM, + &gp, sizeof(gp) ); + } + else + ret = -EINVAL; +#ifndef __alpha__ + if ( ret == -EINVAL ) { + frame = INREG( RADEON_LAST_FRAME_REG ); + ret = 0; + } +#endif if ( ret ) { - UNLOCK_HARDWARE( rmesa ); - fprintf( stderr, "drmRadeonTextureBlit: return = %d\n", ret ); - exit( 1 ); + fprintf( stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, ret ); + exit(1); } -#endif + + return frame; } +static void radeonEmitIrqLocked( radeonContextPtr rmesa ) +{ + drmRadeonIrqEmit ie; + int ret; + + ie.irq_seq = &rmesa->iw.irq_seq; + ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_IRQ_EMIT, + &ie, sizeof(ie) ); + if ( ret ) { + fprintf( stderr, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__, ret ); + exit(1); + } +} -/* ================================================================ - * SwapBuffers with client-side throttling - */ -#define RADEON_MAX_OUTSTANDING 2 +static void radeonWaitIrq( radeonContextPtr rmesa ) +{ + int ret; + + do { + ret = drmCommandWrite( rmesa->dri.fd, DRM_RADEON_IRQ_WAIT, + &rmesa->iw, sizeof(rmesa->iw) ); + } while (ret && (errno == EINTR || errno == EAGAIN)); -static void delay( void ) { -/* Prevent an optimizing compiler from removing a spin loop */ + if ( ret ) { + fprintf( stderr, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__, ret ); + exit(1); + } } -static int radeonWaitForFrameCompletion( radeonContextPtr rmesa ) + +static void radeonWaitForFrameCompletion( radeonContextPtr rmesa ) { - unsigned char *RADEONMMIO = rmesa->radeonScreen->mmio.map; RADEONSAREAPrivPtr sarea = rmesa->sarea; - CARD32 frame; - int wait = 0; - int i; - while ( 1 ) { - frame = INREG( RADEON_LAST_FRAME_REG ); - if ( sarea->last_frame - frame <= RADEON_MAX_OUTSTANDING ) { - break; + if (rmesa->do_irqs) { + if (radeonGetLastFrame(rmesa) < sarea->last_frame) { + if (!rmesa->irqsEmitted) { + while (radeonGetLastFrame (rmesa) < sarea->last_frame) + ; + } + else { + UNLOCK_HARDWARE( rmesa ); + radeonWaitIrq( rmesa ); + LOCK_HARDWARE( rmesa ); + } + rmesa->irqsEmitted = 10; } - wait++; - /* Spin in place a bit so we aren't hammering the bus */ - for ( i = 0 ; i < 1024 ; i++ ) { - delay(); + + if (rmesa->irqsEmitted) { + radeonEmitIrqLocked( rmesa ); + rmesa->irqsEmitted--; + } + } + else { + while (radeonGetLastFrame (rmesa) < sarea->last_frame) { + UNLOCK_HARDWARE( rmesa ); + if (rmesa->do_usleeps) + do_usleep(1, __FUNCTION__); + LOCK_HARDWARE( rmesa ); } } - - return wait; } /* Copy the back color buffer to the front color buffer. @@ -520,26 +744,22 @@ void radeonCopyBuffer( const __DRIdrawablePrivate *dPriv ) rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate; - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { - fprintf( stderr, "\n%s( %p )\n\n", __FUNCTION__, (void*)rmesa->glCtx ); + if ( RADEON_DEBUG & DEBUG_IOCTL ) { + fprintf( stderr, "\n%s( %p )\n\n", __FUNCTION__, rmesa->glCtx ); } RADEON_FIREVERTICES( rmesa ); LOCK_HARDWARE( rmesa ); - nbox = rmesa->dri.drawable->numClipRects; /* must be in locked region */ /* Throttle the frame rate -- only allow one pending swap buffers * request at a time. */ - if ( !radeonWaitForFrameCompletion( rmesa ) ) { - rmesa->hardwareWentIdle = 1; - } else { - rmesa->hardwareWentIdle = 0; - } + radeonWaitForFrameCompletion( rmesa ); + radeonWaitForVBlank( rmesa ); - nbox = dPriv->numClipRects; + nbox = rmesa->dri.drawable->numClipRects; /* must be in locked region */ for ( i = 0 ; i < nbox ; ) { GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS , nbox ); @@ -553,28 +773,16 @@ void radeonCopyBuffer( const __DRIdrawablePrivate *dPriv ) } rmesa->sarea->nbox = n; - ret = drmRadeonSwapBuffers( rmesa->dri.fd ); + ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_SWAP ); if ( ret ) { - fprintf( stderr, "drmRadeonSwapBuffers: return = %d\n", ret ); + fprintf( stderr, "DRM_RADEON_SWAP_BUFFERS: return = %d\n", ret ); UNLOCK_HARDWARE( rmesa ); exit( 1 ); } } UNLOCK_HARDWARE( rmesa ); - - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT_ALL ); - if ( rmesa->state.texture.unit[0].texobj ) - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_TEX0 ); - if ( rmesa->state.texture.unit[1].texobj ) - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_TEX1 ); - - - rmesa->upload_cliprects = 1; - - /* Log the performance counters if necessary */ - radeonPerformanceCounters( rmesa ); } void radeonPageFlip( const __DRIdrawablePrivate *dPriv ) @@ -588,61 +796,54 @@ void radeonPageFlip( const __DRIdrawablePrivate *dPriv ) rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate; - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { - fprintf( stderr, "\n%s( %p ): page=%d\n\n", - __FUNCTION__, (void*)rmesa->glCtx, rmesa->currentPage ); + if ( RADEON_DEBUG & DEBUG_IOCTL ) { + fprintf(stderr, "%s %d\n", __FUNCTION__, + rmesa->sarea->pfCurrentPage ); } RADEON_FIREVERTICES( rmesa ); LOCK_HARDWARE( rmesa ); - /* Throttle the frame rate -- only allow one pending swap buffers - * request at a time. + /* Need to do this for the perf box placement: */ - if ( !radeonWaitForFrameCompletion( rmesa ) ) { - rmesa->hardwareWentIdle = 1; - } else { - rmesa->hardwareWentIdle = 0; + if (rmesa->dri.drawable->numClipRects) + { + XF86DRIClipRectPtr box = rmesa->dri.drawable->pClipRects; + XF86DRIClipRectPtr b = rmesa->sarea->boxes; + b[0] = box[0]; + rmesa->sarea->nbox = 1; } - /* The kernel will have been initialized to perform page flipping - * on a swapbuffers ioctl. + + /* Throttle the frame rate -- only allow one pending swap buffers + * request at a time. */ - ret = drmRadeonSwapBuffers( rmesa->dri.fd ); + radeonWaitForFrameCompletion( rmesa ); + radeonWaitForVBlank( rmesa ); + + ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_FLIP ); UNLOCK_HARDWARE( rmesa ); if ( ret ) { - fprintf( stderr, "drmRadeonSwapBuffers: return = %d\n", ret ); + fprintf( stderr, "DRM_RADEON_FLIP: return = %d\n", ret ); exit( 1 ); } - if ( rmesa->currentPage == 0 ) { + if ( rmesa->sarea->pfCurrentPage == 1 ) { rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset; rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch; - rmesa->currentPage = 1; } else { rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset; rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch; - rmesa->currentPage = 0; } - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); - rmesa->state.hw.context.rb3d_coloroffset = rmesa->state.color.drawOffset; - rmesa->state.hw.context.rb3d_colorpitch = rmesa->state.color.drawPitch; - - /* Log the performance counters if necessary */ - radeonPerformanceCounters( rmesa ); + RADEON_STATECHANGE( rmesa, ctx ); + rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = rmesa->state.color.drawOffset; + rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch; } -void radeonPerformanceCounters( radeonContextPtr rmesa ) -{ -} - -void radeonPerformanceBoxesLocked( radeonContextPtr rmesa ) -{ -} /* ================================================================ * Buffer clear @@ -659,25 +860,29 @@ static void radeonClear( GLcontext *ctx, GLbitfield mask, GLboolean all, CARD32 clear; GLuint flags = 0; GLuint color_mask = 0; -/* GLuint depth_mask = 0; */ GLint ret, i; - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { + if ( RADEON_DEBUG & DEBUG_IOCTL ) { fprintf( stderr, "%s: all=%d cx=%d cy=%d cw=%d ch=%d\n", __FUNCTION__, all, cx, cy, cw, ch ); } - RADEON_FIREVERTICES( rmesa ); + radeonEmitState( rmesa ); + + /* Need to cope with lostcontext here as kernel relies on + * some residual state: + */ + RADEON_FIREVERTICES( rmesa ); if ( mask & DD_FRONT_LEFT_BIT ) { flags |= RADEON_FRONT; - color_mask = rmesa->state.hw.mask.rb3d_planemask; + color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK]; mask &= ~DD_FRONT_LEFT_BIT; } if ( mask & DD_BACK_LEFT_BIT ) { flags |= RADEON_BACK; - color_mask = rmesa->state.hw.mask.rb3d_planemask; + color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK]; mask &= ~DD_BACK_LEFT_BIT; } @@ -691,107 +896,127 @@ static void radeonClear( GLcontext *ctx, GLbitfield mask, GLboolean all, mask &= ~DD_STENCIL_BIT; } - if ( flags ) { - /* Flip top to bottom */ - cx += dPriv->x; - cy = dPriv->y + dPriv->h - cy - ch; + if ( mask ) + _swrast_Clear( ctx, mask, all, cx, cy, cw, ch ); - LOCK_HARDWARE( rmesa ); + if ( !flags ) + return; - /* Throttle the number of clear ioctls we do. - */ - while ( 1 ) { + + /* Flip top to bottom */ + cx += dPriv->x; + cy = dPriv->y + dPriv->h - cy - ch; + + LOCK_HARDWARE( rmesa ); + + /* Throttle the number of clear ioctls we do. + */ + while ( 1 ) { + int ret; + + if (rmesa->dri.screen->drmMinor >= 4) { + drmRadeonGetParam gp; + + gp.param = RADEON_PARAM_LAST_CLEAR; + gp.value = (int *)&clear; + ret = drmCommandWriteRead( rmesa->dri.fd, + DRM_RADEON_GETPARAM, &gp, sizeof(gp) ); + } else + ret = -EINVAL; + +#ifndef __alpha__ + if ( ret == -EINVAL ) { clear = INREG( RADEON_LAST_CLEAR_REG ); - if ( sarea->last_clear - clear <= RADEON_MAX_CLEARS ) { - break; - } - /* Spin in place a bit so we aren't hammering the bus */ - for ( i = 0 ; i < 1024 ; i++ ) { - delay(); - } + ret = 0; + } +#endif + if ( ret ) { + fprintf( stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, ret ); + exit(1); + } + if ( RADEON_DEBUG & DEBUG_IOCTL ) { + fprintf( stderr, "%s( %d )\n", __FUNCTION__, (int)clear ); + if ( ret ) fprintf( stderr, " ( RADEON_LAST_CLEAR register read directly )\n" ); } - /* Emit any new MASKS state. This ioctl uses the old - * sarea-based state mechanism, which is why I'm not using - * emit_state() above. Time for a new ioctl? - */ - if ( rmesa->state.hw.dirty ) { - memcpy( &sarea->ContextState, &rmesa->state.hw, - sizeof(sarea->ContextState)); - sarea->dirty |= RADEON_UPLOAD_CONTEXT_ALL; + if ( sarea->last_clear - clear <= RADEON_MAX_CLEARS ) { + break; } + if ( rmesa->do_usleeps ) { + UNLOCK_HARDWARE( rmesa ); + do_usleep(1, __FUNCTION__); + LOCK_HARDWARE( rmesa ); + } + } - for ( i = 0 ; i < dPriv->numClipRects ; ) { - GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, dPriv->numClipRects ); - XF86DRIClipRectPtr box = dPriv->pClipRects; - XF86DRIClipRectPtr b = rmesa->sarea->boxes; - GLint n = 0; - - if ( !all ) { - for ( ; i < nr ; i++ ) { - GLint x = box[i].x1; - GLint y = box[i].y1; - GLint w = box[i].x2 - x; - GLint h = box[i].y2 - y; - - if ( x < cx ) w -= cx - x, x = cx; - if ( y < cy ) h -= cy - y, y = cy; - if ( x + w > cx + cw ) w = cx + cw - x; - if ( y + h > cy + ch ) h = cy + ch - y; - if ( w <= 0 ) continue; - if ( h <= 0 ) continue; - - b->x1 = x; - b->y1 = y; - b->x2 = x + w; - b->y2 = y + h; - b++; - n++; - } - } else { - for ( ; i < nr ; i++ ) { - *b++ = box[i]; - n++; - } - } + for ( i = 0 ; i < dPriv->numClipRects ; ) { + GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, dPriv->numClipRects ); + XF86DRIClipRectPtr box = dPriv->pClipRects; + XF86DRIClipRectPtr b = rmesa->sarea->boxes; + drmRadeonClearType clear; + drmRadeonClearRect depth_boxes[RADEON_NR_SAREA_CLIPRECTS]; + GLint n = 0; - rmesa->sarea->nbox = n; - -/* fprintf( stderr, */ -/* "drmRadeonClear: flag 0x%x color %x depth %x sten %x nbox %d\n", */ -/* flags, */ -/* rmesa->state.color.clear, */ -/* rmesa->state.depth.clear, */ -/* rmesa->state.stencil.clear, */ -/* rmesa->sarea->nbox ); */ - - ret = drmRadeonClear( rmesa->dri.fd, flags, - rmesa->state.color.clear, - rmesa->state.depth.clear, - rmesa->state.hw.mask.rb3d_planemask, - rmesa->state.stencil.clear, - rmesa->sarea->boxes, rmesa->sarea->nbox ); - - if ( ret ) { - UNLOCK_HARDWARE( rmesa ); - fprintf( stderr, "drmRadeonClear: return = %d\n", ret ); - exit( 1 ); + if ( !all ) { + for ( ; i < nr ; i++ ) { + GLint x = box[i].x1; + GLint y = box[i].y1; + GLint w = box[i].x2 - x; + GLint h = box[i].y2 - y; + + if ( x < cx ) w -= cx - x, x = cx; + if ( y < cy ) h -= cy - y, y = cy; + if ( x + w > cx + cw ) w = cx + cw - x; + if ( y + h > cy + ch ) h = cy + ch - y; + if ( w <= 0 ) continue; + if ( h <= 0 ) continue; + + b->x1 = x; + b->y1 = y; + b->x2 = x + w; + b->y2 = y + h; + b++; + n++; + } + } else { + for ( ; i < nr ; i++ ) { + *b++ = box[i]; + n++; } } - UNLOCK_HARDWARE( rmesa ); + rmesa->sarea->nbox = n; - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT_ALL ); - if ( rmesa->state.texture.unit[0].texobj ) - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_TEX0 ); - if ( rmesa->state.texture.unit[1].texobj ) - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_TEX1 ); - rmesa->upload_cliprects = 1; + clear.flags = flags; + clear.clear_color = rmesa->state.color.clear; + clear.clear_depth = rmesa->state.depth.clear; + clear.color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK]; + clear.depth_mask = rmesa->state.stencil.clear; + clear.depth_boxes = depth_boxes; + + n--; + b = rmesa->sarea->boxes; + for ( ; n >= 0 ; n-- ) { + depth_boxes[n].f[RADEON_CLEAR_X1] = (float)b[n].x1; + depth_boxes[n].f[RADEON_CLEAR_Y1] = (float)b[n].y1; + depth_boxes[n].f[RADEON_CLEAR_X2] = (float)b[n].x2; + depth_boxes[n].f[RADEON_CLEAR_Y2] = (float)b[n].y2; + depth_boxes[n].f[RADEON_CLEAR_DEPTH] = + (float)rmesa->state.depth.clear; + } + + ret = drmCommandWrite( rmesa->dri.fd, DRM_RADEON_CLEAR, + &clear, sizeof(drmRadeonClearType)); + + if ( ret ) { + UNLOCK_HARDWARE( rmesa ); + fprintf( stderr, "DRM_RADEON_CLEAR: return = %d\n", ret ); + exit( 1 ); + } } - if ( mask ) - _swrast_Clear( ctx, mask, all, cx, cy, cw, ch ); + UNLOCK_HARDWARE( rmesa ); } @@ -799,10 +1024,22 @@ void radeonWaitForIdleLocked( radeonContextPtr rmesa ) { int fd = rmesa->dri.fd; int to = 0; - int ret; + int ret, i = 0; + + rmesa->c_drawWaits++; do { - ret = drmRadeonWaitForIdleCP( fd ); + do { + ret = drmCommandNone( fd, DRM_RADEON_CP_IDLE); + } while ( ret && errno == EBUSY && i++ < RADEON_IDLE_RETRY ); + if (ret && ret != -EBUSY) { + /* + * JO - I'm reluctant to print this message while holding the lock + * + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "%s: CP idle %d\n", __FUNCTION__, ret); + */ + } } while ( ( ret == -EBUSY ) && ( to++ < RADEON_TIMEOUT ) ); if ( ret < 0 ) { @@ -813,32 +1050,91 @@ void radeonWaitForIdleLocked( radeonContextPtr rmesa ) } -void radeonInitIoctlFuncs( GLcontext *ctx ) +static void radeonWaitForIdle( radeonContextPtr rmesa ) { - ctx->Driver.Clear = radeonClear; + LOCK_HARDWARE(rmesa); + radeonWaitForIdleLocked( rmesa ); + UNLOCK_HARDWARE(rmesa); } +void radeonWaitForVBlank( radeonContextPtr rmesa ) +{ + drmVBlank vbl; + int ret; + + if ( !rmesa->radeonScreen->irq ) + return; + + if ( getenv("LIBGL_SYNC_REFRESH") ) { + /* Wait for at least one vertical blank since the last call */ + vbl.request.type = DRM_VBLANK_RELATIVE; + vbl.request.sequence = 1; + } else if ( getenv("LIBGL_THROTTLE_REFRESH") ) { + /* Wait for at least one vertical blank since the last call */ + vbl.request.type = DRM_VBLANK_ABSOLUTE; + vbl.request.sequence = rmesa->vbl_seq + 1; + } else { + return; + } + + UNLOCK_HARDWARE( rmesa ); + + if ((ret = drmWaitVBlank( rmesa->dri.fd, &vbl ))) { + fprintf(stderr, "%s: drmWaitVBlank returned %d, IRQs don't seem to be" + " working correctly.\nTry running with LIBGL_THROTTLE_REFRESH" + " and LIBL_SYNC_REFRESH unset.\n", __FUNCTION__, ret); + exit(1); + } else if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s: drmWaitVBlank returned %d\n", __FUNCTION__, ret); + + rmesa->vbl_seq = vbl.reply.sequence; + + LOCK_HARDWARE( rmesa ); +} -void radeonReleaseRetainedBuffer( radeonContextPtr rmesa ) +void radeonFlush( GLcontext *ctx ) { - ASSERT(rmesa->dma.retained); + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); - if (rmesa->dma.retained && - rmesa->dma.retained != rmesa->dma.buffer) { - RADEON_FIREVERTICES(rmesa); /* FIX ME: dependency tracking for retained */ + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s\n", __FUNCTION__); -/* fprintf(stderr, "releaseRetained: retained %p current %p\n", */ -/* rmesa->dma.retained, rmesa->dma.buffer); */ - - LOCK_HARDWARE(rmesa); - drmRadeonFlushPrims( rmesa->dri.fd, - rmesa->dma.retained->idx, - 1, - 0, rmesa->store.state, - 0, rmesa->store.prim); - UNLOCK_HARDWARE(rmesa); + if (rmesa->dma.flush) + rmesa->dma.flush( rmesa ); + + if (rmesa->dri.drmMinor >= 3) { + if (!is_empty_list(&rmesa->hw.dirty)) + radeonEmitState( rmesa ); + + if (rmesa->store.cmd_used) + radeonFlushCmdBuf( rmesa, __FUNCTION__ ); + } +} + +/* Make sure all commands have been sent to the hardware and have + * completed processing. + */ +void radeonFinish( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + radeonFlush( ctx ); + + if (rmesa->do_irqs) { + LOCK_HARDWARE( rmesa ); + radeonEmitIrqLocked( rmesa ); + UNLOCK_HARDWARE( rmesa ); + radeonWaitIrq( rmesa ); } + else + radeonWaitForIdle( rmesa ); +} + - rmesa->dma.retained = 0; +void radeonInitIoctlFuncs( GLcontext *ctx ) +{ + ctx->Driver.Clear = radeonClear; + ctx->Driver.Finish = radeonFinish; + ctx->Driver.Flush = radeonFlush; } + diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.h b/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.h index a56b39e16..8777ae278 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.h +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.h,v 1.4 2002/09/16 18:05:20 eich Exp $ */ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.h,v 1.6 2002/12/16 16:18:58 dawes Exp $ */ /************************************************************************** Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and @@ -39,90 +39,138 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #ifdef GLX_DIRECT_RENDERING -#include "radeon_dri.h" +#include "simple_list.h" #include "radeon_lock.h" -#include "xf86drm.h" -#include "xf86drmRadeon.h" -#define RADEON_BUFFER_MAX_DWORDS (RADEON_BUFFER_SIZE / sizeof(CARD32)) +extern void radeonEmitState( radeonContextPtr rmesa ); +extern void radeonEmitVertexAOS( radeonContextPtr rmesa, + GLuint vertex_size, + GLuint offset ); +extern void radeonEmitVbufPrim( radeonContextPtr rmesa, + GLuint vertex_format, + GLuint primitive, + GLuint vertex_nr ); + +extern void radeonFlushElts( radeonContextPtr rmesa ); + +extern GLushort *radeonAllocEltsOpenEnded( radeonContextPtr rmesa, + GLuint vertex_format, + GLuint primitive, + GLuint min_nr ); + +extern void radeonEmitAOS( radeonContextPtr rmesa, + struct radeon_dma_region **regions, + GLuint n, + GLuint offset ); + + + +extern void radeonFlushCmdBuf( radeonContextPtr rmesa, const char * ); +extern void radeonRefillCurrentDmaRegion( radeonContextPtr rmesa ); + +extern void radeonAllocDmaRegion( radeonContextPtr rmesa, + struct radeon_dma_region *region, + int bytes, + int alignment ); + +extern void radeonAllocDmaRegionVerts( radeonContextPtr rmesa, + struct radeon_dma_region *region, + int numverts, + int vertsize, + int alignment ); + +extern void radeonReleaseDmaRegion( radeonContextPtr rmesa, + struct radeon_dma_region *region, + const char *caller ); -extern drmBufPtr radeonGetBufferLocked( radeonContextPtr rmesa ); -extern void radeonEmitPrim( radeonContextPtr rmesa ); -extern void radeonFlushPrims( radeonContextPtr rmesa ); -extern void radeonFlushPrimsLocked( radeonContextPtr rmesa ); -extern void radeonFlushPrimsGetBuffer( radeonContextPtr rmesa ); -extern void radeonFireBlitLocked( radeonContextPtr rmesa, - drmBufPtr buffer, - GLint offset, GLint pitch, GLint format, - GLint x, GLint y, - GLint width, GLint height ); extern void radeonCopyBuffer( const __DRIdrawablePrivate *drawable ); extern void radeonPageFlip( const __DRIdrawablePrivate *drawable ); +extern void radeonFlush( GLcontext *ctx ); +extern void radeonFinish( GLcontext *ctx ); extern void radeonWaitForIdleLocked( radeonContextPtr rmesa ); -extern void radeonPerformanceCounters( radeonContextPtr rmesa ); -extern void radeonPerformanceBoxesLocked( radeonContextPtr rmesa ); +extern void radeonWaitForVBlank( radeonContextPtr rmesa ); extern void radeonInitIoctlFuncs( GLcontext *ctx ); -extern void radeonReleaseRetainedBuffer( radeonContextPtr rmesa ); +extern void radeonGetAllParams( radeonContextPtr rmesa ); + +/* radeon_compat.c: + */ +extern void radeonCompatEmitPrimitive( radeonContextPtr rmesa, + GLuint vertex_format, + GLuint hw_primitive, + GLuint nrverts ); /* ================================================================ * Helper macros: */ +/* Close off the last primitive, if it exists. + */ +#define RADEON_NEWPRIM( rmesa ) \ +do { \ + if ( rmesa->dma.flush ) \ + rmesa->dma.flush( rmesa ); \ +} while (0) + /* Can accomodate several state changes and primitive changes without * actually firing the buffer. */ -#define RADEON_STATECHANGE( rmesa, flag ) \ -do { \ - if ( 0 ) radeonPrintDirty( __FUNCTION__, flag ); \ - if ( rmesa->dma.low != rmesa->dma.last ) \ - radeonEmitPrim( rmesa ); \ - rmesa->state.hw.dirty |= flag; \ +#define RADEON_STATECHANGE( rmesa, ATOM ) \ +do { \ + RADEON_NEWPRIM( rmesa ); \ + move_to_head( &(rmesa->hw.dirty), &(rmesa->hw.ATOM)); \ } while (0) +#define RADEON_DB_STATE( ATOM ) \ + memcpy( rmesa->hw.ATOM.lastcmd, rmesa->hw.ATOM.cmd, \ + rmesa->hw.ATOM.cmd_size * 4) + +static __inline int RADEON_DB_STATECHANGE( + radeonContextPtr rmesa, + struct radeon_state_atom *atom ) +{ + if (memcmp(atom->cmd, atom->lastcmd, atom->cmd_size*4)) { + int *tmp; + RADEON_NEWPRIM( rmesa ); + move_to_head( &(rmesa->hw.dirty), atom ); + tmp = atom->cmd; + atom->cmd = atom->lastcmd; + atom->lastcmd = tmp; + return 1; + } + else + return 0; +} + /* Fire the buffered vertices no matter what. */ -#define RADEON_FIREVERTICES( rmesa ) \ -do { \ - if ( rmesa->store.primnr || rmesa->dma.low != rmesa->dma.last ) { \ - if ( 0 ) \ - fprintf( stderr, "RADEON_FIREVERTICES in %s\n",__FUNCTION__ ); \ - radeonFlushPrims( rmesa ); \ - } \ +#define RADEON_FIREVERTICES( rmesa ) \ +do { \ + if ( rmesa->store.cmd_used || rmesa->dma.flush ) { \ + radeonFlush( rmesa->glCtx ); \ + } \ } while (0) - -static __inline void *radeonAllocDmaLow( radeonContextPtr rmesa, +/* Alloc space in the command buffer + */ +static __inline char *radeonAllocCmdBuf( radeonContextPtr rmesa, int bytes, const char *where ) { - if ( rmesa->dma.low + bytes > rmesa->dma.high ) { - if (0) fprintf( stderr, "%s flush for %d (%d/%d/%d)\n", - where, bytes, rmesa->dma.last, - rmesa->dma.low, rmesa->dma.high ); - radeonFlushPrimsGetBuffer( rmesa ); - } + if (rmesa->store.cmd_used + bytes > RADEON_CMD_BUF_SZ) + radeonFlushCmdBuf( rmesa, __FUNCTION__ ); + + assert(rmesa->dri.drmMinor >= 3); { - GLubyte *head = rmesa->dma.address + rmesa->dma.low; - if (0) fprintf( stderr, "%s: alloc %d (%d/%d/%d)\n", - where, bytes, rmesa->dma.last, - rmesa->dma.low, rmesa->dma.high ); - rmesa->dma.low += bytes; + char *head = rmesa->store.cmd_buf + rmesa->store.cmd_used; + rmesa->store.cmd_used += bytes; return head; } } -static __inline void *radeonAllocDmaHigh( radeonContextPtr rmesa, int bytes ) -{ - if ( rmesa->dma.low + bytes > rmesa->dma.high ) - radeonFlushPrimsGetBuffer( rmesa ); - - rmesa->dma.high -= bytes; - return (void *)(rmesa->dma.address + rmesa->dma.high); -} diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_lock.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_lock.c index 0c05f507b..7afa8ea9c 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_lock.c +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_lock.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_lock.c,v 1.4 2002/02/22 21:45:00 dawes Exp $ */ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_lock.c,v 1.5 2002/10/30 12:51:55 alanh Exp $ */ /************************************************************************** Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and @@ -38,12 +38,47 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "radeon_lock.h" #include "radeon_tex.h" #include "radeon_state.h" +#include "radeon_ioctl.h" #if DEBUG_LOCKING char *prevLockFile = NULL; int prevLockLine = 0; #endif +/* Turn on/off page flipping according to the flags in the sarea: + */ +static void +radeonUpdatePageFlipping( radeonContextPtr rmesa ) +{ + int use_back; + + if (rmesa->dri.drmMinor < 3) + return; + + rmesa->doPageFlip = rmesa->sarea->pfAllowPageFlip; + + use_back = (rmesa->glCtx->Color.DriverDrawBuffer == GL_BACK_LEFT); + use_back ^= (rmesa->sarea->pfCurrentPage == 1); + + if ( RADEON_DEBUG & DEBUG_VERBOSE ) + fprintf(stderr, "%s allow %d current %d\n", __FUNCTION__, + rmesa->doPageFlip, + rmesa->sarea->pfCurrentPage ); + + if ( use_back ) { + rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset; + rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch; + } else { + rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset; + rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch; + } + + RADEON_STATECHANGE( rmesa, ctx ); + rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = rmesa->state.color.drawOffset; + rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch; +} + + /* Update the hardware state. This is called if another context has * grabbed the hardware lock, which includes the X server. This @@ -73,6 +108,7 @@ void radeonGetLock( radeonContextPtr rmesa, GLuint flags ) DRI_VALIDATE_DRAWABLE_INFO( rmesa->dri.display, sPriv, dPriv ); if ( rmesa->lastStamp != dPriv->lastStamp ) { + radeonUpdatePageFlipping( rmesa ); radeonSetCliprects( rmesa, rmesa->glCtx->Color.DriverDrawBuffer ); radeonUpdateViewportOffset( rmesa->glCtx ); rmesa->lastStamp = dPriv->lastStamp; @@ -81,24 +117,8 @@ void radeonGetLock( radeonContextPtr rmesa, GLuint flags ) if ( sarea->ctxOwner != rmesa->dri.hwContext ) { sarea->ctxOwner = rmesa->dri.hwContext; - rmesa->upload_cliprects = 1; - if ( rmesa->store.statenr ) { - rmesa->store.state[0].dirty = RADEON_UPLOAD_CONTEXT_ALL; - if ( rmesa->store.texture[0][0] ) - rmesa->store.state[0].dirty |= RADEON_UPLOAD_TEX0; - if ( rmesa->store.texture[1][0] ) - rmesa->store.state[0].dirty |= RADEON_UPLOAD_TEX1; - } - else { - rmesa->state.hw.dirty = RADEON_UPLOAD_CONTEXT_ALL; - if ( rmesa->state.texture.unit[0].texobj ) - rmesa->state.hw.dirty |= RADEON_UPLOAD_TEX0; - if ( rmesa->state.texture.unit[1].texobj ) - rmesa->state.hw.dirty |= RADEON_UPLOAD_TEX1; - } - for ( i = 0 ; i < rmesa->texture.numHeaps ; i++ ) { - if ( sarea->texAge[i] != rmesa->texture.age[i] ) { + if ( rmesa->texture.heap[i] && sarea->texAge[i] != rmesa->texture.age[i] ) { radeonAgeTextures( rmesa, i ); } } diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_lock.h b/xc/lib/GL/mesa/src/drv/radeon/radeon_lock.h index 9cb77646a..5402df83c 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_lock.h +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_lock.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_lock.h,v 1.2 2002/02/22 21:45:00 dawes Exp $ */ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_lock.h,v 1.3 2002/10/30 12:51:55 alanh Exp $ */ /************************************************************************** Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and @@ -85,17 +85,18 @@ extern int prevLockLine; * do not do any drawing !!! */ + /* Lock the hardware and validate our state. */ -#define LOCK_HARDWARE( rmesa ) \ - do { \ - char __ret = 0; \ - DEBUG_CHECK_LOCK(); \ - DRM_CAS( rmesa->dri.hwLock, rmesa->dri.hwContext, \ - (DRM_LOCK_HELD | rmesa->dri.hwContext), __ret ); \ - if ( __ret ) \ - radeonGetLock( rmesa, 0 ); \ - DEBUG_LOCK(); \ +#define LOCK_HARDWARE( rmesa ) \ + do { \ + char __ret = 0; \ + DEBUG_CHECK_LOCK(); \ + DRM_CAS( rmesa->dri.hwLock, rmesa->dri.hwContext, \ + (DRM_LOCK_HELD | rmesa->dri.hwContext), __ret ); \ + if ( __ret ) \ + radeonGetLock( rmesa, 0 ); \ + DEBUG_LOCK(); \ } while (0) /* Unlock the hardware. diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_maos.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_maos.c new file mode 100644 index 000000000..c62edd715 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_maos.c @@ -0,0 +1,12 @@ + + +/* If using new packets, can choose either verts or arrays. + * Otherwise, must use verts. + */ +#include "radeon_context.h" +#define RADEON_MAOS_VERTS 1 +#if (RADEON_MAOS_VERTS) || (RADEON_OLD_PACKETS) +#include "radeon_maos_verts.c" +#else +#include "radeon_maos_arrays.c" +#endif diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_maos.h b/xc/lib/GL/mesa/src/drv/radeon/radeon_maos.h new file mode 100644 index 000000000..f4907fe15 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_maos.h @@ -0,0 +1,47 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_maos.h,v 1.1 2002/10/30 12:51:55 alanh Exp $ */ +/************************************************************************** + +Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and + Tungsten Grahpics Inc., Austin, Texas. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, TUNGSTEN GRAHPICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * + */ + +#ifndef __RADEON_MAOS_H__ +#define __RADEON_MAOS_H__ + +#ifdef GLX_DIRECT_RENDERING + +#include "radeon_context.h" + +extern void radeonEmitArrays( GLcontext *ctx, GLuint inputs ); +extern void radeonReleaseArrays( GLcontext *ctx, GLuint newinputs ); + +#endif +#endif diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_maos_arrays.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_maos_arrays.c new file mode 100644 index 000000000..08375d673 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_maos_arrays.c @@ -0,0 +1,592 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_maos_arrays.c,v 1.1 2002/10/30 12:51:55 alanh Exp $ */ +/************************************************************************** + +Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and + Tungsten Graphics Inc., Cedar Park, Texas. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * + */ + +#include "glheader.h" +#include "mtypes.h" +#include "colormac.h" +#include "mem.h" +#include "mmath.h" +#include "macros.h" + +#include "swrast_setup/swrast_setup.h" +#include "math/m_translate.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_imm_debug.h" + +#include "radeon_context.h" +#include "radeon_ioctl.h" +#include "radeon_state.h" +#include "radeon_swtcl.h" +#include "radeon_maos.h" + +/* Usage: + * - from radeon_tcl_render + * - call radeonEmitArrays to ensure uptodate arrays in dma + * - emit primitives (new type?) which reference the data + * -- need to use elts for lineloop, quads, quadstrip/flat + * -- other primitives are all well-formed (need tristrip-1,fake-poly) + * + */ +static void emit_ubyte_rgba3( GLcontext *ctx, + struct radeon_dma_region *rvb, + char *data, + int stride, + int count ) +{ + int i; + radeon_color_t *out = (radeon_color_t *)(rvb->start + rvb->address); + + if (RADEON_DEBUG & DEBUG_VERTS) + fprintf(stderr, "%s count %d stride %d out %p\n", + __FUNCTION__, count, stride, out); + + for (i = 0; i < count; i++) { + out->red = *data; + out->green = *(data+1); + out->blue = *(data+2); + out->alpha = 0xFF; + out++; + data += stride; + } +} + + +#if defined(USE_X86_ASM) +#define COPY_DWORDS( dst, src, nr ) \ +do { \ + int __tmp; \ + __asm__ __volatile__( "rep ; movsl" \ + : "=%c" (__tmp), "=D" (dst), "=S" (__tmp) \ + : "0" (nr), \ + "D" ((long)dst), \ + "S" ((long)src) ); \ +} while (0) +#else +#define COPY_DWORDS( dst, src, nr ) \ +do { \ + int j; \ + for ( j = 0 ; j < nr ; j++ ) \ + dst[j] = ((int *)src)[j]; \ + dst += nr; \ +} while (0) +#endif + + + +static void emit_ubyte_rgba4( GLcontext *ctx, + struct radeon_dma_region *rvb, + char *data, + int stride, + int count ) +{ + int i; + int *out = (int *)(rvb->address + rvb->start); + + if (RADEON_DEBUG & DEBUG_VERTS) + fprintf(stderr, "%s count %d stride %d\n", + __FUNCTION__, count, stride); + + if (stride == 4) + COPY_DWORDS( out, data, count ); + else + for (i = 0; i < count; i++) { + *out++ = LE32_TO_CPU(*(int *)data); + data += stride; + } +} + + +static void emit_ubyte_rgba( GLcontext *ctx, + struct radeon_dma_region *rvb, + char *data, + int size, + int stride, + int count ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + + if (RADEON_DEBUG & DEBUG_VERTS) + fprintf(stderr, "%s %d/%d\n", __FUNCTION__, count, size); + + assert (!rvb->buf); + + if (stride == 0) { + radeonAllocDmaRegion( rmesa, rvb, 4, 4 ); + count = 1; + rvb->aos_start = GET_START(rvb); + rvb->aos_stride = 0; + rvb->aos_size = 1; + } + else { + radeonAllocDmaRegion( rmesa, rvb, 4 * count, 4 ); /* alignment? */ + rvb->aos_start = GET_START(rvb); + rvb->aos_stride = 1; + rvb->aos_size = 1; + } + + /* Emit the data + */ + switch (size) { + case 3: + emit_ubyte_rgba3( ctx, rvb, data, stride, count ); + break; + case 4: + emit_ubyte_rgba4( ctx, rvb, data, stride, count ); + break; + default: + assert(0); + exit(1); + break; + } +} + + + + +static void emit_vec8( GLcontext *ctx, + struct radeon_dma_region *rvb, + char *data, + int stride, + int count ) +{ + int i; + int *out = (int *)(rvb->address + rvb->start); + + if (RADEON_DEBUG & DEBUG_VERTS) + fprintf(stderr, "%s count %d stride %d\n", + __FUNCTION__, count, stride); + + if (stride == 8) + COPY_DWORDS( out, data, count*2 ); + else + for (i = 0; i < count; i++) { + out[0] = *(int *)data; + out[1] = *(int *)(data+4); + out += 2; + data += stride; + } +} + +static void emit_vec12( GLcontext *ctx, + struct radeon_dma_region *rvb, + char *data, + int stride, + int count ) +{ + int i; + int *out = (int *)(rvb->address + rvb->start); + + if (RADEON_DEBUG & DEBUG_VERTS) + fprintf(stderr, "%s count %d stride %d out %p data %p\n", + __FUNCTION__, count, stride, out, data); + + if (stride == 12) + COPY_DWORDS( out, data, count*3 ); + else + for (i = 0; i < count; i++) { + out[0] = *(int *)data; + out[1] = *(int *)(data+4); + out[2] = *(int *)(data+8); + out += 3; + data += stride; + } +} + +static void emit_vec16( GLcontext *ctx, + struct radeon_dma_region *rvb, + char *data, + int stride, + int count ) +{ + int i; + int *out = (int *)(rvb->address + rvb->start); + + if (RADEON_DEBUG & DEBUG_VERTS) + fprintf(stderr, "%s count %d stride %d\n", + __FUNCTION__, count, stride); + + if (stride == 16) + COPY_DWORDS( out, data, count*4 ); + else + for (i = 0; i < count; i++) { + out[0] = *(int *)data; + out[1] = *(int *)(data+4); + out[2] = *(int *)(data+8); + out[3] = *(int *)(data+12); + out += 4; + data += stride; + } +} + + +static void emit_vector( GLcontext *ctx, + struct radeon_dma_region *rvb, + char *data, + int size, + int stride, + int count ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + + if (RADEON_DEBUG & DEBUG_VERTS) + fprintf(stderr, "%s %d/%d\n", __FUNCTION__, count, size); + + assert (!rvb->buf); + + if (stride == 0) { + radeonAllocDmaRegion( rmesa, rvb, size * 4, 4 ); + count = 1; + rvb->aos_start = GET_START(rvb); + rvb->aos_stride = 0; + rvb->aos_size = size; + } + else { + radeonAllocDmaRegion( rmesa, rvb, size * count * 4, 4 ); /* alignment? */ + rvb->aos_start = GET_START(rvb); + rvb->aos_stride = size; + rvb->aos_size = size; + } + + /* Emit the data + */ + switch (size) { + case 2: + emit_vec8( ctx, rvb, data, stride, count ); + break; + case 3: + emit_vec12( ctx, rvb, data, stride, count ); + break; + case 4: + emit_vec16( ctx, rvb, data, stride, count ); + break; + default: + assert(0); + exit(1); + break; + } + +} + + + +static void emit_s0_vec( GLcontext *ctx, + struct radeon_dma_region *rvb, + char *data, + int stride, + int count ) +{ + int i; + int *out = (int *)(rvb->address + rvb->start); + + if (RADEON_DEBUG & DEBUG_VERTS) + fprintf(stderr, "%s count %d stride %d\n", + __FUNCTION__, count, stride); + + for (i = 0; i < count; i++) { + out[0] = *(int *)data; + out[1] = 0; + out += 2; + data += stride; + } +} + +static void emit_stq_vec( GLcontext *ctx, + struct radeon_dma_region *rvb, + char *data, + int stride, + int count ) +{ + int i; + int *out = (int *)(rvb->address + rvb->start); + + if (RADEON_DEBUG & DEBUG_VERTS) + fprintf(stderr, "%s count %d stride %d\n", + __FUNCTION__, count, stride); + + for (i = 0; i < count; i++) { + out[0] = *(int *)data; + out[1] = *(int *)(data+4); + out[2] = *(int *)(data+12); + out += 3; + data += stride; + } +} + + + + +static void emit_tex_vector( GLcontext *ctx, + struct radeon_dma_region *rvb, + char *data, + int size, + int stride, + int count ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + int emitsize; + + if (RADEON_DEBUG & DEBUG_VERTS) + fprintf(stderr, "%s %d/%d\n", __FUNCTION__, count, size); + + assert (!rvb->buf); + + switch (size) { + case 4: emitsize = 3; break; + default: emitsize = 2; break; + } + + + if (stride == 0) { + radeonAllocDmaRegion( rmesa, rvb, 4 * emitsize, 4 ); + count = 1; + rvb->aos_start = GET_START(rvb); + rvb->aos_stride = 0; + rvb->aos_size = emitsize; + } + else { + radeonAllocDmaRegion( rmesa, rvb, 4 * emitsize * count, 4 ); + rvb->aos_start = GET_START(rvb); + rvb->aos_stride = emitsize; + rvb->aos_size = emitsize; + } + + + /* Emit the data + */ + switch (size) { + case 1: + emit_s0_vec( ctx, rvb, data, stride, count ); + break; + case 2: + emit_vec8( ctx, rvb, data, stride, count ); + break; + case 3: + emit_vec8( ctx, rvb, data, stride, count ); + break; + case 4: + emit_stq_vec( ctx, rvb, data, stride, count ); + break; + default: + assert(0); + exit(1); + break; + } +} + + + + +/* Emit any changed arrays to new agp memory, re-emit a packet to + * update the arrays. + */ +void radeonEmitArrays( GLcontext *ctx, GLuint inputs ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb; + struct radeon_dma_region **component = rmesa->tcl.aos_components; + GLuint nr = 0; + GLuint vfmt = 0; + GLuint count = VB->Count; + GLuint vtx; + + if (RADEON_DEBUG & DEBUG_VERTS) + _tnl_print_vert_flags( __FUNCTION__, inputs ); + + if (1) { + if (!rmesa->tcl.obj.buf) + emit_vector( ctx, + &rmesa->tcl.obj, + (char *)VB->ObjPtr->data, + VB->ObjPtr->size, + VB->ObjPtr->stride, + count); + + switch( VB->ObjPtr->size ) { + case 4: vfmt |= RADEON_CP_VC_FRMT_W0; + case 3: vfmt |= RADEON_CP_VC_FRMT_Z; + case 2: vfmt |= RADEON_CP_VC_FRMT_XY; + default: + } + component[nr++] = &rmesa->tcl.obj; + } + + + if (inputs & VERT_NORM) { + if (!rmesa->tcl.norm.buf) + emit_vector( ctx, + &(rmesa->tcl.norm), + (char *)VB->NormalPtr->data, + 3, + VB->NormalPtr->stride, + count); + + vfmt |= RADEON_CP_VC_FRMT_N0; + component[nr++] = &rmesa->tcl.norm; + } + + if (inputs & VERT_RGBA) { + if (VB->ColorPtr[0]->Type == GL_UNSIGNED_BYTE) { + if (!rmesa->tcl.rgba.buf) + emit_ubyte_rgba( ctx, + &rmesa->tcl.rgba, + (char *)VB->ColorPtr[0]->Ptr, + VB->ColorPtr[0]->Size, + VB->ColorPtr[0]->StrideB, + count); + + vfmt |= RADEON_CP_VC_FRMT_PKCOLOR; + } + else { + int emitsize; + + if (VB->ColorPtr[0]->Size == 4 && + (VB->ColorPtr[0]->StrideB != 0 || + ((GLfloat *)VB->ColorPtr[0]->Ptr)[3] != 1.0)) { + vfmt |= RADEON_CP_VC_FRMT_FPCOLOR | RADEON_CP_VC_FRMT_FPALPHA; + emitsize = 4; + } + else { + vfmt |= RADEON_CP_VC_FRMT_FPCOLOR; + emitsize = 3; + } + + + if (!rmesa->tcl.rgba.buf) + emit_vector( ctx, + &(rmesa->tcl.rgba), + (char *)VB->ColorPtr[0]->Ptr, + emitsize, + VB->ColorPtr[0]->StrideB, + count); + } + + component[nr++] = &rmesa->tcl.rgba; + } + + + if (inputs & VERT_SPEC_RGB) { + if (!rmesa->tcl.spec.buf) { + if (VB->SecondaryColorPtr[0]->Type != GL_UNSIGNED_BYTE) + radeon_import_float_spec_colors( ctx ); + + emit_ubyte_rgba( ctx, + &rmesa->tcl.spec, + (char *)VB->SecondaryColorPtr[0]->Ptr, + 3, + VB->SecondaryColorPtr[0]->StrideB, + count); + } + + vfmt |= RADEON_CP_VC_FRMT_PKSPEC; + component[nr++] = &rmesa->tcl.spec; + } + + vtx = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] & + ~(RADEON_TCL_VTX_Q0|RADEON_TCL_VTX_Q1)); + + if (inputs & VERT_TEX0) { + if (!rmesa->tcl.tex[0].buf) + emit_tex_vector( ctx, + &(rmesa->tcl.tex[0]), + (char *)VB->TexCoordPtr[0]->data, + VB->TexCoordPtr[0]->size, + VB->TexCoordPtr[0]->stride, + count ); + + switch( VB->TexCoordPtr[0]->size ) { + case 4: + vtx |= RADEON_TCL_VTX_Q0; + vfmt |= RADEON_CP_VC_FRMT_Q0; + default: + vfmt |= RADEON_CP_VC_FRMT_ST0; + } + component[nr++] = &rmesa->tcl.tex[0]; + } + + if (inputs & VERT_TEX1) { + if (!rmesa->tcl.tex[1].buf) + emit_tex_vector( ctx, + &(rmesa->tcl.tex[1]), + (char *)VB->TexCoordPtr[1]->data, + VB->TexCoordPtr[1]->size, + VB->TexCoordPtr[1]->stride, + count ); + + switch( VB->TexCoordPtr[1]->size ) { + case 4: + vtx |= RADEON_TCL_VTX_Q1; + vfmt |= RADEON_CP_VC_FRMT_Q1; + default: + vfmt |= RADEON_CP_VC_FRMT_ST1; + } + component[nr++] = &rmesa->tcl.tex[1]; + } + + if (vtx != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT]) { + RADEON_STATECHANGE( rmesa, tcl ); + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] = vtx; + } + + rmesa->tcl.nr_aos_components = nr; + rmesa->tcl.vertex_format = vfmt; +} + + +void radeonReleaseArrays( GLcontext *ctx, GLuint newinputs ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + + if (RADEON_DEBUG & DEBUG_VERTS) + _tnl_print_vert_flags( __FUNCTION__, newinputs ); + + if (newinputs & VERT_OBJ) + radeonReleaseDmaRegion( rmesa, &rmesa->tcl.obj, __FUNCTION__ ); + + if (newinputs & VERT_NORM) + radeonReleaseDmaRegion( rmesa, &rmesa->tcl.norm, __FUNCTION__ ); + + if (newinputs & VERT_RGBA) + radeonReleaseDmaRegion( rmesa, &rmesa->tcl.rgba, __FUNCTION__ ); + + if (newinputs & VERT_SPEC_RGB) + radeonReleaseDmaRegion( rmesa, &rmesa->tcl.spec, __FUNCTION__ ); + + if (newinputs & VERT_TEX0) + radeonReleaseDmaRegion( rmesa, &rmesa->tcl.tex[0], __FUNCTION__ ); + + if (newinputs & VERT_TEX1) + radeonReleaseDmaRegion( rmesa, &rmesa->tcl.tex[1], __FUNCTION__ ); +} diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_maos_vbtmp.h b/xc/lib/GL/mesa/src/drv/radeon/radeon_maos_vbtmp.h new file mode 100644 index 000000000..8ce767774 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_maos_vbtmp.h @@ -0,0 +1,371 @@ +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef LOCALVARS +#define LOCALVARS +#endif + +#undef TCL_DEBUG +#ifndef TCL_DEBUG +#define TCL_DEBUG 0 +#endif + +static void TAG(emit)( GLcontext *ctx, + GLuint start, GLuint end, + void *dest ) +{ + LOCALVARS + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + GLuint (*tc0)[4], (*tc1)[4]; + GLfloat *fog; + GLuint (*tc2)[4], (*norm)[3]; + GLubyte (*col)[4], (*spec)[4]; + GLuint tc0_stride, tc1_stride, col_stride, spec_stride, fog_stride; + GLuint tc2_stride, norm_stride; + GLuint (*coord)[4]; + GLuint coord_stride; + GLubyte dummy[4]; + int i; + + union emit_union *v = (union emit_union *)dest; + + + if (RADEON_DEBUG & DEBUG_VERTS) + fprintf(stderr, "%s\n", __FUNCTION__); + + /* The vertex code expects Obj to be clean to element 3. To fix + * this, add more vertex code (for obj-2, obj-3) or preferably move + * to maos. + */ + if (VB->ObjPtr->size < 3) { + if (VB->ObjPtr->flags & VEC_NOT_WRITEABLE) { + VB->import_data( ctx, VERT_OBJ, VEC_NOT_WRITEABLE ); + } + _mesa_vector4f_clean_elem( VB->ObjPtr, VB->Count, 2 ); + } + + if (DO_W && VB->ObjPtr->size < 4) { + if (VB->ObjPtr->flags & VEC_NOT_WRITEABLE) { + VB->import_data( ctx, VERT_OBJ, VEC_NOT_WRITEABLE ); + } + _mesa_vector4f_clean_elem( VB->ObjPtr, VB->Count, 3 ); + } + + coord = (GLuint (*)[4])VB->ObjPtr->data; + coord_stride = VB->ObjPtr->stride; + + if (DO_TEX2) { + const GLuint t2 = GET_TEXSOURCE(2); + tc2 = (GLuint (*)[4])VB->TexCoordPtr[t2]->data; + tc2_stride = VB->TexCoordPtr[t2]->stride; + if (DO_PTEX && VB->TexCoordPtr[t2]->size < 4) { + if (VB->TexCoordPtr[t2]->flags & VEC_NOT_WRITEABLE) { + VB->import_data( ctx, VERT_TEX2, VEC_NOT_WRITEABLE ); + } + _mesa_vector4f_clean_elem( VB->TexCoordPtr[t2], VB->Count, 3 ); + } + } + + if (DO_TEX1) { + if (VB->TexCoordPtr[1]) { + const GLuint t1 = GET_TEXSOURCE(1); + tc1 = (GLuint (*)[4])VB->TexCoordPtr[t1]->data; + tc1_stride = VB->TexCoordPtr[t1]->stride; + if (DO_PTEX && VB->TexCoordPtr[t1]->size < 4) { + if (VB->TexCoordPtr[t1]->flags & VEC_NOT_WRITEABLE) { + VB->import_data( ctx, VERT_TEX1, VEC_NOT_WRITEABLE ); + } + _mesa_vector4f_clean_elem( VB->TexCoordPtr[t1], VB->Count, 3 ); + } + } else { + tc1 = (GLuint (*)[4])&ctx->Current.Texcoord[1]; /* could be anything, really */ + tc1_stride = 0; + } + } + + if (DO_TEX0) { + if (VB->TexCoordPtr[0]) { + const GLuint t0 = GET_TEXSOURCE(0); + tc0_stride = VB->TexCoordPtr[t0]->stride; + tc0 = (GLuint (*)[4])VB->TexCoordPtr[t0]->data; + if (DO_PTEX && VB->TexCoordPtr[t0]->size < 4) { + if (VB->TexCoordPtr[t0]->flags & VEC_NOT_WRITEABLE) { + VB->import_data( ctx, VERT_TEX0, VEC_NOT_WRITEABLE ); + } + _mesa_vector4f_clean_elem( VB->TexCoordPtr[t0], VB->Count, 3 ); + } + } else { + tc0 = (GLuint (*)[4])&ctx->Current.Texcoord[0]; /* could be anything, really */ + tc0_stride = 0; + } + + } + + if (DO_NORM) { + if (VB->NormalPtr) { + norm_stride = VB->NormalPtr->stride; + norm = (GLuint (*)[3])VB->NormalPtr->data; + } else { + norm_stride = 0; + norm = (GLuint (*)[3])&ctx->Current.Normal; + } + } + + if (DO_RGBA) { + if (VB->ColorPtr[0]) { + /* This is incorrect when colormaterial is enabled: + */ + if (VB->ColorPtr[0]->Type != GL_UNSIGNED_BYTE) { + if (0) fprintf(stderr, "IMPORTING FLOAT COLORS\n"); + IMPORT_FLOAT_COLORS( ctx ); + } + col = (GLubyte (*)[4])VB->ColorPtr[0]->Ptr; + col_stride = VB->ColorPtr[0]->StrideB; + } else { + col = &dummy; /* any old memory is fine */ + col_stride = 0; + } + + } + + if (DO_SPEC) { + if (VB->SecondaryColorPtr[0]) { + if (VB->SecondaryColorPtr[0]->Type != GL_UNSIGNED_BYTE) + IMPORT_FLOAT_SPEC_COLORS( ctx ); + spec = (GLubyte (*)[4])VB->SecondaryColorPtr[0]->Ptr; + spec_stride = VB->SecondaryColorPtr[0]->StrideB; + } else { + spec = &dummy; + spec_stride = 0; + } + + } + + if (DO_FOG) { + if (VB->FogCoordPtr) { + fog = VB->FogCoordPtr->data; + fog_stride = VB->FogCoordPtr->stride; + } else { + fog = (GLfloat *)&dummy; *fog = 0; + fog_stride = 0; + } + + } + + + if (VB->importable_data) { + if (start) { + coord = (GLuint (*)[4])((GLubyte *)coord + start * coord_stride); + if (DO_TEX0) + tc0 = (GLuint (*)[4])((GLubyte *)tc0 + start * tc0_stride); + if (DO_TEX1) + tc1 = (GLuint (*)[4])((GLubyte *)tc1 + start * tc1_stride); + if (DO_TEX2) + tc2 = (GLuint (*)[4])((GLubyte *)tc2 + start * tc2_stride); + if (DO_NORM) + norm = (GLuint (*)[3])((GLubyte *)norm + start * norm_stride); + if (DO_RGBA) + STRIDE_4UB(col, start * col_stride); + if (DO_SPEC) + STRIDE_4UB(spec, start * spec_stride); + if (DO_FOG) + STRIDE_F(fog, start * fog_stride); + } + + for (i=start; i < end; i++) { + v[0].ui = coord[0][0]; + v[1].ui = coord[0][1]; + v[2].ui = coord[0][2]; + if (TCL_DEBUG) fprintf(stderr, "%d: %.2f %.2f %.2f ", i, v[0].f, v[1].f, v[2].f); + if (DO_W) { + v[3].ui = coord[0][3]; + if (TCL_DEBUG) fprintf(stderr, "%.2f ", v[3].f); + v += 4; + } + else + v += 3; + coord = (GLuint (*)[4])((GLubyte *)coord + coord_stride); + + if (DO_NORM) { + v[0].ui = norm[0][0]; + v[1].ui = norm[0][1]; + v[2].ui = norm[0][2]; + if (TCL_DEBUG) fprintf(stderr, "norm: %.2f %.2f %.2f ", v[0].f, v[1].f, v[2].f); + v += 3; + norm = (GLuint (*)[3])((GLubyte *)norm + norm_stride); + } + if (DO_RGBA) { + v[0].ui = LE32_TO_CPU(*(GLuint *)&col[0]); + STRIDE_4UB(col, col_stride); + if (TCL_DEBUG) fprintf(stderr, "%x ", v[0].ui); + v++; + } + if (DO_SPEC || DO_FOG) { + if (DO_SPEC) { + v[0].specular.red = spec[0][0]; + v[0].specular.green = spec[0][1]; + v[0].specular.blue = spec[0][2]; + STRIDE_4UB(spec, spec_stride); + } + if (DO_FOG) { + v[0].specular.alpha = fog[0] * 255.0; + STRIDE_F(fog, fog_stride); + } + if (TCL_DEBUG) fprintf(stderr, "%x ", v[0].ui); + v++; + } + if (DO_TEX0) { + v[0].ui = tc0[0][0]; + v[1].ui = tc0[0][1]; + if (TCL_DEBUG) fprintf(stderr, "t0: %.2f %.2f ", v[0].f, v[1].f); + if (DO_PTEX) { + v[2].ui = tc0[0][3]; + if (TCL_DEBUG) fprintf(stderr, "%.2f ", v[2].f); + v += 3; + } + else + v += 2; + tc0 = (GLuint (*)[4])((GLubyte *)tc0 + tc0_stride); + } + if (DO_TEX1) { + v[0].ui = tc1[0][0]; + v[1].ui = tc1[0][1]; + if (TCL_DEBUG) fprintf(stderr, "t1: %.2f %.2f ", v[0].f, v[1].f); + if (DO_PTEX) { + v[2].ui = tc1[0][3]; + if (TCL_DEBUG) fprintf(stderr, "%.2f ", v[2].f); + v += 3; + } + else + v += 2; + tc1 = (GLuint (*)[4])((GLubyte *)tc1 + tc1_stride); + } + if (DO_TEX2) { + v[0].ui = tc2[0][0]; + v[1].ui = tc2[0][1]; + if (DO_PTEX) { + v[2].ui = tc2[0][3]; + v += 3; + } + else + v += 2; + tc2 = (GLuint (*)[4])((GLubyte *)tc2 + tc2_stride); + } + if (TCL_DEBUG) fprintf(stderr, "\n"); + } + } else { + for (i=start; i < end; i++) { + v[0].ui = coord[i][0]; + v[1].ui = coord[i][1]; + v[2].ui = coord[i][2]; + if (DO_W) { + v[3].ui = coord[i][3]; + v += 4; + } + else + v += 3; + + if (DO_NORM) { + v[0].ui = norm[i][0]; + v[1].ui = norm[i][1]; + v[2].ui = norm[i][2]; + v += 3; + } + if (DO_RGBA) { + v[0].ui = LE32_TO_CPU(*(GLuint *)&col[i]); + v++; + } + if (DO_SPEC || DO_FOG) { + if (DO_SPEC) { + v[0].specular.red = spec[i][0]; + v[0].specular.green = spec[i][1]; + v[0].specular.blue = spec[i][2]; + } + if (DO_FOG) { + v[0].specular.alpha = fog[i] * 255.0; + } + v++; + } + if (DO_TEX0) { + v[0].ui = tc0[i][0]; + v[1].ui = tc0[i][1]; + if (DO_PTEX) { + v[2].ui = tc0[i][3]; + v += 3; + } + else + v += 2; + } + if (DO_TEX1) { + v[0].ui = tc1[i][0]; + v[1].ui = tc1[i][1]; + if (DO_PTEX) { + v[2].ui = tc1[i][3]; + v += 3; + } + else + v += 2; + } + if (DO_TEX2) { + v[0].ui = tc2[i][0]; + v[1].ui = tc2[i][1]; + if (DO_PTEX) { + v[2].ui = tc2[i][3]; + v += 3; + } + else + v += 2; + } + } + } +} + + + +static void TAG(init)( void ) +{ + int sz = 3; + if (DO_W) sz++; + if (DO_NORM) sz += 3; + if (DO_RGBA) sz++; + if (DO_SPEC || DO_FOG) sz++; + if (DO_TEX0) sz += 2; + if (DO_TEX0 && DO_PTEX) sz++; + if (DO_TEX1) sz += 2; + if (DO_TEX1 && DO_PTEX) sz++; + if (DO_TEX2) sz += 2; + if (DO_TEX2 && DO_PTEX) sz++; + + setup_tab[IDX].emit = TAG(emit); + setup_tab[IDX].vertex_format = IND; + setup_tab[IDX].vertex_size = sz; +} + + +#undef IND +#undef TAG +#undef IDX diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_maos_verts.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_maos_verts.c new file mode 100644 index 000000000..d91375489 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_maos_verts.c @@ -0,0 +1,336 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_maos_verts.c,v 1.1 2002/10/30 12:51:55 alanh Exp $ */ +/************************************************************************** + +Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and + Tungsten Graphics Inc., Austin, Texas. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * + */ + +#include "radeon_context.h" +#include "radeon_state.h" +#include "radeon_ioctl.h" +#include "radeon_tex.h" +#include "radeon_tcl.h" +#include "radeon_swtcl.h" +#include "radeon_maos.h" + +#include "mmath.h" +#include "mtypes.h" +#include "enums.h" +#include "colormac.h" +#include "light.h" + +#include "array_cache/acache.h" +#include "tnl/tnl.h" +#include "tnl/t_pipeline.h" +#include "tnl/t_imm_debug.h" + +#define RADEON_TCL_MAX_SETUP 13 + +union emit_union { float f; GLuint ui; radeon_color_t specular; }; + +static struct { + void (*emit)( GLcontext *, GLuint, GLuint, void * ); + GLuint vertex_size; + GLuint vertex_format; +} setup_tab[RADEON_TCL_MAX_SETUP]; + +#define DO_W (IND & RADEON_CP_VC_FRMT_W0) +#define DO_RGBA (IND & RADEON_CP_VC_FRMT_PKCOLOR) +#define DO_SPEC (IND & RADEON_CP_VC_FRMT_PKSPEC) +#define DO_FOG (IND & RADEON_CP_VC_FRMT_PKSPEC) +#define DO_TEX0 (IND & RADEON_CP_VC_FRMT_ST0) +#define DO_TEX1 (IND & RADEON_CP_VC_FRMT_ST1) +#define DO_PTEX (IND & RADEON_CP_VC_FRMT_Q0) +#define DO_NORM (IND & RADEON_CP_VC_FRMT_N0) + +#define DO_TEX2 0 +#define DO_TEX3 0 + +#define GET_TEXSOURCE(n) n +#define GET_UBYTE_COLOR_STORE() &RADEON_CONTEXT(ctx)->UbyteColor +#define GET_UBYTE_SPEC_COLOR_STORE() &RADEON_CONTEXT(ctx)->UbyteSecondaryColor + +#define IMPORT_FLOAT_COLORS radeon_import_float_colors +#define IMPORT_FLOAT_SPEC_COLORS radeon_import_float_spec_colors + +/*********************************************************************** + * Generate vertex emit functions * + ***********************************************************************/ + + +/* Defined in order of increasing vertex size: + */ +#define IDX 0 +#define IND (RADEON_CP_VC_FRMT_XY| \ + RADEON_CP_VC_FRMT_Z| \ + RADEON_CP_VC_FRMT_PKCOLOR) +#define TAG(x) x##_rgba +#include "radeon_maos_vbtmp.h" + +#define IDX 1 +#define IND (RADEON_CP_VC_FRMT_XY| \ + RADEON_CP_VC_FRMT_Z| \ + RADEON_CP_VC_FRMT_N0) +#define TAG(x) x##_n +#include "radeon_maos_vbtmp.h" + +#define IDX 2 +#define IND (RADEON_CP_VC_FRMT_XY| \ + RADEON_CP_VC_FRMT_Z| \ + RADEON_CP_VC_FRMT_PKCOLOR| \ + RADEON_CP_VC_FRMT_ST0) +#define TAG(x) x##_rgba_st +#include "radeon_maos_vbtmp.h" + +#define IDX 3 +#define IND (RADEON_CP_VC_FRMT_XY| \ + RADEON_CP_VC_FRMT_Z| \ + RADEON_CP_VC_FRMT_PKCOLOR| \ + RADEON_CP_VC_FRMT_N0) +#define TAG(x) x##_rgba_n +#include "radeon_maos_vbtmp.h" + +#define IDX 4 +#define IND (RADEON_CP_VC_FRMT_XY| \ + RADEON_CP_VC_FRMT_Z| \ + RADEON_CP_VC_FRMT_ST0| \ + RADEON_CP_VC_FRMT_N0) +#define TAG(x) x##_st_n +#include "radeon_maos_vbtmp.h" + +#define IDX 5 +#define IND (RADEON_CP_VC_FRMT_XY| \ + RADEON_CP_VC_FRMT_Z| \ + RADEON_CP_VC_FRMT_PKCOLOR| \ + RADEON_CP_VC_FRMT_ST0| \ + RADEON_CP_VC_FRMT_ST1) +#define TAG(x) x##_rgba_st_st +#include "radeon_maos_vbtmp.h" + +#define IDX 6 +#define IND (RADEON_CP_VC_FRMT_XY| \ + RADEON_CP_VC_FRMT_Z| \ + RADEON_CP_VC_FRMT_PKCOLOR| \ + RADEON_CP_VC_FRMT_ST0| \ + RADEON_CP_VC_FRMT_N0) +#define TAG(x) x##_rgba_st_n +#include "radeon_maos_vbtmp.h" + +#define IDX 7 +#define IND (RADEON_CP_VC_FRMT_XY| \ + RADEON_CP_VC_FRMT_Z| \ + RADEON_CP_VC_FRMT_PKCOLOR| \ + RADEON_CP_VC_FRMT_PKSPEC| \ + RADEON_CP_VC_FRMT_ST0| \ + RADEON_CP_VC_FRMT_ST1) +#define TAG(x) x##_rgba_spec_st_st +#include "radeon_maos_vbtmp.h" + +#define IDX 8 +#define IND (RADEON_CP_VC_FRMT_XY| \ + RADEON_CP_VC_FRMT_Z| \ + RADEON_CP_VC_FRMT_ST0| \ + RADEON_CP_VC_FRMT_ST1| \ + RADEON_CP_VC_FRMT_N0) +#define TAG(x) x##_st_st_n +#include "radeon_maos_vbtmp.h" + +#define IDX 9 +#define IND (RADEON_CP_VC_FRMT_XY| \ + RADEON_CP_VC_FRMT_Z| \ + RADEON_CP_VC_FRMT_PKCOLOR| \ + RADEON_CP_VC_FRMT_PKSPEC| \ + RADEON_CP_VC_FRMT_ST0| \ + RADEON_CP_VC_FRMT_ST1| \ + RADEON_CP_VC_FRMT_N0) +#define TAG(x) x##_rgpa_spec_st_st_n +#include "radeon_maos_vbtmp.h" + +#define IDX 10 +#define IND (RADEON_CP_VC_FRMT_XY| \ + RADEON_CP_VC_FRMT_Z| \ + RADEON_CP_VC_FRMT_PKCOLOR| \ + RADEON_CP_VC_FRMT_ST0| \ + RADEON_CP_VC_FRMT_Q0) +#define TAG(x) x##_rgba_stq +#include "radeon_maos_vbtmp.h" + +#define IDX 11 +#define IND (RADEON_CP_VC_FRMT_XY| \ + RADEON_CP_VC_FRMT_Z| \ + RADEON_CP_VC_FRMT_PKCOLOR| \ + RADEON_CP_VC_FRMT_ST1| \ + RADEON_CP_VC_FRMT_Q1| \ + RADEON_CP_VC_FRMT_ST0| \ + RADEON_CP_VC_FRMT_Q0) +#define TAG(x) x##_rgba_stq_stq +#include "radeon_maos_vbtmp.h" + +#define IDX 12 +#define IND (RADEON_CP_VC_FRMT_XY| \ + RADEON_CP_VC_FRMT_Z| \ + RADEON_CP_VC_FRMT_W0| \ + RADEON_CP_VC_FRMT_PKCOLOR| \ + RADEON_CP_VC_FRMT_PKSPEC| \ + RADEON_CP_VC_FRMT_ST0| \ + RADEON_CP_VC_FRMT_Q0| \ + RADEON_CP_VC_FRMT_ST1| \ + RADEON_CP_VC_FRMT_Q1| \ + RADEON_CP_VC_FRMT_N0) +#define TAG(x) x##_w_rgpa_spec_stq_stq_n +#include "radeon_maos_vbtmp.h" + + + + + +/*********************************************************************** + * Initialization + ***********************************************************************/ + + +static void init_tcl_verts( void ) +{ + init_rgba(); + init_n(); + init_rgba_n(); + init_rgba_st(); + init_st_n(); + init_rgba_st_st(); + init_rgba_st_n(); + init_rgba_spec_st_st(); + init_st_st_n(); + init_rgpa_spec_st_st_n(); + init_rgba_stq(); + init_rgba_stq_stq(); + init_w_rgpa_spec_stq_stq_n(); +} + + +void radeonEmitArrays( GLcontext *ctx, GLuint inputs ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + GLuint req = 0; + GLuint vtx = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] & + ~(RADEON_TCL_VTX_Q0|RADEON_TCL_VTX_Q1)); + int i; + static int firsttime = 1; + + if (firsttime) { + init_tcl_verts(); + firsttime = 0; + } + + if (1) { + req |= RADEON_CP_VC_FRMT_Z; + if (VB->ObjPtr->size == 4) { + req |= RADEON_CP_VC_FRMT_W0; + } + } + + if (inputs & VERT_NORM) { + req |= RADEON_CP_VC_FRMT_N0; + } + + if (inputs & VERT_RGBA) { + req |= RADEON_CP_VC_FRMT_PKCOLOR; + } + + if (inputs & VERT_SPEC_RGB) { + req |= RADEON_CP_VC_FRMT_PKSPEC; + } + + if (inputs & VERT_TEX0) { + req |= RADEON_CP_VC_FRMT_ST0; + + if (VB->TexCoordPtr[0]->size == 4) { + req |= RADEON_CP_VC_FRMT_Q0; + vtx |= RADEON_TCL_VTX_Q0; + } + } + + if (inputs & VERT_TEX1) { + req |= RADEON_CP_VC_FRMT_ST1; + + if (VB->TexCoordPtr[1]->size == 4) { + req |= RADEON_CP_VC_FRMT_Q1; + vtx |= RADEON_TCL_VTX_Q1; + } + } + + if (vtx != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT]) { + RADEON_STATECHANGE( rmesa, tcl ); + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] = vtx; + } + + for (i = 0 ; i < RADEON_TCL_MAX_SETUP ; i++) + if ((setup_tab[i].vertex_format & req) == req) + break; + + if (rmesa->tcl.vertex_format == setup_tab[i].vertex_format && + rmesa->tcl.indexed_verts.buf) + return; + + if (rmesa->tcl.indexed_verts.buf) + radeonReleaseArrays( ctx, ~0 ); + + radeonAllocDmaRegionVerts( rmesa, + &rmesa->tcl.indexed_verts, + VB->Count, + setup_tab[i].vertex_size * 4, + 4); + + setup_tab[i].emit( ctx, 0, VB->Count, + rmesa->tcl.indexed_verts.address + + rmesa->tcl.indexed_verts.start ); + + rmesa->tcl.vertex_format = setup_tab[i].vertex_format; + rmesa->tcl.indexed_verts.aos_start = GET_START( &rmesa->tcl.indexed_verts ); + rmesa->tcl.indexed_verts.aos_size = setup_tab[i].vertex_size; + rmesa->tcl.indexed_verts.aos_stride = setup_tab[i].vertex_size; + + rmesa->tcl.aos_components[0] = &rmesa->tcl.indexed_verts; + rmesa->tcl.nr_aos_components = 1; +} + + + +void radeonReleaseArrays( GLcontext *ctx, GLuint newinputs ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + + if (RADEON_DEBUG & DEBUG_VERTS) + _tnl_print_vert_flags( __FUNCTION__, newinputs ); + + if (newinputs) + radeonReleaseDmaRegion( rmesa, &rmesa->tcl.indexed_verts, __FUNCTION__ ); +} diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_sanity.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_sanity.c new file mode 100644 index 000000000..51c1d45c5 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_sanity.c @@ -0,0 +1,979 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_sanity.c,v 1.1 2002/10/30 12:51:55 alanh Exp $ */ +/************************************************************************** + +Copyright 2002 ATI Technologies Inc., Ontario, Canada, and + Tungsten Graphics Inc, Cedar Park, TX. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * + */ + +#include "radeon_context.h" +#include "radeon_ioctl.h" +#include "radeon_sanity.h" + +/* Set this '1' to get more verbiage. + */ +#define MORE_VERBOSE 1 + +#if MORE_VERBOSE +#define VERBOSE (RADEON_DEBUG & DEBUG_VERBOSE) +#define NORMAL (1) +#else +#define VERBOSE 0 +#define NORMAL (RADEON_DEBUG & DEBUG_VERBOSE) +#endif + + +/* New (1.3) state mechanism. 3 commands (packet, scalar, vector) in + * 1.3 cmdbuffers allow all previous state to be updated as well as + * the tcl scalar and vector areas. + */ +static struct { + int start; + int len; + const char *name; +} packet[RADEON_MAX_STATE_PACKETS] = { + { RADEON_PP_MISC,7,"RADEON_PP_MISC" }, + { RADEON_PP_CNTL,3,"RADEON_PP_CNTL" }, + { RADEON_RB3D_COLORPITCH,1,"RADEON_RB3D_COLORPITCH" }, + { RADEON_RE_LINE_PATTERN,2,"RADEON_RE_LINE_PATTERN" }, + { RADEON_SE_LINE_WIDTH,1,"RADEON_SE_LINE_WIDTH" }, + { RADEON_PP_LUM_MATRIX,1,"RADEON_PP_LUM_MATRIX" }, + { RADEON_PP_ROT_MATRIX_0,2,"RADEON_PP_ROT_MATRIX_0" }, + { RADEON_RB3D_STENCILREFMASK,3,"RADEON_RB3D_STENCILREFMASK" }, + { RADEON_SE_VPORT_XSCALE,6,"RADEON_SE_VPORT_XSCALE" }, + { RADEON_SE_CNTL,2,"RADEON_SE_CNTL" }, + { RADEON_SE_CNTL_STATUS,1,"RADEON_SE_CNTL_STATUS" }, + { RADEON_RE_MISC,1,"RADEON_RE_MISC" }, + { RADEON_PP_TXFILTER_0,6,"RADEON_PP_TXFILTER_0" }, + { RADEON_PP_BORDER_COLOR_0,1,"RADEON_PP_BORDER_COLOR_0" }, + { RADEON_PP_TXFILTER_1,6,"RADEON_PP_TXFILTER_1" }, + { RADEON_PP_BORDER_COLOR_1,1,"RADEON_PP_BORDER_COLOR_1" }, + { RADEON_PP_TXFILTER_2,6,"RADEON_PP_TXFILTER_2" }, + { RADEON_PP_BORDER_COLOR_2,1,"RADEON_PP_BORDER_COLOR_2" }, + { RADEON_SE_ZBIAS_FACTOR,2,"RADEON_SE_ZBIAS_FACTOR" }, + { RADEON_SE_TCL_OUTPUT_VTX_FMT,11,"RADEON_SE_TCL_OUTPUT_VTX_FMT" }, + { RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED,17,"RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED" }, +}; + +struct reg_names { + int idx; + const char *name; +}; + +static struct reg_names reg_names[] = { + { RADEON_PP_MISC, "RADEON_PP_MISC" }, + { RADEON_PP_FOG_COLOR, "RADEON_PP_FOG_COLOR" }, + { RADEON_RE_SOLID_COLOR, "RADEON_RE_SOLID_COLOR" }, + { RADEON_RB3D_BLENDCNTL, "RADEON_RB3D_BLENDCNTL" }, + { RADEON_RB3D_DEPTHOFFSET, "RADEON_RB3D_DEPTHOFFSET" }, + { RADEON_RB3D_DEPTHPITCH, "RADEON_RB3D_DEPTHPITCH" }, + { RADEON_RB3D_ZSTENCILCNTL, "RADEON_RB3D_ZSTENCILCNTL" }, + { RADEON_PP_CNTL, "RADEON_PP_CNTL" }, + { RADEON_RB3D_CNTL, "RADEON_RB3D_CNTL" }, + { RADEON_RB3D_COLOROFFSET, "RADEON_RB3D_COLOROFFSET" }, + { RADEON_RB3D_COLORPITCH, "RADEON_RB3D_COLORPITCH" }, + { RADEON_SE_CNTL, "RADEON_SE_CNTL" }, + { RADEON_SE_COORD_FMT, "RADEON_SE_COORDFMT" }, + { RADEON_SE_CNTL_STATUS, "RADEON_SE_CNTL_STATUS" }, + { RADEON_RE_LINE_PATTERN, "RADEON_RE_LINE_PATTERN" }, + { RADEON_RE_LINE_STATE, "RADEON_RE_LINE_STATE" }, + { RADEON_SE_LINE_WIDTH, "RADEON_SE_LINE_WIDTH" }, + { RADEON_RB3D_STENCILREFMASK, "RADEON_RB3D_STENCILREFMASK" }, + { RADEON_RB3D_ROPCNTL, "RADEON_RB3D_ROPCNTL" }, + { RADEON_RB3D_PLANEMASK, "RADEON_RB3D_PLANEMASK" }, + { RADEON_SE_VPORT_XSCALE, "RADEON_SE_VPORT_XSCALE" }, + { RADEON_SE_VPORT_XOFFSET, "RADEON_SE_VPORT_XOFFSET" }, + { RADEON_SE_VPORT_YSCALE, "RADEON_SE_VPORT_YSCALE" }, + { RADEON_SE_VPORT_YOFFSET, "RADEON_SE_VPORT_YOFFSET" }, + { RADEON_SE_VPORT_ZSCALE, "RADEON_SE_VPORT_ZSCALE" }, + { RADEON_SE_VPORT_ZOFFSET, "RADEON_SE_VPORT_ZOFFSET" }, + { RADEON_RE_MISC, "RADEON_RE_MISC" }, + { RADEON_PP_TXFILTER_0, "RADEON_PP_TXFILTER_0" }, + { RADEON_PP_TXFILTER_1, "RADEON_PP_TXFILTER_1" }, + { RADEON_PP_TXFILTER_2, "RADEON_PP_TXFILTER_2" }, + { RADEON_PP_TXFORMAT_0, "RADEON_PP_TXFORMAT_0" }, + { RADEON_PP_TXFORMAT_1, "RADEON_PP_TXFORMAT_1" }, + { RADEON_PP_TXFORMAT_2, "RADEON_PP_TXFORMAT_3" }, + { RADEON_PP_TXOFFSET_0, "RADEON_PP_TXOFFSET_0" }, + { RADEON_PP_TXOFFSET_1, "RADEON_PP_TXOFFSET_1" }, + { RADEON_PP_TXOFFSET_2, "RADEON_PP_TXOFFSET_3" }, + { RADEON_PP_TXCBLEND_0, "RADEON_PP_TXCBLEND_0" }, + { RADEON_PP_TXCBLEND_1, "RADEON_PP_TXCBLEND_1" }, + { RADEON_PP_TXCBLEND_2, "RADEON_PP_TXCBLEND_3" }, + { RADEON_PP_TXABLEND_0, "RADEON_PP_TXABLEND_0" }, + { RADEON_PP_TXABLEND_1, "RADEON_PP_TXABLEND_1" }, + { RADEON_PP_TXABLEND_2, "RADEON_PP_TXABLEND_3" }, + { RADEON_PP_TFACTOR_0, "RADEON_PP_TFACTOR_0" }, + { RADEON_PP_TFACTOR_1, "RADEON_PP_TFACTOR_1" }, + { RADEON_PP_TFACTOR_2, "RADEON_PP_TFACTOR_3" }, + { RADEON_PP_BORDER_COLOR_0, "RADEON_PP_BORDER_COLOR_0" }, + { RADEON_PP_BORDER_COLOR_1, "RADEON_PP_BORDER_COLOR_1" }, + { RADEON_PP_BORDER_COLOR_2, "RADEON_PP_BORDER_COLOR_3" }, + { RADEON_SE_ZBIAS_FACTOR, "RADEON_SE_ZBIAS_FACTOR" }, + { RADEON_SE_ZBIAS_CONSTANT, "RADEON_SE_ZBIAS_CONSTANT" }, + { RADEON_SE_TCL_OUTPUT_VTX_FMT, "RADEON_SE_TCL_OUTPUT_VTXFMT" }, + { RADEON_SE_TCL_OUTPUT_VTX_SEL, "RADEON_SE_TCL_OUTPUT_VTXSEL" }, + { RADEON_SE_TCL_MATRIX_SELECT_0, "RADEON_SE_TCL_MATRIX_SELECT_0" }, + { RADEON_SE_TCL_MATRIX_SELECT_1, "RADEON_SE_TCL_MATRIX_SELECT_1" }, + { RADEON_SE_TCL_UCP_VERT_BLEND_CTL, "RADEON_SE_TCL_UCP_VERT_BLEND_CTL" }, + { RADEON_SE_TCL_TEXTURE_PROC_CTL, "RADEON_SE_TCL_TEXTURE_PROC_CTL" }, + { RADEON_SE_TCL_LIGHT_MODEL_CTL, "RADEON_SE_TCL_LIGHT_MODEL_CTL" }, + { RADEON_SE_TCL_PER_LIGHT_CTL_0, "RADEON_SE_TCL_PER_LIGHT_CTL_0" }, + { RADEON_SE_TCL_PER_LIGHT_CTL_1, "RADEON_SE_TCL_PER_LIGHT_CTL_1" }, + { RADEON_SE_TCL_PER_LIGHT_CTL_2, "RADEON_SE_TCL_PER_LIGHT_CTL_2" }, + { RADEON_SE_TCL_PER_LIGHT_CTL_3, "RADEON_SE_TCL_PER_LIGHT_CTL_3" }, + { RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, "RADEON_SE_TCL_EMMISSIVE_RED" }, + { RADEON_SE_TCL_MATERIAL_EMMISSIVE_GREEN, "RADEON_SE_TCL_EMMISSIVE_GREEN" }, + { RADEON_SE_TCL_MATERIAL_EMMISSIVE_BLUE, "RADEON_SE_TCL_EMMISSIVE_BLUE" }, + { RADEON_SE_TCL_MATERIAL_EMMISSIVE_ALPHA, "RADEON_SE_TCL_EMMISSIVE_ALPHA" }, + { RADEON_SE_TCL_MATERIAL_AMBIENT_RED, "RADEON_SE_TCL_AMBIENT_RED" }, + { RADEON_SE_TCL_MATERIAL_AMBIENT_GREEN, "RADEON_SE_TCL_AMBIENT_GREEN" }, + { RADEON_SE_TCL_MATERIAL_AMBIENT_BLUE, "RADEON_SE_TCL_AMBIENT_BLUE" }, + { RADEON_SE_TCL_MATERIAL_AMBIENT_ALPHA, "RADEON_SE_TCL_AMBIENT_ALPHA" }, + { RADEON_SE_TCL_MATERIAL_DIFFUSE_RED, "RADEON_SE_TCL_DIFFUSE_RED" }, + { RADEON_SE_TCL_MATERIAL_DIFFUSE_GREEN, "RADEON_SE_TCL_DIFFUSE_GREEN" }, + { RADEON_SE_TCL_MATERIAL_DIFFUSE_BLUE, "RADEON_SE_TCL_DIFFUSE_BLUE" }, + { RADEON_SE_TCL_MATERIAL_DIFFUSE_ALPHA, "RADEON_SE_TCL_DIFFUSE_ALPHA" }, + { RADEON_SE_TCL_MATERIAL_SPECULAR_RED, "RADEON_SE_TCL_SPECULAR_RED" }, + { RADEON_SE_TCL_MATERIAL_SPECULAR_GREEN, "RADEON_SE_TCL_SPECULAR_GREEN" }, + { RADEON_SE_TCL_MATERIAL_SPECULAR_BLUE, "RADEON_SE_TCL_SPECULAR_BLUE" }, + { RADEON_SE_TCL_MATERIAL_SPECULAR_ALPHA, "RADEON_SE_TCL_SPECULAR_ALPHA" }, + { RADEON_SE_TCL_SHININESS, "RADEON_SE_TCL_SHININESS" }, + { RADEON_SE_COORD_FMT, "RADEON_SE_COORD_FMT" } +}; + +static struct reg_names scalar_names[] = { + { RADEON_SS_LIGHT_DCD_ADDR, "LIGHT_DCD" }, + { RADEON_SS_LIGHT_SPOT_EXPONENT_ADDR, "LIGHT_SPOT_EXPONENT" }, + { RADEON_SS_LIGHT_SPOT_CUTOFF_ADDR, "LIGHT_SPOT_CUTOFF" }, + { RADEON_SS_LIGHT_SPECULAR_THRESH_ADDR, "LIGHT_SPECULAR_THRESH" }, + { RADEON_SS_LIGHT_RANGE_CUTOFF_ADDR, "LIGHT_RANGE_CUTOFF" }, + { RADEON_SS_VERT_GUARD_CLIP_ADJ_ADDR, "VERT_GUARD_CLIP" }, + { RADEON_SS_VERT_GUARD_DISCARD_ADJ_ADDR, "VERT_GUARD_DISCARD" }, + { RADEON_SS_HORZ_GUARD_CLIP_ADJ_ADDR, "HORZ_GUARD_CLIP" }, + { RADEON_SS_HORZ_GUARD_DISCARD_ADJ_ADDR, "HORZ_GUARD_DISCARD" }, + { RADEON_SS_SHININESS, "SHININESS" }, + { 1000, "" }, +}; + +/* Puff these out to make them look like normal (dword) registers. + */ +static struct reg_names vector_names[] = { + { RADEON_VS_MATRIX_0_ADDR * 4, "MATRIX_0" }, + { RADEON_VS_MATRIX_1_ADDR * 4, "MATRIX_1" }, + { RADEON_VS_MATRIX_2_ADDR * 4, "MATRIX_2" }, + { RADEON_VS_MATRIX_3_ADDR * 4, "MATRIX_3" }, + { RADEON_VS_MATRIX_4_ADDR * 4, "MATRIX_4" }, + { RADEON_VS_MATRIX_5_ADDR * 4, "MATRIX_5" }, + { RADEON_VS_MATRIX_6_ADDR * 4, "MATRIX_6" }, + { RADEON_VS_MATRIX_7_ADDR * 4, "MATRIX_7" }, + { RADEON_VS_MATRIX_8_ADDR * 4, "MATRIX_8" }, + { RADEON_VS_MATRIX_9_ADDR * 4, "MATRIX_9" }, + { RADEON_VS_MATRIX_10_ADDR * 4, "MATRIX_10" }, + { RADEON_VS_MATRIX_11_ADDR * 4, "MATRIX_11" }, + { RADEON_VS_MATRIX_12_ADDR * 4, "MATRIX_12" }, + { RADEON_VS_MATRIX_13_ADDR * 4, "MATRIX_13" }, + { RADEON_VS_MATRIX_14_ADDR * 4, "MATRIX_14" }, + { RADEON_VS_MATRIX_15_ADDR * 4, "MATRIX_15" }, + { RADEON_VS_LIGHT_AMBIENT_ADDR * 4, "LIGHT_AMBIENT" }, + { RADEON_VS_LIGHT_DIFFUSE_ADDR * 4, "LIGHT_DIFFUSE" }, + { RADEON_VS_LIGHT_SPECULAR_ADDR * 4, "LIGHT_SPECULAR" }, + { RADEON_VS_LIGHT_DIRPOS_ADDR * 4, "LIGHT_DIRPOS" }, + { RADEON_VS_LIGHT_HWVSPOT_ADDR * 4, "LIGHT_HWVSPOT" }, + { RADEON_VS_LIGHT_ATTENUATION_ADDR * 4, "LIGHT_ATTENUATION" }, + { RADEON_VS_MATRIX_EYE2CLIP_ADDR * 4, "MATRIX_EYE2CLIP" }, + { RADEON_VS_UCP_ADDR * 4, "UCP" }, + { RADEON_VS_GLOBAL_AMBIENT_ADDR * 4, "GLOBAL_AMBIENT" }, + { RADEON_VS_FOG_PARAM_ADDR * 4, "FOG_PARAM" }, + { RADEON_VS_EYE_VECTOR_ADDR * 4, "EYE_VECTOR" }, + { 1000, "" }, +}; + +union fi { float f; int i; }; + +#define ISVEC 1 +#define ISFLOAT 2 +#define TOUCHED 4 + +struct reg { + int idx; + struct reg_names *closest; + int flags; + union fi current; + union fi *values; + int nvalues; + int nalloc; + float vmin, vmax; +}; + + +static struct reg regs[Elements(reg_names)+1]; +static struct reg scalars[512+1]; +static struct reg vectors[512*4+1]; + +static int total, total_changed, bufs; + +static void init_regs( void ) +{ + struct reg_names *tmp; + int i; + + for (i = 0 ; i < Elements(regs) ; i++) { + regs[i].idx = reg_names[i].idx; + regs[i].closest = ®_names[i]; + regs[i].flags = 0; + } + + for (i = 0, tmp = scalar_names ; i < Elements(scalars) ; i++) { + if (tmp[1].idx == i) tmp++; + scalars[i].idx = i; + scalars[i].closest = tmp; + scalars[i].flags = ISFLOAT; + } + + for (i = 0, tmp = vector_names ; i < Elements(vectors) ; i++) { + if (tmp[1].idx*4 == i) tmp++; + vectors[i].idx = i; + vectors[i].closest = tmp; + vectors[i].flags = ISFLOAT|ISVEC; + } + + regs[Elements(regs)-1].idx = -1; + scalars[Elements(scalars)-1].idx = -1; + vectors[Elements(vectors)-1].idx = -1; +} + +static int find_or_add_value( struct reg *reg, int val ) +{ + int j; + + for ( j = 0 ; j < reg->nvalues ; j++) + if ( val == reg->values[j].i ) + return 1; + + if (j == reg->nalloc) { + reg->nalloc += 5; + reg->nalloc *= 2; + reg->values = (union fi *) realloc( reg->values, + reg->nalloc * sizeof(union fi) ); + } + + reg->values[reg->nvalues++].i = val; + return 0; +} + +static struct reg *lookup_reg( struct reg *tab, int reg ) +{ + int i; + + for (i = 0 ; tab[i].idx != -1 ; i++) { + if (tab[i].idx == reg) + return &tab[i]; + } + + fprintf(stderr, "*** unknown reg 0x%x\n", reg); + return 0; +} + + +static const char *get_reg_name( struct reg *reg ) +{ + static char tmp[80]; + + if (reg->idx == reg->closest->idx) + return reg->closest->name; + + + if (reg->flags & ISVEC) { + if (reg->idx/4 != reg->closest->idx) + sprintf(tmp, "%s+%d[%d]", + reg->closest->name, + (reg->idx/4) - reg->closest->idx, + reg->idx%4); + else + sprintf(tmp, "%s[%d]", reg->closest->name, reg->idx%4); + } + else { + if (reg->idx != reg->closest->idx) + sprintf(tmp, "%s+%d", reg->closest->name, reg->idx - reg->closest->idx); + else + sprintf(tmp, "%s", reg->closest->name); + } + + return tmp; +} + +static int print_int_reg_assignment( struct reg *reg, int data ) +{ + int changed = (reg->current.i != data); + int ever_seen = find_or_add_value( reg, data ); + + if (VERBOSE || (NORMAL && (changed || !ever_seen))) + fprintf(stderr, " %s <-- 0x%x", get_reg_name(reg), data); + + if (NORMAL) { + if (!ever_seen) + fprintf(stderr, " *** BRAND NEW VALUE"); + else if (changed) + fprintf(stderr, " *** CHANGED"); + } + + reg->current.i = data; + + if (VERBOSE || (NORMAL && (changed || !ever_seen))) + fprintf(stderr, "\n"); + + return changed; +} + + +static int print_float_reg_assignment( struct reg *reg, float data ) +{ + int changed = (reg->current.f != data); + int newmin = (data < reg->vmin); + int newmax = (data > reg->vmax); + + if (VERBOSE || (NORMAL && (newmin || newmax || changed))) + fprintf(stderr, " %s <-- %.3f", get_reg_name(reg), data); + + if (NORMAL) { + if (newmin) { + fprintf(stderr, " *** NEW MIN (prev %.3f)", reg->vmin); + reg->vmin = data; + } + else if (newmax) { + fprintf(stderr, " *** NEW MAX (prev %.3f)", reg->vmax); + reg->vmax = data; + } + else if (changed) { + fprintf(stderr, " *** CHANGED"); + } + } + + reg->current.f = data; + + if (VERBOSE || (NORMAL && (newmin || newmax || changed))) + fprintf(stderr, "\n"); + + return changed; +} + +static int print_reg_assignment( struct reg *reg, int data ) +{ + reg->flags |= TOUCHED; + if (reg->flags & ISFLOAT) + return print_float_reg_assignment( reg, *(float *)&data ); + else + return print_int_reg_assignment( reg, data ); +} + +static void print_reg( struct reg *reg ) +{ + if (reg->flags & TOUCHED) { + if (reg->flags & ISFLOAT) { + fprintf(stderr, " %s == %f\n", get_reg_name(reg), reg->current.f); + } else { + fprintf(stderr, " %s == 0x%x\n", get_reg_name(reg), reg->current.i); + } + } +} + + +static void dump_state( void ) +{ + int i; + + for (i = 0 ; i < Elements(regs) ; i++) + print_reg( ®s[i] ); + + for (i = 0 ; i < Elements(scalars) ; i++) + print_reg( &scalars[i] ); + + for (i = 0 ; i < Elements(vectors) ; i++) + print_reg( &vectors[i] ); +} + + + +static int radeon_emit_packets( + drmRadeonCmdHeader header, + drmRadeonCmdBuffer *cmdbuf ) +{ + int id = (int)header.packet.packet_id; + int sz = packet[id].len; + int *data = (int *)cmdbuf->buf; + int i; + + if (sz * sizeof(int) > cmdbuf->bufsz) { + fprintf(stderr, "Packet overflows cmdbuf\n"); + return -EINVAL; + } + + if (!packet[id].name) { + fprintf(stderr, "*** Unknown packet 0 nr %d\n", id ); + return -EINVAL; + } + + + if (VERBOSE) + fprintf(stderr, "Packet 0 reg %s nr %d\n", packet[id].name, sz ); + + for ( i = 0 ; i < sz ; i++) { + struct reg *reg = lookup_reg( regs, packet[id].start + i*4 ); + if (print_reg_assignment( reg, data[i] )) + total_changed++; + total++; + } + + cmdbuf->buf += sz * sizeof(int); + cmdbuf->bufsz -= sz * sizeof(int); + return 0; +} + + +static int radeon_emit_scalars( + drmRadeonCmdHeader header, + drmRadeonCmdBuffer *cmdbuf ) +{ + int sz = header.scalars.count; + int *data = (int *)cmdbuf->buf; + int start = header.scalars.offset; + int stride = header.scalars.stride; + int i; + + if (VERBOSE) + fprintf(stderr, "emit scalars, start %d stride %d nr %d (end %d)\n", + start, stride, sz, start + stride * sz); + + + for (i = 0 ; i < sz ; i++, start += stride) { + struct reg *reg = lookup_reg( scalars, start ); + if (print_reg_assignment( reg, data[i] )) + total_changed++; + total++; + } + + cmdbuf->buf += sz * sizeof(int); + cmdbuf->bufsz -= sz * sizeof(int); + return 0; +} + + +static int radeon_emit_scalars2( + drmRadeonCmdHeader header, + drmRadeonCmdBuffer *cmdbuf ) +{ + int sz = header.scalars.count; + int *data = (int *)cmdbuf->buf; + int start = header.scalars.offset + 0x100; + int stride = header.scalars.stride; + int i; + + if (VERBOSE) + fprintf(stderr, "emit scalars2, start %d stride %d nr %d (end %d)\n", + start, stride, sz, start + stride * sz); + + if (start + stride * sz > 257) { + fprintf(stderr, "emit scalars OVERFLOW %d/%d/%d\n", start, stride, sz); + return -1; + } + + for (i = 0 ; i < sz ; i++, start += stride) { + struct reg *reg = lookup_reg( scalars, start ); + if (print_reg_assignment( reg, data[i] )) + total_changed++; + total++; + } + + cmdbuf->buf += sz * sizeof(int); + cmdbuf->bufsz -= sz * sizeof(int); + return 0; +} + +/* Check: inf/nan/extreme-size? + * Check: table start, end, nr, etc. + */ +static int radeon_emit_vectors( + drmRadeonCmdHeader header, + drmRadeonCmdBuffer *cmdbuf ) +{ + int sz = header.vectors.count; + int *data = (int *)cmdbuf->buf; + int start = header.vectors.offset; + int stride = header.vectors.stride; + int i,j; + + if (VERBOSE) + fprintf(stderr, "emit vectors, start %d stride %d nr %d (end %d) (0x%x)\n", + start, stride, sz, start + stride * sz, header.i); + +/* if (start + stride * (sz/4) > 128) { */ +/* fprintf(stderr, "emit vectors OVERFLOW %d/%d/%d\n", start, stride, sz); */ +/* return -1; */ +/* } */ + + for (i = 0 ; i < sz ; start += stride) { + int changed = 0; + for (j = 0 ; j < 4 ; i++,j++) { + struct reg *reg = lookup_reg( vectors, start*4+j ); + if (print_reg_assignment( reg, data[i] )) + changed = 1; + } + if (changed) + total_changed += 4; + total += 4; + } + + + cmdbuf->buf += sz * sizeof(int); + cmdbuf->bufsz -= sz * sizeof(int); + return 0; +} + + +static int print_vertex_format( int vfmt ) +{ + if (NORMAL) { + fprintf(stderr, " %s(%x): %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + "vertex format", + vfmt, + "xy,", + (vfmt & RADEON_CP_VC_FRMT_Z) ? "z," : "", + (vfmt & RADEON_CP_VC_FRMT_W0) ? "w0," : "", + (vfmt & RADEON_CP_VC_FRMT_FPCOLOR) ? "fpcolor," : "", + (vfmt & RADEON_CP_VC_FRMT_FPALPHA) ? "fpalpha," : "", + (vfmt & RADEON_CP_VC_FRMT_PKCOLOR) ? "pkcolor," : "", + (vfmt & RADEON_CP_VC_FRMT_FPSPEC) ? "fpspec," : "", + (vfmt & RADEON_CP_VC_FRMT_FPFOG) ? "fpfog," : "", + (vfmt & RADEON_CP_VC_FRMT_PKSPEC) ? "pkspec," : "", + (vfmt & RADEON_CP_VC_FRMT_ST0) ? "st0," : "", + (vfmt & RADEON_CP_VC_FRMT_ST1) ? "st1," : "", + (vfmt & RADEON_CP_VC_FRMT_Q1) ? "q1," : "", + (vfmt & RADEON_CP_VC_FRMT_ST2) ? "st2," : "", + (vfmt & RADEON_CP_VC_FRMT_Q2) ? "q2," : "", + (vfmt & RADEON_CP_VC_FRMT_ST3) ? "st3," : "", + (vfmt & RADEON_CP_VC_FRMT_Q3) ? "q3," : "", + (vfmt & RADEON_CP_VC_FRMT_Q0) ? "q0," : "", + (vfmt & RADEON_CP_VC_FRMT_N0) ? "n0," : "", + (vfmt & RADEON_CP_VC_FRMT_XY1) ? "xy1," : "", + (vfmt & RADEON_CP_VC_FRMT_Z1) ? "z1," : "", + (vfmt & RADEON_CP_VC_FRMT_W1) ? "w1," : "", + (vfmt & RADEON_CP_VC_FRMT_N1) ? "n1," : ""); + + +/* if (!find_or_add_value( &others[V_VTXFMT], vfmt )) */ +/* fprintf(stderr, " *** NEW VALUE"); */ + + fprintf(stderr, "\n"); + } + + return 0; +} + +static char *primname[0xf] = { + "NONE", + "POINT", + "LINE", + "LINE_STRIP", + "TRI_LIST", + "TRI_FAN", + "TRI_STRIP", + "TRI_TYPE_2", + "RECT_LIST", + "3VRT_POINT_LIST", + "3VRT_LINE_LIST", +}; + +static int print_prim_and_flags( int prim ) +{ + int numverts; + + if (NORMAL) + fprintf(stderr, " %s(%x): %s%s%s%s%s%s%s\n", + "prim flags", + prim, + ((prim & 0x30) == RADEON_CP_VC_CNTL_PRIM_WALK_IND) ? "IND," : "", + ((prim & 0x30) == RADEON_CP_VC_CNTL_PRIM_WALK_LIST) ? "LIST," : "", + ((prim & 0x30) == RADEON_CP_VC_CNTL_PRIM_WALK_RING) ? "RING," : "", + (prim & RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA) ? "RGBA," : "BGRA, ", + (prim & RADEON_CP_VC_CNTL_MAOS_ENABLE) ? "MAOS," : "", + (prim & RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE) ? "RADEON," : "", + (prim & RADEON_CP_VC_CNTL_TCL_ENABLE) ? "TCL," : ""); + + if ((prim & 0xf) > RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST) { + fprintf(stderr, " *** Bad primitive: %x\n", prim & 0xf); + return -1; + } + + numverts = prim>>16; + + if (NORMAL) + fprintf(stderr, " prim: %s numverts %d\n", primname[prim&0xf], numverts); + + switch (prim & 0xf) { + case RADEON_CP_VC_CNTL_PRIM_TYPE_NONE: + case RADEON_CP_VC_CNTL_PRIM_TYPE_POINT: + if (numverts < 1) { + fprintf(stderr, "Bad nr verts for line %d\n", numverts); + return -1; + } + break; + case RADEON_CP_VC_CNTL_PRIM_TYPE_LINE: + if ((numverts & 1) || numverts == 0) { + fprintf(stderr, "Bad nr verts for line %d\n", numverts); + return -1; + } + break; + case RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP: + if (numverts < 2) { + fprintf(stderr, "Bad nr verts for line_strip %d\n", numverts); + return -1; + } + break; + case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST: + case RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_POINT_LIST: + case RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST: + case RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST: + if (numverts % 3 || numverts == 0) { + fprintf(stderr, "Bad nr verts for tri %d\n", numverts); + return -1; + } + break; + case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN: + case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP: + if (numverts < 3) { + fprintf(stderr, "Bad nr verts for strip/fan %d\n", numverts); + return -1; + } + break; + default: + fprintf(stderr, "Bad primitive\n"); + return -1; + } + return 0; +} + +/* build in knowledge about each packet type + */ +static int radeon_emit_packet3( drmRadeonCmdBuffer *cmdbuf ) +{ + int cmdsz; + int *cmd = (int *)cmdbuf->buf; + int *tmp; + int i, stride, size, start; + + cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16); + + if ((cmd[0] & RADEON_CP_PACKET_MASK) != RADEON_CP_PACKET3 || + cmdsz * 4 > cmdbuf->bufsz || + cmdsz > RADEON_CP_PACKET_MAX_DWORDS) { + fprintf(stderr, "Bad packet\n"); + return -EINVAL; + } + + switch( cmd[0] & ~RADEON_CP_PACKET_COUNT_MASK ) { + case RADEON_CP_PACKET3_NOP: + if (NORMAL) + fprintf(stderr, "PACKET3_NOP, %d dwords\n", cmdsz); + break; + case RADEON_CP_PACKET3_NEXT_CHAR: + if (NORMAL) + fprintf(stderr, "PACKET3_NEXT_CHAR, %d dwords\n", cmdsz); + break; + case RADEON_CP_PACKET3_PLY_NEXTSCAN: + if (NORMAL) + fprintf(stderr, "PACKET3_PLY_NEXTSCAN, %d dwords\n", cmdsz); + break; + case RADEON_CP_PACKET3_SET_SCISSORS: + if (NORMAL) + fprintf(stderr, "PACKET3_SET_SCISSORS, %d dwords\n", cmdsz); + break; + case RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM: + if (NORMAL) + fprintf(stderr, "PACKET3_3D_RNDR_GEN_INDX_PRIM, %d dwords\n", + cmdsz); + break; + case RADEON_CP_PACKET3_LOAD_MICROCODE: + if (NORMAL) + fprintf(stderr, "PACKET3_LOAD_MICROCODE, %d dwords\n", cmdsz); + break; + case RADEON_CP_PACKET3_WAIT_FOR_IDLE: + if (NORMAL) + fprintf(stderr, "PACKET3_WAIT_FOR_IDLE, %d dwords\n", cmdsz); + break; + + case RADEON_CP_PACKET3_3D_DRAW_VBUF: + if (NORMAL) + fprintf(stderr, "PACKET3_3D_DRAW_VBUF, %d dwords\n", cmdsz); + print_vertex_format(cmd[1]); + print_prim_and_flags(cmd[2]); + break; + + case RADEON_CP_PACKET3_3D_DRAW_IMMD: + if (NORMAL) + fprintf(stderr, "PACKET3_3D_DRAW_IMMD, %d dwords\n", cmdsz); + break; + case RADEON_CP_PACKET3_3D_DRAW_INDX: { + int neltdwords; + if (NORMAL) + fprintf(stderr, "PACKET3_3D_DRAW_INDX, %d dwords\n", cmdsz); + print_vertex_format(cmd[1]); + print_prim_and_flags(cmd[2]); + neltdwords = cmd[2]>>16; + neltdwords += neltdwords & 1; + neltdwords /= 2; + if (neltdwords + 3 != cmdsz) + fprintf(stderr, "Mismatch in DRAW_INDX, %d vs cmdsz %d\n", + neltdwords, cmdsz); + break; + } + case RADEON_CP_PACKET3_LOAD_PALETTE: + if (NORMAL) + fprintf(stderr, "PACKET3_LOAD_PALETTE, %d dwords\n", cmdsz); + break; + case RADEON_CP_PACKET3_3D_LOAD_VBPNTR: + if (NORMAL) { + fprintf(stderr, "PACKET3_3D_LOAD_VBPNTR, %d dwords\n", cmdsz); + fprintf(stderr, " nr arrays: %d\n", cmd[1]); + } + + if (cmd[1]/2 + cmd[1]%2 != cmdsz - 3) { + fprintf(stderr, " ****** MISMATCH %d/%d *******\n", + cmd[1]/2 + cmd[1]%2 + 3, cmdsz); + return -EINVAL; + } + + if (NORMAL) { + tmp = cmd+2; + for (i = 0 ; i < cmd[1] ; i++) { + if (i & 1) { + stride = (tmp[0]>>24) & 0xff; + size = (tmp[0]>>16) & 0xff; + start = tmp[2]; + tmp += 3; + } + else { + stride = (tmp[0]>>8) & 0xff; + size = (tmp[0]) & 0xff; + start = tmp[1]; + } + fprintf(stderr, " array %d: start 0x%x vsize %d vstride %d\n", + i, start, size, stride ); + } + } + break; + case RADEON_CP_PACKET3_CNTL_PAINT: + if (NORMAL) + fprintf(stderr, "PACKET3_CNTL_PAINT, %d dwords\n", cmdsz); + break; + case RADEON_CP_PACKET3_CNTL_BITBLT: + if (NORMAL) + fprintf(stderr, "PACKET3_CNTL_BITBLT, %d dwords\n", cmdsz); + break; + case RADEON_CP_PACKET3_CNTL_SMALLTEXT: + if (NORMAL) + fprintf(stderr, "PACKET3_CNTL_SMALLTEXT, %d dwords\n", cmdsz); + break; + case RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT: + if (NORMAL) + fprintf(stderr, "PACKET3_CNTL_HOSTDATA_BLT, %d dwords\n", + cmdsz); + break; + case RADEON_CP_PACKET3_CNTL_POLYLINE: + if (NORMAL) + fprintf(stderr, "PACKET3_CNTL_POLYLINE, %d dwords\n", cmdsz); + break; + case RADEON_CP_PACKET3_CNTL_POLYSCANLINES: + if (NORMAL) + fprintf(stderr, "PACKET3_CNTL_POLYSCANLINES, %d dwords\n", + cmdsz); + break; + case RADEON_CP_PACKET3_CNTL_PAINT_MULTI: + if (NORMAL) + fprintf(stderr, "PACKET3_CNTL_PAINT_MULTI, %d dwords\n", + cmdsz); + break; + case RADEON_CP_PACKET3_CNTL_BITBLT_MULTI: + if (NORMAL) + fprintf(stderr, "PACKET3_CNTL_BITBLT_MULTI, %d dwords\n", + cmdsz); + break; + case RADEON_CP_PACKET3_CNTL_TRANS_BITBLT: + if (NORMAL) + fprintf(stderr, "PACKET3_CNTL_TRANS_BITBLT, %d dwords\n", + cmdsz); + break; + default: + fprintf(stderr, "UNKNOWN PACKET, %d dwords\n", cmdsz); + break; + } + + cmdbuf->buf += cmdsz * 4; + cmdbuf->bufsz -= cmdsz * 4; + return 0; +} + + +/* Check cliprects for bounds, then pass on to above: + */ +static int radeon_emit_packet3_cliprect( drmRadeonCmdBuffer *cmdbuf ) +{ + XF86DRIClipRectRec *boxes = (XF86DRIClipRectRec *)cmdbuf->boxes; + int i = 0; + + if (VERBOSE && total_changed) { + dump_state(); + total_changed = 0; + } + else fprintf(stderr, "total_changed zero\n"); + + if (NORMAL) { + do { + if ( i < cmdbuf->nbox ) { + fprintf(stderr, "Emit box %d/%d %d,%d %d,%d\n", + i, cmdbuf->nbox, + boxes[i].x1, boxes[i].y1, boxes[i].x2, boxes[i].y2); + } + } while ( ++i < cmdbuf->nbox ); + } + + if (cmdbuf->nbox == 1) + cmdbuf->nbox = 0; + + return radeon_emit_packet3( cmdbuf ); +} + + +int radeonSanityCmdBuffer( radeonContextPtr rmesa, + int nbox, + XF86DRIClipRectRec *boxes ) +{ + int idx; + drmRadeonCmdBuffer cmdbuf; + drmRadeonCmdHeader header; + static int inited = 0; + + if (!inited) { + init_regs(); + inited = 1; + } + + cmdbuf.buf = rmesa->store.cmd_buf; + cmdbuf.bufsz = rmesa->store.cmd_used; + cmdbuf.boxes = (drmClipRect *)boxes; + cmdbuf.nbox = nbox; + + while ( cmdbuf.bufsz >= sizeof(header) ) { + + header.i = *(int *)cmdbuf.buf; + cmdbuf.buf += sizeof(header); + cmdbuf.bufsz -= sizeof(header); + + switch (header.header.cmd_type) { + case RADEON_CMD_PACKET: + if (radeon_emit_packets( header, &cmdbuf )) { + fprintf(stderr,"radeon_emit_packets failed\n"); + return -EINVAL; + } + break; + + case RADEON_CMD_SCALARS: + if (radeon_emit_scalars( header, &cmdbuf )) { + fprintf(stderr,"radeon_emit_scalars failed\n"); + return -EINVAL; + } + break; + + case RADEON_CMD_SCALARS2: + if (radeon_emit_scalars2( header, &cmdbuf )) { + fprintf(stderr,"radeon_emit_scalars failed\n"); + return -EINVAL; + } + break; + + case RADEON_CMD_VECTORS: + if (radeon_emit_vectors( header, &cmdbuf )) { + fprintf(stderr,"radeon_emit_vectors failed\n"); + return -EINVAL; + } + break; + + case RADEON_CMD_DMA_DISCARD: + idx = header.dma.buf_idx; + if (NORMAL) + fprintf(stderr, "RADEON_CMD_DMA_DISCARD buf %d\n", idx); + bufs++; + break; + + case RADEON_CMD_PACKET3: + if (radeon_emit_packet3( &cmdbuf )) { + fprintf(stderr,"radeon_emit_packet3 failed\n"); + return -EINVAL; + } + break; + + case RADEON_CMD_PACKET3_CLIP: + if (radeon_emit_packet3_cliprect( &cmdbuf )) { + fprintf(stderr,"radeon_emit_packet3_clip failed\n"); + return -EINVAL; + } + break; + + case RADEON_CMD_WAIT: + break; + + default: + fprintf(stderr,"bad cmd_type %d at %p\n", + header.header.cmd_type, + cmdbuf.buf - sizeof(header)); + return -EINVAL; + } + } + + if (0) + { + static int n = 0; + n++; + if (n == 10) { + fprintf(stderr, "Bufs %d Total emitted %d real changes %d (%.2f%%)\n", + bufs, + total, total_changed, + ((float)total_changed/(float)total*100.0)); + fprintf(stderr, "Total emitted per buf: %.2f\n", + (float)total/(float)bufs); + fprintf(stderr, "Real changes per buf: %.2f\n", + (float)total_changed/(float)bufs); + + bufs = n = total = total_changed = 0; + } + } + + return 0; +} diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_sanity.h b/xc/lib/GL/mesa/src/drv/radeon/radeon_sanity.h new file mode 100644 index 000000000..58e8335dd --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_sanity.h @@ -0,0 +1,8 @@ +#ifndef RADEON_SANITY_H +#define RADEON_SANITY_H + +extern int radeonSanityCmdBuffer( radeonContextPtr rmesa, + int nbox, + XF86DRIClipRectRec *boxes ); + +#endif diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_screen.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_screen.c index 443cdfc3a..a45974624 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_screen.c +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_screen.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_screen.c,v 1.4 2002/02/22 21:45:00 dawes Exp $ */ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_screen.c,v 1.6 2002/12/16 16:18:58 dawes Exp $ */ /************************************************************************** Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and @@ -35,11 +35,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "radeon_screen.h" -#include "radeon_context.h" -#include "radeon_ioctl.h" - #include "mem.h" + #if 1 /* Including xf86PciInfo.h introduces a bunch of errors... */ @@ -47,6 +45,16 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define PCI_CHIP_RADEON_QE 0x5145 #define PCI_CHIP_RADEON_QF 0x5146 #define PCI_CHIP_RADEON_QG 0x5147 + +#define PCI_CHIP_RADEON_QY 0x5159 +#define PCI_CHIP_RADEON_QZ 0x515A + +#define PCI_CHIP_RADEON_LW 0x4C57 /* mobility 7 - has tcl */ + +#define PCI_CHIP_RADEON_LY 0x4C59 +#define PCI_CHIP_RADEON_LZ 0x4C5A + +#define PCI_CHIP_RV200_QW 0x5157 /* a confusing name for a radeon */ #endif @@ -62,7 +70,9 @@ radeonScreenPtr radeonCreateScreen( __DRIscreenPrivate *sPriv ) int major, minor, patch; if ( XF86DRIQueryVersion( sPriv->display, &major, &minor, &patch ) ) { if ( major != 4 || minor < 0 ) { - __driUtilMessage( "Radeon DRI driver expected DRI version 4.0.x but got version %d.%d.%d", major, minor, patch ); + __driUtilMessage( "Radeon DRI driver expected DRI version 4.0.x " + "but got version %d.%d.%d", + major, minor, patch ); return NULL; } } @@ -71,29 +81,78 @@ radeonScreenPtr radeonCreateScreen( __DRIscreenPrivate *sPriv ) /* Check that the DDX driver version is compatible */ if ( sPriv->ddxMajor != 4 || sPriv->ddxMinor < 0 ) { - __driUtilMessage( "Radeon DRI driver expected DDX driver version 4.0.x but got version %d.%d.%d", sPriv->ddxMajor, sPriv->ddxMinor, sPriv->ddxPatch ); + __driUtilMessage( "Radeon DRI driver expected DDX driver version 4.0.x " + "but got version %d.%d.%d", + sPriv->ddxMajor, sPriv->ddxMinor, sPriv->ddxPatch ); return NULL; } /* Check that the DRM driver version is compatible */ + /* KW: Check minor number here too -- compatibility mode is broken + * atm. + */ if ( sPriv->drmMajor != 1 || - sPriv->drmMinor < 2 ) { - __driUtilMessage( "Radeon DRI driver expected DRM driver version 1.2.x but got version %d.%d.%d", sPriv->drmMajor, sPriv->drmMinor, sPriv->drmPatch ); + sPriv->drmMinor < 3) { + __driUtilMessage( "Radeon DRI driver expected DRM driver version 1.3.x " + "or newer but got version %d.%d.%d", + sPriv->drmMajor, sPriv->drmMinor, sPriv->drmPatch ); return NULL; } + /* Allocate the private area */ radeonScreen = (radeonScreenPtr) CALLOC( sizeof(*radeonScreen) ); if ( !radeonScreen ) { - __driUtilMessage("radeonCreateScreen(): CALLOC radeonScreen struct failed"); + __driUtilMessage("%s: CALLOC radeonScreen struct failed", + __FUNCTION__); return NULL; } + if ( sPriv->drmMinor < 3 || + getenv("RADEON_COMPAT")) { + fprintf( stderr, "Radeon DRI driver:\n\t" + "Compatibility mode for DRM driver version %d.%d.%d\n\t" + "TCL will be disabled, expect reduced performance\n\t" + "(prefer DRM radeon.o 1.3.x or newer)\n\t", + sPriv->drmMajor, sPriv->drmMinor, sPriv->drmPatch ); + } + + /* This is first since which regions we map depends on whether or * not we are using a PCI card. */ radeonScreen->IsPCI = radeonDRIPriv->IsPCI; + if (sPriv->drmMinor >= 3) { + int ret; + drmRadeonGetParam gp; + + gp.param = RADEON_PARAM_AGP_BUFFER_OFFSET; + gp.value = &radeonScreen->agp_buffer_offset; + + ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM, + &gp, sizeof(gp)); + if (ret) { + FREE( radeonScreen ); + fprintf(stderr, "drmRadeonGetParam (RADEON_PARAM_AGP_BUFFER_OFFSET): %d\n", ret); + return NULL; + } + + if (sPriv->drmMinor >= 6) { + gp.param = RADEON_PARAM_IRQ_NR; + gp.value = &radeonScreen->irq; + + ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM, + &gp, sizeof(gp)); + if (ret) { + FREE( radeonScreen ); + fprintf(stderr, "drmRadeonGetParam (RADEON_PARAM_IRQ_NR): %d\n", ret); + return NULL; + } + } + + } + radeonScreen->mmio.handle = radeonDRIPriv->registerHandle; radeonScreen->mmio.size = radeonDRIPriv->registerSize; if ( drmMap( sPriv->fd, @@ -144,16 +203,21 @@ radeonScreenPtr radeonCreateScreen( __DRIscreenPrivate *sPriv ) } } - + radeonScreen->chipset = 0; switch ( radeonDRIPriv->deviceID ) { + default: + fprintf(stderr, "unknown chip id, assuming full radeon support\n"); case PCI_CHIP_RADEON_QD: case PCI_CHIP_RADEON_QE: case PCI_CHIP_RADEON_QF: case PCI_CHIP_RADEON_QG: - radeonScreen->chipset = RADEON_CARD_TYPE_RADEON; - break; - default: - radeonScreen->chipset = RADEON_CARD_TYPE_RADEON; + case PCI_CHIP_RV200_QW: + case PCI_CHIP_RADEON_LW: + radeonScreen->chipset |= RADEON_CHIPSET_TCL; + case PCI_CHIP_RADEON_QY: + case PCI_CHIP_RADEON_QZ: + case PCI_CHIP_RADEON_LY: + case PCI_CHIP_RADEON_LZ: break; } diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_screen.h b/xc/lib/GL/mesa/src/drv/radeon/radeon_screen.h index b5f11bcad..12cecd0dc 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_screen.h +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_screen.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_screen.h,v 1.3 2002/02/22 21:45:01 dawes Exp $ */ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_screen.h,v 1.5 2002/12/16 16:18:58 dawes Exp $ */ /************************************************************************** Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and @@ -39,24 +39,33 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #ifdef GLX_DIRECT_RENDERING -#include <X11/Xlibint.h> +/* + * IMPORTS: these headers contain all the DRI, X and kernel-related + * definitions that we need. + */ #include "dri_util.h" -#include "xf86drm.h" -#include "xf86drmRadeon.h" +#include "radeon_common.h" +#include "radeon_dri.h" +#include "radeon_reg.h" #include "radeon_sarea.h" + typedef struct { drmHandle handle; /* Handle to the DRM region */ drmSize size; /* Size of the DRM region */ drmAddress map; /* Mapping of the DRM region */ } radeonRegionRec, *radeonRegionPtr; +/* chipset features */ +#define RADEON_CHIPSET_TCL (1 << 0) + typedef struct { int chipset; int cpp; int IsPCI; /* Current card is a PCI card */ int AGPMode; + unsigned int irq; /* IRQ number (0 means none) */ unsigned int frontOffset; unsigned int frontPitch; @@ -82,6 +91,7 @@ typedef struct { __DRIscreenPrivate *driScreen; unsigned int sarea_priv_offset; + unsigned int agp_buffer_offset; /* offset in card memory space */ } radeonScreenRec, *radeonScreenPtr; extern radeonScreenPtr radeonCreateScreen( __DRIscreenPrivate *sPriv ); diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_span.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_span.c index 41a2668df..044073320 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_span.c +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_span.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_span.c,v 1.5 2002/02/22 21:45:01 dawes Exp $ */ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_span.c,v 1.6 2002/10/30 12:51:56 alanh Exp $ */ /************************************************************************** Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and @@ -31,7 +31,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. * Authors: * Kevin E. Martin <martin@valinux.com> * Gareth Hughes <gareth@valinux.com> - * Keith Whitwell <keithw@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> * */ @@ -292,12 +292,22 @@ static void radeonSetReadBuffer( GLcontext *ctx, switch ( mode ) { case GL_FRONT_LEFT: - rmesa->state.pixel.readOffset = rmesa->radeonScreen->frontOffset; - rmesa->state.pixel.readPitch = rmesa->radeonScreen->frontPitch; + if ( rmesa->sarea->pfCurrentPage == 1 ) { + rmesa->state.pixel.readOffset = rmesa->radeonScreen->backOffset; + rmesa->state.pixel.readPitch = rmesa->radeonScreen->backPitch; + } else { + rmesa->state.pixel.readOffset = rmesa->radeonScreen->frontOffset; + rmesa->state.pixel.readPitch = rmesa->radeonScreen->frontPitch; + } break; case GL_BACK_LEFT: - rmesa->state.pixel.readOffset = rmesa->radeonScreen->backOffset; - rmesa->state.pixel.readPitch = rmesa->radeonScreen->backPitch; + if ( rmesa->sarea->pfCurrentPage == 1 ) { + rmesa->state.pixel.readOffset = rmesa->radeonScreen->frontOffset; + rmesa->state.pixel.readPitch = rmesa->radeonScreen->frontPitch; + } else { + rmesa->state.pixel.readOffset = rmesa->radeonScreen->backOffset; + rmesa->state.pixel.readPitch = rmesa->radeonScreen->backPitch; + } break; default: assert(0); diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_state.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_state.c index 9077ee43f..fd921f8f9 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_state.c +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_state.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_state.c,v 1.5 2002/09/16 18:05:20 eich Exp $ */ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_state.c,v 1.8 2002/12/16 16:18:58 dawes Exp $ */ /* * Copyright 2000, 2001 VA Linux Systems Inc., Fremont, California. * @@ -25,19 +25,23 @@ * * Authors: * Gareth Hughes <gareth@valinux.com> - * Keith Whitwell <keithw@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> */ #include "radeon_context.h" -#include "radeon_state.h" #include "radeon_ioctl.h" -#include "radeon_tris.h" -#include "radeon_vb.h" +#include "radeon_state.h" +#include "radeon_tcl.h" #include "radeon_tex.h" +#include "radeon_swtcl.h" +#include "radeon_vtxfmt.h" +#include "mem.h" #include "mmath.h" #include "enums.h" #include "colormac.h" +#include "light.h" +#include "api_arrayelt.h" #include "swrast/swrast.h" #include "array_cache/acache.h" @@ -46,6 +50,14 @@ #include "swrast_setup/swrast_setup.h" +#define MODEL_PROJ 0 +#define MODEL 1 +#define MODEL_IT 2 +#define TEXMAT_0 3 +#define TEXMAT_1 4 +#define TEXMAT_2 5 + + /* ============================================================= * Alpha blending */ @@ -53,55 +65,56 @@ static void radeonAlphaFunc( GLcontext *ctx, GLenum func, GLchan ref ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + int pp_misc = rmesa->hw.ctx.cmd[CTX_PP_MISC]; - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); + RADEON_STATECHANGE( rmesa, ctx ); - rmesa->state.hw.context.pp_misc &= ~(RADEON_ALPHA_TEST_OP_MASK | - RADEON_REF_ALPHA_MASK); + pp_misc &= ~(RADEON_ALPHA_TEST_OP_MASK | RADEON_REF_ALPHA_MASK); + pp_misc |= (ref & RADEON_REF_ALPHA_MASK); switch ( func ) { case GL_NEVER: - rmesa->state.hw.context.pp_misc |= RADEON_ALPHA_TEST_FAIL; + pp_misc |= RADEON_ALPHA_TEST_FAIL; break; case GL_LESS: - rmesa->state.hw.context.pp_misc |= RADEON_ALPHA_TEST_LESS; + pp_misc |= RADEON_ALPHA_TEST_LESS; break; case GL_EQUAL: - rmesa->state.hw.context.pp_misc |= RADEON_ALPHA_TEST_EQUAL; + pp_misc |= RADEON_ALPHA_TEST_EQUAL; break; case GL_LEQUAL: - rmesa->state.hw.context.pp_misc |= RADEON_ALPHA_TEST_LEQUAL; + pp_misc |= RADEON_ALPHA_TEST_LEQUAL; break; case GL_GREATER: - rmesa->state.hw.context.pp_misc |= RADEON_ALPHA_TEST_GREATER; + pp_misc |= RADEON_ALPHA_TEST_GREATER; break; case GL_NOTEQUAL: - rmesa->state.hw.context.pp_misc |= RADEON_ALPHA_TEST_NEQUAL; + pp_misc |= RADEON_ALPHA_TEST_NEQUAL; break; case GL_GEQUAL: - rmesa->state.hw.context.pp_misc |= RADEON_ALPHA_TEST_GEQUAL; + pp_misc |= RADEON_ALPHA_TEST_GEQUAL; break; case GL_ALWAYS: - rmesa->state.hw.context.pp_misc |= RADEON_ALPHA_TEST_PASS; + pp_misc |= RADEON_ALPHA_TEST_PASS; break; } - rmesa->state.hw.context.pp_misc |= (ref & RADEON_REF_ALPHA_MASK); + rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc; } static void radeonBlendEquation( GLcontext *ctx, GLenum mode ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - GLuint b = rmesa->state.hw.context.rb3d_blendcntl & ~RADEON_COMB_FCN_MASK; + GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & ~RADEON_COMB_FCN_MASK; GLboolean fallback = GL_FALSE; switch ( mode ) { - case GL_FUNC_ADD_EXT: + case GL_FUNC_ADD: case GL_LOGIC_OP: b |= RADEON_COMB_FCN_ADD_CLAMP; break; - case GL_FUNC_SUBTRACT_EXT: + case GL_FUNC_SUBTRACT: b |= RADEON_COMB_FCN_SUB_CLAMP; break; @@ -112,12 +125,12 @@ static void radeonBlendEquation( GLcontext *ctx, GLenum mode ) FALLBACK( rmesa, RADEON_FALLBACK_BLEND_EQ, fallback ); if ( !fallback ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); - rmesa->state.hw.context.rb3d_blendcntl = b; + RADEON_STATECHANGE( rmesa, ctx ); + rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b; if ( ctx->Color.ColorLogicOpEnabled ) { - rmesa->state.hw.context.rb3d_cntl |= RADEON_ROP_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE; } else { - rmesa->state.hw.context.rb3d_cntl &= ~RADEON_ROP_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE; } } } @@ -125,8 +138,8 @@ static void radeonBlendEquation( GLcontext *ctx, GLenum mode ) static void radeonBlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - GLuint b = rmesa->state.hw.context.rb3d_blendcntl & ~(RADEON_SRC_BLEND_MASK | - RADEON_DST_BLEND_MASK); + GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & + ~(RADEON_SRC_BLEND_MASK | RADEON_DST_BLEND_MASK); GLboolean fallback = GL_FALSE; switch ( ctx->Color.BlendSrcRGB ) { @@ -142,6 +155,12 @@ static void radeonBlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor ) case GL_ONE_MINUS_DST_COLOR: b |= RADEON_SRC_BLEND_GL_ONE_MINUS_DST_COLOR; break; + case GL_SRC_COLOR: + b |= RADEON_SRC_BLEND_GL_SRC_COLOR; + break; + case GL_ONE_MINUS_SRC_COLOR: + b |= RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR; + break; case GL_SRC_ALPHA: b |= RADEON_SRC_BLEND_GL_SRC_ALPHA; break; @@ -184,6 +203,12 @@ static void radeonBlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor ) case GL_ONE_MINUS_SRC_ALPHA: b |= RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA; break; + case GL_DST_COLOR: + b |= RADEON_DST_BLEND_GL_DST_COLOR; + break; + case GL_ONE_MINUS_DST_COLOR: + b |= RADEON_DST_BLEND_GL_ONE_MINUS_DST_COLOR; + break; case GL_DST_ALPHA: b |= RADEON_DST_BLEND_GL_DST_ALPHA; break; @@ -200,8 +225,8 @@ static void radeonBlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor ) FALLBACK( rmesa, RADEON_FALLBACK_BLEND_FUNC, fallback ); if ( !fallback ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); - rmesa->state.hw.context.rb3d_blendcntl = b; + RADEON_STATECHANGE( rmesa, ctx ); + rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b; } } @@ -221,33 +246,33 @@ static void radeonDepthFunc( GLcontext *ctx, GLenum func ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); - rmesa->state.hw.context.rb3d_zstencilcntl &= ~RADEON_Z_TEST_MASK; + RADEON_STATECHANGE( rmesa, ctx ); + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_Z_TEST_MASK; switch ( ctx->Depth.Func ) { case GL_NEVER: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_Z_TEST_NEVER; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_NEVER; break; case GL_LESS: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_Z_TEST_LESS; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_LESS; break; case GL_EQUAL: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_Z_TEST_EQUAL; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_EQUAL; break; case GL_LEQUAL: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_Z_TEST_LEQUAL; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_LEQUAL; break; case GL_GREATER: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_Z_TEST_GREATER; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_GREATER; break; case GL_NOTEQUAL: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_Z_TEST_NEQUAL; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_NEQUAL; break; case GL_GEQUAL: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_Z_TEST_GEQUAL; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_GEQUAL; break; case GL_ALWAYS: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_Z_TEST_ALWAYS; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_ALWAYS; break; } } @@ -256,19 +281,19 @@ static void radeonDepthFunc( GLcontext *ctx, GLenum func ) static void radeonDepthMask( GLcontext *ctx, GLboolean flag ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); + RADEON_STATECHANGE( rmesa, ctx ); if ( ctx->Depth.Mask ) { - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_Z_WRITE_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_WRITE_ENABLE; } else { - rmesa->state.hw.context.rb3d_zstencilcntl &= ~RADEON_Z_WRITE_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_Z_WRITE_ENABLE; } } static void radeonClearDepth( GLcontext *ctx, GLclampd d ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - GLuint format = (rmesa->state.hw.context.rb3d_zstencilcntl & + GLuint format = (rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] & RADEON_DEPTH_FORMAT_MASK); switch ( format ) { @@ -286,22 +311,157 @@ static void radeonClearDepth( GLcontext *ctx, GLclampd d ) * Fog */ + static void radeonFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - GLchan c[4]; + union { int i; float f; } c, d; + GLchan col[4]; + + c.i = rmesa->hw.fog.cmd[FOG_C]; + d.i = rmesa->hw.fog.cmd[FOG_D]; + + switch (pname) { + case GL_FOG_MODE: + if (!ctx->Fog.Enabled) + return; + RADEON_STATECHANGE(rmesa, tcl); + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK; + switch (ctx->Fog.Mode) { + case GL_LINEAR: + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_LINEAR; + if (ctx->Fog.Start == ctx->Fog.End) { + c.f = 1.0F; + d.f = 1.0F; + } + else { + c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start); + d.f = 1.0/(ctx->Fog.End-ctx->Fog.Start); + } + break; + case GL_EXP: + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP; + c.f = 0.0; + d.f = ctx->Fog.Density; + break; + case GL_EXP2: + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP2; + c.f = 0.0; + d.f = -(ctx->Fog.Density * ctx->Fog.Density); + break; + default: + return; + } + break; + case GL_FOG_DENSITY: + switch (ctx->Fog.Mode) { + case GL_EXP: + c.f = 0.0; + d.f = ctx->Fog.Density; + break; + case GL_EXP2: + c.f = 0.0; + d.f = -(ctx->Fog.Density * ctx->Fog.Density); + break; + default: + break; + } + break; + case GL_FOG_START: + case GL_FOG_END: + if (ctx->Fog.Mode == GL_LINEAR) { + if (ctx->Fog.Start == ctx->Fog.End) { + c.f = 1.0F; + d.f = 1.0F; + } else { + c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start); + d.f = 1.0/(ctx->Fog.End-ctx->Fog.Start); + } + } + break; + case GL_FOG_COLOR: + RADEON_STATECHANGE( rmesa, ctx ); + UNCLAMPED_FLOAT_TO_RGB_CHAN( col, ctx->Fog.Color ); + rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = + radeonPackColor( 4, col[0], col[1], col[2], 0 ); + break; + case GL_FOG_COORDINATE_SOURCE_EXT: + /* What to do? + */ + break; + default: + return; + } - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); - UNCLAMPED_FLOAT_TO_RGB_CHAN( c, ctx->Fog.Color ); - rmesa->state.hw.context.pp_fog_color = - radeonPackColor( 4, c[0], c[1], c[2], 0 ); + if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) { + RADEON_STATECHANGE( rmesa, fog ); + rmesa->hw.fog.cmd[FOG_C] = c.i; + rmesa->hw.fog.cmd[FOG_D] = d.i; + } } /* ============================================================= - * Clipping + * Scissoring */ + +static GLboolean intersect_rect( XF86DRIClipRectPtr out, + XF86DRIClipRectPtr a, + XF86DRIClipRectPtr b ) +{ + *out = *a; + if ( b->x1 > out->x1 ) out->x1 = b->x1; + if ( b->y1 > out->y1 ) out->y1 = b->y1; + if ( b->x2 < out->x2 ) out->x2 = b->x2; + if ( b->y2 < out->y2 ) out->y2 = b->y2; + if ( out->x1 >= out->x2 ) return GL_FALSE; + if ( out->y1 >= out->y2 ) return GL_FALSE; + return GL_TRUE; +} + + +void radeonRecalcScissorRects( radeonContextPtr rmesa ) +{ + XF86DRIClipRectPtr out; + int i; + + /* Grow cliprect store? + */ + if (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) { + while (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) { + rmesa->state.scissor.numAllocedClipRects += 1; /* zero case */ + rmesa->state.scissor.numAllocedClipRects *= 2; + } + + if (rmesa->state.scissor.pClipRects) + FREE(rmesa->state.scissor.pClipRects); + + rmesa->state.scissor.pClipRects = + MALLOC( rmesa->state.scissor.numAllocedClipRects * + sizeof(XF86DRIClipRectRec) ); + + if (!rmesa->state.scissor.numAllocedClipRects) { +/* FALLBACK( rmesa, RADEON_FALLBACK_MEMORY, GL_TRUE ); */ + rmesa->state.scissor.numAllocedClipRects = 0; + return; + } + } + + out = rmesa->state.scissor.pClipRects; + rmesa->state.scissor.numClipRects = 0; + + for ( i = 0 ; i < rmesa->numClipRects ; i++ ) { + if ( intersect_rect( out, + &rmesa->pClipRects[i], + &rmesa->state.scissor.rect ) ) { + rmesa->state.scissor.numClipRects++; + out++; + } + } +} + + static void radeonUpdateScissor( GLcontext *ctx ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); @@ -319,8 +479,7 @@ static void radeonUpdateScissor( GLcontext *ctx ) rmesa->state.scissor.rect.x2 = w + dPriv->x + 1; rmesa->state.scissor.rect.y2 = h + dPriv->y + 1; - if ( ctx->Scissor.Enabled ) - rmesa->upload_cliprects = 1; + radeonRecalcScissorRects( rmesa ); } } @@ -330,10 +489,11 @@ static void radeonScissor( GLcontext *ctx, { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - if ( ctx->Scissor.Enabled ) + if ( ctx->Scissor.Enabled ) { RADEON_FIREVERTICES( rmesa ); /* don't pipeline cliprect changes */ + radeonUpdateScissor( ctx ); + } - radeonUpdateScissor( ctx ); } @@ -344,27 +504,37 @@ static void radeonScissor( GLcontext *ctx, static void radeonCullFace( GLcontext *ctx, GLenum unused ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - GLuint s = rmesa->state.hw.setup1.se_cntl; + GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL]; + GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL]; s |= RADEON_FFACE_SOLID | RADEON_BFACE_SOLID; + t &= ~(RADEON_CULL_FRONT | RADEON_CULL_BACK); if ( ctx->Polygon.CullFlag ) { switch ( ctx->Polygon.CullFaceMode ) { case GL_FRONT: s &= ~RADEON_FFACE_SOLID; + t |= RADEON_CULL_FRONT; break; case GL_BACK: s &= ~RADEON_BFACE_SOLID; + t |= RADEON_CULL_BACK; break; case GL_FRONT_AND_BACK: s &= ~(RADEON_FFACE_SOLID | RADEON_BFACE_SOLID); + t |= (RADEON_CULL_FRONT | RADEON_CULL_BACK); break; } } - if ( rmesa->state.hw.setup1.se_cntl != s ) { - RADEON_STATECHANGE(rmesa, RADEON_UPLOAD_SETUP); - rmesa->state.hw.setup1.se_cntl = s; + if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) { + RADEON_STATECHANGE(rmesa, set ); + rmesa->hw.set.cmd[SET_SE_CNTL] = s; + } + + if ( rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] != t ) { + RADEON_STATECHANGE(rmesa, tcl ); + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = t; } } @@ -372,15 +542,19 @@ static void radeonFrontFace( GLcontext *ctx, GLenum mode ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_SETUP ); - rmesa->state.hw.setup1.se_cntl &= ~RADEON_FFACE_CULL_DIR_MASK; + RADEON_STATECHANGE( rmesa, set ); + rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_FFACE_CULL_DIR_MASK; + + RADEON_STATECHANGE( rmesa, tcl ); + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_CULL_FRONT_IS_CCW; switch ( mode ) { case GL_CW: - rmesa->state.hw.setup1.se_cntl |= RADEON_FFACE_CULL_CW; + rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_FFACE_CULL_CW; break; case GL_CCW: - rmesa->state.hw.setup1.se_cntl |= RADEON_FFACE_CULL_CCW; + rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_FFACE_CULL_CCW; + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_CULL_FRONT_IS_CCW; break; } } @@ -393,15 +567,16 @@ static void radeonLineWidth( GLcontext *ctx, GLfloat widthf ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_LINE | RADEON_UPLOAD_SETUP ); + RADEON_STATECHANGE( rmesa, lin ); + RADEON_STATECHANGE( rmesa, set ); /* Line width is stored in U6.4 format. */ - rmesa->state.hw.line.se_line_width = (GLuint)(widthf * 16.0); + rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] = (GLuint)(widthf * 16.0); if ( widthf > 1.0 ) { - rmesa->state.hw.setup1.se_cntl |= RADEON_WIDELINE_ENABLE; + rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_WIDELINE_ENABLE; } else { - rmesa->state.hw.setup1.se_cntl &= ~RADEON_WIDELINE_ENABLE; + rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_WIDELINE_ENABLE; } } @@ -409,10 +584,9 @@ static void radeonLineStipple( GLcontext *ctx, GLint factor, GLushort pattern ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_LINE ); - - rmesa->state.hw.line.re_line_pattern = ((((GLuint)factor & 0xff) << 16) | - ((GLuint)pattern)); + RADEON_STATECHANGE( rmesa, lin ); + rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] = + ((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern)); } @@ -430,9 +604,9 @@ static void radeonColorMask( GLcontext *ctx, ctx->Color.ColorMask[BCOMP], ctx->Color.ColorMask[ACOMP] ); - if ( rmesa->state.hw.mask.rb3d_planemask != mask ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_MASKS ); - rmesa->state.hw.mask.rb3d_planemask = mask; + if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) { + RADEON_STATECHANGE( rmesa, msk ); + rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask; } } @@ -447,15 +621,16 @@ static void radeonPolygonOffset( GLcontext *ctx, radeonContextPtr rmesa = RADEON_CONTEXT(ctx); GLfloat constant = units * rmesa->state.depth.scale; - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_ZBIAS ); - rmesa->state.hw.zbias.se_zbias_factor = *(GLuint *)&factor; - rmesa->state.hw.zbias.se_zbias_constant = *(GLuint *)&constant; + RADEON_STATECHANGE( rmesa, zbs ); + rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR] = *(GLuint *)&factor; + rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = *(GLuint *)&constant; } static void radeonPolygonStipple( GLcontext *ctx, const GLubyte *mask ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); GLuint i; + drmRadeonStipple stipple; /* Must flip pattern upside down. */ @@ -463,15 +638,34 @@ static void radeonPolygonStipple( GLcontext *ctx, const GLubyte *mask ) rmesa->state.stipple.mask[31 - i] = ((GLuint *) mask)[i]; } + /* TODO: push this into cmd mechanism + */ RADEON_FIREVERTICES( rmesa ); LOCK_HARDWARE( rmesa ); /* FIXME: Use window x,y offsets into stipple RAM. */ - drmRadeonPolygonStipple( rmesa->dri.fd, rmesa->state.stipple.mask ); + stipple.mask = rmesa->state.stipple.mask; + drmCommandWrite( rmesa->dri.fd, DRM_RADEON_STIPPLE, + &stipple, sizeof(drmRadeonStipple) ); UNLOCK_HARDWARE( rmesa ); } +static void radeonPolygonMode( GLcontext *ctx, GLenum face, GLenum mode ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLboolean flag = (ctx->_TriangleCaps & DD_TRI_UNFILLED) != 0; + + /* Can't generally do unfilled via tcl, but some good special + * cases work. + */ + TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_UNFILLED, flag); + if (rmesa->TclFallback) { + radeonChooseRenderState( ctx ); + radeonChooseVertexState( ctx ); + } +} + /* ============================================================= * Rendering attributes @@ -487,34 +681,478 @@ static void radeonPolygonStipple( GLcontext *ctx, const GLubyte *mask ) static void radeonUpdateSpecular( GLcontext *ctx ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - CARD32 p = rmesa->state.hw.context.pp_cntl; + CARD32 p = rmesa->hw.ctx.cmd[CTX_PP_CNTL]; - if ( ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR && - ctx->Light.Enabled) { + if ( ctx->_TriangleCaps & DD_SEPARATE_SPECULAR ) { p |= RADEON_SPECULAR_ENABLE; } else { p &= ~RADEON_SPECULAR_ENABLE; } - if ( rmesa->state.hw.context.pp_cntl != p ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); - rmesa->state.hw.context.pp_cntl = p; + if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) { + RADEON_STATECHANGE( rmesa, ctx ); + rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p; + } + + /* Bizzare: have to leave lighting enabled to get fog. + */ + RADEON_STATECHANGE( rmesa, tcl ); + if ((ctx->Light.Enabled && + ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) { + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE; + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE; + } + else if (ctx->Fog.Enabled) { + if (ctx->Light.Enabled) { + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE; + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE; + } else { + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_DIFFUSE; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE; + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE; + } + } + else if (ctx->Light.Enabled) { + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_SPECULAR; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~RADEON_TCL_VTX_PK_SPEC; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE; + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE; + } else if (ctx->Fog.ColorSumEnabled ) { + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_SPECULAR; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_DIFFUSE; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE; + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LIGHTING_ENABLE; + } else { + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_SPECULAR; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_DIFFUSE; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~RADEON_TCL_VTX_PK_SPEC; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE; + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LIGHTING_ENABLE; + } + + /* Update vertex/render formats + */ + if (rmesa->TclFallback) { + radeonChooseRenderState( ctx ); + radeonChooseVertexState( ctx ); + } +} + + +/* ============================================================= + * Materials + */ + + +/* Update on colormaterial, material emmissive/ambient, + * lightmodel.globalambient + */ +static void update_global_ambient( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + float *fcmd = (float *)RADEON_DB_STATE( glt ); + + /* Need to do more if both emmissive & ambient are PREMULT: + */ + if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] & + ((3 << RADEON_EMISSIVE_SOURCE_SHIFT) | + (3 << RADEON_AMBIENT_SOURCE_SHIFT))) == 0) + { + COPY_3V( &fcmd[GLT_RED], + ctx->Light.Material[0].Emission); + ACC_SCALE_3V( &fcmd[GLT_RED], + ctx->Light.Model.Ambient, + ctx->Light.Material[0].Ambient); + } + else + { + COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient ); + } + + RADEON_DB_STATECHANGE(rmesa, &rmesa->hw.glt); +} + +/* Update on change to + * - light[p].colors + * - light[p].enabled + * - material, + * - colormaterial enabled + * - colormaterial bitmask + */ +static void update_light_colors( GLcontext *ctx, GLuint p ) +{ + struct gl_light *l = &ctx->Light.Light[p]; + +/* fprintf(stderr, "%s\n", __FUNCTION__); */ + + if (l->Enabled) { + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + float *fcmd = (float *)RADEON_DB_STATE( lit[p] ); + GLuint bitmask = ctx->Light.ColorMaterialBitmask; + struct gl_material *mat = &ctx->Light.Material[0]; + + COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient ); + COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse ); + COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular ); + + if (!ctx->Light.ColorMaterialEnabled) + bitmask = 0; + + if ((bitmask & FRONT_AMBIENT_BIT) == 0) + SELF_SCALE_3V( &fcmd[LIT_AMBIENT_RED], mat->Ambient ); + + if ((bitmask & FRONT_DIFFUSE_BIT) == 0) + SELF_SCALE_3V( &fcmd[LIT_DIFFUSE_RED], mat->Diffuse ); + + if ((bitmask & FRONT_SPECULAR_BIT) == 0) + SELF_SCALE_3V( &fcmd[LIT_SPECULAR_RED], mat->Specular ); + + RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] ); + } +} + +/* Also fallback for asym colormaterial mode in twoside lighting... + */ +static void check_twoside_fallback( GLcontext *ctx ) +{ + GLboolean fallback = GL_FALSE; + + if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) { + if (memcmp( &ctx->Light.Material[0], + &ctx->Light.Material[1], + sizeof(struct gl_material)) != 0) + fallback = GL_TRUE; + else if (ctx->Light.ColorMaterialEnabled && + (ctx->Light.ColorMaterialBitmask & BACK_MATERIAL_BITS) != + ((ctx->Light.ColorMaterialBitmask & FRONT_MATERIAL_BITS)<<1)) + fallback = GL_TRUE; + } + + TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_LIGHT_TWOSIDE, fallback ); +} + +static void radeonColorMaterial( GLcontext *ctx, GLenum face, GLenum mode ) +{ + if (ctx->Light.ColorMaterialEnabled) { + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLuint light_model_ctl = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]; + GLuint mask = ctx->Light.ColorMaterialBitmask; + + /* Default to PREMULT: + */ + light_model_ctl &= ~((3 << RADEON_EMISSIVE_SOURCE_SHIFT) | + (3 << RADEON_AMBIENT_SOURCE_SHIFT) | + (3 << RADEON_DIFFUSE_SOURCE_SHIFT) | + (3 << RADEON_SPECULAR_SOURCE_SHIFT)); + + if (mask & FRONT_EMISSION_BIT) { + light_model_ctl |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE << + RADEON_EMISSIVE_SOURCE_SHIFT); + } + + if (mask & FRONT_AMBIENT_BIT) { + light_model_ctl |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE << + RADEON_AMBIENT_SOURCE_SHIFT); + } + + if (mask & FRONT_DIFFUSE_BIT) { + light_model_ctl |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE << + RADEON_DIFFUSE_SOURCE_SHIFT); + } + + if (mask & FRONT_SPECULAR_BIT) { + light_model_ctl |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE << + RADEON_SPECULAR_SOURCE_SHIFT); + } + + if (light_model_ctl != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]) { + GLuint p; + + RADEON_STATECHANGE( rmesa, tcl ); + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = light_model_ctl; + + for (p = 0 ; p < MAX_LIGHTS; p++) + update_light_colors( ctx, p ); + update_global_ambient( ctx ); + } + } + + check_twoside_fallback( ctx ); +} + +void radeonUpdateMaterial( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( mtl ); + GLuint p; + GLuint mask = ~0; + + if (ctx->Light.ColorMaterialEnabled) + mask &= ~ctx->Light.ColorMaterialBitmask; + + if (RADEON_DEBUG & DEBUG_STATE) + fprintf(stderr, "%s\n", __FUNCTION__); + + + if (mask & FRONT_EMISSION_BIT) { + fcmd[MTL_EMMISSIVE_RED] = ctx->Light.Material[0].Emission[0]; + fcmd[MTL_EMMISSIVE_GREEN] = ctx->Light.Material[0].Emission[1]; + fcmd[MTL_EMMISSIVE_BLUE] = ctx->Light.Material[0].Emission[2]; + fcmd[MTL_EMMISSIVE_ALPHA] = ctx->Light.Material[0].Emission[3]; + } + if (mask & FRONT_AMBIENT_BIT) { + fcmd[MTL_AMBIENT_RED] = ctx->Light.Material[0].Ambient[0]; + fcmd[MTL_AMBIENT_GREEN] = ctx->Light.Material[0].Ambient[1]; + fcmd[MTL_AMBIENT_BLUE] = ctx->Light.Material[0].Ambient[2]; + fcmd[MTL_AMBIENT_ALPHA] = ctx->Light.Material[0].Ambient[3]; + } + if (mask & FRONT_DIFFUSE_BIT) { + fcmd[MTL_DIFFUSE_RED] = ctx->Light.Material[0].Diffuse[0]; + fcmd[MTL_DIFFUSE_GREEN] = ctx->Light.Material[0].Diffuse[1]; + fcmd[MTL_DIFFUSE_BLUE] = ctx->Light.Material[0].Diffuse[2]; + fcmd[MTL_DIFFUSE_ALPHA] = ctx->Light.Material[0].Diffuse[3]; + } + if (mask & FRONT_SPECULAR_BIT) { + fcmd[MTL_SPECULAR_RED] = ctx->Light.Material[0].Specular[0]; + fcmd[MTL_SPECULAR_GREEN] = ctx->Light.Material[0].Specular[1]; + fcmd[MTL_SPECULAR_BLUE] = ctx->Light.Material[0].Specular[2]; + fcmd[MTL_SPECULAR_ALPHA] = ctx->Light.Material[0].Specular[3]; + } + if (mask & FRONT_SHININESS_BIT) { + fcmd[MTL_SHININESS] = ctx->Light.Material[0].Shininess; + } + + if (RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mtl )) { + for (p = 0 ; p < MAX_LIGHTS; p++) + update_light_colors( ctx, p ); + + check_twoside_fallback( ctx ); + update_global_ambient( ctx ); + } + else if (RADEON_DEBUG & (DEBUG_PRIMS|DEBUG_STATE)) + fprintf(stderr, "%s: Elided noop material call\n", __FUNCTION__); +} + +/* _NEW_LIGHT + * _NEW_MODELVIEW + * _MESA_NEW_NEED_EYE_COORDS + * + * Uses derived state from mesa: + * _VP_inf_norm + * _h_inf_norm + * _Position + * _NormDirection + * _ModelViewInvScale + * _NeedEyeCoords + * _EyeZDir + * + * which are calculated in light.c and are correct for the current + * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW + * and _MESA_NEW_NEED_EYE_COORDS. + */ +static void update_light( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + + /* Have to check these, or have an automatic shortcircuit mechanism + * to remove noop statechanges. (Or just do a better job on the + * front end). + */ + { + GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]; + + if (ctx->_NeedEyeCoords) + tmp &= ~RADEON_LIGHT_IN_MODELSPACE; + else + tmp |= RADEON_LIGHT_IN_MODELSPACE; + + + /* Leave this test disabled: (unexplained q3 lockup) (even with + new packets) + */ + if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]) + { + RADEON_STATECHANGE( rmesa, tcl ); + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = tmp; + } + } + + { + GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( eye ); + fcmd[EYE_X] = ctx->_EyeZDir[0]; + fcmd[EYE_Y] = ctx->_EyeZDir[1]; + fcmd[EYE_Z] = - ctx->_EyeZDir[2]; + fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale; + RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.eye ); + } + + +/* RADEON_STATECHANGE( rmesa, glt ); */ + + if (ctx->Light.Enabled) { + GLint p; + for (p = 0 ; p < MAX_LIGHTS; p++) { + if (ctx->Light.Light[p].Enabled) { + struct gl_light *l = &ctx->Light.Light[p]; + GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( lit[p] ); + + if (l->EyePosition[3] == 0.0) { + COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm ); + COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm ); + fcmd[LIT_POSITION_W] = 0; + fcmd[LIT_DIRECTION_W] = 0; + } else { + COPY_4V( &fcmd[LIT_POSITION_X], l->_Position ); + fcmd[LIT_DIRECTION_X] = -l->_NormDirection[0]; + fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1]; + fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[2]; + fcmd[LIT_DIRECTION_W] = 0; + } + + RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] ); + } + } + } +} + +static void radeonLightfv( GLcontext *ctx, GLenum light, + GLenum pname, const GLfloat *params ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLint p = light - GL_LIGHT0; + struct gl_light *l = &ctx->Light.Light[p]; + GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd; + + + switch (pname) { + case GL_AMBIENT: + case GL_DIFFUSE: + case GL_SPECULAR: + update_light_colors( ctx, p ); + break; + + case GL_SPOT_DIRECTION: + /* picked up in update_light */ + break; + + case GL_POSITION: { + /* positions picked up in update_light, but can do flag here */ + GLuint flag = (p&1)? RADEON_LIGHT_1_IS_LOCAL : RADEON_LIGHT_0_IS_LOCAL; + GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2; + + RADEON_STATECHANGE(rmesa, tcl); + if (l->EyePosition[3] != 0.0F) + rmesa->hw.tcl.cmd[idx] |= flag; + else + rmesa->hw.tcl.cmd[idx] &= ~flag; + break; + } + + case GL_SPOT_EXPONENT: + RADEON_STATECHANGE(rmesa, lit[p]); + fcmd[LIT_SPOT_EXPONENT] = params[0]; + break; + + case GL_SPOT_CUTOFF: { + GLuint flag = (p&1) ? RADEON_LIGHT_1_IS_SPOT : RADEON_LIGHT_0_IS_SPOT; + GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2; + + RADEON_STATECHANGE(rmesa, lit[p]); + fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff; + + RADEON_STATECHANGE(rmesa, tcl); + if (l->SpotCutoff != 180.0F) + rmesa->hw.tcl.cmd[idx] |= flag; + else + rmesa->hw.tcl.cmd[idx] &= ~flag; + break; + } + + case GL_CONSTANT_ATTENUATION: + RADEON_STATECHANGE(rmesa, lit[p]); + fcmd[LIT_ATTEN_CONST] = params[0]; + break; + case GL_LINEAR_ATTENUATION: + RADEON_STATECHANGE(rmesa, lit[p]); + fcmd[LIT_ATTEN_LINEAR] = params[0]; + break; + case GL_QUADRATIC_ATTENUATION: + RADEON_STATECHANGE(rmesa, lit[p]); + fcmd[LIT_ATTEN_QUADRATIC] = params[0]; + break; + default: + return; } + } + + static void radeonLightModelfv( GLcontext *ctx, GLenum pname, const GLfloat *param ) { - if ( pname == GL_LIGHT_MODEL_COLOR_CONTROL ) { - radeonUpdateSpecular(ctx); + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + + switch (pname) { + case GL_LIGHT_MODEL_AMBIENT: + update_global_ambient( ctx ); + break; + + case GL_LIGHT_MODEL_LOCAL_VIEWER: + RADEON_STATECHANGE( rmesa, tcl ); + if (ctx->Light.Model.LocalViewer) + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LOCAL_VIEWER; + else + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LOCAL_VIEWER; + break; + + case GL_LIGHT_MODEL_TWO_SIDE: + RADEON_STATECHANGE( rmesa, tcl ); + if (ctx->Light.Model.TwoSide) + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_LIGHT_TWOSIDE; + else + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_LIGHT_TWOSIDE; + + check_twoside_fallback( ctx ); + + if (rmesa->TclFallback) { + radeonChooseRenderState( ctx ); + radeonChooseVertexState( ctx ); + } + break; + + case GL_LIGHT_MODEL_COLOR_CONTROL: + radeonUpdateSpecular(ctx); + + RADEON_STATECHANGE( rmesa, tcl ); + if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= + ~RADEON_DIFFUSE_SPECULAR_COMBINE; + else + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= + RADEON_DIFFUSE_SPECULAR_COMBINE; + break; + + default: + break; } } static void radeonShadeModel( GLcontext *ctx, GLenum mode ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - GLuint s = rmesa->state.hw.setup1.se_cntl; + GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL]; s &= ~(RADEON_DIFFUSE_SHADE_MASK | RADEON_ALPHA_SHADE_MASK | @@ -538,9 +1176,45 @@ static void radeonShadeModel( GLcontext *ctx, GLenum mode ) return; } - if ( rmesa->state.hw.setup1.se_cntl != s ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_SETUP ); - rmesa->state.hw.setup1.se_cntl = s; + if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) { + RADEON_STATECHANGE( rmesa, set ); + rmesa->hw.set.cmd[SET_SE_CNTL] = s; + } +} + + +/* ============================================================= + * User clip planes + */ + +static void radeonClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq ) +{ + GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0; + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p]; + + RADEON_STATECHANGE( rmesa, ucp[p] ); + rmesa->hw.ucp[p].cmd[UCP_X] = ip[0]; + rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1]; + rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2]; + rmesa->hw.ucp[p].cmd[UCP_W] = ip[3]; +} + +static void radeonUpdateClipPlanes( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLuint p; + + for (p = 0; p < ctx->Const.MaxClipPlanes; p++) { + if (ctx->Transform.ClipEnabled[p]) { + GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p]; + + RADEON_STATECHANGE( rmesa, ucp[p] ); + rmesa->hw.ucp[p].cmd[UCP_X] = ip[0]; + rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1]; + rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2]; + rmesa->hw.ucp[p].cmd[UCP_W] = ip[3]; + } } } @@ -556,50 +1230,50 @@ static void radeonStencilFunc( GLcontext *ctx, GLenum func, GLuint refmask = ((ctx->Stencil.Ref << RADEON_STENCIL_REF_SHIFT) | (ctx->Stencil.ValueMask << RADEON_STENCIL_MASK_SHIFT)); - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT | RADEON_UPLOAD_MASKS ); + RADEON_STATECHANGE( rmesa, ctx ); + RADEON_STATECHANGE( rmesa, msk ); - rmesa->state.hw.context.rb3d_zstencilcntl &= ~RADEON_STENCIL_TEST_MASK; - rmesa->state.hw.mask.rb3d_stencilrefmask &= ~(RADEON_STENCIL_REF_MASK| - RADEON_STENCIL_VALUE_MASK); + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_STENCIL_TEST_MASK; + rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(RADEON_STENCIL_REF_MASK| + RADEON_STENCIL_VALUE_MASK); switch ( ctx->Stencil.Function ) { case GL_NEVER: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_TEST_NEVER; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_NEVER; break; case GL_LESS: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_TEST_LESS; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_LESS; break; case GL_EQUAL: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_TEST_EQUAL; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_EQUAL; break; case GL_LEQUAL: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_TEST_LEQUAL; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_LEQUAL; break; case GL_GREATER: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_TEST_GREATER; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_GREATER; break; case GL_NOTEQUAL: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_TEST_NEQUAL; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_NEQUAL; break; case GL_GEQUAL: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_TEST_GEQUAL; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_GEQUAL; break; case GL_ALWAYS: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_TEST_ALWAYS; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_ALWAYS; break; } - rmesa->state.hw.mask.rb3d_stencilrefmask |= refmask; + rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask; } static void radeonStencilMask( GLcontext *ctx, GLuint mask ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_MASKS ); - rmesa->state.hw.mask.rb3d_stencilrefmask &= ~RADEON_STENCIL_WRITE_MASK; - - rmesa->state.hw.mask.rb3d_stencilrefmask |= + RADEON_STATECHANGE( rmesa, msk ); + rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~RADEON_STENCIL_WRITE_MASK; + rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= (ctx->Stencil.WriteMask << RADEON_STENCIL_WRITEMASK_SHIFT); } @@ -608,71 +1282,71 @@ static void radeonStencilOp( GLcontext *ctx, GLenum fail, { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); - rmesa->state.hw.context.rb3d_zstencilcntl &= ~(RADEON_STENCIL_FAIL_MASK | + RADEON_STATECHANGE( rmesa, ctx ); + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(RADEON_STENCIL_FAIL_MASK | RADEON_STENCIL_ZFAIL_MASK | RADEON_STENCIL_ZPASS_MASK); switch ( ctx->Stencil.FailFunc ) { case GL_KEEP: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_FAIL_KEEP; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_KEEP; break; case GL_ZERO: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_FAIL_ZERO; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_ZERO; break; case GL_REPLACE: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_FAIL_REPLACE; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_REPLACE; break; case GL_INCR: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_FAIL_INC; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_INC; break; case GL_DECR: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_FAIL_DEC; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_DEC; break; case GL_INVERT: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_FAIL_INVERT; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_INVERT; break; } switch ( ctx->Stencil.ZFailFunc ) { case GL_KEEP: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_ZFAIL_KEEP; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_KEEP; break; case GL_ZERO: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_ZFAIL_ZERO; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_ZERO; break; case GL_REPLACE: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_ZFAIL_REPLACE; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_REPLACE; break; case GL_INCR: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_ZFAIL_INC; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_INC; break; case GL_DECR: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_ZFAIL_DEC; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_DEC; break; case GL_INVERT: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_ZFAIL_INVERT; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_INVERT; break; } switch ( ctx->Stencil.ZPassFunc ) { case GL_KEEP: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_ZPASS_KEEP; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_KEEP; break; case GL_ZERO: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_ZPASS_ZERO; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_ZERO; break; case GL_REPLACE: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_ZPASS_REPLACE; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_REPLACE; break; case GL_INCR: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_ZPASS_INC; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_INC; break; case GL_DECR: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_ZPASS_DEC; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_DEC; break; case GL_INVERT: - rmesa->state.hw.context.rb3d_zstencilcntl |= RADEON_STENCIL_ZPASS_INVERT; + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_INVERT; break; } } @@ -681,9 +1355,10 @@ static void radeonClearStencil( GLcontext *ctx, GLint s ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - rmesa->state.stencil.clear = ((GLuint) ctx->Stencil.Clear | - (0xff << RADEON_STENCIL_MASK_SHIFT) | - (ctx->Stencil.WriteMask << RADEON_STENCIL_WRITEMASK_SHIFT)); + rmesa->state.stencil.clear = + ((GLuint) ctx->Stencil.Clear | + (0xff << RADEON_STENCIL_MASK_SHIFT) | + (ctx->Stencil.WriteMask << RADEON_STENCIL_WRITEMASK_SHIFT)); } @@ -695,6 +1370,7 @@ static void radeonClearStencil( GLcontext *ctx, GLint s ) * To correctly position primitives: */ #define SUBPIXEL_X 0.125 +#define SUBPIXEL_Y 0.125 void radeonUpdateWindow( GLcontext *ctx ) { @@ -707,20 +1383,18 @@ void radeonUpdateWindow( GLcontext *ctx ) GLfloat sx = v[MAT_SX]; GLfloat tx = v[MAT_TX] + xoffset + SUBPIXEL_X; GLfloat sy = - v[MAT_SY]; - GLfloat ty = (- v[MAT_TY]) + yoffset; + GLfloat ty = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y; GLfloat sz = v[MAT_SZ] * rmesa->state.depth.scale; GLfloat tz = v[MAT_TZ] * rmesa->state.depth.scale; - -/* fprintf(stderr, "radeonUpdateWindow %d,%d %dx%d\n", */ -/* dPriv->x, dPriv->y, dPriv->w, dPriv->h); */ - - RADEON_STATECHANGE(rmesa, RADEON_UPLOAD_VIEWPORT); - rmesa->state.hw.viewport.se_vport_xscale = *(GLuint *)&sx; - rmesa->state.hw.viewport.se_vport_xoffset = *(GLuint *)&tx; - rmesa->state.hw.viewport.se_vport_yscale = *(GLuint *)&sy; - rmesa->state.hw.viewport.se_vport_yoffset = *(GLuint *)&ty; - rmesa->state.hw.viewport.se_vport_zscale = *(GLuint *)&sz; - rmesa->state.hw.viewport.se_vport_zoffset = *(GLuint *)&tz; + RADEON_FIREVERTICES( rmesa ); + RADEON_STATECHANGE( rmesa, vpt ); + + rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = *(GLuint *)&sx; + rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx; + rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = *(GLuint *)&sy; + rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty; + rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = *(GLuint *)&sz; + rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = *(GLuint *)&tz; } @@ -753,29 +1427,19 @@ void radeonUpdateViewportOffset( GLcontext *ctx ) GLfloat tx = v[MAT_TX] + xoffset; GLfloat ty = (- v[MAT_TY]) + yoffset; - if ( rmesa->state.hw.viewport.se_vport_xoffset != tx || - rmesa->state.hw.viewport.se_vport_yoffset != ty ) + if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != *(GLuint *)&tx || + rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != *(GLuint *)&ty ) { - rmesa->state.hw.viewport.se_vport_xoffset = *(GLuint *)&tx; - rmesa->state.hw.viewport.se_vport_yoffset = *(GLuint *)&ty; - - if (rmesa->store.statenr) { - int i; - rmesa->store.state[0].dirty |= RADEON_UPLOAD_VIEWPORT; - /* Note: assume vport x/yoffset are constant over the buffer: - */ - for (i = 0 ; i < rmesa->store.statenr ; i++) { - rmesa->store.state[i].viewport.se_vport_xoffset = *(GLuint *)&tx; - rmesa->store.state[i].viewport.se_vport_yoffset = *(GLuint *)&ty; - } - } else { - rmesa->state.hw.dirty |= RADEON_UPLOAD_VIEWPORT; - } - + /* Note: this should also modify whatever data the context reset + * code uses... + */ + rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx; + rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty; + /* update polygon stipple x/y screen offset */ { GLuint stx, sty; - GLuint m = rmesa->state.hw.misc.re_misc; + GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC]; m &= ~(RADEON_STIPPLE_X_OFFSET_MASK | RADEON_STIPPLE_Y_OFFSET_MASK); @@ -788,9 +1452,9 @@ void radeonUpdateViewportOffset( GLcontext *ctx ) m |= ((stx << RADEON_STIPPLE_X_OFFSET_SHIFT) | (sty << RADEON_STIPPLE_Y_OFFSET_SHIFT)); - if ( rmesa->state.hw.misc.re_misc != m ) { - rmesa->state.hw.misc.re_misc = m; - RADEON_STATECHANGE(rmesa, RADEON_UPLOAD_MISC); + if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) { + RADEON_STATECHANGE( rmesa, msc ); + rmesa->hw.msc.cmd[MSC_RE_MISC] = m; } } } @@ -845,8 +1509,8 @@ static void radeonLogicOpCode( GLcontext *ctx, GLenum opcode ) ASSERT( rop < 16 ); - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_MASKS ); - rmesa->state.hw.mask.rb3d_ropcntl = radeon_rop_tab[rop]; + RADEON_STATECHANGE( rmesa, msk ); + rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = radeon_rop_tab[rop]; } @@ -860,7 +1524,9 @@ void radeonSetCliprects( radeonContextPtr rmesa, GLenum mode ) rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects; break; case GL_BACK_LEFT: - if ( dPriv->numBackClipRects == 0 ) { + /* Can't ignore 2d windows if we are page flipping. + */ + if ( dPriv->numBackClipRects == 0 || rmesa->doPageFlip ) { rmesa->numClipRects = dPriv->numClipRects; rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects; } @@ -870,10 +1536,12 @@ void radeonSetCliprects( radeonContextPtr rmesa, GLenum mode ) } break; default: + fprintf(stderr, "bad mode in radeonSetCliprects\n"); return; } - rmesa->upload_cliprects = 1; + if (rmesa->state.scissor.enabled) + radeonRecalcScissorRects( rmesa ); } @@ -881,19 +1549,37 @@ static void radeonSetDrawBuffer( GLcontext *ctx, GLenum mode ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + if (RADEON_DEBUG & DEBUG_DRI) + fprintf(stderr, "%s %s\n", __FUNCTION__, + _mesa_lookup_enum_by_nr( mode )); + RADEON_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */ switch ( mode ) { case GL_FRONT_LEFT: FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE ); - rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset; - rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch; + if ( rmesa->sarea->pfCurrentPage == 1 ) { + rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset; + rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch; + } else { + rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset; + rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch; + } + rmesa->state.pixel.readOffset = rmesa->state.color.drawOffset; + rmesa->state.pixel.readPitch = rmesa->state.color.drawPitch; radeonSetCliprects( rmesa, GL_FRONT_LEFT ); break; case GL_BACK_LEFT: FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE ); - rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset; - rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch; + if ( rmesa->sarea->pfCurrentPage == 1 ) { + rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset; + rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch; + } else { + rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset; + rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch; + } + rmesa->state.pixel.readOffset = rmesa->state.color.drawOffset; + rmesa->state.pixel.readPitch = rmesa->state.color.drawPitch; radeonSetCliprects( rmesa, GL_BACK_LEFT ); break; default: @@ -901,10 +1587,10 @@ static void radeonSetDrawBuffer( GLcontext *ctx, GLenum mode ) return; } - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); - rmesa->state.hw.context.rb3d_coloroffset = (rmesa->state.color.drawOffset & + RADEON_STATECHANGE( rmesa, ctx ); + rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = (rmesa->state.color.drawOffset & RADEON_COLOROFFSET_MASK); - rmesa->state.hw.context.rb3d_colorpitch = rmesa->state.color.drawPitch; + rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch; } @@ -915,9 +1601,10 @@ static void radeonSetDrawBuffer( GLcontext *ctx, GLenum mode ) static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLuint p, flag; - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) - fprintf( stderr, "%s( %s = %s )\n",__FUNCTION__, + if ( RADEON_DEBUG & DEBUG_STATE ) + fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__, _mesa_lookup_enum_by_nr( cap ), state ? "GL_TRUE" : "GL_FALSE" ); @@ -930,369 +1617,487 @@ static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state ) break; case GL_ALPHA_TEST: - RADEON_STATECHANGE(rmesa, RADEON_UPLOAD_CONTEXT); + RADEON_STATECHANGE( rmesa, ctx ); if (state) { - rmesa->state.hw.context.pp_cntl |= RADEON_ALPHA_TEST_ENABLE; + rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ALPHA_TEST_ENABLE; } else { - rmesa->state.hw.context.pp_cntl &= ~RADEON_ALPHA_TEST_ENABLE; + rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ALPHA_TEST_ENABLE; } break; case GL_BLEND: - RADEON_STATECHANGE(rmesa, RADEON_UPLOAD_CONTEXT); + RADEON_STATECHANGE( rmesa, ctx ); if (state) { - rmesa->state.hw.context.rb3d_cntl |= RADEON_ALPHA_BLEND_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ALPHA_BLEND_ENABLE; + } else { + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ALPHA_BLEND_ENABLE; + } + if ( ctx->Color.ColorLogicOpEnabled ) { + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE; } else { - rmesa->state.hw.context.rb3d_cntl &= ~RADEON_ALPHA_BLEND_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE; } break; + case GL_CLIP_PLANE0: + case GL_CLIP_PLANE1: + case GL_CLIP_PLANE2: + case GL_CLIP_PLANE3: + case GL_CLIP_PLANE4: + case GL_CLIP_PLANE5: + p = cap-GL_CLIP_PLANE0; + RADEON_STATECHANGE( rmesa, tcl ); + if (state) { + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (RADEON_UCP_ENABLE_0<<p); + radeonClipPlane( ctx, cap, NULL ); + } + else { + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(RADEON_UCP_ENABLE_0<<p); + } + break; + + case GL_COLOR_MATERIAL: + radeonColorMaterial( ctx, 0, 0 ); + if (!state) + radeonUpdateMaterial( ctx ); + break; + case GL_CULL_FACE: radeonCullFace( ctx, 0 ); break; case GL_DEPTH_TEST: - RADEON_STATECHANGE(rmesa, RADEON_UPLOAD_CONTEXT); + RADEON_STATECHANGE(rmesa, ctx ); if ( state ) { - rmesa->state.hw.context.rb3d_cntl |= RADEON_Z_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_Z_ENABLE; } else { - rmesa->state.hw.context.rb3d_cntl &= ~RADEON_Z_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_Z_ENABLE; } break; case GL_DITHER: - RADEON_STATECHANGE(rmesa, RADEON_UPLOAD_CONTEXT); + RADEON_STATECHANGE(rmesa, ctx ); if ( state ) { - rmesa->state.hw.context.rb3d_cntl |= RADEON_DITHER_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_DITHER_ENABLE; } else { - rmesa->state.hw.context.rb3d_cntl &= ~RADEON_DITHER_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_DITHER_ENABLE; } break; case GL_FOG: - RADEON_STATECHANGE(rmesa, RADEON_UPLOAD_CONTEXT); + RADEON_STATECHANGE(rmesa, ctx ); if ( state ) { - rmesa->state.hw.context.pp_cntl |= RADEON_FOG_ENABLE; + rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_FOG_ENABLE; + radeonFogfv( ctx, GL_FOG_MODE, 0 ); } else { - rmesa->state.hw.context.pp_cntl &= ~RADEON_FOG_ENABLE; + rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_FOG_ENABLE; + RADEON_STATECHANGE(rmesa, tcl); + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK; } + radeonUpdateSpecular( ctx ); /* for PK_SPEC */ + if (rmesa->TclFallback) + radeonChooseVertexState( ctx ); + break; + + case GL_LIGHT0: + case GL_LIGHT1: + case GL_LIGHT2: + case GL_LIGHT3: + case GL_LIGHT4: + case GL_LIGHT5: + case GL_LIGHT6: + case GL_LIGHT7: + RADEON_STATECHANGE(rmesa, tcl); + p = cap - GL_LIGHT0; + if (p&1) + flag = (RADEON_LIGHT_1_ENABLE | + RADEON_LIGHT_1_ENABLE_AMBIENT | + RADEON_LIGHT_1_ENABLE_SPECULAR); + else + flag = (RADEON_LIGHT_0_ENABLE | + RADEON_LIGHT_0_ENABLE_AMBIENT | + RADEON_LIGHT_0_ENABLE_SPECULAR); + + if (state) + rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag; + else + rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag; + + /* + */ + update_light_colors( ctx, p ); break; case GL_LIGHTING: + RADEON_STATECHANGE(rmesa, tcl); + if (state) { +/* rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE; */ +/* rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE; */ + } + else { +/* rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LIGHTING_ENABLE; */ +/* rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_DIFFUSE; */ + } radeonUpdateSpecular(ctx); + check_twoside_fallback( ctx ); break; case GL_LINE_SMOOTH: - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); + RADEON_STATECHANGE( rmesa, ctx ); if ( state ) { - rmesa->state.hw.context.pp_cntl |= RADEON_ANTI_ALIAS_LINE; + rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ANTI_ALIAS_LINE; } else { - rmesa->state.hw.context.pp_cntl &= ~RADEON_ANTI_ALIAS_LINE; + rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ANTI_ALIAS_LINE; } break; case GL_LINE_STIPPLE: - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); + RADEON_STATECHANGE( rmesa, ctx ); if ( state ) { - rmesa->state.hw.context.pp_cntl |= RADEON_PATTERN_ENABLE; + rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_PATTERN_ENABLE; } else { - rmesa->state.hw.context.pp_cntl &= ~RADEON_PATTERN_ENABLE; + rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_PATTERN_ENABLE; } break; case GL_COLOR_LOGIC_OP: - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); + RADEON_STATECHANGE( rmesa, ctx ); if ( state ) { - rmesa->state.hw.context.rb3d_cntl |= RADEON_ROP_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE; } else { - rmesa->state.hw.context.rb3d_cntl &= ~RADEON_ROP_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE; } break; - - case GL_POLYGON_OFFSET_POINT: - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_SETUP ); + + case GL_NORMALIZE: + RADEON_STATECHANGE( rmesa, tcl ); if ( state ) { - rmesa->state.hw.setup1.se_cntl |= RADEON_ZBIAS_ENABLE_POINT; + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_NORMALIZE_NORMALS; } else { - rmesa->state.hw.setup1.se_cntl &= ~RADEON_ZBIAS_ENABLE_POINT; + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_NORMALIZE_NORMALS; + } + break; + + case GL_POLYGON_OFFSET_POINT: + if (rmesa->dri.drmMinor == 1) { + radeonChooseRenderState( ctx ); + } + else { + RADEON_STATECHANGE( rmesa, set ); + if ( state ) { + rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_POINT; + } else { + rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_POINT; + } } break; case GL_POLYGON_OFFSET_LINE: - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_SETUP ); - if ( state ) { - rmesa->state.hw.setup1.se_cntl |= RADEON_ZBIAS_ENABLE_LINE; - } else { - rmesa->state.hw.setup1.se_cntl &= ~RADEON_ZBIAS_ENABLE_LINE; + if (rmesa->dri.drmMinor == 1) { + radeonChooseRenderState( ctx ); + } + else { + RADEON_STATECHANGE( rmesa, set ); + if ( state ) { + rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_LINE; + } else { + rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_LINE; + } } break; case GL_POLYGON_OFFSET_FILL: - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_SETUP ); - if ( state ) { - rmesa->state.hw.setup1.se_cntl |= RADEON_ZBIAS_ENABLE_TRI; - } else { - rmesa->state.hw.setup1.se_cntl &= ~RADEON_ZBIAS_ENABLE_TRI; + if (rmesa->dri.drmMinor == 1) { + radeonChooseRenderState( ctx ); + } + else { + RADEON_STATECHANGE( rmesa, set ); + if ( state ) { + rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_TRI; + } else { + rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_TRI; + } } break; case GL_POLYGON_SMOOTH: - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); + RADEON_STATECHANGE( rmesa, ctx ); if ( state ) { - rmesa->state.hw.context.pp_cntl |= RADEON_ANTI_ALIAS_POLY; + rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ANTI_ALIAS_POLY; } else { - rmesa->state.hw.context.pp_cntl &= ~RADEON_ANTI_ALIAS_POLY; + rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ANTI_ALIAS_POLY; } break; case GL_POLYGON_STIPPLE: - RADEON_STATECHANGE(rmesa, RADEON_UPLOAD_CONTEXT); + RADEON_STATECHANGE(rmesa, ctx ); if ( state ) { - rmesa->state.hw.context.pp_cntl |= RADEON_STIPPLE_ENABLE; + rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_STIPPLE_ENABLE; } else { - rmesa->state.hw.context.pp_cntl &= ~RADEON_STIPPLE_ENABLE; + rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_STIPPLE_ENABLE; } break; + case GL_RESCALE_NORMAL_EXT: { + GLboolean tmp = ctx->_NeedEyeCoords ? state : !state; + RADEON_STATECHANGE( rmesa, tcl ); + if ( tmp ) { + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_RESCALE_NORMALS; + } else { + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS; + } + break; + } + case GL_SCISSOR_TEST: RADEON_FIREVERTICES( rmesa ); rmesa->state.scissor.enabled = state; - rmesa->upload_cliprects = 1; + radeonUpdateScissor( ctx ); break; case GL_STENCIL_TEST: if ( rmesa->state.stencil.hwBuffer ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); + RADEON_STATECHANGE( rmesa, ctx ); if ( state ) { - rmesa->state.hw.context.rb3d_cntl |= RADEON_STENCIL_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_STENCIL_ENABLE; } else { - rmesa->state.hw.context.rb3d_cntl &= ~RADEON_STENCIL_ENABLE; + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_STENCIL_ENABLE; } } else { FALLBACK( rmesa, RADEON_FALLBACK_STENCIL, state ); } break; + case GL_TEXTURE_GEN_Q: + case GL_TEXTURE_GEN_R: + case GL_TEXTURE_GEN_S: + case GL_TEXTURE_GEN_T: + /* Picked up in radeonUpdateTextureState. + */ + rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE; + break; + + case GL_COLOR_SUM_EXT: + radeonUpdateSpecular ( ctx ); + break; + default: return; } } +static void radeonLightingSpaceChange( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLboolean tmp; + RADEON_STATECHANGE( rmesa, tcl ); + + if (RADEON_DEBUG & DEBUG_STATE) + fprintf(stderr, "%s %d\n", __FUNCTION__, ctx->_NeedEyeCoords); + + if (ctx->_NeedEyeCoords) + tmp = ctx->Transform.RescaleNormals; + else + tmp = !ctx->Transform.RescaleNormals; + + if ( tmp ) { + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_RESCALE_NORMALS; + } else { + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS; + } +} + /* ============================================================= - * State initialization, management + * Deferred state management - matrices, textures, other? */ -void radeonPrintDirty( const char *msg, GLuint state ) -{ - fprintf( stderr, - "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s\n", - msg, - state, - (state & RADEON_UPLOAD_CONTEXT) ? "context, " : "", - (state & RADEON_UPLOAD_LINE) ? "line, " : "", - (state & RADEON_UPLOAD_BUMPMAP) ? "bumpmap, " : "", - (state & RADEON_UPLOAD_MASKS) ? "masks, " : "", - (state & RADEON_UPLOAD_VIEWPORT) ? "viewport, " : "", - (state & RADEON_UPLOAD_SETUP) ? "setup, " : "", - (state & RADEON_UPLOAD_TCL) ? "tcl, " : "", - (state & RADEON_UPLOAD_MISC) ? "misc, " : "", - (state & RADEON_UPLOAD_TEX0) ? "tex0, " : "", - (state & RADEON_UPLOAD_TEX1) ? "tex1, " : "", - (state & RADEON_UPLOAD_TEX2) ? "tex2, " : ""); -} +static void upload_matrix( radeonContextPtr rmesa, GLfloat *src, int idx ) +{ + float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0; + int i; + + for (i = 0 ; i < 4 ; i++) { + *dest++ = src[i]; + *dest++ = src[i+4]; + *dest++ = src[i+8]; + *dest++ = src[i+12]; + } -static void radeonInvalidateState( GLcontext *ctx, GLuint new_state ) + RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] ); +} + +static void upload_matrix_t( radeonContextPtr rmesa, GLfloat *src, int idx ) { - _swrast_InvalidateState( ctx, new_state ); - _swsetup_InvalidateState( ctx, new_state ); - _ac_InvalidateState( ctx, new_state ); - _tnl_InvalidateState( ctx, new_state ); - RADEON_CONTEXT(ctx)->NewGLState |= new_state; + float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0; + memcpy(dest, src, 16*sizeof(float)); + RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] ); } +static void update_texturematrix( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + GLuint tpc = rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL]; + GLuint vs = rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL]; + int unit; + rmesa->TexMatEnabled = 0; -/* Initialize the context's hardware state. - */ -void radeonInitState( radeonContextPtr rmesa ) -{ - GLcontext *ctx = rmesa->glCtx; - GLuint color_fmt, depth_fmt; + for (unit = 0 ; unit < 2; unit++) { + if (!ctx->Texture.Unit[unit]._ReallyEnabled) { + } + else if (ctx->TextureMatrix[unit].type != MATRIX_IDENTITY) { + GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4; + + rmesa->TexMatEnabled |= (RADEON_TEXGEN_TEXMAT_0_ENABLE| + RADEON_TEXMAT_0_ENABLE) << unit; + + if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) { + /* Need to preconcatenate any active texgen + * obj/eyeplane matrices: + */ + _math_matrix_mul_matrix( &rmesa->tmpmat, + &rmesa->TexGenMatrix[unit], + &ctx->TextureMatrix[unit] ); + upload_matrix( rmesa, rmesa->tmpmat.m, TEXMAT_0+unit ); + } + else { + rmesa->TexMatEnabled |= + (RADEON_TEXGEN_INPUT_TEXCOORD_0+unit) << inputshift; + upload_matrix( rmesa, ctx->TextureMatrix[unit].m, + TEXMAT_0+unit ); + } + } + else if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) { + upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m, + TEXMAT_0+unit ); + } + } - switch ( rmesa->radeonScreen->cpp ) { - case 2: - color_fmt = RADEON_COLOR_FORMAT_RGB565; - break; - case 4: - color_fmt = RADEON_COLOR_FORMAT_ARGB8888; - break; - default: - fprintf( stderr, "Error: Unsupported pixel depth... exiting\n" ); - exit( -1 ); + + tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled); + + vs &= ~((0xf << RADEON_TCL_TEX_0_OUTPUT_SHIFT) | + (0xf << RADEON_TCL_TEX_1_OUTPUT_SHIFT)); + + if (tpc & RADEON_TEXGEN_TEXMAT_0_ENABLE) + vs |= RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT; + else + vs |= RADEON_TCL_TEX_INPUT_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT; + + if (tpc & RADEON_TEXGEN_TEXMAT_1_ENABLE) + vs |= RADEON_TCL_TEX_COMPUTED_TEX_1 << RADEON_TCL_TEX_1_OUTPUT_SHIFT; + else + vs |= RADEON_TCL_TEX_INPUT_TEX_1 << RADEON_TCL_TEX_1_OUTPUT_SHIFT; + + if (tpc != rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] || + vs != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL]) { + + RADEON_STATECHANGE(rmesa, tcl); + rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] = tpc; + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] = vs; } +} - rmesa->state.color.clear = 0x00000000; - switch ( ctx->Visual.depthBits ) { - case 16: - rmesa->state.depth.clear = 0x0000ffff; - rmesa->state.depth.scale = 1.0 / (GLfloat)0xffff; - depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z; - rmesa->state.stencil.clear = 0x00000000; - break; - case 24: - rmesa->state.depth.clear = 0x00ffffff; - rmesa->state.depth.scale = 1.0 / (GLfloat)0xffffff; - depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z; - rmesa->state.stencil.clear = 0xffff0000; - break; - default: - fprintf( stderr, "Error: Unsupported depth %d... exiting\n", - ctx->Visual.depthBits ); - exit( -1 ); + +void radeonValidateState( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLuint new_state = rmesa->NewGLState; + + if (new_state & _NEW_TEXTURE) { + radeonUpdateTextureState( ctx ); + new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */ } - /* Only have hw stencil when depth buffer is 24 bits deep */ - rmesa->state.stencil.hwBuffer = ( ctx->Visual.stencilBits > 0 && - ctx->Visual.depthBits == 24 ); + /* Need an event driven matrix update? + */ + if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION)) + upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, MODEL_PROJ ); - rmesa->RenderIndex = ~0; - rmesa->Fallback = 0; - rmesa->render_primitive = GL_TRIANGLES; - rmesa->hw_primitive = RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST; + /* Need these for lighting (shouldn't upload otherwise) + */ + if (new_state & (_NEW_MODELVIEW)) { + upload_matrix( rmesa, ctx->ModelView.m, MODEL ); + upload_matrix_t( rmesa, ctx->ModelView.inv, MODEL_IT ); + } - if ( ctx->Visual.doubleBufferMode ) { - rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset; - rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch; - } else { - rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset; - rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch; + /* Does this need to be triggered on eg. modelview for + * texgen-derived objplane/eyeplane matrices? + */ + if (new_state & _NEW_TEXTURE_MATRIX) { + update_texturematrix( ctx ); + } + + if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) { + update_light( ctx ); } - rmesa->state.pixel.readOffset = rmesa->state.color.drawOffset; - rmesa->state.pixel.readPitch = rmesa->state.color.drawPitch; - /* Harware state: + /* emit all active clip planes if projection matrix changes. */ - rmesa->state.hw.context.pp_misc = (RADEON_ALPHA_TEST_PASS | - RADEON_CHROMA_FUNC_FAIL | - RADEON_CHROMA_KEY_NEAREST | - RADEON_SHADOW_FUNC_EQUAL | - RADEON_SHADOW_PASS_1 | - RADEON_RIGHT_HAND_CUBE_OGL); + if (new_state & (_NEW_PROJECTION)) { + if (ctx->Transform._AnyClip) + radeonUpdateClipPlanes( ctx ); + } - rmesa->state.hw.context.pp_fog_color = ((0x00000000 & RADEON_FOG_COLOR_MASK) | - RADEON_FOG_VERTEX | - RADEON_FOG_USE_DEPTH); - rmesa->state.hw.context.re_solid_color = 0x00000000; + rmesa->NewGLState = 0; +} - rmesa->state.hw.context.rb3d_blendcntl = (RADEON_COMB_FCN_ADD_CLAMP | - RADEON_SRC_BLEND_GL_ONE | - RADEON_DST_BLEND_GL_ZERO ); - rmesa->state.hw.context.rb3d_depthoffset = rmesa->radeonScreen->depthOffset; +static void radeonInvalidateState( GLcontext *ctx, GLuint new_state ) +{ + _swrast_InvalidateState( ctx, new_state ); + _swsetup_InvalidateState( ctx, new_state ); + _ac_InvalidateState( ctx, new_state ); + _tnl_InvalidateState( ctx, new_state ); + _ae_invalidate_state( ctx, new_state ); + RADEON_CONTEXT(ctx)->NewGLState |= new_state; + radeonVtxfmtInvalidate( ctx ); +} - rmesa->state.hw.context.rb3d_depthpitch = ((rmesa->radeonScreen->depthPitch & - RADEON_DEPTHPITCH_MASK) | - RADEON_DEPTH_ENDIAN_NO_SWAP); +static void radeonWrapRunPipeline( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); - rmesa->state.hw.context.rb3d_zstencilcntl = (depth_fmt | - RADEON_Z_TEST_LESS | - RADEON_STENCIL_TEST_ALWAYS | - RADEON_STENCIL_FAIL_KEEP | - RADEON_STENCIL_ZPASS_KEEP | - RADEON_STENCIL_ZFAIL_KEEP | - RADEON_Z_WRITE_ENABLE); + if (0) + fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState); - rmesa->state.hw.context.pp_cntl = (RADEON_SCISSOR_ENABLE | - RADEON_ANTI_ALIAS_NONE); + /* Validate state: + */ + if (rmesa->NewGLState) + radeonValidateState( ctx ); - rmesa->state.hw.context.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE | - color_fmt | - RADEON_ZBLOCK16); + if (tnl->vb.Material) { + TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_TRUE ); + } - rmesa->state.hw.context.rb3d_coloroffset = (rmesa->state.color.drawOffset & - RADEON_COLOROFFSET_MASK); + /* Run the pipeline. + */ + _tnl_run_pipeline( ctx ); - rmesa->state.hw.context.re_width_height = ((0x7ff << RADEON_RE_WIDTH_SHIFT) | - (0x7ff << RADEON_RE_HEIGHT_SHIFT)); - - rmesa->state.hw.context.rb3d_colorpitch = ((rmesa->state.color.drawPitch & - RADEON_COLORPITCH_MASK) | - RADEON_COLOR_ENDIAN_NO_SWAP); - - rmesa->state.hw.setup1.se_cntl = (RADEON_FFACE_CULL_CCW | - RADEON_BFACE_SOLID | - RADEON_FFACE_SOLID | - RADEON_FLAT_SHADE_VTX_LAST | - RADEON_DIFFUSE_SHADE_GOURAUD | - RADEON_ALPHA_SHADE_GOURAUD | - RADEON_SPECULAR_SHADE_GOURAUD | - RADEON_FOG_SHADE_GOURAUD | - RADEON_VPORT_XY_XFORM_ENABLE | - RADEON_VPORT_Z_XFORM_ENABLE | - RADEON_VTX_PIX_CENTER_OGL | - RADEON_ROUND_MODE_TRUNC | - RADEON_ROUND_PREC_8TH_PIX); - - rmesa->state.hw.vertex.se_coord_fmt = ( -#if 1 - RADEON_VTX_XY_PRE_MULT_1_OVER_W0 | - RADEON_VTX_Z_PRE_MULT_1_OVER_W0 | -#else - RADEON_VTX_W0_IS_NOT_1_OVER_W0 | -#endif - RADEON_TEX1_W_ROUTING_USE_Q1); - - rmesa->state.hw.setup2.se_cntl_status = (RADEON_VC_NO_SWAP | - RADEON_TCL_BYPASS); - - rmesa->state.hw.line.re_line_pattern = ((0x0000 & RADEON_LINE_PATTERN_MASK) | - (0 << RADEON_LINE_REPEAT_COUNT_SHIFT) | - (0 << RADEON_LINE_PATTERN_START_SHIFT) | - RADEON_LINE_PATTERN_LITTLE_BIT_ORDER); - - rmesa->state.hw.line.re_line_state = ((0 << RADEON_LINE_CURRENT_PTR_SHIFT) | - (1 << RADEON_LINE_CURRENT_COUNT_SHIFT)); - - rmesa->state.hw.line.se_line_width = (1 << 4); - - rmesa->state.hw.bumpmap.pp_lum_matrix = 0x00000000; - rmesa->state.hw.bumpmap.pp_rot_matrix_0 = 0x00000000; - rmesa->state.hw.bumpmap.pp_rot_matrix_1 = 0x00000000; - - rmesa->state.hw.mask.rb3d_stencilrefmask = ((0x00 << RADEON_STENCIL_REF_SHIFT) | - (0xff << RADEON_STENCIL_MASK_SHIFT) | - (0xff << RADEON_STENCIL_WRITEMASK_SHIFT)); - - rmesa->state.hw.mask.rb3d_ropcntl = RADEON_ROP_COPY; - rmesa->state.hw.mask.rb3d_planemask = 0xffffffff; - - rmesa->state.hw.viewport.se_vport_xscale = 0x00000000; - rmesa->state.hw.viewport.se_vport_xoffset = 0x00000000; - rmesa->state.hw.viewport.se_vport_yscale = 0x00000000; - rmesa->state.hw.viewport.se_vport_yoffset = 0x00000000; - rmesa->state.hw.viewport.se_vport_zscale = 0x00000000; - rmesa->state.hw.viewport.se_vport_zoffset = 0x00000000; - - rmesa->state.hw.misc.re_misc = ((0 << RADEON_STIPPLE_X_OFFSET_SHIFT) | - (0 << RADEON_STIPPLE_Y_OFFSET_SHIFT) | - RADEON_STIPPLE_BIG_BIT_ORDER); - - rmesa->state.hw.dirty = RADEON_UPLOAD_CONTEXT_ALL; + if (tnl->vb.Material) { + TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_FALSE ); + radeonUpdateMaterial( ctx ); /* not needed any more? */ + } } + + + /* Initialize the driver's state functions. */ void radeonInitStateFuncs( GLcontext *ctx ) { ctx->Driver.UpdateState = radeonInvalidateState; + ctx->Driver.LightingSpaceChange = radeonLightingSpaceChange; ctx->Driver.SetDrawBuffer = radeonSetDrawBuffer; @@ -1304,6 +2109,7 @@ void radeonInitStateFuncs( GLcontext *ctx ) ctx->Driver.ClearDepth = radeonClearDepth; ctx->Driver.ClearIndex = NULL; ctx->Driver.ClearStencil = radeonClearStencil; + ctx->Driver.ClipPlane = radeonClipPlane; ctx->Driver.ColorMask = radeonColorMask; ctx->Driver.CullFace = radeonCullFace; ctx->Driver.DepthFunc = radeonDepthFunc; @@ -1315,12 +2121,15 @@ void radeonInitStateFuncs( GLcontext *ctx ) ctx->Driver.Hint = NULL; ctx->Driver.IndexMask = NULL; ctx->Driver.LightModelfv = radeonLightModelfv; - ctx->Driver.Lightfv = NULL; + ctx->Driver.Lightfv = radeonLightfv; ctx->Driver.LineStipple = radeonLineStipple; ctx->Driver.LineWidth = radeonLineWidth; ctx->Driver.LogicOpcode = radeonLogicOpCode; - ctx->Driver.PolygonMode = NULL; - ctx->Driver.PolygonOffset = radeonPolygonOffset; + ctx->Driver.PolygonMode = radeonPolygonMode; + + if (RADEON_CONTEXT(ctx)->dri.drmMinor > 1) + ctx->Driver.PolygonOffset = radeonPolygonOffset; + ctx->Driver.PolygonStipple = radeonPolygonStipple; ctx->Driver.RenderMode = radeonRenderMode; ctx->Driver.Scissor = radeonScissor; @@ -1337,7 +2146,6 @@ void radeonInitStateFuncs( GLcontext *ctx ) ctx->Driver.CopyPixels = _swrast_CopyPixels; ctx->Driver.DrawPixels = _swrast_DrawPixels; ctx->Driver.ReadPixels = _swrast_ReadPixels; - ctx->Driver.ResizeBuffers = _swrast_alloc_buffers; /* Swrast hooks for imaging extensions: */ @@ -1345,4 +2153,7 @@ void radeonInitStateFuncs( GLcontext *ctx ) ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable; ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D; ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D; + + TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = radeonUpdateMaterial; + TNL_CONTEXT(ctx)->Driver.RunPipeline = radeonWrapRunPipeline; } diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_state.h b/xc/lib/GL/mesa/src/drv/radeon/radeon_state.h index b34e17133..45a368d95 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_state.h +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_state.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_state.h,v 1.3 2002/09/16 18:05:20 eich Exp $ */ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_state.h,v 1.5 2002/11/05 17:46:09 tsi Exp $ */ /************************************************************************** Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and @@ -44,20 +44,33 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. extern void radeonInitState( radeonContextPtr rmesa ); extern void radeonInitStateFuncs( GLcontext *ctx ); -extern void radeonUpdateWindow( GLcontext *ctx ); +extern void radeonUpdateMaterial( GLcontext *ctx ); + extern void radeonSetCliprects( radeonContextPtr rmesa, GLenum mode ); +extern void radeonRecalcScissorRects( radeonContextPtr rmesa ); extern void radeonUpdateViewportOffset( GLcontext *ctx ); +extern void radeonUpdateWindow( GLcontext *ctx ); -extern void radeonPrintDirty( const char *msg, GLuint state ); +extern void radeonValidateState( GLcontext *ctx ); + +extern void radeonPrintDirty( radeonContextPtr rmesa, + const char *msg ); extern void radeonFallback( GLcontext *ctx, GLuint bit, GLboolean mode ); #define FALLBACK( rmesa, bit, mode ) do { \ - if ( 0 ) fprintf( stderr, "FALLBACK in %s: #%d=%d\n",__FUNCTION__, \ - bit, mode ); \ + if ( 0 ) fprintf( stderr, "FALLBACK in %s: #%d=%d\n", \ + __FUNCTION__, bit, mode ); \ radeonFallback( rmesa->glCtx, bit, mode ); \ } while (0) +#define MODEL_PROJ 0 +#define MODEL 1 +#define MODEL_IT 2 +#define TEXMAT_0 3 +#define TEXMAT_1 4 +#define TEXMAT_2 5 + #endif #endif diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_state_init.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_state_init.c new file mode 100644 index 000000000..79c07e863 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_state_init.c @@ -0,0 +1,556 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_state_init.c,v 1.3 2003/02/22 06:21:11 dawes Exp $ */ +/* + * Copyright 2000, 2001 VA Linux Systems Inc., Fremont, California. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Gareth Hughes <gareth@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include "radeon_context.h" +#include "radeon_ioctl.h" +#include "radeon_state.h" +#include "radeon_tcl.h" +#include "radeon_tex.h" +#include "radeon_swtcl.h" +#include "radeon_vtxfmt.h" + +#include "mem.h" +#include "mmath.h" +#include "enums.h" +#include "colormac.h" +#include "light.h" +#include "api_arrayelt.h" + +#include "swrast/swrast.h" +#include "array_cache/acache.h" +#include "tnl/tnl.h" +#include "tnl/t_pipeline.h" +#include "swrast_setup/swrast_setup.h" + +/* ============================================================= + * State initialization + */ + +void radeonPrintDirty( radeonContextPtr rmesa, const char *msg ) +{ + struct radeon_state_atom *l; + + fprintf(stderr, msg); + fprintf(stderr, ": "); + + foreach(l, &(rmesa->hw.dirty)) { + fprintf(stderr, "%s, ", l->name); + } + + fprintf(stderr, "\n"); +} + +static int cmdpkt( int id ) +{ + drmRadeonCmdHeader h; + h.i = 0; + h.packet.cmd_type = RADEON_CMD_PACKET; + h.packet.packet_id = id; + return h.i; +} + +static int cmdvec( int offset, int stride, int count ) +{ + drmRadeonCmdHeader h; + h.i = 0; + h.vectors.cmd_type = RADEON_CMD_VECTORS; + h.vectors.offset = offset; + h.vectors.stride = stride; + h.vectors.count = count; + return h.i; +} + +static int cmdscl( int offset, int stride, int count ) +{ + drmRadeonCmdHeader h; + h.i = 0; + h.scalars.cmd_type = RADEON_CMD_SCALARS; + h.scalars.offset = offset; + h.scalars.stride = stride; + h.scalars.count = count; + return h.i; +} + +#define CHECK( NM, FLAG ) \ +static GLboolean check_##NM( GLcontext *ctx ) \ +{ \ + return FLAG; \ +} + +#define TCL_CHECK( NM, FLAG ) \ +static GLboolean check_##NM( GLcontext *ctx ) \ +{ \ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \ + return !rmesa->TclFallback && (FLAG); \ +} + + +CHECK( always, GL_TRUE ) +CHECK( tex0, ctx->Texture.Unit[0]._ReallyEnabled ) +CHECK( tex1, ctx->Texture.Unit[1]._ReallyEnabled ) +CHECK( fog, ctx->Fog.Enabled ) +TCL_CHECK( tcl, GL_TRUE ) +TCL_CHECK( tcl_tex0, ctx->Texture.Unit[0]._ReallyEnabled ) +TCL_CHECK( tcl_tex1, ctx->Texture.Unit[1]._ReallyEnabled ) +TCL_CHECK( tcl_lighting, ctx->Light.Enabled ) +TCL_CHECK( tcl_eyespace_or_lighting, ctx->_NeedEyeCoords || ctx->Light.Enabled ) +TCL_CHECK( tcl_lit0, ctx->Light.Enabled && ctx->Light.Light[0].Enabled ) +TCL_CHECK( tcl_lit1, ctx->Light.Enabled && ctx->Light.Light[1].Enabled ) +TCL_CHECK( tcl_lit2, ctx->Light.Enabled && ctx->Light.Light[2].Enabled ) +TCL_CHECK( tcl_lit3, ctx->Light.Enabled && ctx->Light.Light[3].Enabled ) +TCL_CHECK( tcl_lit4, ctx->Light.Enabled && ctx->Light.Light[4].Enabled ) +TCL_CHECK( tcl_lit5, ctx->Light.Enabled && ctx->Light.Light[5].Enabled ) +TCL_CHECK( tcl_lit6, ctx->Light.Enabled && ctx->Light.Light[6].Enabled ) +TCL_CHECK( tcl_lit7, ctx->Light.Enabled && ctx->Light.Light[7].Enabled ) +TCL_CHECK( tcl_ucp0, ctx->Transform.ClipEnabled[0] ) +TCL_CHECK( tcl_ucp1, ctx->Transform.ClipEnabled[1] ) +TCL_CHECK( tcl_ucp2, ctx->Transform.ClipEnabled[2] ) +TCL_CHECK( tcl_ucp3, ctx->Transform.ClipEnabled[3] ) +TCL_CHECK( tcl_ucp4, ctx->Transform.ClipEnabled[4] ) +TCL_CHECK( tcl_ucp5, ctx->Transform.ClipEnabled[5] ) +TCL_CHECK( tcl_eyespace_or_fog, ctx->_NeedEyeCoords || ctx->Fog.Enabled ) + + + +/* Initialize the context's hardware state. + */ +void radeonInitState( radeonContextPtr rmesa ) +{ + GLcontext *ctx = rmesa->glCtx; + GLuint color_fmt, depth_fmt, i; + + switch ( rmesa->radeonScreen->cpp ) { + case 2: + color_fmt = RADEON_COLOR_FORMAT_RGB565; + break; + case 4: + color_fmt = RADEON_COLOR_FORMAT_ARGB8888; + break; + default: + fprintf( stderr, "Error: Unsupported pixel depth... exiting\n" ); + exit( -1 ); + } + + rmesa->state.color.clear = 0x00000000; + + switch ( ctx->Visual.depthBits ) { + case 16: + rmesa->state.depth.clear = 0x0000ffff; + rmesa->state.depth.scale = 1.0 / (GLfloat)0xffff; + depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z; + rmesa->state.stencil.clear = 0x00000000; + break; + case 24: + rmesa->state.depth.clear = 0x00ffffff; + rmesa->state.depth.scale = 1.0 / (GLfloat)0xffffff; + depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z; + rmesa->state.stencil.clear = 0xff000000; + break; + default: + fprintf( stderr, "Error: Unsupported depth %d... exiting\n", + ctx->Visual.depthBits ); + exit( -1 ); + } + + /* Only have hw stencil when depth buffer is 24 bits deep */ + rmesa->state.stencil.hwBuffer = ( ctx->Visual.stencilBits > 0 && + ctx->Visual.depthBits == 24 ); + + rmesa->Fallback = 0; + + if ( ctx->Visual.doubleBufferMode && rmesa->sarea->pfCurrentPage == 0 ) { + rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset; + rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch; + } else { + rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset; + rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch; + } + rmesa->state.pixel.readOffset = rmesa->state.color.drawOffset; + rmesa->state.pixel.readPitch = rmesa->state.color.drawPitch; + + /* Initialize lists: + */ + make_empty_list(&(rmesa->hw.dirty)); + make_empty_list(&(rmesa->hw.clean)); + + +#define ALLOC_STATE( ATOM, CHK, SZ, NM, FLAG ) \ + do { \ + rmesa->hw.ATOM.cmd_size = SZ; \ + rmesa->hw.ATOM.cmd = (int *)CALLOC(SZ * sizeof(int)); \ + rmesa->hw.ATOM.lastcmd = (int *)CALLOC(SZ * sizeof(int)); \ + rmesa->hw.ATOM.name = NM; \ + rmesa->hw.ATOM.is_tcl = FLAG; \ + rmesa->hw.ATOM.check = check_##CHK; \ + insert_at_head(&(rmesa->hw.dirty), &(rmesa->hw.ATOM)); \ + } while (0) + + + /* Allocate state buffers: + */ + ALLOC_STATE( ctx, always, CTX_STATE_SIZE, "CTX/context", 0 ); + ALLOC_STATE( lin, always, LIN_STATE_SIZE, "LIN/line", 0 ); + ALLOC_STATE( msk, always, MSK_STATE_SIZE, "MSK/mask", 0 ); + ALLOC_STATE( vpt, always, VPT_STATE_SIZE, "VPT/viewport", 0 ); + ALLOC_STATE( set, always, SET_STATE_SIZE, "SET/setup", 0 ); + ALLOC_STATE( msc, always, MSC_STATE_SIZE, "MSC/misc", 0 ); + ALLOC_STATE( zbs, always, ZBS_STATE_SIZE, "ZBS/zbias", 0 ); + ALLOC_STATE( tcl, always, TCL_STATE_SIZE, "TCL/tcl", 1 ); + ALLOC_STATE( mtl, tcl_lighting, MTL_STATE_SIZE, "MTL/material", 1 ); + ALLOC_STATE( grd, always, GRD_STATE_SIZE, "GRD/guard-band", 1 ); + ALLOC_STATE( fog, fog, FOG_STATE_SIZE, "FOG/fog", 1 ); + ALLOC_STATE( glt, tcl_lighting, GLT_STATE_SIZE, "GLT/light-global", 1 ); + ALLOC_STATE( eye, tcl_lighting, EYE_STATE_SIZE, "EYE/eye-vector", 1 ); + ALLOC_STATE( tex[0], tex0, TEX_STATE_SIZE, "TEX/tex-0", 0 ); + ALLOC_STATE( tex[1], tex1, TEX_STATE_SIZE, "TEX/tex-1", 0 ); + ALLOC_STATE( mat[0], tcl, MAT_STATE_SIZE, "MAT/modelproject", 1 ); + ALLOC_STATE( mat[1], tcl_eyespace_or_fog, MAT_STATE_SIZE, "MAT/modelview", 1 ); + ALLOC_STATE( mat[2], tcl_eyespace_or_lighting, MAT_STATE_SIZE, "MAT/it-modelview", 1 ); + ALLOC_STATE( mat[3], tcl_tex0, MAT_STATE_SIZE, "MAT/texmat0", 1 ); + ALLOC_STATE( mat[4], tcl_tex1, MAT_STATE_SIZE, "MAT/texmat1", 1 ); + ALLOC_STATE( ucp[0], tcl_ucp0, UCP_STATE_SIZE, "UCP/userclip-0", 1 ); + ALLOC_STATE( ucp[1], tcl_ucp1, UCP_STATE_SIZE, "UCP/userclip-1", 1 ); + ALLOC_STATE( ucp[2], tcl_ucp2, UCP_STATE_SIZE, "UCP/userclip-2", 1 ); + ALLOC_STATE( ucp[3], tcl_ucp3, UCP_STATE_SIZE, "UCP/userclip-3", 1 ); + ALLOC_STATE( ucp[4], tcl_ucp4, UCP_STATE_SIZE, "UCP/userclip-4", 1 ); + ALLOC_STATE( ucp[5], tcl_ucp5, UCP_STATE_SIZE, "UCP/userclip-5", 1 ); + ALLOC_STATE( lit[0], tcl_lit0, LIT_STATE_SIZE, "LIT/light-0", 1 ); + ALLOC_STATE( lit[1], tcl_lit1, LIT_STATE_SIZE, "LIT/light-1", 1 ); + ALLOC_STATE( lit[2], tcl_lit2, LIT_STATE_SIZE, "LIT/light-2", 1 ); + ALLOC_STATE( lit[3], tcl_lit3, LIT_STATE_SIZE, "LIT/light-3", 1 ); + ALLOC_STATE( lit[4], tcl_lit4, LIT_STATE_SIZE, "LIT/light-4", 1 ); + ALLOC_STATE( lit[5], tcl_lit5, LIT_STATE_SIZE, "LIT/light-5", 1 ); + ALLOC_STATE( lit[6], tcl_lit6, LIT_STATE_SIZE, "LIT/light-6", 1 ); + ALLOC_STATE( lit[7], tcl_lit7, LIT_STATE_SIZE, "LIT/light-7", 1 ); + + + /* Fill in the packet headers: + */ + rmesa->hw.ctx.cmd[CTX_CMD_0] = cmdpkt(RADEON_EMIT_PP_MISC); + rmesa->hw.ctx.cmd[CTX_CMD_1] = cmdpkt(RADEON_EMIT_PP_CNTL); + rmesa->hw.ctx.cmd[CTX_CMD_2] = cmdpkt(RADEON_EMIT_RB3D_COLORPITCH); + rmesa->hw.lin.cmd[LIN_CMD_0] = cmdpkt(RADEON_EMIT_RE_LINE_PATTERN); + rmesa->hw.lin.cmd[LIN_CMD_1] = cmdpkt(RADEON_EMIT_SE_LINE_WIDTH); + rmesa->hw.msk.cmd[MSK_CMD_0] = cmdpkt(RADEON_EMIT_RB3D_STENCILREFMASK); + rmesa->hw.vpt.cmd[VPT_CMD_0] = cmdpkt(RADEON_EMIT_SE_VPORT_XSCALE); + rmesa->hw.set.cmd[SET_CMD_0] = cmdpkt(RADEON_EMIT_SE_CNTL); + rmesa->hw.set.cmd[SET_CMD_1] = cmdpkt(RADEON_EMIT_SE_CNTL_STATUS); + rmesa->hw.msc.cmd[MSC_CMD_0] = cmdpkt(RADEON_EMIT_RE_MISC); + rmesa->hw.tex[0].cmd[TEX_CMD_0] = cmdpkt(RADEON_EMIT_PP_TXFILTER_0); + rmesa->hw.tex[0].cmd[TEX_CMD_1] = cmdpkt(RADEON_EMIT_PP_BORDER_COLOR_0); + rmesa->hw.tex[1].cmd[TEX_CMD_0] = cmdpkt(RADEON_EMIT_PP_TXFILTER_1); + rmesa->hw.tex[1].cmd[TEX_CMD_1] = cmdpkt(RADEON_EMIT_PP_BORDER_COLOR_1); + rmesa->hw.zbs.cmd[ZBS_CMD_0] = cmdpkt(RADEON_EMIT_SE_ZBIAS_FACTOR); + rmesa->hw.tcl.cmd[TCL_CMD_0] = cmdpkt(RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT); + rmesa->hw.mtl.cmd[MTL_CMD_0] = + cmdpkt(RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED); + rmesa->hw.grd.cmd[GRD_CMD_0] = + cmdscl( RADEON_SS_VERT_GUARD_CLIP_ADJ_ADDR, 1, 4 ); + rmesa->hw.fog.cmd[FOG_CMD_0] = + cmdvec( RADEON_VS_FOG_PARAM_ADDR, 1, 4 ); + rmesa->hw.glt.cmd[GLT_CMD_0] = + cmdvec( RADEON_VS_GLOBAL_AMBIENT_ADDR, 1, 4 ); + rmesa->hw.eye.cmd[EYE_CMD_0] = + cmdvec( RADEON_VS_EYE_VECTOR_ADDR, 1, 4 ); + + for (i = 0 ; i < 5; i++) { + rmesa->hw.mat[i].cmd[MAT_CMD_0] = + cmdvec( RADEON_VS_MATRIX_0_ADDR + i*4, 1, 16); + } + + for (i = 0 ; i < 8; i++) { + rmesa->hw.lit[i].cmd[LIT_CMD_0] = + cmdvec( RADEON_VS_LIGHT_AMBIENT_ADDR + i, 8, 24 ); + rmesa->hw.lit[i].cmd[LIT_CMD_1] = + cmdscl( RADEON_SS_LIGHT_DCD_ADDR + i, 8, 6 ); + } + + for (i = 0 ; i < 6; i++) { + rmesa->hw.ucp[i].cmd[UCP_CMD_0] = + cmdvec( RADEON_VS_UCP_ADDR + i, 1, 4 ); + } + + rmesa->last_ReallyEnabled = -1; + + /* Initial Harware state: + */ + rmesa->hw.ctx.cmd[CTX_PP_MISC] = (RADEON_ALPHA_TEST_PASS | + RADEON_CHROMA_FUNC_FAIL | + RADEON_CHROMA_KEY_NEAREST | + RADEON_SHADOW_FUNC_EQUAL | + RADEON_SHADOW_PASS_1 | + RADEON_RIGHT_HAND_CUBE_OGL); + + rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = (RADEON_FOG_VERTEX | + RADEON_FOG_USE_DEPTH); + + rmesa->hw.ctx.cmd[CTX_RE_SOLID_COLOR] = 0x00000000; + + rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = (RADEON_COMB_FCN_ADD_CLAMP | + RADEON_SRC_BLEND_GL_ONE | + RADEON_DST_BLEND_GL_ZERO ); + + rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHOFFSET] = + rmesa->radeonScreen->depthOffset; + + rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHPITCH] = + ((rmesa->radeonScreen->depthPitch & + RADEON_DEPTHPITCH_MASK) | + RADEON_DEPTH_ENDIAN_NO_SWAP); + + rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] = (depth_fmt | + RADEON_Z_TEST_LESS | + RADEON_STENCIL_TEST_ALWAYS | + RADEON_STENCIL_FAIL_KEEP | + RADEON_STENCIL_ZPASS_KEEP | + RADEON_STENCIL_ZFAIL_KEEP | + RADEON_Z_WRITE_ENABLE); + + rmesa->hw.ctx.cmd[CTX_PP_CNTL] = (RADEON_SCISSOR_ENABLE | + RADEON_ANTI_ALIAS_NONE); + + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = (RADEON_PLANE_MASK_ENABLE | + color_fmt | + (1<<15)); + + rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_DITHER_ENABLE; + + rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = (rmesa->state.color.drawOffset & + RADEON_COLOROFFSET_MASK); + + rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = ((rmesa->state.color.drawPitch & + RADEON_COLORPITCH_MASK) | + RADEON_COLOR_ENDIAN_NO_SWAP); + + rmesa->hw.set.cmd[SET_SE_CNTL] = (RADEON_FFACE_CULL_CCW | + RADEON_BFACE_SOLID | + RADEON_FFACE_SOLID | +/* RADEON_BADVTX_CULL_DISABLE | */ + RADEON_FLAT_SHADE_VTX_LAST | + RADEON_DIFFUSE_SHADE_GOURAUD | + RADEON_ALPHA_SHADE_GOURAUD | + RADEON_SPECULAR_SHADE_GOURAUD | + RADEON_FOG_SHADE_GOURAUD | + RADEON_VPORT_XY_XFORM_ENABLE | + RADEON_VPORT_Z_XFORM_ENABLE | + RADEON_VTX_PIX_CENTER_OGL | + RADEON_ROUND_MODE_TRUNC | + RADEON_ROUND_PREC_8TH_PIX); + + rmesa->hw.set.cmd[SET_SE_CNTL_STATUS] = +#ifdef MESA_BIG_ENDIAN + RADEON_VC_32BIT_SWAP; +#else + RADEON_VC_NO_SWAP; +#endif + + if (!(rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL)) { + rmesa->hw.set.cmd[SET_SE_CNTL_STATUS] |= RADEON_TCL_BYPASS; + } + + rmesa->hw.set.cmd[SET_SE_COORDFMT] = ( + RADEON_VTX_W0_IS_NOT_1_OVER_W0 | + RADEON_TEX1_W_ROUTING_USE_Q1); + + + rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] = ((1 << 16) | 0xffff); + + rmesa->hw.lin.cmd[LIN_RE_LINE_STATE] = + ((0 << RADEON_LINE_CURRENT_PTR_SHIFT) | + (1 << RADEON_LINE_CURRENT_COUNT_SHIFT)); + + rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] = (1 << 4); + + rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] = + ((0x00 << RADEON_STENCIL_REF_SHIFT) | + (0xff << RADEON_STENCIL_MASK_SHIFT) | + (0xff << RADEON_STENCIL_WRITEMASK_SHIFT)); + + rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = RADEON_ROP_COPY; + rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = 0xffffffff; + + rmesa->hw.msc.cmd[MSC_RE_MISC] = + ((0 << RADEON_STIPPLE_X_OFFSET_SHIFT) | + (0 << RADEON_STIPPLE_Y_OFFSET_SHIFT) | + RADEON_STIPPLE_BIG_BIT_ORDER); + + rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = 0x00000000; + rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = 0x00000000; + rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = 0x00000000; + rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = 0x00000000; + rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = 0x00000000; + rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = 0x00000000; + + rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] = RADEON_BORDER_MODE_OGL; + rmesa->hw.tex[0].cmd[TEX_PP_TXFORMAT] = + (RADEON_TXFORMAT_ENDIAN_NO_SWAP | + RADEON_TXFORMAT_PERSPECTIVE_ENABLE | + RADEON_TXFORMAT_ST_ROUTE_STQ0 | + (2 << RADEON_TXFORMAT_WIDTH_SHIFT) | + (2 << RADEON_TXFORMAT_HEIGHT_SHIFT)); + rmesa->hw.tex[0].cmd[TEX_PP_TXOFFSET] = 0x2000; + rmesa->hw.tex[0].cmd[TEX_PP_BORDER_COLOR] = 0; + rmesa->hw.tex[0].cmd[TEX_PP_TXCBLEND] = + (RADEON_COLOR_ARG_A_ZERO | + RADEON_COLOR_ARG_B_ZERO | + RADEON_COLOR_ARG_C_CURRENT_COLOR | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX); + rmesa->hw.tex[0].cmd[TEX_PP_TXABLEND] = + (RADEON_ALPHA_ARG_A_ZERO | + RADEON_ALPHA_ARG_B_ZERO | + RADEON_ALPHA_ARG_C_CURRENT_ALPHA | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX); + rmesa->hw.tex[0].cmd[TEX_PP_TFACTOR] = 0; + + rmesa->hw.tex[1].cmd[TEX_PP_TXFILTER] = RADEON_BORDER_MODE_OGL; + rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] = + (RADEON_TXFORMAT_ENDIAN_NO_SWAP | + RADEON_TXFORMAT_PERSPECTIVE_ENABLE | + RADEON_TXFORMAT_ST_ROUTE_STQ1 | + (2 << RADEON_TXFORMAT_WIDTH_SHIFT) | + (2 << RADEON_TXFORMAT_HEIGHT_SHIFT)); + rmesa->hw.tex[1].cmd[TEX_PP_TXOFFSET] = 0x8000; + rmesa->hw.tex[1].cmd[TEX_PP_BORDER_COLOR] = 0; + rmesa->hw.tex[1].cmd[TEX_PP_TXCBLEND] = + (RADEON_COLOR_ARG_A_ZERO | + RADEON_COLOR_ARG_B_ZERO | + RADEON_COLOR_ARG_C_CURRENT_COLOR | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX); + rmesa->hw.tex[1].cmd[TEX_PP_TXABLEND] = + (RADEON_ALPHA_ARG_A_ZERO | + RADEON_ALPHA_ARG_B_ZERO | + RADEON_ALPHA_ARG_C_CURRENT_ALPHA | + RADEON_BLEND_CTL_ADD | + RADEON_SCALE_1X | + RADEON_CLAMP_TX); + rmesa->hw.tex[1].cmd[TEX_PP_TFACTOR] = 0; + + /* Can oly add ST1 at the time of doing some multitex but can keep + * it after that. Errors if DIFFUSE is missing. + */ + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] = + (RADEON_TCL_VTX_Z0 | + RADEON_TCL_VTX_W0 | + RADEON_TCL_VTX_PK_DIFFUSE + ); /* need to keep this uptodate */ + + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] = + ( RADEON_TCL_COMPUTE_XYZW | + (RADEON_TCL_TEX_INPUT_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT) | + (RADEON_TCL_TEX_INPUT_TEX_1 << RADEON_TCL_TEX_1_OUTPUT_SHIFT) | + (RADEON_TCL_TEX_INPUT_TEX_2 << RADEON_TCL_TEX_2_OUTPUT_SHIFT)); + + + /* XXX */ + rmesa->hw.tcl.cmd[TCL_MATRIX_SELECT_0] = + ((MODEL << RADEON_MODELVIEW_0_SHIFT) | + (MODEL_IT << RADEON_IT_MODELVIEW_0_SHIFT)); + + rmesa->hw.tcl.cmd[TCL_MATRIX_SELECT_1] = + ((MODEL_PROJ << RADEON_MODELPROJECT_0_SHIFT) | + (TEXMAT_0 << RADEON_TEXMAT_0_SHIFT) | + (TEXMAT_1 << RADEON_TEXMAT_1_SHIFT)); + + rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = + (RADEON_UCP_IN_CLIP_SPACE | + RADEON_CULL_FRONT_IS_CCW); + + rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] = 0; + + rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = + (RADEON_SPECULAR_LIGHTS | + RADEON_DIFFUSE_SPECULAR_COMBINE | + RADEON_LOCAL_LIGHT_VEC_GL | + (RADEON_LM_SOURCE_STATE_PREMULT << RADEON_EMISSIVE_SOURCE_SHIFT) | + (RADEON_LM_SOURCE_STATE_PREMULT << RADEON_AMBIENT_SOURCE_SHIFT) | + (RADEON_LM_SOURCE_STATE_PREMULT << RADEON_DIFFUSE_SOURCE_SHIFT) | + (RADEON_LM_SOURCE_STATE_PREMULT << RADEON_SPECULAR_SOURCE_SHIFT)); + + for (i = 0 ; i < 8; i++) { + struct gl_light *l = &ctx->Light.Light[i]; + GLenum p = GL_LIGHT0 + i; + *(float *)&(rmesa->hw.lit[i].cmd[LIT_RANGE_CUTOFF]) = FLT_MAX; + + ctx->Driver.Lightfv( ctx, p, GL_AMBIENT, l->Ambient ); + ctx->Driver.Lightfv( ctx, p, GL_DIFFUSE, l->Diffuse ); + ctx->Driver.Lightfv( ctx, p, GL_SPECULAR, l->Specular ); + ctx->Driver.Lightfv( ctx, p, GL_POSITION, 0 ); + ctx->Driver.Lightfv( ctx, p, GL_SPOT_DIRECTION, 0 ); + ctx->Driver.Lightfv( ctx, p, GL_SPOT_EXPONENT, &l->SpotExponent ); + ctx->Driver.Lightfv( ctx, p, GL_SPOT_CUTOFF, &l->SpotCutoff ); + ctx->Driver.Lightfv( ctx, p, GL_CONSTANT_ATTENUATION, + &l->ConstantAttenuation ); + ctx->Driver.Lightfv( ctx, p, GL_LINEAR_ATTENUATION, + &l->LinearAttenuation ); + ctx->Driver.Lightfv( ctx, p, GL_QUADRATIC_ATTENUATION, + &l->QuadraticAttenuation ); + } + + ctx->Driver.LightModelfv( ctx, GL_LIGHT_MODEL_AMBIENT, + ctx->Light.Model.Ambient ); + + TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx ); + + for (i = 0 ; i < 6; i++) { + ctx->Driver.ClipPlane( ctx, GL_CLIP_PLANE0 + i, NULL ); + } + + ctx->Driver.Fogfv( ctx, GL_FOG_MODE, 0 ); + ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density ); + ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start ); + ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End ); + ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color ); + ctx->Driver.Fogfv( ctx, GL_FOG_COORDINATE_SOURCE_EXT, 0 ); + + + /* Set up vector and scalar state commands: + */ +/* upload_matrix( rmesa, ctx->ModelView.m, MODEL ); */ +/* upload_matrix_t( rmesa, ctx->ModelView.inv, MODEL_IT ); */ +/* upload_matrix( rmesa, ctx->TextureMatrix[0].m, TEXMAT_0 ); */ +/* upload_matrix( rmesa, ctx->TextureMatrix[1].m, TEXMAT_1 ); */ +/* upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, TEXMAT_2 ); */ + + rmesa->hw.grd.cmd[GRD_VERT_GUARD_CLIP_ADJ] = IEEE_ONE; + rmesa->hw.grd.cmd[GRD_VERT_GUARD_DISCARD_ADJ] = IEEE_ONE; + rmesa->hw.grd.cmd[GRD_HORZ_GUARD_CLIP_ADJ] = IEEE_ONE; + rmesa->hw.grd.cmd[GRD_HORZ_GUARD_DISCARD_ADJ] = IEEE_ONE; + + rmesa->hw.eye.cmd[EYE_X] = 0; + rmesa->hw.eye.cmd[EYE_Y] = 0; + rmesa->hw.eye.cmd[EYE_Z] = IEEE_ONE; + rmesa->hw.eye.cmd[EYE_RESCALE_FACTOR] = IEEE_ONE; +} diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_swtcl.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_swtcl.c new file mode 100644 index 000000000..2194add40 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_swtcl.c @@ -0,0 +1,1189 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_swtcl.c,v 1.4 2003/02/15 22:18:48 dawes Exp $ */ +/************************************************************************** + +Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and + VA Linux Systems Inc., Fremont, California. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * + */ + +#include "glheader.h" +#include "mtypes.h" +#include "colormac.h" +#include "enums.h" +#include "mem.h" +#include "mmath.h" +#include "macros.h" + +#include "swrast_setup/swrast_setup.h" +#include "math/m_translate.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +#include "radeon_context.h" +#include "radeon_ioctl.h" +#include "radeon_state.h" +#include "radeon_swtcl.h" +#include "radeon_tcl.h" + +/*********************************************************************** + * Build render functions from dd templates * + ***********************************************************************/ + + +#define RADEON_XYZW_BIT 0x01 +#define RADEON_RGBA_BIT 0x02 +#define RADEON_SPEC_BIT 0x04 +#define RADEON_TEX0_BIT 0x08 +#define RADEON_TEX1_BIT 0x10 +#define RADEON_PTEX_BIT 0x20 +#define RADEON_MAX_SETUP 0x40 + +static void flush_last_swtcl_prim( radeonContextPtr rmesa ); +static void flush_last_swtcl_prim_compat( radeonContextPtr rmesa ); + +static struct { + void (*emit)( GLcontext *, GLuint, GLuint, void *, GLuint ); + interp_func interp; + copy_pv_func copy_pv; + GLboolean (*check_tex_sizes)( GLcontext *ctx ); + GLuint vertex_size; + GLuint vertex_stride_shift; + GLuint vertex_format; +} setup_tab[RADEON_MAX_SETUP]; + + +#define TINY_VERTEX_FORMAT (RADEON_CP_VC_FRMT_XY | \ + RADEON_CP_VC_FRMT_Z | \ + RADEON_CP_VC_FRMT_PKCOLOR) + +#define NOTEX_VERTEX_FORMAT (RADEON_CP_VC_FRMT_XY | \ + RADEON_CP_VC_FRMT_Z | \ + RADEON_CP_VC_FRMT_W0 | \ + RADEON_CP_VC_FRMT_PKCOLOR | \ + RADEON_CP_VC_FRMT_PKSPEC) + +#define TEX0_VERTEX_FORMAT (RADEON_CP_VC_FRMT_XY | \ + RADEON_CP_VC_FRMT_Z | \ + RADEON_CP_VC_FRMT_W0 | \ + RADEON_CP_VC_FRMT_PKCOLOR | \ + RADEON_CP_VC_FRMT_PKSPEC | \ + RADEON_CP_VC_FRMT_ST0) + +#define TEX1_VERTEX_FORMAT (RADEON_CP_VC_FRMT_XY | \ + RADEON_CP_VC_FRMT_Z | \ + RADEON_CP_VC_FRMT_W0 | \ + RADEON_CP_VC_FRMT_PKCOLOR | \ + RADEON_CP_VC_FRMT_PKSPEC | \ + RADEON_CP_VC_FRMT_ST0 | \ + RADEON_CP_VC_FRMT_ST1) + +#define PROJ_TEX1_VERTEX_FORMAT (RADEON_CP_VC_FRMT_XY | \ + RADEON_CP_VC_FRMT_Z | \ + RADEON_CP_VC_FRMT_W0 | \ + RADEON_CP_VC_FRMT_PKCOLOR | \ + RADEON_CP_VC_FRMT_PKSPEC | \ + RADEON_CP_VC_FRMT_ST0 | \ + RADEON_CP_VC_FRMT_Q0 | \ + RADEON_CP_VC_FRMT_ST1 | \ + RADEON_CP_VC_FRMT_Q1) + +#define TEX2_VERTEX_FORMAT 0 +#define TEX3_VERTEX_FORMAT 0 +#define PROJ_TEX3_VERTEX_FORMAT 0 + +#define DO_XYZW (IND & RADEON_XYZW_BIT) +#define DO_RGBA (IND & RADEON_RGBA_BIT) +#define DO_SPEC (IND & RADEON_SPEC_BIT) +#define DO_FOG (IND & RADEON_SPEC_BIT) +#define DO_TEX0 (IND & RADEON_TEX0_BIT) +#define DO_TEX1 (IND & RADEON_TEX1_BIT) +#define DO_TEX2 0 +#define DO_TEX3 0 +#define DO_PTEX (IND & RADEON_PTEX_BIT) + +#define VERTEX radeonVertex +#define VERTEX_COLOR radeon_color_t +#define GET_VIEWPORT_MAT() 0 +#define GET_TEXSOURCE(n) n +#define GET_VERTEX_FORMAT() RADEON_CONTEXT(ctx)->swtcl.vertex_format +#define GET_VERTEX_STORE() RADEON_CONTEXT(ctx)->swtcl.verts +#define GET_VERTEX_STRIDE_SHIFT() RADEON_CONTEXT(ctx)->swtcl.vertex_stride_shift +#define GET_UBYTE_COLOR_STORE() &RADEON_CONTEXT(ctx)->UbyteColor +#define GET_UBYTE_SPEC_COLOR_STORE() &RADEON_CONTEXT(ctx)->UbyteSecondaryColor + +#define HAVE_HW_VIEWPORT 1 +/* Tiny vertices don't seem to work atm - haven't looked into why. + */ +#define HAVE_HW_DIVIDE (IND & ~(RADEON_XYZW_BIT|RADEON_RGBA_BIT)) +#define HAVE_TINY_VERTICES 1 +#define HAVE_RGBA_COLOR 1 +#define HAVE_NOTEX_VERTICES 1 +#define HAVE_TEX0_VERTICES 1 +#define HAVE_TEX1_VERTICES 1 +#define HAVE_TEX2_VERTICES 0 +#define HAVE_TEX3_VERTICES 0 +#define HAVE_PTEX_VERTICES 1 + +#define CHECK_HW_DIVIDE (!(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE| \ + DD_TRI_UNFILLED))) + +#define IMPORT_QUALIFIER +#define IMPORT_FLOAT_COLORS radeon_import_float_colors +#define IMPORT_FLOAT_SPEC_COLORS radeon_import_float_spec_colors + +#define INTERP_VERTEX setup_tab[RADEON_CONTEXT(ctx)->swtcl.SetupIndex].interp +#define COPY_PV_VERTEX setup_tab[RADEON_CONTEXT(ctx)->swtcl.SetupIndex].copy_pv + + +/*********************************************************************** + * Generate pv-copying and translation functions * + ***********************************************************************/ + +#define TAG(x) radeon_##x +#define IND ~0 +#include "tnl_dd/t_dd_vb.c" +#undef IND + + +/*********************************************************************** + * Generate vertex emit and interp functions * + ***********************************************************************/ + +#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT) +#define TAG(x) x##_wg +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_TEX0_BIT) +#define TAG(x) x##_wgt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_TEX0_BIT|RADEON_PTEX_BIT) +#define TAG(x) x##_wgpt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_TEX0_BIT|RADEON_TEX1_BIT) +#define TAG(x) x##_wgt0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_TEX0_BIT|RADEON_TEX1_BIT|\ + RADEON_PTEX_BIT) +#define TAG(x) x##_wgpt0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT) +#define TAG(x) x##_wgfs +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT|\ + RADEON_TEX0_BIT) +#define TAG(x) x##_wgfst0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT|\ + RADEON_TEX0_BIT|RADEON_PTEX_BIT) +#define TAG(x) x##_wgfspt0 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT|\ + RADEON_TEX0_BIT|RADEON_TEX1_BIT) +#define TAG(x) x##_wgfst0t1 +#include "tnl_dd/t_dd_vbtmp.h" + +#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT|\ + RADEON_TEX0_BIT|RADEON_TEX1_BIT|RADEON_PTEX_BIT) +#define TAG(x) x##_wgfspt0t1 +#include "tnl_dd/t_dd_vbtmp.h" + + +/*********************************************************************** + * Initialization + ***********************************************************************/ + +static void init_setup_tab( void ) +{ + init_wg(); + init_wgt0(); + init_wgpt0(); + init_wgt0t1(); + init_wgpt0t1(); + init_wgfs(); + init_wgfst0(); + init_wgfspt0(); + init_wgfst0t1(); + init_wgfspt0t1(); +} + + + +void radeonPrintSetupFlags(char *msg, GLuint flags ) +{ + fprintf(stderr, "%s(%x): %s%s%s%s%s%s\n", + msg, + (int)flags, + (flags & RADEON_XYZW_BIT) ? " xyzw," : "", + (flags & RADEON_RGBA_BIT) ? " rgba," : "", + (flags & RADEON_SPEC_BIT) ? " spec/fog," : "", + (flags & RADEON_TEX0_BIT) ? " tex-0," : "", + (flags & RADEON_TEX1_BIT) ? " tex-1," : "", + (flags & RADEON_PTEX_BIT) ? " proj-tex," : ""); +} + + +static void radeonRenderStart( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + + if (!setup_tab[rmesa->swtcl.SetupIndex].check_tex_sizes(ctx)) { + GLuint ind = rmesa->swtcl.SetupIndex |= (RADEON_PTEX_BIT|RADEON_RGBA_BIT); + + /* Radeon handles projective textures nicely; just have to change + * up to the new vertex format. + */ + if (setup_tab[ind].vertex_format != rmesa->swtcl.vertex_format) { + RADEON_NEWPRIM(rmesa); + rmesa->swtcl.vertex_format = setup_tab[ind].vertex_format; + rmesa->swtcl.vertex_size = setup_tab[ind].vertex_size; + rmesa->swtcl.vertex_stride_shift = setup_tab[ind].vertex_stride_shift; + } + + if (!(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) { + tnl->Driver.Render.Interp = setup_tab[rmesa->swtcl.SetupIndex].interp; + tnl->Driver.Render.CopyPV = setup_tab[rmesa->swtcl.SetupIndex].copy_pv; + } + } + + if (rmesa->dma.flush != 0 && + rmesa->dma.flush != flush_last_swtcl_prim && + rmesa->dma.flush != flush_last_swtcl_prim_compat) + rmesa->dma.flush( rmesa ); +} + + +void radeonBuildVertices( GLcontext *ctx, GLuint start, GLuint count, + GLuint newinputs ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + GLubyte *v = ((GLubyte *)rmesa->swtcl.verts + + (start << rmesa->swtcl.vertex_stride_shift)); + GLuint stride = 1 << rmesa->swtcl.vertex_stride_shift; + + newinputs |= rmesa->swtcl.SetupNewInputs; + rmesa->swtcl.SetupNewInputs = 0; + + if (!newinputs) + return; + + setup_tab[rmesa->swtcl.SetupIndex].emit( ctx, start, count, v, stride ); +} + +void radeonChooseVertexState( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint ind = (RADEON_XYZW_BIT | RADEON_RGBA_BIT); + + if (!rmesa->TclFallback || rmesa->Fallback) + return; + + if (ctx->Fog.Enabled || (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)) + ind |= RADEON_SPEC_BIT; + + if (ctx->Texture._ReallyEnabled & TEXTURE1_ANY) + ind |= RADEON_TEX0_BIT|RADEON_TEX1_BIT; + else if (ctx->Texture._ReallyEnabled & TEXTURE0_ANY) + ind |= RADEON_TEX0_BIT; + + rmesa->swtcl.SetupIndex = ind; + + if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) { + tnl->Driver.Render.Interp = radeon_interp_extras; + tnl->Driver.Render.CopyPV = radeon_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 != rmesa->swtcl.vertex_format) { + RADEON_NEWPRIM(rmesa); + rmesa->swtcl.vertex_format = setup_tab[ind].vertex_format; + rmesa->swtcl.vertex_size = setup_tab[ind].vertex_size; + rmesa->swtcl.vertex_stride_shift = setup_tab[ind].vertex_stride_shift; + } + + { + GLuint se_coord_fmt, needproj; + + /* HW perspective divide is a win, but tiny vertex formats are a + * bigger one. + */ + if (setup_tab[ind].vertex_format == TINY_VERTEX_FORMAT || + (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) { + needproj = GL_TRUE; + se_coord_fmt = (RADEON_VTX_XY_PRE_MULT_1_OVER_W0 | + RADEON_VTX_Z_PRE_MULT_1_OVER_W0 | + RADEON_TEX1_W_ROUTING_USE_Q1); + } + else { + needproj = GL_FALSE; + se_coord_fmt = (RADEON_VTX_W0_IS_NOT_1_OVER_W0 | + RADEON_TEX1_W_ROUTING_USE_Q1); + } + + if ( se_coord_fmt != rmesa->hw.set.cmd[SET_SE_COORDFMT] ) { + RADEON_STATECHANGE( rmesa, set ); + rmesa->hw.set.cmd[SET_SE_COORDFMT] = se_coord_fmt; + } + _tnl_need_projected_coords( ctx, needproj ); + } +} + + +/* Flush vertices in the current dma region. + */ +static void flush_last_swtcl_prim( radeonContextPtr rmesa ) +{ + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s\n", __FUNCTION__); + + if (rmesa->dma.current.buf) { + struct radeon_dma_region *current = &rmesa->dma.current; + GLuint current_offset = (rmesa->radeonScreen->agp_buffer_offset + + current->buf->buf->idx * RADEON_BUFFER_SIZE + + current->start); + + assert (!(rmesa->swtcl.hw_primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND)); + + assert (current->start + + rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 == + current->ptr); + + if (rmesa->dma.current.start != rmesa->dma.current.ptr) { + radeonEmitVertexAOS( rmesa, + rmesa->swtcl.vertex_size, + current_offset); + + radeonEmitVbufPrim( rmesa, + rmesa->swtcl.vertex_format, + rmesa->swtcl.hw_primitive, + rmesa->swtcl.numverts); + } + + rmesa->swtcl.numverts = 0; + current->start = current->ptr; + + rmesa->dma.flush = 0; + } +} + + +static void flush_last_swtcl_prim_compat( radeonContextPtr rmesa ) +{ + struct radeon_dma_region *current = &rmesa->dma.current; + + if (RADEON_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s buf %p start %d ptr %d\n", + __FUNCTION__, + current->buf, + current->start, + current->ptr); + + assert (!(rmesa->swtcl.hw_primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND)); + assert (current->start + + rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 == + current->ptr); + assert (current->start == 0); + + if (current->ptr && current->buf) { + assert (current->buf->refcount == 1); + + radeonCompatEmitPrimitive( rmesa, + rmesa->swtcl.vertex_format, + rmesa->swtcl.hw_primitive, + rmesa->swtcl.numverts); + + /* The buffer has been released: + */ + FREE(current->buf); + current->buf = 0; + current->start = 0; + current->ptr = current->end; + + } + + rmesa->swtcl.numverts = 0; + rmesa->dma.flush = 0; +} + + +/* Alloc space in the current dma region. + */ +static __inline void *radeonAllocDmaLowVerts( radeonContextPtr rmesa, + int nverts, int vsize ) +{ + GLuint bytes = vsize * nverts; + + if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end ) + radeonRefillCurrentDmaRegion( rmesa ); + + if (!rmesa->dma.flush) { + if (rmesa->dri.drmMinor == 1) + rmesa->dma.flush = flush_last_swtcl_prim_compat; + else + rmesa->dma.flush = flush_last_swtcl_prim; + } + + assert( vsize == rmesa->swtcl.vertex_size * 4 ); + assert( rmesa->dma.flush == flush_last_swtcl_prim || + rmesa->dma.flush == flush_last_swtcl_prim_compat); + assert (rmesa->dma.current.start + + rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 == + rmesa->dma.current.ptr); + + + { + GLubyte *head = rmesa->dma.current.address + rmesa->dma.current.ptr; + rmesa->dma.current.ptr += bytes; + rmesa->swtcl.numverts += nverts; + return head; + } + +} + + + + +void radeon_emit_contiguous_verts( GLcontext *ctx, GLuint start, GLuint count ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLuint vertex_size = rmesa->swtcl.vertex_size * 4; + CARD32 *dest = radeonAllocDmaLowVerts( rmesa, count-start, vertex_size ); + setup_tab[rmesa->swtcl.SetupIndex].emit( ctx, start, count, dest, + vertex_size ); +} + + + +void radeon_emit_indexed_verts( GLcontext *ctx, GLuint start, GLuint count ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + + radeonAllocDmaRegionVerts( rmesa, + &rmesa->swtcl.indexed_verts, + count - start, + rmesa->swtcl.vertex_size * 4, + 64); + + setup_tab[rmesa->swtcl.SetupIndex].emit( + ctx, start, count, + rmesa->swtcl.indexed_verts.address + rmesa->swtcl.indexed_verts.start, + rmesa->swtcl.vertex_size * 4 ); +} + + +/* + * Render unclipped vertex buffers by emitting vertices directly to + * dma buffers. Use strip/fan hardware primitives where possible. + * Try to simulate missing primitives with indexed vertices. + */ +#define HAVE_POINTS 1 +#define HAVE_LINES 1 +#define HAVE_LINE_STRIPS 1 +#define HAVE_TRIANGLES 1 +#define HAVE_TRI_STRIPS 1 +#define HAVE_TRI_STRIP_1 0 +#define HAVE_TRI_FANS 1 +#define HAVE_QUADS 0 +#define HAVE_QUAD_STRIPS 0 +#define HAVE_POLYGONS 0 +#define HAVE_ELTS 1 + +static const GLuint hw_prim[GL_POLYGON+1] = { + RADEON_CP_VC_CNTL_PRIM_TYPE_POINT, + RADEON_CP_VC_CNTL_PRIM_TYPE_LINE, + 0, + RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP, + RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST, + RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP, + RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN, + 0, + 0, + 0 +}; + +static __inline void radeonDmaPrimitive( radeonContextPtr rmesa, GLenum prim ) +{ + RADEON_NEWPRIM( rmesa ); + rmesa->swtcl.hw_primitive = hw_prim[prim]; + assert(rmesa->dma.current.ptr == rmesa->dma.current.start); +} + +static __inline void radeonEltPrimitive( radeonContextPtr rmesa, GLenum prim ) +{ + RADEON_NEWPRIM( rmesa ); + rmesa->swtcl.hw_primitive = hw_prim[prim] | RADEON_CP_VC_CNTL_PRIM_WALK_IND; +} + + +static void VERT_FALLBACK( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + tnl->Driver.Render.PrimitiveNotify( ctx, flags & PRIM_MODE_MASK ); + tnl->Driver.Render.BuildVertices( ctx, start, count, ~0 ); + tnl->Driver.Render.PrimTabVerts[flags&PRIM_MODE_MASK]( ctx, start, count, flags ); + RADEON_CONTEXT(ctx)->swtcl.SetupNewInputs = VERT_CLIP; +} + +static void ELT_FALLBACK( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + tnl->Driver.Render.PrimitiveNotify( ctx, flags & PRIM_MODE_MASK ); + tnl->Driver.Render.BuildVertices( ctx, start, count, ~0 ); + tnl->Driver.Render.PrimTabElts[flags&PRIM_MODE_MASK]( ctx, start, count, flags ); + RADEON_CONTEXT(ctx)->swtcl.SetupNewInputs = VERT_CLIP; +} + + +#define LOCAL_VARS radeonContextPtr rmesa = RADEON_CONTEXT(ctx) +#define ELTS_VARS GLushort *dest +#define INIT( prim ) radeonDmaPrimitive( rmesa, prim ) +#define ELT_INIT(prim) radeonEltPrimitive( rmesa, prim ) +#define NEW_PRIMITIVE() RADEON_NEWPRIM( rmesa ) +#define NEW_BUFFER() radeonRefillCurrentDmaRegion( rmesa ) +#define GET_CURRENT_VB_MAX_VERTS() \ + (((int)rmesa->dma.current.end - (int)rmesa->dma.current.ptr) / (rmesa->swtcl.vertex_size*4)) +#define GET_SUBSEQUENT_VB_MAX_VERTS() \ + ((RADEON_BUFFER_SIZE) / (rmesa->swtcl.vertex_size*4)) + +#if RADEON_OLD_PACKETS +# define GET_CURRENT_VB_MAX_ELTS() \ + ((RADEON_CMD_BUF_SZ - (rmesa->store.cmd_used + 24)) / 2) +#else +# define GET_CURRENT_VB_MAX_ELTS() \ + ((RADEON_CMD_BUF_SZ - (rmesa->store.cmd_used + 16)) / 2) +#endif +#define GET_SUBSEQUENT_VB_MAX_ELTS() \ + ((RADEON_CMD_BUF_SZ - 1024) / 2) + + + +/* How do you extend an existing primitive? + */ +#define ALLOC_ELTS(nr) \ +do { \ + if (rmesa->dma.flush == radeonFlushElts && \ + rmesa->store.cmd_used + nr*2 < RADEON_CMD_BUF_SZ) { \ + \ + dest = (GLushort *)(rmesa->store.cmd_buf + \ + rmesa->store.cmd_used); \ + rmesa->store.cmd_used += nr*2; \ + } \ + else { \ + if (rmesa->dma.flush) { \ + rmesa->dma.flush( rmesa ); \ + } \ + \ + radeonEmitVertexAOS( rmesa, \ + rmesa->swtcl.vertex_size, \ + (rmesa->radeonScreen->agp_buffer_offset + \ + rmesa->swtcl.indexed_verts.buf->buf->idx * \ + RADEON_BUFFER_SIZE + \ + rmesa->swtcl.indexed_verts.start)); \ + \ + dest = radeonAllocEltsOpenEnded( rmesa, \ + rmesa->swtcl.vertex_format, \ + rmesa->swtcl.hw_primitive, \ + nr ); \ + } \ +} while (0) + +#define ALLOC_ELTS_NEW_PRIMITIVE(nr) ALLOC_ELTS( nr ) + +#ifdef MESA_BIG_ENDIAN +/* We could do without (most of) this ugliness if dest was always 32 bit word aligned... */ +#define EMIT_ELT(offset, x) do { \ + int off = offset + ( ( (GLuint)dest & 0x2 ) >> 1 ); \ + GLushort *des = (GLushort *)( (GLuint)dest & ~0x2 ); \ + (des)[ off + 1 - 2 * ( off & 1 ) ] = (GLushort)(x); } while (0) +#else +#define EMIT_ELT(offset, x) (dest)[offset] = (GLushort) (x) +#endif +#define EMIT_TWO_ELTS(offset, x, y) *(GLuint *)(dest+offset) = ((y)<<16)|(x); +#define INCR_ELTS( nr ) dest += nr +#define RELEASE_ELT_VERTS() \ + radeonReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, __FUNCTION__ ) +#define EMIT_VERTS( ctx, j, nr ) \ + radeon_emit_contiguous_verts(ctx, j, (j)+(nr)) +#define EMIT_INDEXED_VERTS( ctx, start, count ) \ + radeon_emit_indexed_verts( ctx, start, count ) + + +#define TAG(x) radeon_dma_##x +#include "tnl_dd/t_dd_dmatmp.h" + + +/**********************************************************************/ +/* Render pipeline stage */ +/**********************************************************************/ + + +static GLboolean radeon_run_render( GLcontext *ctx, + struct gl_pipeline_stage *stage ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint i, length, flags = 0; + render_func *tab = TAG(render_tab_verts); + + if (rmesa->swtcl.indexed_verts.buf && (!VB->Elts || stage->changed_inputs)) + RELEASE_ELT_VERTS(); + + if (VB->ClipOrMask || /* No clipping */ + rmesa->swtcl.RenderIndex != 0 || /* No per-vertex manipulations */ + ctx->Line.StippleFlag) /* GH: THIS IS A HACK!!! */ + return GL_TRUE; + + if (rmesa->dri.drmMinor < 3) { + /* drm 1.1 doesn't support vertex primitives starting in the + * middle of a buffer. It doesn't support sane indexed vertices + * either. drm 1.2 fixes both of these problems, but we don't have a + * compatibility layer to that version yet. + */ + return GL_TRUE; + } + + tnl->Driver.Render.Start( ctx ); + + if (VB->Elts) { + tab = TAG(render_tab_elts); + if (!rmesa->swtcl.indexed_verts.buf) + if (!TAG(emit_elt_verts)(ctx, 0, VB->Count)) + return GL_TRUE; /* too many vertices */ + } + + for (i = 0 ; !(flags & PRIM_LAST) ; i += length) + { + flags = VB->Primitive[i]; + length = VB->PrimitiveLength[i]; + + if (RADEON_DEBUG & DEBUG_PRIMS) + fprintf(stderr, "radeon_render.c: prim %s %d..%d\n", + _mesa_lookup_enum_by_nr(flags & PRIM_MODE_MASK), + i, i+length); + + if (length) + tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags ); + } + + tnl->Driver.Render.Finish( ctx ); + + return GL_FALSE; /* finished the pipe */ +} + + + +static void radeon_check_render( GLcontext *ctx, + struct gl_pipeline_stage *stage ) +{ + GLuint inputs = VERT_OBJ|VERT_CLIP|VERT_RGBA; + + if (ctx->RenderMode == GL_RENDER) { + if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) + inputs |= VERT_SPEC_RGB; + + if (ctx->Texture.Unit[0]._ReallyEnabled) + inputs |= VERT_TEX(0); + + if (ctx->Texture.Unit[1]._ReallyEnabled) + inputs |= VERT_TEX(1); + + if (ctx->Fog.Enabled) + inputs |= VERT_FOG_COORD; + } + + stage->inputs = inputs; +} + + +static void dtr( struct gl_pipeline_stage *stage ) +{ + (void)stage; +} + + +const struct gl_pipeline_stage _radeon_render_stage = +{ + "radeon render", + (_DD_NEW_SEPARATE_SPECULAR | + _NEW_TEXTURE| + _NEW_FOG| + _NEW_RENDERMODE), /* re-check (new inputs) */ + 0, /* re-run (always runs) */ + GL_TRUE, /* active */ + 0, 0, /* inputs (set in check_render), outputs */ + 0, 0, /* changed_inputs, private */ + dtr, /* destructor */ + radeon_check_render, /* check - initially set to alloc data */ + radeon_run_render /* run */ +}; + + + +/**************************************************************************/ + + +static const GLuint reduced_hw_prim[GL_POLYGON+1] = { + RADEON_CP_VC_CNTL_PRIM_TYPE_POINT, + RADEON_CP_VC_CNTL_PRIM_TYPE_LINE, + RADEON_CP_VC_CNTL_PRIM_TYPE_LINE, + RADEON_CP_VC_CNTL_PRIM_TYPE_LINE, + RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST, + RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST, + RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST, + RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST, + RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST, + RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST +}; + +static void radeonRasterPrimitive( GLcontext *ctx, GLuint hwprim ); +static void radeonRenderPrimitive( GLcontext *ctx, GLenum prim ); +static void radeonResetLineStipple( GLcontext *ctx ); + + +/*********************************************************************** + * Emit primitives as inline vertices * + ***********************************************************************/ + +#define CTX_ARG radeonContextPtr rmesa +#define CTX_ARG2 rmesa +#define GET_VERTEX_DWORDS() rmesa->swtcl.vertex_size +#define ALLOC_VERTS( n, size ) radeonAllocDmaLowVerts( rmesa, n, size * 4 ) +#undef LOCAL_VARS +#define LOCAL_VARS \ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \ + const GLuint shift = rmesa->swtcl.vertex_stride_shift; \ + const char *radeonverts = (char *)rmesa->swtcl.verts; +#define VERT(x) (radeonVertex *)(radeonverts + (x << shift)) +#define VERTEX radeonVertex +#undef TAG +#define TAG(x) radeon_##x +#include "tnl_dd/t_dd_triemit.h" + + +/*********************************************************************** + * Macros for t_dd_tritmp.h to draw basic primitives * + ***********************************************************************/ + +#define QUAD( a, b, c, d ) radeon_quad( rmesa, a, b, c, d ) +#define TRI( a, b, c ) radeon_triangle( rmesa, a, b, c ) +#define LINE( a, b ) radeon_line( rmesa, a, b ) +#define POINT( a ) radeon_point( rmesa, a ) + +/*********************************************************************** + * Build render functions from dd templates * + ***********************************************************************/ + +#define RADEON_TWOSIDE_BIT 0x01 +#define RADEON_UNFILLED_BIT 0x02 +#define RADEON_OFFSET_BIT 0x04 /* drmMinor == 1 */ +#define RADEON_MAX_TRIFUNC 0x08 + + +static struct { + points_func points; + line_func line; + triangle_func triangle; + quad_func quad; +} rast_tab[RADEON_MAX_TRIFUNC]; + + +#define DO_FALLBACK 0 +#define DO_OFFSET (IND & RADEON_OFFSET_BIT) +#define DO_UNFILLED (IND & RADEON_UNFILLED_BIT) +#define DO_TWOSIDE (IND & RADEON_TWOSIDE_BIT) +#define DO_FLAT 0 +#define DO_TRI 1 +#define DO_QUAD 1 +#define DO_LINE 1 +#define DO_POINTS 1 +#define DO_FULL_QUAD 1 + +#define HAVE_RGBA 1 +#define HAVE_SPEC 1 +#define HAVE_INDEX 0 +#define HAVE_BACK_COLORS 0 +#define HAVE_HW_FLATSHADE 1 +#define TAB rast_tab + +#define DEPTH_SCALE 1.0 +#define UNFILLED_TRI unfilled_tri +#define UNFILLED_QUAD unfilled_quad +#define VERT_X(_v) _v->v.x +#define VERT_Y(_v) _v->v.y +#define VERT_Z(_v) _v->v.z +#define AREA_IS_CCW( a ) (a < 0) +#define GET_VERTEX(e) (rmesa->swtcl.verts + (e<<rmesa->swtcl.vertex_stride_shift)) + +#define VERT_SET_RGBA( v, c ) v->ui[coloroffset] = LE32_TO_CPU(*(GLuint *)c) +#define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset] +#define VERT_SAVE_RGBA( idx ) color[idx] = CPU_TO_LE32(v[idx]->ui[coloroffset]) +#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = LE32_TO_CPU(color[idx]) + +#define VERT_SET_SPEC( v0, c ) if (havespec) { \ + v0->v.specular.red = (c)[0]; \ + v0->v.specular.green = (c)[1]; \ + v0->v.specular.blue = (c)[2]; } +#define VERT_COPY_SPEC( v0, v1 ) if (havespec) { \ + v0->v.specular.red = v1->v.specular.red; \ + v0->v.specular.green = v1->v.specular.green; \ + v0->v.specular.blue = v1->v.specular.blue; } +#define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = CPU_TO_LE32(v[idx]->ui[5]) +#define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = LE32_TO_CPU(spec[idx]) + +#undef LOCAL_VARS +#define LOCAL_VARS(n) \ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \ + GLuint color[n], spec[n]; \ + GLuint coloroffset = (rmesa->swtcl.vertex_size == 4 ? 3 : 4); \ + GLboolean havespec = (rmesa->swtcl.vertex_size > 4); \ + (void) color; (void) spec; (void) coloroffset; (void) havespec; + +/*********************************************************************** + * Helpers for rendering unfilled primitives * + ***********************************************************************/ + +#define RASTERIZE(x) radeonRasterPrimitive( ctx, reduced_hw_prim[x] ) +#define RENDER_PRIMITIVE rmesa->swtcl.render_primitive +#undef TAG +#define TAG(x) x +#include "tnl_dd/t_dd_unfilled.h" +#undef IND + + +/*********************************************************************** + * Generate GL render functions * + ***********************************************************************/ + + +#define IND (0) +#define TAG(x) x +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (RADEON_TWOSIDE_BIT) +#define TAG(x) x##_twoside +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (RADEON_UNFILLED_BIT) +#define TAG(x) x##_unfilled +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (RADEON_TWOSIDE_BIT|RADEON_UNFILLED_BIT) +#define TAG(x) x##_twoside_unfilled +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (RADEON_OFFSET_BIT) +#define TAG(x) x##_offset +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (RADEON_TWOSIDE_BIT|RADEON_OFFSET_BIT) +#define TAG(x) x##_twoside_offset +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (RADEON_UNFILLED_BIT|RADEON_OFFSET_BIT) +#define TAG(x) x##_unfilled_offset +#include "tnl_dd/t_dd_tritmp.h" + +#define IND (RADEON_TWOSIDE_BIT|RADEON_UNFILLED_BIT|RADEON_OFFSET_BIT) +#define TAG(x) x##_twoside_unfilled_offset +#include "tnl_dd/t_dd_tritmp.h" + + +static void init_rast_tab( void ) +{ + init(); + init_twoside(); + init_unfilled(); + init_twoside_unfilled(); + init_offset(); + init_twoside_offset(); + init_unfilled_offset(); + init_twoside_unfilled_offset(); +} + +/**********************************************************************/ +/* Render unclipped begin/end objects */ +/**********************************************************************/ + +#define VERT(x) (radeonVertex *)(radeonverts + (x << shift)) +#define RENDER_POINTS( start, count ) \ + for ( ; start < count ; start++) \ + radeon_point( rmesa, VERT(start) ) +#define RENDER_LINE( v0, v1 ) \ + radeon_line( rmesa, VERT(v0), VERT(v1) ) +#define RENDER_TRI( v0, v1, v2 ) \ + radeon_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) ) +#define RENDER_QUAD( v0, v1, v2, v3 ) \ + radeon_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) ) +#undef INIT +#define INIT(x) do { \ + radeonRenderPrimitive( ctx, x ); \ +} while (0) +#undef LOCAL_VARS +#define LOCAL_VARS \ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \ + const GLuint shift = rmesa->swtcl.vertex_stride_shift; \ + const char *radeonverts = (char *)rmesa->swtcl.verts; \ + const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \ + const GLboolean stipple = ctx->Line.StippleFlag; \ + (void) elt; (void) stipple; +#define RESET_STIPPLE if ( stipple ) radeonResetLineStipple( ctx ); +#define RESET_OCCLUSION +#define PRESERVE_VB_DEFS +#define ELT(x) (x) +#define TAG(x) radeon_##x##_verts +#include "tnl/t_vb_rendertmp.h" +#undef ELT +#undef TAG +#define TAG(x) radeon_##x##_elts +#define ELT(x) elt[x] +#include "tnl/t_vb_rendertmp.h" + + + +/**********************************************************************/ +/* Choose render functions */ +/**********************************************************************/ + +void radeonChooseRenderState( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLuint index = 0; + GLuint flags = ctx->_TriangleCaps; + + if (!rmesa->TclFallback || rmesa->Fallback) + return; + + if (flags & DD_TRI_LIGHT_TWOSIDE) index |= RADEON_TWOSIDE_BIT; + if (flags & DD_TRI_UNFILLED) index |= RADEON_UNFILLED_BIT; + if ((flags & DD_TRI_OFFSET) && + rmesa->dri.drmMinor == 1) index |= RADEON_OFFSET_BIT; + + if (index != rmesa->swtcl.RenderIndex) { + tnl->Driver.Render.Points = rast_tab[index].points; + tnl->Driver.Render.Line = rast_tab[index].line; + tnl->Driver.Render.ClippedLine = rast_tab[index].line; + tnl->Driver.Render.Triangle = rast_tab[index].triangle; + tnl->Driver.Render.Quad = rast_tab[index].quad; + + if (index == 0) { + tnl->Driver.Render.PrimTabVerts = radeon_render_tab_verts; + tnl->Driver.Render.PrimTabElts = radeon_render_tab_elts; + tnl->Driver.Render.ClippedPolygon = radeon_fast_clipped_poly; + } else { + tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; + tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; + tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon; + } + + rmesa->swtcl.RenderIndex = index; + } +} + + +/**********************************************************************/ +/* High level hooks for t_vb_render.c */ +/**********************************************************************/ + + +static void radeonRasterPrimitive( GLcontext *ctx, GLuint hwprim ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + + if (rmesa->swtcl.hw_primitive != hwprim) { + RADEON_NEWPRIM( rmesa ); + rmesa->swtcl.hw_primitive = hwprim; + } +} + +static void radeonRenderPrimitive( GLcontext *ctx, GLenum prim ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + rmesa->swtcl.render_primitive = prim; + if (prim < GL_TRIANGLES || !(ctx->_TriangleCaps & DD_TRI_UNFILLED)) + radeonRasterPrimitive( ctx, reduced_hw_prim[prim] ); +} + +static void radeonRenderFinish( GLcontext *ctx ) +{ +} + +static void radeonResetLineStipple( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + RADEON_STATECHANGE( rmesa, lin ); +} + + +/**********************************************************************/ +/* Transition to/from hardware rasterization. */ +/**********************************************************************/ + +static char *fallbackStrings[] = { + "Texture mode", + "glDrawBuffer(GL_FRONT_AND_BACK)", + "glEnable(GL_STENCIL) without hw stencil buffer", + "glRenderMode(selection or feedback)", + "glBlendEquation", + "glBlendFunc(mode != ADD)" + "RADEON_NO_RAST" +}; + + +static char *getFallbackString(GLuint bit) +{ + int i = 0; + while (bit > 1) { + i++; + bit >>= 1; + } + return fallbackStrings[i]; +} + + +void radeonFallback( GLcontext *ctx, GLuint bit, GLboolean mode ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint oldfallback = rmesa->Fallback; + + if (mode) { + rmesa->Fallback |= bit; + if (oldfallback == 0) { + RADEON_FIREVERTICES( rmesa ); + TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_RASTER, GL_TRUE ); + _swsetup_Wakeup( ctx ); + _tnl_need_projected_coords( ctx, GL_TRUE ); + rmesa->swtcl.RenderIndex = ~0; + if (RADEON_DEBUG & DEBUG_FALLBACKS) { + fprintf(stderr, "Radeon begin rasterization fallback: 0x%x %s\n", + bit, getFallbackString(bit)); + } + } + } + else { + rmesa->Fallback &= ~bit; + if (oldfallback == bit) { + _swrast_flush( ctx ); + tnl->Driver.Render.Start = radeonRenderStart; + tnl->Driver.Render.PrimitiveNotify = radeonRenderPrimitive; + tnl->Driver.Render.Finish = radeonRenderFinish; + tnl->Driver.Render.BuildVertices = radeonBuildVertices; + tnl->Driver.Render.ResetLineStipple = radeonResetLineStipple; + TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_RASTER, GL_FALSE ); + if (rmesa->TclFallback) { + /* These are already done if rmesa->TclFallback goes to + * zero above. But not if it doesn't (RADEON_NO_TCL for + * example?) + */ + radeonChooseVertexState( ctx ); + radeonChooseRenderState( ctx ); + } + if (RADEON_DEBUG & DEBUG_FALLBACKS) { + fprintf(stderr, "Radeon end rasterization fallback: 0x%x %s\n", + bit, getFallbackString(bit)); + } + } + } +} + + +/**********************************************************************/ +/* Initialization. */ +/**********************************************************************/ + +void radeonInitSwtcl( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLuint size = TNL_CONTEXT(ctx)->vb.Size; + static int firsttime = 1; + + if (firsttime) { + init_rast_tab(); + init_setup_tab(); + firsttime = 0; + } + + tnl->Driver.Render.Start = radeonRenderStart; + tnl->Driver.Render.Finish = radeonRenderFinish; + tnl->Driver.Render.PrimitiveNotify = radeonRenderPrimitive; + tnl->Driver.Render.ResetLineStipple = radeonResetLineStipple; + tnl->Driver.Render.BuildVertices = radeonBuildVertices; + + rmesa->swtcl.verts = (char *)ALIGN_MALLOC( size * 16 * 4, 32 ); + rmesa->swtcl.RenderIndex = ~0; + rmesa->swtcl.render_primitive = GL_TRIANGLES; + rmesa->swtcl.hw_primitive = 0; +} + + +void radeonDestroySwtcl( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + + if (rmesa->swtcl.indexed_verts.buf) + radeonReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, + __FUNCTION__ ); + + if (rmesa->swtcl.verts) { + ALIGN_FREE(rmesa->swtcl.verts); + rmesa->swtcl.verts = 0; + } + + if (rmesa->UbyteSecondaryColor.Ptr) { + ALIGN_FREE(rmesa->UbyteSecondaryColor.Ptr); + rmesa->UbyteSecondaryColor.Ptr = 0; + } + + if (rmesa->UbyteColor.Ptr) { + ALIGN_FREE(rmesa->UbyteColor.Ptr); + rmesa->UbyteColor.Ptr = 0; + } +} diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_swtcl.h b/xc/lib/GL/mesa/src/drv/radeon/radeon_swtcl.h new file mode 100644 index 000000000..fe874cd7b --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_swtcl.h @@ -0,0 +1,76 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_swtcl.h,v 1.1 2002/10/30 12:51:57 alanh Exp $ */ +/************************************************************************** + +Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and + VA Linux Systems Inc., Fremont, California. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * + */ + +#ifndef __RADEON_TRIS_H__ +#define __RADEON_TRIS_H__ + +#include "mtypes.h" +#include "swrast/swrast.h" +#include "radeon_context.h" + +extern void radeonInitSwtcl( GLcontext *ctx ); +extern void radeonDestroySwtcl( GLcontext *ctx ); + +extern void radeonChooseRenderState( GLcontext *ctx ); +extern void radeonChooseVertexState( GLcontext *ctx ); + +extern void radeonCheckTexSizes( GLcontext *ctx ); + +extern void radeonBuildVertices( GLcontext *ctx, GLuint start, GLuint count, + GLuint newinputs ); + +extern void radeonPrintSetupFlags(char *msg, GLuint flags ); + + +extern void radeon_emit_contiguous_verts( GLcontext *ctx, + GLuint start, + GLuint count ); + +extern void radeon_emit_indexed_verts( GLcontext *ctx, + GLuint start, + GLuint count ); + +extern void radeon_translate_vertex( GLcontext *ctx, + const radeonVertex *src, + SWvertex *dst ); + +extern void radeon_print_vertex( GLcontext *ctx, const radeonVertex *v ); + +extern void radeon_import_float_colors( GLcontext *ctx ); +extern void radeon_import_float_spec_colors( GLcontext *ctx ); + + + +#endif diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_tcl.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_tcl.c new file mode 100644 index 000000000..c8fc07474 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_tcl.c @@ -0,0 +1,545 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_tcl.c,v 1.1 2002/10/30 12:51:57 alanh Exp $ */ +/************************************************************************** + +Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and + Tungsten Graphics Inc., Austin, Texas. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * + */ + +#include "radeon_context.h" +#include "radeon_state.h" +#include "radeon_ioctl.h" +#include "radeon_tex.h" +#include "radeon_tcl.h" +#include "radeon_swtcl.h" +#include "radeon_maos.h" + +#include "mmath.h" +#include "mtypes.h" +#include "enums.h" +#include "colormac.h" +#include "light.h" + +#include "array_cache/acache.h" +#include "tnl/tnl.h" +#include "tnl/t_pipeline.h" + + + +/* + * Render unclipped vertex buffers by emitting vertices directly to + * dma buffers. Use strip/fan hardware primitives where possible. + * Try to simulate missing primitives with indexed vertices. + */ +#define HAVE_POINTS 1 +#define HAVE_LINES 1 +#define HAVE_LINE_LOOP 0 +#define HAVE_LINE_STRIPS 1 +#define HAVE_TRIANGLES 1 +#define HAVE_TRI_STRIPS 1 +#define HAVE_TRI_STRIP_1 0 +#define HAVE_TRI_FANS 1 +#define HAVE_QUADS 0 +#define HAVE_QUAD_STRIPS 0 +#define HAVE_POLYGONS 1 +#define HAVE_ELTS 1 + + +#define HW_POINTS RADEON_CP_VC_CNTL_PRIM_TYPE_POINT +#define HW_LINES RADEON_CP_VC_CNTL_PRIM_TYPE_LINE +#define HW_LINE_LOOP 0 +#define HW_LINE_STRIP RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP +#define HW_TRIANGLES RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST +#define HW_TRIANGLE_STRIP_0 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP +#define HW_TRIANGLE_STRIP_1 0 +#define HW_TRIANGLE_FAN RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN +#define HW_QUADS 0 +#define HW_QUAD_STRIP 0 +#define HW_POLYGON RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN + + +static GLboolean discreet_prim[0x10] = { + 0, /* none */ + 1, /* points */ + 1, /* lines */ + 0, /* line_strip */ + 1, /* tri_list */ + 0, /* tri_fan */ + 0, /* tri_type_2 */ + 1, /* rect list (unused) */ + 1, /* 3 vert point */ + 1, /* 3 vert line */ + 0, + 0, + 0, + 0, + 0, +}; + + +#define LOCAL_VARS radeonContextPtr rmesa = RADEON_CONTEXT(ctx) +#define ELTS_VARS GLushort *dest + +#define ELT_INIT(prim, hw_prim) \ + radeonTclPrimitive( ctx, prim, hw_prim | RADEON_CP_VC_CNTL_PRIM_WALK_IND ) + +#define GET_ELTS() rmesa->tcl.Elts + + +#define NEW_PRIMITIVE() RADEON_NEWPRIM( rmesa ) +#define NEW_BUFFER() radeonRefillCurrentDmaRegion( rmesa ) + +/* Don't really know how many elts will fit in what's left of cmdbuf, + * as there is state to emit, etc: + */ + +#if 0 +#define GET_CURRENT_VB_MAX_ELTS() \ + ((RADEON_CMD_BUF_SZ - (rmesa->store.cmd_used + 16)) / 2) +#define GET_SUBSEQUENT_VB_MAX_ELTS() ((RADEON_CMD_BUF_SZ - 16) / 2) +#else +/* Testing on isosurf shows a maximum around here. Don't know if it's + * the card or driver or kernel module that is causing the behaviour. + */ +#define GET_CURRENT_VB_MAX_ELTS() 300 +#define GET_SUBSEQUENT_VB_MAX_ELTS() 300 +#endif + +#define RESET_STIPPLE() do { \ + RADEON_STATECHANGE( rmesa, lin ); \ + radeonEmitState( rmesa ); \ +} while (0) + +#define AUTO_STIPPLE( mode ) do { \ + RADEON_STATECHANGE( rmesa, lin ); \ + if (mode) \ + rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] |= \ + RADEON_LINE_PATTERN_AUTO_RESET; \ + else \ + rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] &= \ + ~RADEON_LINE_PATTERN_AUTO_RESET; \ + radeonEmitState( rmesa ); \ +} while (0) + + +/* How do you extend an existing primitive? + */ +#define ALLOC_ELTS(nr) \ +do { \ + if (rmesa->dma.flush == radeonFlushElts && \ + rmesa->store.cmd_used + nr*2 < RADEON_CMD_BUF_SZ) { \ + \ + dest = (GLushort *)(rmesa->store.cmd_buf + \ + rmesa->store.cmd_used); \ + rmesa->store.cmd_used += nr*2; \ + } \ + else { \ + if (rmesa->dma.flush) \ + rmesa->dma.flush( rmesa ); \ + \ + radeonEmitAOS( rmesa, \ + rmesa->tcl.aos_components, \ + rmesa->tcl.nr_aos_components, \ + 0 ); \ + \ + dest = radeonAllocEltsOpenEnded( rmesa, \ + rmesa->tcl.vertex_format, \ + rmesa->tcl.hw_primitive, \ + nr ); \ + } \ +} while (0) + + + +/* TODO: Try to extend existing primitive if both are identical, + * discreet and there are no intervening state changes. (Somewhat + * duplicates changes to DrawArrays code) + */ +static void EMIT_PRIM( GLcontext *ctx, + GLenum prim, + GLuint hwprim, + GLuint start, + GLuint count) +{ + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + radeonTclPrimitive( ctx, prim, hwprim ); + + radeonEmitAOS( rmesa, + rmesa->tcl.aos_components, + rmesa->tcl.nr_aos_components, + start ); + + /* Why couldn't this packet have taken an offset param? + */ + radeonEmitVbufPrim( rmesa, + rmesa->tcl.vertex_format, + rmesa->tcl.hw_primitive, + count - start ); +} + + + +/* Try & join small primitives + */ +#if 0 +#define PREFER_DISCRETE_ELT_PRIM( NR, PRIM ) 0 +#else +#define PREFER_DISCRETE_ELT_PRIM( NR, PRIM ) \ + ((NR) < 20 || \ + ((NR) < 40 && \ + rmesa->tcl.hw_primitive == (PRIM| \ + RADEON_CP_VC_CNTL_PRIM_WALK_IND| \ + RADEON_CP_VC_CNTL_TCL_ENABLE))) +#endif + +#ifdef MESA_BIG_ENDIAN +/* We could do without (most of) this ugliness if dest was always 32 bit word aligned... */ +#define EMIT_ELT(offset, x) do { \ + int off = offset + ( ( (GLuint)dest & 0x2 ) >> 1 ); \ + GLushort *des = (GLushort *)( (GLuint)dest & ~0x2 ); \ + (des)[ off + 1 - 2 * ( off & 1 ) ] = (GLushort)(x); } while (0) +#else +#define EMIT_ELT(offset, x) (dest)[offset] = (GLushort) (x) +#endif +#define EMIT_TWO_ELTS(offset, x, y) *(GLuint *)(dest+offset) = ((y)<<16)|(x); +#define INCR_ELTS( nr ) dest += nr +#define RELEASE_ELT_VERTS() \ + radeonReleaseArrays( ctx, ~0 ) + + + +#define TAG(x) tcl_##x +#include "tnl_dd/t_dd_dmatmp2.h" + +/**********************************************************************/ +/* External entrypoints */ +/**********************************************************************/ + +void radeonEmitPrimitive( GLcontext *ctx, + GLuint first, + GLuint last, + GLuint flags ) +{ + tcl_render_tab_verts[flags&PRIM_MODE_MASK]( ctx, first, last, flags ); +} + +void radeonEmitEltPrimitive( GLcontext *ctx, + GLuint first, + GLuint last, + GLuint flags ) +{ + tcl_render_tab_elts[flags&PRIM_MODE_MASK]( ctx, first, last, flags ); +} + +void radeonTclPrimitive( GLcontext *ctx, + GLenum prim, + int hw_prim ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLuint se_cntl; + GLuint newprim = hw_prim | RADEON_CP_VC_CNTL_TCL_ENABLE; + + if (newprim != rmesa->tcl.hw_primitive || + !discreet_prim[hw_prim&0xf]) { + RADEON_NEWPRIM( rmesa ); + rmesa->tcl.hw_primitive = newprim; + } + + se_cntl = rmesa->hw.set.cmd[SET_SE_CNTL]; + se_cntl &= ~RADEON_FLAT_SHADE_VTX_LAST; + + if (prim == GL_POLYGON && (ctx->_TriangleCaps & DD_FLATSHADE)) + se_cntl |= RADEON_FLAT_SHADE_VTX_0; + else + se_cntl |= RADEON_FLAT_SHADE_VTX_LAST; + + if (se_cntl != rmesa->hw.set.cmd[SET_SE_CNTL]) { + RADEON_STATECHANGE( rmesa, set ); + rmesa->hw.set.cmd[SET_SE_CNTL] = se_cntl; + } +} + + +/**********************************************************************/ +/* Render pipeline stage */ +/**********************************************************************/ + + +/* TCL render. + */ +static GLboolean radeon_run_tcl_render( GLcontext *ctx, + struct gl_pipeline_stage *stage ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint i,flags = 0,length; + + /* TODO: separate this from the swtnl pipeline + */ + if (rmesa->TclFallback) + return GL_TRUE; /* fallback to software t&l */ + + if (VB->Count == 0) + return GL_FALSE; + + radeonReleaseArrays( ctx, stage->changed_inputs ); + radeonEmitArrays( ctx, stage->inputs ); + + rmesa->tcl.Elts = VB->Elts; + + for (i = VB->FirstPrimitive ; !(flags & PRIM_LAST) ; i += length) + { + flags = VB->Primitive[i]; + length = VB->PrimitiveLength[i]; + + if (RADEON_DEBUG & DEBUG_PRIMS) + fprintf(stderr, "%s: prim %s %d..%d\n", + __FUNCTION__, + _mesa_lookup_enum_by_nr(flags & PRIM_MODE_MASK), + i, i+length); + + if (!length) + continue; + + if (rmesa->tcl.Elts) + radeonEmitEltPrimitive( ctx, i, i+length, flags ); + else + radeonEmitPrimitive( ctx, i, i+length, flags ); + } + + return GL_FALSE; /* finished the pipe */ +} + + + +static void radeon_check_tcl_render( GLcontext *ctx, + struct gl_pipeline_stage *stage ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLuint inputs = VERT_OBJ; + + if (ctx->RenderMode == GL_RENDER) { + /* Make all this event-driven: + */ + if (ctx->Light.Enabled) { + inputs |= VERT_NORM; + + if (ctx->Light.ColorMaterialEnabled) { + inputs |= VERT_RGBA; + } + } + else { + inputs |= VERT_RGBA; + + if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) { + inputs |= VERT_SPEC_RGB; + } + } + + if (ctx->Texture.Unit[0]._ReallyEnabled) { + if (ctx->Texture.Unit[0].TexGenEnabled) { + if (rmesa->TexGenNeedNormals[0]) { + inputs |= VERT_NORM; + } + } else { + inputs |= VERT_TEX(0); + } + } + + if (ctx->Texture.Unit[1]._ReallyEnabled) { + if (ctx->Texture.Unit[1].TexGenEnabled) { + if (rmesa->TexGenNeedNormals[1]) { + inputs |= VERT_NORM; + } + } else { + inputs |= VERT_TEX(1); + } + } + + stage->inputs = inputs; + stage->active = 1; + } + else + stage->active = 0; +} + +static void radeon_init_tcl_render( GLcontext *ctx, + struct gl_pipeline_stage *stage ) +{ + stage->check = radeon_check_tcl_render; + stage->check( ctx, stage ); +} + +static void dtr( struct gl_pipeline_stage *stage ) +{ + (void)stage; +} + + +/* Initial state for tcl stage. + */ +const struct gl_pipeline_stage _radeon_tcl_stage = +{ + "radeon render", + (_DD_NEW_SEPARATE_SPECULAR | + _NEW_LIGHT| + _NEW_TEXTURE| + _NEW_FOG| + _NEW_RENDERMODE), /* re-check (new inputs) */ + 0, /* re-run (always runs) */ + GL_TRUE, /* active */ + 0, 0, /* inputs (set in check_render), outputs */ + 0, 0, /* changed_inputs, private */ + dtr, /* destructor */ + radeon_init_tcl_render, /* check - initially set to alloc data */ + radeon_run_tcl_render /* run */ +}; + + + +/**********************************************************************/ +/* Validate state at pipeline start */ +/**********************************************************************/ + + +/*----------------------------------------------------------------------- + * Manage TCL fallbacks + */ + + +static void transition_to_swtnl( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint se_cntl; + + RADEON_NEWPRIM( rmesa ); + rmesa->swtcl.vertex_format = 0; + + radeonChooseVertexState( ctx ); + radeonChooseRenderState( ctx ); + + _mesa_validate_all_lighting_tables( ctx ); + + tnl->Driver.NotifyMaterialChange = + _mesa_validate_all_lighting_tables; + + radeonReleaseArrays( ctx, ~0 ); + + se_cntl = rmesa->hw.set.cmd[SET_SE_CNTL]; + se_cntl |= RADEON_FLAT_SHADE_VTX_LAST; + + if (se_cntl != rmesa->hw.set.cmd[SET_SE_CNTL]) { + RADEON_STATECHANGE( rmesa, set ); + rmesa->hw.set.cmd[SET_SE_CNTL] = se_cntl; + } +} + + +static void transition_to_hwtnl( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint se_coord_fmt = (RADEON_VTX_W0_IS_NOT_1_OVER_W0 | + RADEON_TEX1_W_ROUTING_USE_Q1); + + if ( se_coord_fmt != rmesa->hw.set.cmd[SET_SE_COORDFMT] ) { + RADEON_STATECHANGE( rmesa, set ); + rmesa->hw.set.cmd[SET_SE_COORDFMT] = se_coord_fmt; + _tnl_need_projected_coords( ctx, GL_FALSE ); + } + + radeonUpdateMaterial( ctx ); + + tnl->Driver.NotifyMaterialChange = radeonUpdateMaterial; + + if ( rmesa->dma.flush ) + rmesa->dma.flush( rmesa ); + + rmesa->dma.flush = 0; + rmesa->swtcl.vertex_format = 0; + + if (rmesa->swtcl.indexed_verts.buf) + radeonReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, + __FUNCTION__ ); + + if (RADEON_DEBUG & DEBUG_FALLBACKS) + fprintf(stderr, "Radeon end tcl fallback\n"); +} + +static char *fallbackStrings[] = { + "Rasterization fallback", + "Unfilled triangles", + "Twosided lighting, differing materials", + "Materials in VB (maybe between begin/end)", + "Texgen unit 0", + "Texgen unit 1", + "Texgen unit 2", + "User disable" +}; + + +static char *getFallbackString(GLuint bit) +{ + int i = 0; + while (bit > 1) { + i++; + bit >>= 1; + } + return fallbackStrings[i]; +} + + + +void radeonTclFallback( GLcontext *ctx, GLuint bit, GLboolean mode ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLuint oldfallback = rmesa->TclFallback; + + if (mode) { + rmesa->TclFallback |= bit; + if (oldfallback == 0) { + if (RADEON_DEBUG & DEBUG_FALLBACKS) + fprintf(stderr, "Radeon begin tcl fallback %s\n", + getFallbackString( bit )); + transition_to_swtnl( ctx ); + } + } + else { + rmesa->TclFallback &= ~bit; + if (oldfallback == bit) { + if (RADEON_DEBUG & DEBUG_FALLBACKS) + fprintf(stderr, "Radeon end tcl fallback %s\n", + getFallbackString( bit )); + transition_to_hwtnl( ctx ); + } + } +} diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_tcl.h b/xc/lib/GL/mesa/src/drv/radeon/radeon_tcl.h new file mode 100644 index 000000000..c35916c6a --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_tcl.h @@ -0,0 +1,66 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_tcl.h,v 1.2 2003/02/08 21:26:45 dawes Exp $ */ +/************************************************************************** + +Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and + Tungsten Grahpics Inc., Austin, Texas. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, TUNGSTEN GRAHPICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * + */ + +#ifndef __RADEON_TCL_H__ +#define __RADEON_TCL_H__ + +#ifdef GLX_DIRECT_RENDERING + +#include "radeon_context.h" + +extern void radeonTclPrimitive( GLcontext *ctx, GLenum prim, int hw_prim ); +extern void radeonEmitEltPrimitive( GLcontext *ctx, GLuint first, GLuint last, + GLuint flags ); +extern void radeonEmitPrimitive( GLcontext *ctx, GLuint first, GLuint last, + GLuint flags ); + +extern void radeonTclFallback( GLcontext *ctx, GLuint bit, GLboolean mode ); + +#define RADEON_TCL_FALLBACK_RASTER 0x1 /* rasterization */ +#define RADEON_TCL_FALLBACK_UNFILLED 0x2 /* unfilled tris */ +#define RADEON_TCL_FALLBACK_LIGHT_TWOSIDE 0x4 /* twoside tris */ +#define RADEON_TCL_FALLBACK_MATERIAL 0x8 /* material in vb */ +#define RADEON_TCL_FALLBACK_TEXGEN_0 0x10 /* texgen, unit 0 */ +#define RADEON_TCL_FALLBACK_TEXGEN_1 0x20 /* texgen, unit 1 */ +#define RADEON_TCL_FALLBACK_TEXGEN_2 0x40 /* texgen, unit 2 */ +#define RADEON_TCL_FALLBACK_TCL_DISABLE 0x80 /* user disable */ + +#define RADEON_MAX_TCL_VERTSIZE (15*4) + +#define TCL_FALLBACK( ctx, bit, mode ) radeonTclFallback( ctx, bit, mode ) + + +#endif +#endif diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_tex.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_tex.c index 701cd6f25..c804f48e2 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_tex.c +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_tex.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_tex.c,v 1.6 2002/09/16 18:05:20 eich Exp $ */ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_tex.c,v 1.9 2002/12/16 16:18:59 dawes Exp $ */ /* * Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and * VA Linux Systems Inc., Fremont, California. @@ -32,7 +32,7 @@ #include "radeon_context.h" #include "radeon_state.h" #include "radeon_ioctl.h" -#include "radeon_vb.h" +#include "radeon_swtcl.h" #include "radeon_tex.h" #include "colormac.h" @@ -40,11 +40,9 @@ #include "enums.h" #include "image.h" #include "mem.h" -#include "mmath.h" #include "simple_list.h" #include "texformat.h" #include "texstore.h" -#include "texutil.h" /* ============================================================= @@ -65,6 +63,18 @@ static void radeonSetTexWrap( radeonTexObjPtr t, GLenum swrap, GLenum twrap ) case GL_CLAMP_TO_EDGE: t->pp_txfilter |= RADEON_CLAMP_S_CLAMP_LAST; break; + case GL_CLAMP_TO_BORDER: + t->pp_txfilter |= RADEON_CLAMP_S_CLAMP_BORDER; + break; + case GL_MIRRORED_REPEAT: + t->pp_txfilter |= RADEON_CLAMP_S_MIRROR; + break; + case GL_MIRROR_CLAMP_ATI: + t->pp_txfilter |= RADEON_CLAMP_S_MIRROR_CLAMP_BORDER; + break; + case GL_MIRROR_CLAMP_TO_EDGE_ATI: + t->pp_txfilter |= RADEON_CLAMP_S_MIRROR_CLAMP_LAST; + break; } switch ( twrap ) { @@ -77,6 +87,18 @@ static void radeonSetTexWrap( radeonTexObjPtr t, GLenum swrap, GLenum twrap ) case GL_CLAMP_TO_EDGE: t->pp_txfilter |= RADEON_CLAMP_T_CLAMP_LAST; break; + case GL_CLAMP_TO_BORDER: + t->pp_txfilter |= RADEON_CLAMP_T_CLAMP_BORDER; + break; + case GL_MIRRORED_REPEAT: + t->pp_txfilter |= RADEON_CLAMP_T_MIRROR; + break; + case GL_MIRROR_CLAMP_ATI: + t->pp_txfilter |= RADEON_CLAMP_T_MIRROR_CLAMP_BORDER; + break; + case GL_MIRROR_CLAMP_TO_EDGE_ATI: + t->pp_txfilter |= RADEON_CLAMP_T_MIRROR_CLAMP_LAST; + break; } } @@ -167,27 +189,19 @@ static radeonTexObjPtr radeonAllocTexObj( struct gl_texture_object *texObj ) if (!t) return NULL; - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { - fprintf( stderr, "%s( %p, %p )\n",__FUNCTION__, (void*)texObj, (void*)t ); + if ( RADEON_DEBUG & DEBUG_TEXTURE ) { + fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, texObj, t ); } - /* Initialize non-image-dependent parts of the state: - */ t->tObj = texObj; -#if 0 - t->dirty_images = ~0; -#endif - t->pp_txfilter = RADEON_BORDER_MODE_OGL; - t->pp_txformat = (RADEON_TXFORMAT_ENDIAN_NO_SWAP | - RADEON_TXFORMAT_PERSPECTIVE_ENABLE); - make_empty_list( t ); + /* Initialize non-image-dependent parts of the state: + */ radeonSetTexWrap( t, texObj->WrapS, texObj->WrapT ); radeonSetTexMaxAnisotropy( t, texObj->MaxAnisotropy ); radeonSetTexFilter( t, texObj->MinFilter, texObj->MagFilter ); radeonSetTexBorderColor( t, texObj->BorderColor ); - return t; } @@ -202,6 +216,7 @@ radeonChooseTextureFormat( GLcontext *ctx, GLint internalFormat, switch ( internalFormat ) { case 4: case GL_RGBA: + case GL_COMPRESSED_RGBA: if ( format == GL_BGRA ) { if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) { return &_mesa_texformat_argb8888; @@ -217,6 +232,7 @@ radeonChooseTextureFormat( GLcontext *ctx, GLint internalFormat, case 3: case GL_RGB: + case GL_COMPRESSED_RGB: if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) { return &_mesa_texformat_rgb565; } @@ -251,6 +267,7 @@ radeonChooseTextureFormat( GLcontext *ctx, GLint internalFormat, case GL_ALPHA8: case GL_ALPHA12: case GL_ALPHA16: + case GL_COMPRESSED_ALPHA: return &_mesa_texformat_al88; case 1: @@ -259,6 +276,7 @@ radeonChooseTextureFormat( GLcontext *ctx, GLint internalFormat, case GL_LUMINANCE8: case GL_LUMINANCE12: case GL_LUMINANCE16: + case GL_COMPRESSED_LUMINANCE: return &_mesa_texformat_al88; case 2: @@ -269,6 +287,7 @@ radeonChooseTextureFormat( GLcontext *ctx, GLint internalFormat, case GL_LUMINANCE12_ALPHA4: case GL_LUMINANCE12_ALPHA12: case GL_LUMINANCE16_ALPHA16: + case GL_COMPRESSED_LUMINANCE_ALPHA: return &_mesa_texformat_al88; case GL_INTENSITY: @@ -276,6 +295,7 @@ radeonChooseTextureFormat( GLcontext *ctx, GLint internalFormat, case GL_INTENSITY8: case GL_INTENSITY12: case GL_INTENSITY16: + case GL_COMPRESSED_INTENSITY: return &_mesa_texformat_i8; default: @@ -316,13 +336,6 @@ static void radeonTexImage1D( GLcontext *ctx, GLenum target, GLint level, &ctx->Unpack, texObj, texImage); t->dirty_images |= (1 << level); - - if ( t == rmesa->state.texture.unit[0].texobj ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_TEX0 ); - } - if ( t == rmesa->state.texture.unit[1].texobj ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_TEX1 ); - } } @@ -357,13 +370,6 @@ static void radeonTexSubImage1D( GLcontext *ctx, GLenum target, GLint level, texImage); t->dirty_images |= (1 << level); - - if ( t == rmesa->state.texture.unit[0].texobj ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_TEX0 ); - } - if ( t == rmesa->state.texture.unit[1].texobj ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_TEX1 ); - } } @@ -378,6 +384,8 @@ static void radeonTexImage2D( GLcontext *ctx, GLenum target, GLint level, radeonContextPtr rmesa = RADEON_CONTEXT(ctx); radeonTexObjPtr t = (radeonTexObjPtr)texObj->DriverData; +/* fprintf(stderr, "%s\n", __FUNCTION__); */ + if ( t ) { radeonSwapOutTexObj( rmesa, t ); } @@ -396,13 +404,6 @@ static void radeonTexImage2D( GLcontext *ctx, GLenum target, GLint level, &ctx->Unpack, texObj, texImage); t->dirty_images |= (1 << level); - - if ( t == rmesa->state.texture.unit[0].texobj ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_TEX0 ); - } - if ( t == rmesa->state.texture.unit[1].texobj ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_TEX1 ); - } } @@ -418,10 +419,11 @@ static void radeonTexSubImage2D( GLcontext *ctx, GLenum target, GLint level, radeonContextPtr rmesa = RADEON_CONTEXT(ctx); radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData; +/* fprintf(stderr, "%s\n", __FUNCTION__); */ + assert( t ); /* this _should_ be true */ if ( t ) { radeonSwapOutTexObj( rmesa, t ); - t->dirty_images |= (1 << level); } else { t = radeonAllocTexObj(texObj); @@ -437,88 +439,12 @@ static void radeonTexSubImage2D( GLcontext *ctx, GLenum target, GLint level, texImage); t->dirty_images |= (1 << level); - - if ( t == rmesa->state.texture.unit[0].texobj ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_TEX0 ); - } - if ( t == rmesa->state.texture.unit[1].texobj ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_TEX1 ); - } -} - -#if 0 -static void radeonTexImage3D( GLcontext *ctx, GLenum target, GLint level, - GLint internalFormat, - GLint width, GLint height, GLint depth, - GLint border, - GLenum format, GLenum type, const GLvoid *pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage ) -{ - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - radeonTexObjPtr t = (radeonTexObjPtr)texObj->DriverData; - - if ( t ) { - radeonSwapOutTexObj( rmesa, t ); - } - else { - t = radeonAllocTexObj( texObj ); - if (!t) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); - return; - } - texObj->DriverData = t; - } - - /* Note, this will call radeonChooseTextureFormat */ - _mesa_store_teximage3d(ctx, target, level, internalFormat, - width, height, depth, border, format, type, pixels, - &ctx->Unpack, texObj, texImage); - - t->dirty_images |= (1 << level); - - if ( t == rmesa->state.texture.unit[0].texobj ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_TEX0 ); - } - if ( t == rmesa->state.texture.unit[1].texobj ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_TEX1 ); - } } -static void radeonTexSubImage3D( GLcontext *ctx, GLenum target, GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLint depth, - GLenum format, GLenum type, - const GLvoid *pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage ) -{ - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData; - - assert( t ); /* this _should_ be true */ - - _mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset, - width, height, depth, format, type, pixels, - packing, texObj, texImage); - - t->dirty_images |= (1 << level); - - if ( t == rmesa->state.texture.unit[0].texobj ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_TEX0 ); - } - if ( t == rmesa->state.texture.unit[1].texobj ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_TEX1 ); - } -} -#endif - #define SCALED_FLOAT_TO_BYTE( x, scale ) \ - ((((GLint)((256.0F / scale) * (x))) - 1) / 2) + (((GLuint)((255.0F / scale) * (x))) / 2) static void radeonTexEnv( GLcontext *ctx, GLenum target, GLenum pname, const GLfloat *param ) @@ -527,7 +453,7 @@ static void radeonTexEnv( GLcontext *ctx, GLenum target, GLuint unit = ctx->Texture.CurrentUnit; struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { + if ( RADEON_DEBUG & DEBUG_STATE ) { fprintf( stderr, "%s( %s )\n", __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) ); } @@ -538,11 +464,9 @@ static void radeonTexEnv( GLcontext *ctx, GLenum target, GLuint envColor; UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor ); envColor = radeonPackColor( 4, c[0], c[1], c[2], c[3] ); - if ( rmesa->state.hw.texture[unit].pp_tfactor != envColor ) { - if ( rmesa->state.texture.unit[unit].texobj ) { - RADEON_STATECHANGE( rmesa, (RADEON_UPLOAD_TEX0 << unit) ); - } - rmesa->state.hw.texture[unit].pp_tfactor = envColor; + if ( rmesa->hw.tex[unit].cmd[TEX_PP_TFACTOR] != envColor ) { + RADEON_STATECHANGE( rmesa, tex[unit] ); + rmesa->hw.tex[unit].cmd[TEX_PP_TFACTOR] = envColor; } break; } @@ -560,14 +484,14 @@ static void radeonTexEnv( GLcontext *ctx, GLenum target, if ( bias == 0 ) { b = 0; } else if ( bias > 0 ) { - b = ((GLuint)SCALED_FLOAT_TO_BYTE( bias, 4.0 )) << 8; + b = ((GLuint)SCALED_FLOAT_TO_BYTE( bias, 4.0 )) << RADEON_LOD_BIAS_SHIFT; } else { - b = ((GLuint)SCALED_FLOAT_TO_BYTE( bias, 1.0 )) << 8; + b = ((GLuint)SCALED_FLOAT_TO_BYTE( bias, 1.0 )) << RADEON_LOD_BIAS_SHIFT; } - if ( rmesa->state.hw.texture[unit].pp_txfilter != b ) { - if ( rmesa->state.texture.unit[unit].texobj ) - RADEON_STATECHANGE( rmesa, (RADEON_UPLOAD_TEX0 << unit) ); - rmesa->state.hw.texture[unit].pp_txfilter = b; + if ( (rmesa->hw.tex[unit].cmd[TEX_PP_TXFILTER] & RADEON_LOD_BIAS_MASK) != b ) { + RADEON_STATECHANGE( rmesa, tex[unit] ); + rmesa->hw.tex[unit].cmd[TEX_PP_TXFILTER] &= ~RADEON_LOD_BIAS_MASK; + rmesa->hw.tex[unit].cmd[TEX_PP_TXFILTER] |= (b & RADEON_LOD_BIAS_MASK); } break; } @@ -584,8 +508,8 @@ static void radeonTexParameter( GLcontext *ctx, GLenum target, radeonContextPtr rmesa = RADEON_CONTEXT(ctx); radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData; - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { - fprintf( stderr, "%s( %s )\n",__FUNCTION__, + if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) { + fprintf( stderr, "%s( %s )\n", __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) ); } @@ -596,6 +520,8 @@ static void radeonTexParameter( GLcontext *ctx, GLenum target, switch ( pname ) { case GL_TEXTURE_MIN_FILTER: case GL_TEXTURE_MAG_FILTER: + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + radeonSetTexMaxAnisotropy( t, texObj->MaxAnisotropy ); radeonSetTexFilter( t, texObj->MinFilter, texObj->MagFilter ); break; @@ -608,10 +534,6 @@ static void radeonTexParameter( GLcontext *ctx, GLenum target, radeonSetTexBorderColor( t, texObj->BorderColor ); break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: - radeonSetTexMaxAnisotropy( t, texObj->MaxAnisotropy ); - break; - case GL_TEXTURE_BASE_LEVEL: case GL_TEXTURE_MAX_LEVEL: case GL_TEXTURE_MIN_LOD: @@ -628,12 +550,9 @@ static void radeonTexParameter( GLcontext *ctx, GLenum target, return; } - if ( t == rmesa->state.texture.unit[0].texobj ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_TEX0 ); - } - if ( t == rmesa->state.texture.unit[1].texobj ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_TEX1 ); - } + /* Mark this texobj as dirty (one bit per tex unit) + */ + t->dirty_state = TEX_ALL; } @@ -644,8 +563,8 @@ static void radeonBindTexture( GLcontext *ctx, GLenum target, radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData; GLuint unit = ctx->Texture.CurrentUnit; - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { - fprintf( stderr, "%s( %p ) unit=%d\n",__FUNCTION__, (void*)texObj, unit ); + if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) { + fprintf( stderr, "%s( %p ) unit=%d\n", __FUNCTION__, texObj, unit ); } if ( target == GL_TEXTURE_2D || target == GL_TEXTURE_1D ) { @@ -662,8 +581,8 @@ static void radeonDeleteTexture( GLcontext *ctx, radeonContextPtr rmesa = RADEON_CONTEXT(ctx); radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData; - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { - fprintf( stderr, "%s( %p )\n",__FUNCTION__, (void*)texObj ); + if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) { + fprintf( stderr, "%s( %p )\n", __FUNCTION__, texObj ); } if ( t ) { @@ -717,6 +636,27 @@ static void radeonInitTextureObjects( GLcontext *ctx ) ctx->Texture.CurrentUnit = tmp; } +/* Need: + * - Same GEN_MODE for all active bits + * - Same EyePlane/ObjPlane for all active bits when using Eye/Obj + * - STRQ presumably all supported (matrix means incoming R values + * can end up in STQ, this has implications for vertex support, + * presumably ok if maos is used, though?) + * + * Basically impossible to do this on the fly - just collect some + * basic info & do the checks from ValidateState(). + */ +static void radeonTexGen( GLcontext *ctx, + GLenum coord, + GLenum pname, + const GLfloat *params ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLuint unit = ctx->Texture.CurrentUnit; + rmesa->recheck_texgen[unit] = GL_TRUE; +} + + void radeonInitTextureFuncs( GLcontext *ctx ) { ctx->Driver.ChooseTextureFormat = radeonChooseTextureFormat; @@ -730,7 +670,7 @@ void radeonInitTextureFuncs( GLcontext *ctx ) ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d; ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d; ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d; - ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d; + ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d; ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage; ctx->Driver.BindTexture = radeonBindTexture; @@ -743,6 +683,7 @@ void radeonInitTextureFuncs( GLcontext *ctx ) ctx->Driver.TexEnv = radeonTexEnv; ctx->Driver.TexParameter = radeonTexParameter; + ctx->Driver.TexGen = radeonTexGen; radeonInitTextureObjects( ctx ); } diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_texmem.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_texmem.c index efa1fa26a..f87853b35 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_texmem.c +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_texmem.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_texmem.c,v 1.4 2002/09/16 18:05:20 eich Exp $ */ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_texmem.c,v 1.7 2002/12/16 16:18:59 dawes Exp $ */ /************************************************************************** Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and @@ -35,17 +35,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "radeon_context.h" -#include "radeon_state.h" -#include "radeon_ioctl.h" -#include "radeon_vb.h" #include "radeon_tex.h" #include "context.h" -#include "colormac.h" -#include "mmath.h" -#include "macros.h" #include "simple_list.h" -#include "enums.h" #include "mem.h" @@ -57,8 +50,8 @@ void radeonDestroyTexObj( radeonContextPtr rmesa, radeonTexObjPtr t ) if ( !t ) return; - if ( RADEON_DEBUG & DEBUG_VERBOSE_TEXTURE ) { - fprintf( stderr, "%s( %p, %p )\n",__FUNCTION__, (void*)t, (void*)t->tObj ); + if ( RADEON_DEBUG & DEBUG_TEXTURE ) { + fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, t, t->tObj ); } if ( t->memBlock ) { @@ -75,12 +68,14 @@ void radeonDestroyTexObj( radeonContextPtr rmesa, radeonTexObjPtr t ) if ( t == rmesa->state.texture.unit[0].texobj ) { rmesa->state.texture.unit[0].texobj = NULL; - rmesa->state.hw.dirty &= ~RADEON_UPLOAD_TEX0; + remove_from_list( &rmesa->hw.tex[0] ); + make_empty_list( &rmesa->hw.tex[0] ); } if ( t == rmesa->state.texture.unit[1].texobj ) { rmesa->state.texture.unit[1].texobj = NULL; - rmesa->state.hw.dirty &= ~RADEON_UPLOAD_TEX1; + remove_from_list( &rmesa->hw.tex[1] ); + make_empty_list( &rmesa->hw.tex[1] ); } } @@ -88,12 +83,13 @@ void radeonDestroyTexObj( radeonContextPtr rmesa, radeonTexObjPtr t ) FREE( t ); } + /* Keep track of swapped out texture objects. */ void radeonSwapOutTexObj( radeonContextPtr rmesa, radeonTexObjPtr t ) { - if ( RADEON_DEBUG & DEBUG_VERBOSE_TEXTURE ) { - fprintf( stderr, "%s( %p, %p )\n",__FUNCTION__, (void*)t, (void*)t->tObj ); + if ( RADEON_DEBUG & DEBUG_TEXTURE ) { + fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, t, t->tObj ); } /* Bump the performace counter */ @@ -124,8 +120,7 @@ void radeonPrintLocalLRU( radeonContextPtr rmesa, int heap ) t->memBlock->ofs, t->memBlock->size ); } else { - fprintf( stderr, "Texture (bound %d) at 0x%x sz 0x%x\n", - t->bound, + fprintf( stderr, "Texture at 0x%x sz 0x%x\n", t->memBlock->ofs, t->memBlock->size ); } @@ -139,7 +134,7 @@ void radeonPrintGlobalLRU( radeonContextPtr rmesa, int heap ) radeon_tex_region_t *list = rmesa->sarea->texList[heap]; int i, j; - fprintf( stderr, "\nGlobal LRU, heap %d list %p:\n", heap, (void*)list ); + fprintf( stderr, "\nGlobal LRU, heap %d list %p:\n", heap, list ); for ( i = 0, j = RADEON_NR_TEX_REGIONS ; i < RADEON_NR_TEX_REGIONS ; i++ ) { fprintf( stderr, "list[%d] age %d next %d prev %d\n", @@ -329,9 +324,11 @@ static void radeonUploadSubImage( radeonContextPtr rmesa, GLuint format, pitch, offset; GLint imageWidth, imageHeight; GLint ret; + drmRadeonTexture tex; + drmRadeonTexImage tmp; - if ( RADEON_DEBUG & DEBUG_VERBOSE_TEXTURE ) { - fprintf( stderr, "%s( %p, %p )\n",__FUNCTION__, (void*)t, (void*)t->tObj ); + if ( RADEON_DEBUG & DEBUG_TEXTURE ) { + fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, t, t->tObj ); } /* Ensure we have a valid texture to upload */ @@ -343,13 +340,13 @@ static void radeonUploadSubImage( radeonContextPtr rmesa, texImage = t->tObj->Image[level]; if ( !texImage ) { - if ( RADEON_DEBUG & DEBUG_VERBOSE_TEXTURE ) - fprintf( stderr, "%s: texImage %d is NULL!\n",__FUNCTION__, level ); + if ( RADEON_DEBUG & DEBUG_TEXTURE ) + fprintf( stderr, "%s: texImage %d is NULL!\n", __FUNCTION__, level ); return; } if ( !texImage->Data ) { - if ( RADEON_DEBUG & DEBUG_VERBOSE_TEXTURE ) - fprintf( stderr, "%s: image data is NULL!\n",__FUNCTION__ ); + if ( RADEON_DEBUG & DEBUG_TEXTURE ) + fprintf( stderr, "%s: image data is NULL!\n", __FUNCTION__ ); return; } @@ -380,7 +377,7 @@ static void radeonUploadSubImage( radeonContextPtr rmesa, rmesa->c_textureBytes += (dwords << 2); #endif - if ( RADEON_DEBUG & DEBUG_VERBOSE_MSG ) { + if ( RADEON_DEBUG & (DEBUG_TEXTURE|DEBUG_IOCTL) ) { GLint imageX = 0; GLint imageY = 0; GLint blitX = t->image[level].x; @@ -397,12 +394,24 @@ static void radeonUploadSubImage( radeonContextPtr rmesa, } t->image[level].data = texImage->Data; - ret = drmRadeonLoadTexture( rmesa->dri.fd, offset, pitch, format, - imageWidth, imageHeight, &t->image[level] ); + + tex.offset = offset; + tex.pitch = pitch; + tex.format = format; + tex.width = imageWidth; + tex.height = imageHeight; + tex.image = &tmp; + + memcpy( &tmp, &t->image[level], sizeof(drmRadeonTexImage) ); + + do { + ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_TEXTURE, + &tex, sizeof(drmRadeonTexture) ); + } while ( ret && errno == EAGAIN ); if ( ret ) { UNLOCK_HARDWARE( rmesa ); - fprintf( stderr, "drmRadeonTextureBlit: return = %d\n", ret ); + fprintf( stderr, "DRM_RADEON_TEXTURE: return = %d\n", ret ); fprintf( stderr, " offset=0x%08x pitch=0x%x format=%d\n", offset, pitch, format ); fprintf( stderr, " image width=%d height=%d\n", @@ -412,8 +421,6 @@ static void radeonUploadSubImage( radeonContextPtr rmesa, t->image[level].data ); exit( 1 ); } - - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT | RADEON_UPLOAD_MASKS ); } /* Upload the texture images associated with texture `t'. This might @@ -425,10 +432,12 @@ int radeonUploadTexImages( radeonContextPtr rmesa, radeonTexObjPtr t ) const int numLevels = t->lastLevel - t->firstLevel + 1; int i; int heap; + radeonTexObjPtr t0 = rmesa->state.texture.unit[0].texobj; + radeonTexObjPtr t1 = rmesa->state.texture.unit[1].texobj; - if ( RADEON_DEBUG & DEBUG_VERBOSE_TEXTURE ) { - fprintf( stderr, "%s( %p, %p ) sz=%d lvls=%d-%d\n",__FUNCTION__, - (void*)rmesa->glCtx, (void*)t->tObj, t->totalSize, + if ( RADEON_DEBUG & (DEBUG_TEXTURE|DEBUG_IOCTL) ) { + fprintf( stderr, "%s( %p, %p ) sz=%d lvls=%d-%d\n", __FUNCTION__, + rmesa->glCtx, t->tObj, t->totalSize, t->firstLevel, t->lastLevel ); } @@ -465,7 +474,8 @@ int radeonUploadTexImages( radeonContextPtr rmesa, radeonTexObjPtr t ) /* Kick out textures until the requested texture fits */ while ( !t->memBlock ) { - if ( rmesa->texture.objects[heap].prev->bound ) { + if ( rmesa->texture.objects[heap].prev == t0 || + rmesa->texture.objects[heap].prev == t1 ) { fprintf( stderr, "radeonUploadTexImages: ran into bound texture\n" ); UNLOCK_HARDWARE( rmesa ); @@ -512,11 +522,9 @@ int radeonUploadTexImages( radeonContextPtr rmesa, radeonTexObjPtr t ) } #endif - if ( t == rmesa->state.texture.unit[0].texobj ) - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_TEX0 ); - - if ( t == rmesa->state.texture.unit[1].texobj ) - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_TEX1 ); + /* Mark this texobj as dirty on all units: + */ + t->dirty_state = TEX_ALL; } /* Let the world know we've used this memory recently */ diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_texstate.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_texstate.c index f66f589cd..943074514 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_texstate.c +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_texstate.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_texstate.c,v 1.3 2002/09/16 18:05:21 eich Exp $ */ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_texstate.c,v 1.6 2002/12/16 16:18:59 dawes Exp $ */ /************************************************************************** Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and @@ -37,16 +37,13 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "radeon_context.h" #include "radeon_state.h" #include "radeon_ioctl.h" -#include "radeon_vb.h" +#include "radeon_swtcl.h" #include "radeon_tex.h" +#include "radeon_tcl.h" -#include "colormac.h" #include "context.h" #include "enums.h" -#include "macros.h" #include "mem.h" -#include "mmath.h" -#include "simple_list.h" #include "texformat.h" @@ -228,6 +225,8 @@ static void radeonSetTexImages( radeonContextPtr rmesa, t->pp_txformat |= ((log2Width << RADEON_TXFORMAT_WIDTH_SHIFT) | (log2Height << RADEON_TXFORMAT_HEIGHT_SHIFT)); + t->dirty_state = TEX_ALL; + radeonUploadTexImages( rmesa, t ); } @@ -723,7 +722,7 @@ do { \ * Texture unit state management */ -static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) +static GLboolean radeonUpdateTextureEnv( GLcontext *ctx, int unit ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; @@ -733,9 +732,9 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) GLuint color_arg[3], alpha_arg[3]; GLuint i, numColorArgs = 0, numAlphaArgs = 0; - if ( RADEON_DEBUG & DEBUG_VERBOSE_API ) { - fprintf( stderr, "%s( %p, %d ) format=%s\n",__FUNCTION__, - (void*)ctx, unit, _mesa_lookup_enum_by_nr( format ) ); + if ( RADEON_DEBUG & DEBUG_TEXTURE ) { + fprintf( stderr, "%s( %p, %d ) format=%s\n", __FUNCTION__, + ctx, unit, _mesa_lookup_enum_by_nr( format ) ); } /* Set the texture environment state. Isn't this nice and clean? @@ -764,7 +763,7 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) break; case GL_COLOR_INDEX: default: - return; + return GL_FALSE; } break; @@ -787,7 +786,7 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) break; case GL_COLOR_INDEX: default: - return; + return GL_FALSE; } break; @@ -807,7 +806,7 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) break; case GL_COLOR_INDEX: default: - return; + return GL_FALSE; } break; @@ -830,7 +829,7 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) break; case GL_COLOR_INDEX: default: - return; + return GL_FALSE; } break; @@ -853,7 +852,7 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) break; case GL_COLOR_INDEX: default: - return; + return GL_FALSE; } break; @@ -872,16 +871,19 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) break; case GL_MODULATE: case GL_ADD: - case GL_ADD_SIGNED_EXT: + case GL_ADD_SIGNED: + case GL_SUBTRACT: + case GL_DOT3_RGB: + case GL_DOT3_RGBA: case GL_DOT3_RGB_EXT: case GL_DOT3_RGBA_EXT: numColorArgs = 2; break; - case GL_INTERPOLATE_EXT: + case GL_INTERPOLATE: numColorArgs = 3; break; default: - return; + return GL_FALSE; } switch ( texUnit->CombineModeA ) { @@ -890,14 +892,15 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) break; case GL_MODULATE: case GL_ADD: - case GL_ADD_SIGNED_EXT: + case GL_ADD_SIGNED: + case GL_SUBTRACT: numAlphaArgs = 2; break; - case GL_INTERPOLATE_EXT: + case GL_INTERPOLATE: numAlphaArgs = 3; break; default: - return; + return GL_FALSE; } /* Step 1: @@ -911,17 +914,17 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) case GL_TEXTURE: color_arg[i] = radeon_texture_color[op][unit]; break; - case GL_CONSTANT_EXT: + case GL_CONSTANT: color_arg[i] = radeon_tfactor_color[op]; break; - case GL_PRIMARY_COLOR_EXT: + case GL_PRIMARY_COLOR: color_arg[i] = radeon_primary_color[op]; break; - case GL_PREVIOUS_EXT: + case GL_PREVIOUS: color_arg[i] = radeon_previous_color[op]; break; default: - return; + return GL_FALSE; } } @@ -933,17 +936,17 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) case GL_TEXTURE: alpha_arg[i] = radeon_texture_alpha[op][unit]; break; - case GL_CONSTANT_EXT: + case GL_CONSTANT: alpha_arg[i] = radeon_tfactor_alpha[op]; break; - case GL_PRIMARY_COLOR_EXT: + case GL_PRIMARY_COLOR: alpha_arg[i] = radeon_primary_alpha[op]; break; - case GL_PREVIOUS_EXT: + case GL_PREVIOUS: alpha_arg[i] = radeon_previous_alpha[op]; break; default: - return; + return GL_FALSE; } } @@ -973,7 +976,7 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) RADEON_COLOR_ARG( 0, A ); RADEON_COLOR_ARG( 1, C ); break; - case GL_ADD_SIGNED_EXT: + case GL_ADD_SIGNED: color_combine = (RADEON_COLOR_ARG_B_ZERO | RADEON_COMP_ARG_B | RADEON_BLEND_CTL_ADDSIGNED | @@ -981,13 +984,31 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) RADEON_COLOR_ARG( 0, A ); RADEON_COLOR_ARG( 1, C ); break; - case GL_INTERPOLATE_EXT: + case GL_SUBTRACT: + color_combine = (RADEON_COLOR_ARG_B_ZERO | + RADEON_COMP_ARG_B | + RADEON_BLEND_CTL_SUBTRACT | + RADEON_CLAMP_TX); + RADEON_COLOR_ARG( 0, A ); + RADEON_COLOR_ARG( 1, C ); + break; + case GL_INTERPOLATE: color_combine = (RADEON_BLEND_CTL_BLEND | RADEON_CLAMP_TX); RADEON_COLOR_ARG( 0, B ); RADEON_COLOR_ARG( 1, A ); RADEON_COLOR_ARG( 2, C ); break; + + case GL_DOT3_RGB: + case GL_DOT3_RGBA: + if ( texUnit->CombineScaleShiftRGB + != (RADEON_SCALE_1X >> RADEON_SCALE_SHIFT) ) + { + return GL_FALSE; + } + /* FALLTHROUGH */ + case GL_DOT3_RGB_EXT: case GL_DOT3_RGBA_EXT: color_combine = (RADEON_COLOR_ARG_C_ZERO | @@ -997,7 +1018,7 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) RADEON_COLOR_ARG( 1, B ); break; default: - return; + return GL_FALSE; } switch ( texUnit->CombineModeA ) { @@ -1023,7 +1044,7 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) RADEON_ALPHA_ARG( 0, A ); RADEON_ALPHA_ARG( 1, C ); break; - case GL_ADD_SIGNED_EXT: + case GL_ADD_SIGNED: alpha_combine = (RADEON_ALPHA_ARG_B_ZERO | RADEON_COMP_ARG_B | RADEON_BLEND_CTL_ADDSIGNED | @@ -1031,7 +1052,15 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) RADEON_ALPHA_ARG( 0, A ); RADEON_ALPHA_ARG( 1, C ); break; - case GL_INTERPOLATE_EXT: + case GL_SUBTRACT: + alpha_combine = (RADEON_COLOR_ARG_B_ZERO | + RADEON_COMP_ARG_B | + RADEON_BLEND_CTL_SUBTRACT | + RADEON_CLAMP_TX); + RADEON_ALPHA_ARG( 0, A ); + RADEON_ALPHA_ARG( 1, C ); + break; + case GL_INTERPOLATE: alpha_combine = (RADEON_BLEND_CTL_BLEND | RADEON_CLAMP_TX); RADEON_ALPHA_ARG( 0, B ); @@ -1039,23 +1068,26 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) RADEON_ALPHA_ARG( 2, C ); break; default: - return; + return GL_FALSE; } - if ( texUnit->CombineModeRGB == GL_DOT3_RGB_EXT ) { + if ( (texUnit->CombineModeRGB == GL_DOT3_RGB_EXT) + || (texUnit->CombineModeRGB == GL_DOT3_RGB_ARB) ) { alpha_combine |= RADEON_DOT_ALPHA_DONT_REPLICATE; } /* Step 3: - * Apply the scale factor. The EXT extension has a somewhat - * unnecessary restriction that the scale must be 4x. The ARB - * extension will likely drop this and we can just apply the - * scale factors regardless. + * Apply the scale factor. The EXT version of the DOT3 extension does + * not support the scale factor, but the ARB version (and the version in + * OpenGL 1.3) does. The catch is that the Radeon only supports a 1X + * multiplier in hardware w/the ARB version. */ if ( texUnit->CombineModeRGB != GL_DOT3_RGB_EXT && - texUnit->CombineModeRGB != GL_DOT3_RGBA_EXT ) { - color_combine |= (texUnit->CombineScaleShiftRGB << 21); - alpha_combine |= (texUnit->CombineScaleShiftA << 21); + texUnit->CombineModeRGB != GL_DOT3_RGBA_EXT && + texUnit->CombineModeRGB != GL_DOT3_RGB && + texUnit->CombineModeRGB != GL_DOT3_RGBA ) { + color_combine |= (texUnit->CombineScaleShiftRGB << RADEON_SCALE_SHIFT); + alpha_combine |= (texUnit->CombineScaleShiftA << RADEON_SCALE_SHIFT); } else { @@ -1068,57 +1100,227 @@ static void radeonUpdateTextureEnv( GLcontext *ctx, int unit ) break; default: - return; + return GL_FALSE; + } + + if ( rmesa->hw.tex[unit].cmd[TEX_PP_TXCBLEND] != color_combine || + rmesa->hw.tex[unit].cmd[TEX_PP_TXABLEND] != alpha_combine ) { + RADEON_STATECHANGE( rmesa, tex[unit] ); + rmesa->hw.tex[unit].cmd[TEX_PP_TXCBLEND] = color_combine; + rmesa->hw.tex[unit].cmd[TEX_PP_TXABLEND] = alpha_combine; + } + + return GL_TRUE; +} + +#define TEXOBJ_TXFILTER_MASK (RADEON_MAX_MIP_LEVEL_MASK | \ + RADEON_MIN_FILTER_MASK | \ + RADEON_MAG_FILTER_MASK | \ + RADEON_MAX_ANISO_MASK | \ + RADEON_CLAMP_S_MASK | \ + RADEON_CLAMP_T_MASK) + +#define TEXOBJ_TXFORMAT_MASK (RADEON_TXFORMAT_WIDTH_MASK | \ + RADEON_TXFORMAT_HEIGHT_MASK | \ + RADEON_TXFORMAT_FORMAT_MASK | \ + RADEON_TXFORMAT_ALPHA_IN_MAP) + + +static void import_tex_obj_state( radeonContextPtr rmesa, + int unit, + radeonTexObjPtr texobj ) +{ + GLuint *cmd = RADEON_DB_STATE( tex[unit] ); + + cmd[TEX_PP_TXFILTER] &= ~TEXOBJ_TXFILTER_MASK; + cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK; + cmd[TEX_PP_TXFILTER] |= texobj->pp_txfilter & TEXOBJ_TXFILTER_MASK; + cmd[TEX_PP_TXFORMAT] |= texobj->pp_txformat & TEXOBJ_TXFORMAT_MASK; + cmd[TEX_PP_TXOFFSET] = texobj->pp_txoffset; + cmd[TEX_PP_BORDER_COLOR] = texobj->pp_border_color; + texobj->dirty_state &= ~(1<<unit); + + RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.tex[unit] ); +} + + + + +static void set_texgen_matrix( radeonContextPtr rmesa, + GLuint unit, + GLfloat *s_plane, + GLfloat *t_plane ) +{ + static const GLfloat scale_identity[4] = { 1,1,1,1 }; + + if (!TEST_EQ_4V( s_plane, scale_identity) || + !(TEST_EQ_4V( t_plane, scale_identity))) { + rmesa->TexGenEnabled |= RADEON_TEXMAT_0_ENABLE<<unit; + rmesa->TexGenMatrix[unit].m[0] = s_plane[0]; + rmesa->TexGenMatrix[unit].m[4] = s_plane[1]; + rmesa->TexGenMatrix[unit].m[8] = s_plane[2]; + rmesa->TexGenMatrix[unit].m[12] = s_plane[3]; + + rmesa->TexGenMatrix[unit].m[1] = t_plane[0]; + rmesa->TexGenMatrix[unit].m[5] = t_plane[1]; + rmesa->TexGenMatrix[unit].m[9] = t_plane[2]; + rmesa->TexGenMatrix[unit].m[13] = t_plane[3]; + rmesa->NewGLState |= _NEW_TEXTURE_MATRIX; + } +} + +/* Ignoring the Q texcoord for now. + * + * Returns GL_FALSE if fallback required. + */ +static GLboolean radeon_validate_texgen( GLcontext *ctx, GLuint unit ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4; + GLuint tmp = rmesa->TexGenEnabled; + + rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_TEXMAT_0_ENABLE<<unit); + rmesa->TexGenEnabled &= ~(RADEON_TEXMAT_0_ENABLE<<unit); + rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_INPUT_MASK<<inputshift); + rmesa->TexGenNeedNormals[unit] = 0; + + if (0) + fprintf(stderr, "%s unit %d cleared texgenEnabled %x\n", __FUNCTION__, + unit, rmesa->TexGenEnabled); + + if ((texUnit->TexGenEnabled & (S_BIT|T_BIT)) == 0) { + /* Disabled, no fallback: + */ + rmesa->TexGenEnabled |= + (RADEON_TEXGEN_INPUT_TEXCOORD_0+unit) << inputshift; + return GL_TRUE; + } + else if (texUnit->TexGenEnabled & Q_BIT) { + /* Very easy to do this, in fact would remove a fallback case + * elsewhere, but I haven't done it yet... Fallback: + */ + fprintf(stderr, "fallback Q_BIT\n"); + return GL_FALSE; + } + else if ((texUnit->TexGenEnabled & (S_BIT|T_BIT)) != (S_BIT|T_BIT) || + texUnit->GenModeS != texUnit->GenModeT) { + /* Mixed modes, fallback: + */ +/* fprintf(stderr, "fallback mixed texgen\n"); */ + return GL_FALSE; + } + else + rmesa->TexGenEnabled |= RADEON_TEXGEN_TEXMAT_0_ENABLE << unit; + + switch (texUnit->GenModeS) { + case GL_OBJECT_LINEAR: + rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_OBJ << inputshift; + set_texgen_matrix( rmesa, unit, + texUnit->ObjectPlaneS, + texUnit->ObjectPlaneT); + break; + + case GL_EYE_LINEAR: + rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE << inputshift; + set_texgen_matrix( rmesa, unit, + texUnit->EyePlaneS, + texUnit->EyePlaneT); + break; + + case GL_REFLECTION_MAP_NV: + rmesa->TexGenNeedNormals[unit] = GL_TRUE; + rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE_REFLECT<<inputshift; + break; + + case GL_NORMAL_MAP_NV: + rmesa->TexGenNeedNormals[unit] = GL_TRUE; + rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE_NORMAL<<inputshift; + break; + + case GL_SPHERE_MAP: + default: + /* Unsupported mode, fallback: + */ + /* fprintf(stderr, "fallback unsupported texgen\n"); */ + return GL_FALSE; } - if ( rmesa->state.hw.texture[unit].pp_txcblend != color_combine || - rmesa->state.hw.texture[unit].pp_txablend != alpha_combine ) { - RADEON_STATECHANGE( rmesa, (RADEON_UPLOAD_TEX0 << unit) ); - rmesa->state.hw.texture[unit].pp_txcblend = color_combine; - rmesa->state.hw.texture[unit].pp_txablend = alpha_combine; + if (tmp != rmesa->TexGenEnabled) { + rmesa->NewGLState |= _NEW_TEXTURE_MATRIX; } + +/* fprintf(stderr, "%s unit %d texgenEnabled %x\n", __FUNCTION__, */ +/* unit, rmesa->TexGenEnabled); */ + return GL_TRUE; } -static void radeonUpdateTextureUnit( GLcontext *ctx, int unit ) + + + +static GLboolean radeonUpdateTextureUnit( GLcontext *ctx, int unit ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; +/* fprintf(stderr, "%s\n", __FUNCTION__); */ + if ( texUnit->_ReallyEnabled & (TEXTURE0_1D|TEXTURE0_2D) ) { struct gl_texture_object *tObj = texUnit->_Current; radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData; - GLuint flag = RADEON_UPLOAD_TEX0 << unit; GLenum format; /* Fallback if there's a texture border */ - if ( tObj->Image[tObj->BaseLevel]->Border > 0 ) { - FALLBACK( rmesa, RADEON_FALLBACK_TEXTURE, GL_TRUE ); - return; - } + if ( tObj->Image[tObj->BaseLevel]->Border > 0 ) + return GL_FALSE; /* Upload teximages (not pipelined) */ if ( t->dirty_images ) { RADEON_FIREVERTICES( rmesa ); radeonSetTexImages( rmesa, tObj ); - if ( !t->memBlock ) { - FALLBACK( rmesa, RADEON_FALLBACK_TEXTURE, GL_TRUE ); - return; - } + /* Fallback if we can't upload: + */ + if ( !t->memBlock ) + return GL_FALSE; } /* Update state if this is a different texture object to last * time. */ if ( rmesa->state.texture.unit[unit].texobj != t ) { - if ( rmesa->state.texture.unit[unit].texobj == NULL ) { - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); - rmesa->state.hw.context.pp_cntl |= (RADEON_TEX_0_ENABLE | - RADEON_TEX_BLEND_0_ENABLE)<<unit; - } - RADEON_STATECHANGE( rmesa, flag ); rmesa->state.texture.unit[unit].texobj = t; - radeonUpdateTexLRU( rmesa, t ); /* done too often */ + t->dirty_state |= 1<<unit; + radeonUpdateTexLRU( rmesa, t ); /* XXX: should be locked! */ + } + + + /* Newly enabled? + */ + if ( !(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (RADEON_TEX_0_ENABLE<<unit))) { + RADEON_STATECHANGE( rmesa, ctx ); + rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= + (RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE) << unit; + + RADEON_STATECHANGE( rmesa, tcl ); + + if (unit == 0) + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_ST0; + else + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_ST1; + + rmesa->recheck_texgen[unit] = GL_TRUE; + } + + if (t->dirty_state & (1<<unit)) { + import_tex_obj_state( rmesa, unit, t ); + } + + if (rmesa->recheck_texgen[unit]) { + GLboolean fallback = !radeon_validate_texgen( ctx, unit ); + TCL_FALLBACK( ctx, (RADEON_TCL_FALLBACK_TEXGEN_0<<unit), fallback); + rmesa->recheck_texgen[unit] = 0; + rmesa->NewGLState |= _NEW_TEXTURE_MATRIX; } format = tObj->Image[tObj->BaseLevel]->Format; @@ -1126,27 +1328,76 @@ static void radeonUpdateTextureUnit( GLcontext *ctx, int unit ) rmesa->state.texture.unit[unit].envMode != texUnit->EnvMode ) { rmesa->state.texture.unit[unit].format = format; rmesa->state.texture.unit[unit].envMode = texUnit->EnvMode; - radeonUpdateTextureEnv( ctx, unit ); + if ( ! radeonUpdateTextureEnv( ctx, unit ) ) { + return GL_FALSE; + } } } else if ( texUnit->_ReallyEnabled ) { - FALLBACK( rmesa, RADEON_FALLBACK_TEXTURE, GL_TRUE ); - return; + /* 3d textures, etc: + */ + return GL_FALSE; } - else { + else if (rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (RADEON_TEX_0_ENABLE<<unit)) { /* Texture unit disabled */ rmesa->state.texture.unit[unit].texobj = 0; - rmesa->state.hw.dirty &= ~(RADEON_UPLOAD_TEX0 << unit); - RADEON_STATECHANGE( rmesa, RADEON_UPLOAD_CONTEXT ); - rmesa->state.hw.context.pp_cntl &= ~((RADEON_TEX_0_ENABLE | - RADEON_TEX_BLEND_0_ENABLE) << unit); + RADEON_STATECHANGE( rmesa, ctx ); + rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= + ~((RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE) << unit); + + RADEON_STATECHANGE( rmesa, tcl ); + switch (unit) { + case 0: + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~(RADEON_TCL_VTX_ST0 | + RADEON_TCL_VTX_Q0); + break; + case 1: + rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~(RADEON_TCL_VTX_ST1 | + RADEON_TCL_VTX_Q1); + break; + default: + break; + } + + + if (rmesa->TclFallback & (RADEON_TCL_FALLBACK_TEXGEN_0<<unit)) { + TCL_FALLBACK( ctx, (RADEON_TCL_FALLBACK_TEXGEN_0<<unit), GL_FALSE); + rmesa->recheck_texgen[unit] = GL_TRUE; + } + + + + { + GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4; + GLuint tmp = rmesa->TexGenEnabled; + + rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_TEXMAT_0_ENABLE<<unit); + rmesa->TexGenEnabled &= ~(RADEON_TEXMAT_0_ENABLE<<unit); + rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_INPUT_MASK<<inputshift); + rmesa->TexGenNeedNormals[unit] = 0; + rmesa->TexGenEnabled |= + (RADEON_TEXGEN_INPUT_TEXCOORD_0+unit) << inputshift; + + if (tmp != rmesa->TexGenEnabled) { + rmesa->recheck_texgen[unit] = GL_TRUE; + rmesa->NewGLState |= _NEW_TEXTURE_MATRIX; + } + } } + + return GL_TRUE; } void radeonUpdateTextureState( GLcontext *ctx ) { radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - FALLBACK( rmesa, RADEON_FALLBACK_TEXTURE, GL_FALSE ); - radeonUpdateTextureUnit( ctx, 0 ); - radeonUpdateTextureUnit( ctx, 1 ); + GLboolean ok; + + ok = (radeonUpdateTextureUnit( ctx, 0 ) && + radeonUpdateTextureUnit( ctx, 1 )); + + FALLBACK( rmesa, RADEON_FALLBACK_TEXTURE, !ok ); + + if (rmesa->TclFallback) + radeonChooseVertexState( ctx ); } diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.c index 6b06a33c2..3da333549 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.c +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.c @@ -1,607 +1,979 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.c,v 1.2 2002/09/10 00:39:39 dawes Exp $ */ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.c,v 1.5 2002/12/16 16:18:59 dawes Exp $ */ +/************************************************************************** + +Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and + Tungsten Graphics Inc., Cedar Park, Texas. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + /* - * Copyright 2000, 2001 VA Linux Systems Inc., Fremont, California. - * - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * * Authors: - * Gareth Hughes <gareth@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> + * */ - - #include "glheader.h" +#include "radeon_context.h" +#include "radeon_state.h" +#include "radeon_ioctl.h" +#include "radeon_tex.h" +#include "radeon_tcl.h" +#include "radeon_vtxfmt.h" + #include "api_noop.h" -#include "colormac.h" +#include "api_arrayelt.h" #include "context.h" -#include "light.h" -#include "macros.h" #include "mem.h" #include "mmath.h" #include "mtypes.h" -#include "simple_list.h" +#include "enums.h" +#include "glapi.h" +#include "colormac.h" +#include "light.h" +#include "state.h" #include "vtxfmt.h" -#include "math/m_xform.h" #include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_array_api.h" -#include "radeon_context.h" -#include "radeon_ioctl.h" -#include "radeon_vb.h" -#include "radeon_vtxfmt.h" - +struct radeon_vb vb; -#define VERTEX radeonVertex -#define TNL_VERTEX radeonTnlVertex +static void radeonFlushVertices( GLcontext *, GLuint ); +static void count_func( const char *name, struct dynfn *l ) +{ + int i = 0; + struct dynfn *f; + foreach (f, l) i++; + if (i) fprintf(stderr, "%s: %d\n", name, i ); +} -#define LINTERP( T, A, B ) ((A) + (T) * ((B) - (A))) - -#define INTERP_RGBA( t, out, a, b ) \ -do { \ - GLint i; \ - for ( i = 0 ; i < 4 ; i++ ) { \ - GLfloat fa = UBYTE_TO_FLOAT( a[i] ); \ - GLfloat fb = UBYTE_TO_FLOAT( b[i] ); \ - GLfloat fo = LINTERP( t, fa, fb ); \ - UNCLAMPED_FLOAT_TO_UBYTE( out[i], fo ); \ - } \ -} while (0) - +static void count_funcs( radeonContextPtr rmesa ) +{ + count_func( "Vertex2f", &rmesa->vb.dfn_cache.Vertex2f ); + count_func( "Vertex2fv", &rmesa->vb.dfn_cache.Vertex2fv ); + count_func( "Vertex3f", &rmesa->vb.dfn_cache.Vertex3f ); + count_func( "Vertex3fv", &rmesa->vb.dfn_cache.Vertex3fv ); + count_func( "Color4ub", &rmesa->vb.dfn_cache.Color4ub ); + count_func( "Color4ubv", &rmesa->vb.dfn_cache.Color4ubv ); + count_func( "Color3ub", &rmesa->vb.dfn_cache.Color3ub ); + count_func( "Color3ubv", &rmesa->vb.dfn_cache.Color3ubv ); + count_func( "Color4f", &rmesa->vb.dfn_cache.Color4f ); + count_func( "Color4fv", &rmesa->vb.dfn_cache.Color4fv ); + count_func( "Color3f", &rmesa->vb.dfn_cache.Color3f ); + count_func( "Color3fv", &rmesa->vb.dfn_cache.Color3fv ); + count_func( "SecondaryColor3f", &rmesa->vb.dfn_cache.SecondaryColor3fEXT ); + count_func( "SecondaryColor3fv", &rmesa->vb.dfn_cache.SecondaryColor3fvEXT ); + count_func( "SecondaryColor3ub", &rmesa->vb.dfn_cache.SecondaryColor3ubEXT ); + count_func( "SecondaryColor3ubv", &rmesa->vb.dfn_cache.SecondaryColor3ubvEXT ); + count_func( "Normal3f", &rmesa->vb.dfn_cache.Normal3f ); + count_func( "Normal3fv", &rmesa->vb.dfn_cache.Normal3fv ); + count_func( "TexCoord2f", &rmesa->vb.dfn_cache.TexCoord2f ); + count_func( "TexCoord2fv", &rmesa->vb.dfn_cache.TexCoord2fv ); + count_func( "TexCoord1f", &rmesa->vb.dfn_cache.TexCoord1f ); + count_func( "TexCoord1fv", &rmesa->vb.dfn_cache.TexCoord1fv ); + count_func( "MultiTexCoord2fARB", &rmesa->vb.dfn_cache.MultiTexCoord2fARB ); + count_func( "MultiTexCoord2fvARB", &rmesa->vb.dfn_cache.MultiTexCoord2fvARB ); + count_func( "MultiTexCoord1fARB", &rmesa->vb.dfn_cache.MultiTexCoord1fARB ); + count_func( "MultiTexCoord1fvARB", &rmesa->vb.dfn_cache.MultiTexCoord1fvARB ); +} +void radeon_copy_to_current( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); -/* ================================================================ - * Color functions: Always update ctx->Current.* - */ + assert(ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT); + assert(vb.context == ctx); -/* ================================================================ - * Material functions: - */ + if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_N0) { + ctx->Current.Normal[0] = vb.normalptr[0]; + ctx->Current.Normal[1] = vb.normalptr[1]; + ctx->Current.Normal[2] = vb.normalptr[2]; + } -static __inline void radeon_recalc_base_color( GLcontext *ctx ) -{ - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - struct gl_light *light; + if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_PKCOLOR) { + ctx->Current.Color[0] = UBYTE_TO_FLOAT( vb.colorptr->red ); + ctx->Current.Color[1] = UBYTE_TO_FLOAT( vb.colorptr->green ); + ctx->Current.Color[2] = UBYTE_TO_FLOAT( vb.colorptr->blue ); + ctx->Current.Color[3] = UBYTE_TO_FLOAT( vb.colorptr->alpha ); + } + + if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_FPCOLOR) { + ctx->Current.Color[0] = vb.floatcolorptr[0]; + ctx->Current.Color[1] = vb.floatcolorptr[1]; + ctx->Current.Color[2] = vb.floatcolorptr[2]; + } - COPY_3V( rmesa->state.light.base_color, ctx->Light._BaseColor[0] ); - foreach ( light, &ctx->Light.EnabledList ) { - ACC_3V( rmesa->state.light.base_color, light->_MatAmbient[0] ); + if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_FPALPHA) + ctx->Current.Color[3] = vb.floatcolorptr[3]; + + if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_PKSPEC) { + ctx->Current.SecondaryColor[0] = UBYTE_TO_FLOAT( vb.specptr->red ); + ctx->Current.SecondaryColor[1] = UBYTE_TO_FLOAT( vb.specptr->green ); + ctx->Current.SecondaryColor[2] = UBYTE_TO_FLOAT( vb.specptr->blue ); + } + + if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_ST0) { + ctx->Current.Texcoord[0][0] = vb.texcoordptr[0][0]; + ctx->Current.Texcoord[0][1] = vb.texcoordptr[0][1]; + ctx->Current.Texcoord[0][2] = 0.0F; + ctx->Current.Texcoord[0][3] = 1.0F; } - - UNCLAMPED_FLOAT_TO_UBYTE( rmesa->state.light.base_alpha, - ctx->Light.Material[0].Diffuse[3] ); -} + if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_ST1) { + ctx->Current.Texcoord[1][0] = vb.texcoordptr[1][0]; + ctx->Current.Texcoord[1][1] = vb.texcoordptr[1][1]; + ctx->Current.Texcoord[1][2] = 0.0F; + ctx->Current.Texcoord[1][3] = 1.0F; + } -/* ================================================================ - * Normal functions: - */ + ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT; +} -struct radeon_norm_tab { - void (*normal3f_multi)( GLfloat x, GLfloat y, GLfloat z ); - void (*normal3fv_multi)( const GLfloat *v ); - void (*normal3f_single)( GLfloat x, GLfloat y, GLfloat z ); - void (*normal3fv_single)( const GLfloat *v ); +static GLboolean discreet_gl_prim[GL_POLYGON+1] = { + 1, /* 0 points */ + 1, /* 1 lines */ + 0, /* 2 line_strip */ + 0, /* 3 line_loop */ + 1, /* 4 tris */ + 0, /* 5 tri_fan */ + 0, /* 6 tri_strip */ + 1, /* 7 quads */ + 0, /* 8 quadstrip */ + 0, /* 9 poly */ }; -static struct radeon_norm_tab norm_tab[0x4]; - +static void flush_prims( radeonContextPtr rmesa ) +{ + int i,j; + struct radeon_dma_region tmp = rmesa->dma.current; + + tmp.buf->refcount++; + tmp.aos_size = vb.vertex_size; + tmp.aos_stride = vb.vertex_size; + tmp.aos_start = GET_START(&tmp); + + rmesa->dma.current.ptr = rmesa->dma.current.start += + (vb.initial_counter - vb.counter) * vb.vertex_size * 4; + + rmesa->tcl.vertex_format = rmesa->vb.vertex_format; + rmesa->tcl.aos_components[0] = &tmp; + rmesa->tcl.nr_aos_components = 1; + rmesa->dma.flush = 0; + + /* Optimize the primitive list: + */ + if (rmesa->vb.nrprims > 1) { + for (j = 0, i = 1 ; i < rmesa->vb.nrprims; i++) { + int pj = rmesa->vb.primlist[j].prim & 0xf; + int pi = rmesa->vb.primlist[i].prim & 0xf; + + if (pj == pi && discreet_gl_prim[pj] && + rmesa->vb.primlist[i].start == rmesa->vb.primlist[j].end) { + rmesa->vb.primlist[j].end = rmesa->vb.primlist[i].end; + } + else { + j++; + if (j != i) rmesa->vb.primlist[j] = rmesa->vb.primlist[i]; + } + } + rmesa->vb.nrprims = j+1; + } -#define HAVE_HW_LIGHTING 0 + for (i = 0 ; i < rmesa->vb.nrprims; i++) { + if (RADEON_DEBUG & DEBUG_PRIMS) + fprintf(stderr, "vtxfmt prim %d: %s %d..%d\n", i, + _mesa_lookup_enum_by_nr( rmesa->vb.primlist[i].prim & + PRIM_MODE_MASK ), + rmesa->vb.primlist[i].start, + rmesa->vb.primlist[i].end); + + radeonEmitPrimitive( vb.context, + rmesa->vb.primlist[i].start, + rmesa->vb.primlist[i].end, + rmesa->vb.primlist[i].prim ); + } -#define GET_CURRENT_VERTEX \ - GET_CURRENT_CONTEXT(ctx); \ - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \ - radeonTnlVertexPtr v = rmesa->imm.v0 + rmesa->vb.nrprims = 0; + radeonReleaseDmaRegion( rmesa, &tmp, __FUNCTION__ ); +} -#define CURRENT_NORMAL rmesa->state.current.normal -#define BASE_COLOR rmesa->state.light.base_color -#define BASE_ALPHA rmesa->state.light.base_alpha -#define VERT_COLOR( COMP ) v->color[COMP] +static void start_prim( radeonContextPtr rmesa, GLuint mode ) +{ + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s %d\n", __FUNCTION__, vb.initial_counter - vb.counter); + rmesa->vb.primlist[rmesa->vb.nrprims].start = vb.initial_counter - vb.counter; + rmesa->vb.primlist[rmesa->vb.nrprims].prim = mode; +} -#define IND (0) -#define TAG(x) radeon_##x -#define PRESERVE_NORMAL_DEFS -#include "tnl_dd/t_dd_imm_napi.h" +static void note_last_prim( radeonContextPtr rmesa, GLuint flags ) +{ + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s %d\n", __FUNCTION__, vb.initial_counter - vb.counter); -#define IND (NORM_RESCALE) -#define TAG(x) radeon_##x##_rescale -#define PRESERVE_NORMAL_DEFS -#include "tnl_dd/t_dd_imm_napi.h" + if (rmesa->vb.prim[0] != GL_POLYGON+1) { + rmesa->vb.primlist[rmesa->vb.nrprims].prim |= flags; + rmesa->vb.primlist[rmesa->vb.nrprims].end = vb.initial_counter - vb.counter; -#define IND (NORM_NORMALIZE) -#define TAG(x) radeon_##x##_normalize -#include "tnl_dd/t_dd_imm_napi.h" + if (++(rmesa->vb.nrprims) == RADEON_MAX_PRIMS) + flush_prims( rmesa ); + } +} -static void radeon_init_norm_funcs( void ) +static void copy_vertex( radeonContextPtr rmesa, GLuint n, GLfloat *dst ) { - radeon_init_norm(); - radeon_init_norm_rescale(); - radeon_init_norm_normalize(); -} + GLuint i; + GLfloat *src = (GLfloat *)(rmesa->dma.current.address + + rmesa->dma.current.ptr + + (rmesa->vb.primlist[rmesa->vb.nrprims].start + n) * + vb.vertex_size * 4); -static void radeon_choose_Normal3f( GLfloat x, GLfloat y, GLfloat z ) -{ - GET_CURRENT_CONTEXT(ctx); - GLuint index; + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "copy_vertex %d\n", rmesa->vb.primlist[rmesa->vb.nrprims].start + n); - if ( ctx->Light.Enabled ) { - if ( ctx->Transform.Normalize ) { - index = NORM_NORMALIZE; - } - else if ( !ctx->Transform.RescaleNormals && - ctx->_ModelViewInvScale != 1.0 ) { - index = NORM_RESCALE; - } - else { - index = 0; - } + for (i = 0 ; i < vb.vertex_size; i++) { + dst[i] = src[i]; + } +} - if ( ctx->Light.EnabledList.next == ctx->Light.EnabledList.prev ) { - ctx->Exec->Normal3f = norm_tab[index].normal3f_single; +/* NOTE: This actually reads the copied vertices back from uncached + * memory. Could also use the counter/notify mechanism to populate + * tmp on the fly as vertices are generated. + */ +static GLuint copy_dma_verts( radeonContextPtr rmesa, GLfloat (*tmp)[15] ) +{ + GLuint ovf, i; + GLuint nr = (vb.initial_counter - vb.counter) - rmesa->vb.primlist[rmesa->vb.nrprims].start; + + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s %d verts\n", __FUNCTION__, nr); + + switch( rmesa->vb.prim[0] ) + { + case GL_POINTS: + return 0; + case GL_LINES: + ovf = nr&1; + for (i = 0 ; i < ovf ; i++) + copy_vertex( rmesa, nr-ovf+i, tmp[i] ); + return i; + case GL_TRIANGLES: + ovf = nr%3; + for (i = 0 ; i < ovf ; i++) + copy_vertex( rmesa, nr-ovf+i, tmp[i] ); + return i; + case GL_QUADS: + ovf = nr&3; + for (i = 0 ; i < ovf ; i++) + copy_vertex( rmesa, nr-ovf+i, tmp[i] ); + return i; + case GL_LINE_STRIP: + if (nr == 0) + return 0; + copy_vertex( rmesa, nr-1, tmp[0] ); + return 1; + case GL_LINE_LOOP: + case GL_TRIANGLE_FAN: + case GL_POLYGON: + if (nr == 0) + return 0; + else if (nr == 1) { + copy_vertex( rmesa, 0, tmp[0] ); + return 1; } else { - ctx->Exec->Normal3f = norm_tab[index].normal3f_multi; + copy_vertex( rmesa, 0, tmp[0] ); + copy_vertex( rmesa, nr-1, tmp[1] ); + return 2; } - } else { - ctx->Exec->Normal3f = _mesa_noop_Normal3f; + case GL_TRIANGLE_STRIP: + ovf = MIN2( nr-1, 2 ); + for (i = 0 ; i < ovf ; i++) + copy_vertex( rmesa, nr-ovf+i, tmp[i] ); + return i; + case GL_QUAD_STRIP: + ovf = MIN2( nr-1, 2 ); + if (nr > 2) ovf += nr&1; + for (i = 0 ; i < ovf ; i++) + copy_vertex( rmesa, nr-ovf+i, tmp[i] ); + return i; + default: + assert(0); + return 0; } - - glNormal3f( x, y, z ); } -static void radeon_choose_Normal3fv( const GLfloat *v ) +static void VFMT_FALLBACK_OUTSIDE_BEGIN_END( const char *caller ) { - GET_CURRENT_CONTEXT(ctx); - GLuint index; + GLcontext *ctx = vb.context; + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - if ( ctx->Light.Enabled ) { - if ( ctx->Transform.Normalize ) { - index = NORM_NORMALIZE; - } - else if ( !ctx->Transform.RescaleNormals && - ctx->_ModelViewInvScale != 1.0 ) { - index = NORM_RESCALE; - } - else { - index = 0; - } + if (RADEON_DEBUG & (DEBUG_VFMT|DEBUG_FALLBACKS)) + fprintf(stderr, "%s from %s\n", __FUNCTION__, caller); - if ( ctx->Light.EnabledList.next == ctx->Light.EnabledList.prev ) { - ctx->Exec->Normal3fv = norm_tab[index].normal3fv_single; - } else { - ctx->Exec->Normal3fv = norm_tab[index].normal3fv_multi; - } - } else { - ctx->Exec->Normal3fv = _mesa_noop_Normal3fv; - } + if (ctx->Driver.NeedFlush) + radeonFlushVertices( ctx, ctx->Driver.NeedFlush ); + + if (ctx->NewState) + _mesa_update_state( ctx ); /* clear state so fell_back sticks */ + + _tnl_wakeup_exec( ctx ); - glNormal3fv( v ); + assert( rmesa->dma.flush == 0 ); + rmesa->vb.fell_back = GL_TRUE; + rmesa->vb.installed = GL_FALSE; + vb.context = 0; } +static void VFMT_FALLBACK( const char *caller ) +{ + GLcontext *ctx = vb.context; + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLfloat tmp[3][15]; + GLuint i, prim; + GLuint ind = rmesa->vb.vertex_format; + GLuint nrverts; + GLfloat alpha = 1.0; + if (RADEON_DEBUG & (DEBUG_FALLBACKS|DEBUG_VFMT)) + fprintf(stderr, "%s from %s\n", __FUNCTION__, caller); -/* ================================================================ - * Texture functions: - */ + if (rmesa->vb.prim[0] == GL_POLYGON+1) { + VFMT_FALLBACK_OUTSIDE_BEGIN_END( __FUNCTION__ ); + return; + } -#define GET_CURRENT \ - GET_CURRENT_CONTEXT(ctx); \ - radeonContextPtr rmesa = RADEON_CONTEXT(ctx) + /* Copy vertices out of dma: + */ + nrverts = copy_dma_verts( rmesa, tmp ); -#define NUM_TEXTURE_UNITS RADEON_MAX_TEXTURE_UNITS -#define DO_PROJ_TEX + /* Finish the prim at this point: + */ + note_last_prim( rmesa, 0 ); + flush_prims( rmesa ); -#define CURRENT_TEXTURE( unit ) rmesa->state.current.texture[unit] + /* Update ctx->Driver.CurrentExecPrimitive and swap in swtnl. + */ + prim = rmesa->vb.prim[0]; + ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1; + _tnl_wakeup_exec( ctx ); -#define TAG(x) radeon_##x -#include "tnl_dd/t_dd_imm_tapi.h" + assert(rmesa->dma.flush == 0); + rmesa->vb.fell_back = GL_TRUE; + rmesa->vb.installed = GL_FALSE; + vb.context = 0; + glBegin( prim ); + + if (rmesa->vb.installed_color_3f_sz == 4) + alpha = ctx->Current.Color[3]; + /* Replay saved vertices + */ + for (i = 0 ; i < nrverts; i++) { + GLuint offset = 3; + if (ind & RADEON_CP_VC_FRMT_N0) { + glNormal3fv( &tmp[i][offset] ); + offset += 3; + } + if (ind & RADEON_CP_VC_FRMT_PKCOLOR) { + radeon_color_t *col = (radeon_color_t *)&tmp[i][offset]; + glColor4ub( col->red, col->green, col->blue, col->alpha ); + offset++; + } + else if (ind & RADEON_CP_VC_FRMT_FPALPHA) { + glColor4fv( &tmp[i][offset] ); + offset+=4; + } + else if (ind & RADEON_CP_VC_FRMT_FPCOLOR) { + glColor3fv( &tmp[i][offset] ); + offset+=3; + } -/* ================================================================ - * Vertex functions: - */ + if (ind & RADEON_CP_VC_FRMT_PKSPEC) { + radeon_color_t *spec = (radeon_color_t *)&tmp[i][offset]; + _glapi_Dispatch->SecondaryColor3ubEXT( spec->red, spec->green, spec->blue ); + offset++; + } -#define GET_CURRENT_VERTEX \ - GET_CURRENT_CONTEXT(ctx); \ - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \ - radeonTnlVertexPtr v = rmesa->imm.v0 + if (ind & RADEON_CP_VC_FRMT_ST0) { + glTexCoord2fv( &tmp[i][offset] ); + offset += 2; + } -#define CURRENT_VERTEX v->obj -#define SAVE_VERTEX rmesa->imm.save_vertex( ctx, v ) + if (ind & RADEON_CP_VC_FRMT_ST1) { + glMultiTexCoord2fvARB( GL_TEXTURE1_ARB, &tmp[i][offset] ); + offset += 2; + } + glVertex3fv( &tmp[i][0] ); + } -#define TAG(x) radeon_##x -#include "tnl_dd/t_dd_imm_vapi.h" + /* Replay current vertex + */ + if (ind & RADEON_CP_VC_FRMT_N0) + glNormal3fv( vb.normalptr ); + + if (ind & RADEON_CP_VC_FRMT_PKCOLOR) + glColor4ub( vb.colorptr->red, vb.colorptr->green, vb.colorptr->blue, vb.colorptr->alpha ); + else if (ind & RADEON_CP_VC_FRMT_FPALPHA) + glColor4fv( vb.floatcolorptr ); + else if (ind & RADEON_CP_VC_FRMT_FPCOLOR) { + if (rmesa->vb.installed_color_3f_sz == 4 && alpha != 1.0) + glColor4f( vb.floatcolorptr[0], + vb.floatcolorptr[1], + vb.floatcolorptr[2], + alpha ); + else + glColor3fv( vb.floatcolorptr ); + } + if (ind & RADEON_CP_VC_FRMT_PKSPEC) + _glapi_Dispatch->SecondaryColor3ubEXT( vb.specptr->red, vb.specptr->green, vb.specptr->blue ); + if (ind & RADEON_CP_VC_FRMT_ST0) + glTexCoord2fv( vb.texcoordptr[0] ); + if (ind & RADEON_CP_VC_FRMT_ST1) + glMultiTexCoord2fvARB( GL_TEXTURE1_ARB, vb.texcoordptr[1] ); +} -struct radeon_vert_tab { - void (*save_vertex)( GLcontext *ctx, radeonTnlVertexPtr v ); - void (*interpolate_vertex)( GLfloat t, - radeonTnlVertex *O, - const radeonTnlVertex *I, - const radeonTnlVertex *J ); -}; -static struct radeon_vert_tab vert_tab[0xf]; -#define VTX_NORMAL 0x0 -#define VTX_RGBA 0x1 -#define VTX_SPEC 0x2 -#define VTX_TEX0 0x4 -#define VTX_TEX1 0x8 +static void wrap_buffer( void ) +{ + GLcontext *ctx = vb.context; + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLfloat tmp[3][15]; + GLuint i, nrverts; -#define LOCAL_VARS \ - radeonContextPtr rmesa = RADEON_CONTEXT(ctx) + if (RADEON_DEBUG & (DEBUG_VFMT|DEBUG_PRIMS)) + fprintf(stderr, "%s %d\n", __FUNCTION__, vb.initial_counter - vb.counter); -#define CURRENT_COLOR rmesa->state.current.color -#define CURRENT_SPECULAR rmesa->state.current.specular + /* Don't deal with parity. + */ + if ((((vb.initial_counter - vb.counter) - + rmesa->vb.primlist[rmesa->vb.nrprims].start) & 1)) { + vb.counter++; + vb.initial_counter++; + return; + } -#define CURRENT_NORMAL( COMP ) rmesa->state.current.normal[COMP] -#define CURRENT_TEXTURE( U, COMP ) rmesa->state.current.texture[U][COMP] + /* Copy vertices out of dma: + */ + if (rmesa->vb.prim[0] == GL_POLYGON+1) + nrverts = 0; + else { + nrverts = copy_dma_verts( rmesa, tmp ); + + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%d vertices to copy\n", nrverts); + + /* Finish the prim at this point: + */ + note_last_prim( rmesa, 0 ); + } -#define FLUSH_VERTEX rmesa->imm.flush_vertex( ctx, v ); + /* Fire any buffered primitives + */ + flush_prims( rmesa ); + /* Get new buffer + */ + radeonRefillCurrentDmaRegion( rmesa ); -#define IND (VTX_NORMAL) -#define TAG(x) radeon_##x##_NORMAL -#define PRESERVE_VERTEX_DEFS -#include "tnl_dd/t_dd_imm_vertex.h" + /* Reset counter, dmaptr + */ + vb.dmaptr = (int *)(rmesa->dma.current.ptr + rmesa->dma.current.address); + vb.counter = (rmesa->dma.current.end - rmesa->dma.current.ptr) / + (vb.vertex_size * 4); + vb.counter--; + vb.initial_counter = vb.counter; + vb.notify = wrap_buffer; -#define IND (VTX_NORMAL|VTX_TEX0) -#define TAG(x) radeon_##x##_NORMAL_TEX0 -#define PRESERVE_VERTEX_DEFS -#include "tnl_dd/t_dd_imm_vertex.h" + rmesa->dma.flush = flush_prims; -#define IND (VTX_NORMAL|VTX_TEX0|VTX_TEX1) -#define TAG(x) radeon_##x##_NORMAL_TEX0_TEX1 -#define PRESERVE_VERTEX_DEFS -#include "tnl_dd/t_dd_imm_vertex.h" + /* Restart wrapped primitive: + */ + if (rmesa->vb.prim[0] != GL_POLYGON+1) + start_prim( rmesa, rmesa->vb.prim[0] ); -#define IND (VTX_RGBA) -#define TAG(x) radeon_##x##_RGBA -#define PRESERVE_VERTEX_DEFS -#include "tnl_dd/t_dd_imm_vertex.h" + /* Reemit saved vertices + */ + for (i = 0 ; i < nrverts; i++) { + if (RADEON_DEBUG & DEBUG_VERTS) { + int j; + fprintf(stderr, "re-emit vertex %d to %p\n", i, vb.dmaptr); + if (RADEON_DEBUG & DEBUG_VERBOSE) + for (j = 0 ; j < vb.vertex_size; j++) + fprintf(stderr, "\t%08x/%f\n", *(int*)&tmp[i][j], tmp[i][j]); + } -#define IND (VTX_RGBA|VTX_TEX0) -#define TAG(x) radeon_##x##_RGBA_TEX0 -#define PRESERVE_VERTEX_DEFS -#include "tnl_dd/t_dd_imm_vertex.h" + memcpy( vb.dmaptr, tmp[i], vb.vertex_size * 4 ); + vb.dmaptr += vb.vertex_size; + vb.counter--; + } +} -#define IND (VTX_RGBA|VTX_TEX1) -#define TAG(x) radeon_##x##_RGBA_TEX0_TEX1 -#include "tnl_dd/t_dd_imm_vertex.h" -static void radeon_init_vert_funcs( void ) +static GLboolean check_vtx_fmt( GLcontext *ctx ) { - radeon_init_vert_NORMAL(); - radeon_init_vert_NORMAL_TEX0(); - radeon_init_vert_NORMAL_TEX0_TEX1(); - radeon_init_vert_RGBA(); - radeon_init_vert_RGBA_TEX0(); - radeon_init_vert_RGBA_TEX0_TEX1(); -} + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLuint ind = RADEON_CP_VC_FRMT_Z; + if (rmesa->TclFallback || rmesa->vb.fell_back || ctx->CompileFlag) + return GL_FALSE; + if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) + ctx->Driver.FlushVertices( ctx, FLUSH_UPDATE_CURRENT ); + + /* Make all this event-driven: + */ + if (ctx->Light.Enabled) { + ind |= RADEON_CP_VC_FRMT_N0; + + /* TODO: make this data driven: If we receive only ubytes, send + * color as ubytes. Also check if converting (with free + * checking for overflow) is cheaper than sending floats + * directly. + */ + if (ctx->Light.ColorMaterialEnabled) { + ind |= RADEON_CP_VC_FRMT_FPCOLOR; + if (ctx->Color.AlphaEnabled) { + ind |= RADEON_CP_VC_FRMT_FPALPHA; + } + } + } + else { + /* TODO: make this data driven? + */ + ind |= RADEON_CP_VC_FRMT_PKCOLOR; + + if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) { + ind |= RADEON_CP_VC_FRMT_PKSPEC; + } + } + if (ctx->Texture.Unit[0]._ReallyEnabled) { + if (ctx->Texture.Unit[0].TexGenEnabled) { + if (rmesa->TexGenNeedNormals[0]) { + ind |= RADEON_CP_VC_FRMT_N0; + } + } else { + if (ctx->Current.Texcoord[0][2] != 0.0F || + ctx->Current.Texcoord[0][3] != 1.0) { + if (RADEON_DEBUG & (DEBUG_VFMT|DEBUG_FALLBACKS)) + fprintf(stderr, "%s: rq0\n", __FUNCTION__); + return GL_FALSE; + } + ind |= RADEON_CP_VC_FRMT_ST0; + } + } + if (ctx->Texture.Unit[1]._ReallyEnabled) { + if (ctx->Texture.Unit[1].TexGenEnabled) { + if (rmesa->TexGenNeedNormals[1]) { + ind |= RADEON_CP_VC_FRMT_N0; + } + } else { + if (ctx->Current.Texcoord[1][2] != 0.0F || + ctx->Current.Texcoord[1][3] != 1.0) { + if (RADEON_DEBUG & (DEBUG_VFMT|DEBUG_FALLBACKS)) + fprintf(stderr, "%s: rq1\n", __FUNCTION__); + return GL_FALSE; + } + ind |= RADEON_CP_VC_FRMT_ST1; + } + } + if (RADEON_DEBUG & (DEBUG_VFMT|DEBUG_STATE)) + fprintf(stderr, "%s: format: 0x%x\n", __FUNCTION__, ind ); + RADEON_NEWPRIM(rmesa); + rmesa->vb.vertex_format = ind; + vb.vertex_size = 3; + rmesa->vb.prim = &ctx->Driver.CurrentExecPrimitive; -#define LOCAL_VARS \ - radeonContextPtr rmesa = RADEON_CONTEXT(ctx) + vb.normalptr = ctx->Current.Normal; + vb.colorptr = NULL; + vb.floatcolorptr = ctx->Current.Color; + vb.specptr = NULL; + vb.floatspecptr = ctx->Current.SecondaryColor; + vb.texcoordptr[0] = ctx->Current.Texcoord[0]; + vb.texcoordptr[1] = ctx->Current.Texcoord[1]; -#define FLUSH_VERTEX rmesa->imm.flush_vertex + /* Run through and initialize the vertex components in the order + * the hardware understands: + */ + if (ind & RADEON_CP_VC_FRMT_N0) { + vb.normalptr = &vb.vertex[vb.vertex_size].f; + vb.vertex_size += 3; + vb.normalptr[0] = ctx->Current.Normal[0]; + vb.normalptr[1] = ctx->Current.Normal[1]; + vb.normalptr[2] = ctx->Current.Normal[2]; + } -#define IMM_VERTEX( V ) rmesa->imm.V -#define IMM_VERTICES( n ) rmesa->imm.vertices[n] + if (ind & RADEON_CP_VC_FRMT_PKCOLOR) { + vb.colorptr = &vb.vertex[vb.vertex_size].color; + vb.vertex_size += 1; + UNCLAMPED_FLOAT_TO_CHAN( vb.colorptr->red, ctx->Current.Color[0] ); + UNCLAMPED_FLOAT_TO_CHAN( vb.colorptr->green, ctx->Current.Color[1] ); + UNCLAMPED_FLOAT_TO_CHAN( vb.colorptr->blue, ctx->Current.Color[2] ); + UNCLAMPED_FLOAT_TO_CHAN( vb.colorptr->alpha, ctx->Current.Color[3] ); + } + if (ind & RADEON_CP_VC_FRMT_FPCOLOR) { + assert(!(ind & RADEON_CP_VC_FRMT_PKCOLOR)); + vb.floatcolorptr = &vb.vertex[vb.vertex_size].f; + vb.vertex_size += 3; + vb.floatcolorptr[0] = ctx->Current.Color[0]; + vb.floatcolorptr[1] = ctx->Current.Color[1]; + vb.floatcolorptr[2] = ctx->Current.Color[2]; + + if (ind & RADEON_CP_VC_FRMT_FPALPHA) { + vb.vertex_size += 1; + vb.floatcolorptr[3] = ctx->Current.Color[3]; + } + } + + if (ind & RADEON_CP_VC_FRMT_PKSPEC) { + vb.specptr = &vb.vertex[vb.vertex_size].color; + vb.vertex_size += 1; + UNCLAMPED_FLOAT_TO_CHAN( vb.specptr->red, ctx->Current.SecondaryColor[0] ); + UNCLAMPED_FLOAT_TO_CHAN( vb.specptr->green, ctx->Current.SecondaryColor[1] ); + UNCLAMPED_FLOAT_TO_CHAN( vb.specptr->blue, ctx->Current.SecondaryColor[2] ); + } -/* TINY_VERTEX_FORMAT: - */ -#define GET_VERTEX_SPACE( n ) radeonAllocDmaLow( rmesa, n * 16, __FUNCTION__ ) - -#define EMIT_VERTEX( vb, v ) \ -do { \ - vb[0] = *(GLuint *)&(v->clip[0]); \ - vb[1] = *(GLuint *)&(v->clip[1]); \ - vb[2] = *(GLuint *)&(v->clip[2]); \ - vb[3] = *(GLuint *)&(v->color); \ - vb += 4; \ -} while (0) -#define TAG(x) radeon_##x##_tiny -#define PRESERVE_PRIM_DEFS -#include "tnl_dd/t_dd_imm_primtmp.h" + if (ind & RADEON_CP_VC_FRMT_ST0) { + vb.texcoordptr[0] = &vb.vertex[vb.vertex_size].f; + vb.vertex_size += 2; + vb.texcoordptr[0][0] = ctx->Current.Texcoord[0][0]; + vb.texcoordptr[0][1] = ctx->Current.Texcoord[0][1]; + } + + if (ind & RADEON_CP_VC_FRMT_ST1) { + vb.texcoordptr[1] = &vb.vertex[vb.vertex_size].f; + vb.vertex_size += 2; + vb.texcoordptr[1][0] = ctx->Current.Texcoord[1][0]; + vb.texcoordptr[1][1] = ctx->Current.Texcoord[1][1]; + } + + if (rmesa->vb.installed_vertex_format != rmesa->vb.vertex_format) { + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "reinstall on vertex_format change\n"); + _mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt ); + rmesa->vb.installed_vertex_format = rmesa->vb.vertex_format; + } + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s -- success\n", __FUNCTION__); + + return GL_TRUE; +} -/* NOTEX_VERTEX_FORMAT: - */ -#define GET_VERTEX_SPACE( n ) radeonAllocDmaLow( rmesa, n * 24, __FUNCTION__ ) - -#define EMIT_VERTEX( vb, v ) \ -do { \ - vb[0] = *(GLuint *)&(v->clip[0]); \ - vb[1] = *(GLuint *)&(v->clip[1]); \ - vb[2] = *(GLuint *)&(v->clip[2]); \ - vb[3] = *(GLuint *)&(v->clip[3]); \ - vb[4] = *(GLuint *)&(v->color); \ - vb[5] = *(GLuint *)&(v->specular); \ - vb += 6; \ -} while (0) -#define TAG(x) radeon_##x##_notex -#define PRESERVE_PRIM_DEFS -#include "tnl_dd/t_dd_imm_primtmp.h" +void radeonVtxfmtInvalidate( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + rmesa->vb.recheck = GL_TRUE; + rmesa->vb.fell_back = GL_FALSE; +} -/* TEX0_VERTEX_FORMAT: - */ -#define GET_VERTEX_SPACE( n ) radeonAllocDmaLow( rmesa, n * 32, __FUNCTION__ ) - -#define EMIT_VERTEX( vb, v ) \ -do { \ - vb[0] = *(GLuint *)&(v->clip[0]); \ - vb[1] = *(GLuint *)&(v->clip[1]); \ - vb[2] = *(GLuint *)&(v->clip[2]); \ - vb[3] = *(GLuint *)&(v->clip[3]); \ - vb[4] = *(GLuint *)&(v->color); \ - vb[5] = *(GLuint *)&(v->specular); \ - vb[6] = *(GLuint *)&(v->texture[0][0]); \ - vb[7] = *(GLuint *)&(v->texture[0][1]); \ - vb += 8; \ -} while (0) -#define TAG(x) radeon_##x##_tex0 -#define PRESERVE_PRIM_DEFS -#include "tnl_dd/t_dd_imm_primtmp.h" +static void radeonNewList( GLcontext *ctx, GLuint list, GLenum mode ) +{ + VFMT_FALLBACK_OUTSIDE_BEGIN_END( __FUNCTION__ ); +} -/* TEX1_VERTEX_FORMAT: - */ -#define GET_VERTEX_SPACE( n ) radeonAllocDmaLow( rmesa, n * 40, __FUNCTION__ ) - -#define EMIT_VERTEX( vb, v ) \ -do { \ - vb[0] = *(GLuint *)&(v->clip[0]); \ - vb[1] = *(GLuint *)&(v->clip[1]); \ - vb[2] = *(GLuint *)&(v->clip[2]); \ - vb[3] = *(GLuint *)&(v->clip[3]); \ - vb[4] = *(GLuint *)&(v->color); \ - vb[5] = *(GLuint *)&(v->specular); \ - vb[6] = *(GLuint *)&(v->texture[0][0]); \ - vb[7] = *(GLuint *)&(v->texture[0][1]); \ - vb[8] = *(GLuint *)&(v->texture[1][0]); \ - vb[9] = *(GLuint *)&(v->texture[1][1]); \ - vb += 10; \ -} while (0) +static void radeonVtxfmtValidate( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); -#define TAG(x) radeon_##x##_tex1 -#define PRESERVE_PRIM_DEFS -#include "tnl_dd/t_dd_imm_primtmp.h" + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s\n", __FUNCTION__); + if (ctx->Driver.NeedFlush) + ctx->Driver.FlushVertices( ctx, ctx->Driver.NeedFlush ); + rmesa->vb.recheck = GL_FALSE; + if (check_vtx_fmt( ctx )) { + if (!rmesa->vb.installed) { + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "reinstall (new install)\n"); + _mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt ); + ctx->Driver.FlushVertices = radeonFlushVertices; + ctx->Driver.NewList = radeonNewList; + rmesa->vb.installed = GL_TRUE; + vb.context = ctx; + } + else if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s: already installed", __FUNCTION__); + } + else { + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s: failed\n", __FUNCTION__); + + if (rmesa->vb.installed) { + if (rmesa->dma.flush) + rmesa->dma.flush( rmesa ); + _tnl_wakeup_exec( ctx ); + rmesa->vb.installed = GL_FALSE; + vb.context = 0; + } + } +} -/* Bzzt: Material changes are lost on fallback. +/* Materials: */ -static void radeon_Materialfv( GLenum face, GLenum pname, +static void radeon_Materialfv( GLenum face, GLenum pname, const GLfloat *params ) { - GET_CURRENT_CONTEXT(ctx); + GLcontext *ctx = vb.context; + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s\n", __FUNCTION__); + if (rmesa->vb.prim[0] != GL_POLYGON+1) { + VFMT_FALLBACK( __FUNCTION__ ); + glMaterialfv( face, pname, params ); + return; + } _mesa_noop_Materialfv( face, pname, params ); - radeon_recalc_base_color( ctx ); + radeonUpdateMaterial( vb.context ); } - - - -/* ================================================================ - * Fallback functions: +/* Begin/End */ - -static void radeon_do_fallback( GLcontext *ctx ) +static void radeon_Begin( GLenum mode ) { + GLcontext *ctx = vb.context; radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - struct radeon_current_state *current = &rmesa->state.current; + + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s\n", __FUNCTION__); - /* Tell tnl to restore its exec vtxfmt, rehook its driver callbacks - * and revive internal state that depended on those callbacks: - */ - _tnl_wakeup_exec( ctx ); + if (mode > GL_POLYGON) { + _mesa_error( ctx, GL_INVALID_ENUM, "glBegin" ); + return; + } - /* Replay enough vertices that the current primitive is continued - * correctly: - */ - if ( rmesa->imm.prim != PRIM_OUTSIDE_BEGIN_END ) { - glBegin( rmesa->imm.prim ); - /*rmesa->fire_on_fallback( ctx );*/ + if (rmesa->vb.prim[0] != GL_POLYGON+1) { + _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" ); + return; } + + if (ctx->NewState) + _mesa_update_state( ctx ); - /* Replay the current, partially complete vertex: - */ - if ( current->texture[0][3] == 1.0 ) { - glMultiTexCoord3fvARB( GL_TEXTURE0_ARB, current->texture[0] ); - } else { - glMultiTexCoord4fvARB( GL_TEXTURE0_ARB, current->texture[0] ); + if (rmesa->NewGLState) + radeonValidateState( ctx ); + + if (rmesa->vb.recheck) + radeonVtxfmtValidate( ctx ); + + if (!rmesa->vb.installed) { + glBegin( mode ); + return; } - if ( current->texture[1][3] == 1.0 ) { - glMultiTexCoord3fvARB( GL_TEXTURE1_ARB, current->texture[1] ); - } else { - glMultiTexCoord4fvARB( GL_TEXTURE1_ARB, current->texture[1] ); + + if (rmesa->dma.flush && vb.counter < 12) { + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s: flush almost-empty buffers\n", __FUNCTION__); + flush_prims( rmesa ); } - /* FIXME: Secondary color, fog coord... + /* Need to arrange to save vertices here? Or always copy from dma (yuk)? */ + if (!rmesa->dma.flush) { + if (rmesa->dma.current.ptr + 12*vb.vertex_size*4 > + rmesa->dma.current.end) { + RADEON_NEWPRIM( rmesa ); + radeonRefillCurrentDmaRegion( rmesa ); + } - if ( ctx->Light.Enabled ) { - glColor4fv( ctx->Current.Color ); /* Catch ColorMaterial */ - glNormal3fv( current->normal ); - } else { - glColor4ubv( current->color ); + vb.dmaptr = (int *)(rmesa->dma.current.address + rmesa->dma.current.ptr); + vb.counter = (rmesa->dma.current.end - rmesa->dma.current.ptr) / + (vb.vertex_size * 4); + vb.counter--; + vb.initial_counter = vb.counter; + vb.notify = wrap_buffer; + rmesa->dma.flush = flush_prims; + vb.context->Driver.NeedFlush |= FLUSH_STORED_VERTICES; } + + + rmesa->vb.prim[0] = mode; + start_prim( rmesa, mode | PRIM_BEGIN ); } -#define PRE_LOOPBACK( FUNC ) do { \ - GET_CURRENT_CONTEXT(ctx); \ - radeon_do_fallback( ctx ); \ -} while (0) -#define TAG(x) radeon_fallback_##x -#include "vtxfmt_tmp.h" +static void radeon_End( void ) +{ + GLcontext *ctx = vb.context; + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s\n", __FUNCTION__); + + if (rmesa->vb.prim[0] == GL_POLYGON+1) { + _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" ); + return; + } + + note_last_prim( rmesa, PRIM_END ); + rmesa->vb.prim[0] = GL_POLYGON+1; +} +/* Fallback on difficult entrypoints: + */ +#define PRE_LOOPBACK( FUNC ) \ +do { \ + if (RADEON_DEBUG & DEBUG_VFMT) \ + fprintf(stderr, "%s\n", __FUNCTION__); \ + VFMT_FALLBACK( __FUNCTION__ ); \ +} while (0) +#define TAG(x) radeon_fallback_##x +#include "vtxfmt_tmp.h" -static void radeon_Begin( GLenum prim ) +static GLboolean radeonNotifyBegin( GLcontext *ctx, GLenum p ) { - GET_CURRENT_CONTEXT(ctx); - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s\n", __FUNCTION__); - if ( prim > GL_POLYGON ) { - _mesa_error( ctx, GL_INVALID_ENUM, "glBegin" ); - return; - } - if ( rmesa->imm.prim != PRIM_OUTSIDE_BEGIN_END ) { - _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" ); - return; - } + assert(!rmesa->vb.installed); - ctx->Driver.NeedFlush |= (FLUSH_STORED_VERTICES | - FLUSH_UPDATE_CURRENT); + if (ctx->NewState) + _mesa_update_state( ctx ); + if (rmesa->NewGLState) + radeonValidateState( ctx ); - radeonChooseVertexState( ctx ); + if (ctx->Driver.NeedFlush) + ctx->Driver.FlushVertices( ctx, ctx->Driver.NeedFlush ); + if (rmesa->vb.recheck) + radeonVtxfmtValidate( ctx ); - rmesa->imm.prim = prim; - rmesa->imm.v0 = &rmesa->imm.vertices[0]; + if (!rmesa->vb.installed) { + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s -- failed\n", __FUNCTION__); + return GL_FALSE; + } - rmesa->imm.save_vertex = radeon_save_vertex_RGBA; - rmesa->imm.flush_vertex = rmesa->imm.flush_tab[prim]; + radeon_Begin( p ); + return GL_TRUE; } -static void radeon_End( void ) +static void radeonFlushVertices( GLcontext *ctx, GLuint flags ) { - GET_CURRENT_CONTEXT(ctx); - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); - if ( rmesa->imm.prim == PRIM_OUTSIDE_BEGIN_END ) { - _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" ); - return; - } + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s\n", __FUNCTION__); - rmesa->imm.prim = PRIM_OUTSIDE_BEGIN_END; + assert(rmesa->vb.installed); + assert(vb.context == ctx); - ctx->Driver.NeedFlush &= ~(FLUSH_STORED_VERTICES | - FLUSH_UPDATE_CURRENT); -} + if (flags & FLUSH_UPDATE_CURRENT) { + radeon_copy_to_current( ctx ); + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "reinstall on update_current\n"); + _mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt ); + ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT; + } + if (flags & FLUSH_STORED_VERTICES) { + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + assert (rmesa->dma.flush == 0 || + rmesa->dma.flush == flush_prims); + if (rmesa->dma.flush == flush_prims) + flush_prims( RADEON_CONTEXT( ctx ) ); + ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES; + } +} +/* At this point, don't expect very many versions of each function to + * be generated, so not concerned about freeing them? + */ -void radeonInitTnlModule( GLcontext *ctx ) +void radeonVtxfmtInit( GLcontext *ctx ) { - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - GLvertexformat *vfmt = &(rmesa->imm.vtxfmt); - - return; - - radeon_init_norm_funcs(); - radeon_init_vert_funcs(); + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + GLvertexformat *vfmt = &(rmesa->vb.vtxfmt); MEMSET( vfmt, 0, sizeof(GLvertexformat) ); - /* Handled fully in supported states: + /* Hook in chooser functions for codegen, etc: */ - vfmt->ArrayElement = NULL; /* FIXME: ... */ - vfmt->Color3f = radeon_choose_Color3f; - vfmt->Color3fv = radeon_choose_Color3fv; - vfmt->Color3ub = radeon_choose_Color3ub; - vfmt->Color3ubv = radeon_choose_Color3ubv; - vfmt->Color4f = radeon_choose_Color4f; - vfmt->Color4fv = radeon_choose_Color4fv; - vfmt->Color4ub = radeon_choose_Color4ub; - vfmt->Color4ubv = radeon_choose_Color4ubv; - vfmt->FogCoordfvEXT = radeon_FogCoordfvEXT; - vfmt->FogCoordfEXT = radeon_FogCoordfEXT; - vfmt->Materialfv = radeon_Materialfv; - vfmt->MultiTexCoord1fARB = radeon_MultiTexCoord1fARB; - vfmt->MultiTexCoord1fvARB = radeon_MultiTexCoord1fvARB; - vfmt->MultiTexCoord2fARB = radeon_MultiTexCoord2fARB; - vfmt->MultiTexCoord2fvARB = radeon_MultiTexCoord2fvARB; - vfmt->MultiTexCoord3fARB = radeon_MultiTexCoord3fARB; - vfmt->MultiTexCoord3fvARB = radeon_MultiTexCoord3fvARB; - vfmt->MultiTexCoord4fARB = radeon_MultiTexCoord4fARB; - vfmt->MultiTexCoord4fvARB = radeon_MultiTexCoord4fvARB; - vfmt->Normal3f = radeon_choose_Normal3f; - vfmt->Normal3fv = radeon_choose_Normal3fv; - vfmt->SecondaryColor3ubEXT = radeon_SecondaryColor3ubEXT; - vfmt->SecondaryColor3ubvEXT = radeon_SecondaryColor3ubvEXT; - vfmt->SecondaryColor3fEXT = radeon_SecondaryColor3fEXT; - vfmt->SecondaryColor3fvEXT = radeon_SecondaryColor3fvEXT; - vfmt->TexCoord1f = radeon_TexCoord1f; - vfmt->TexCoord1fv = radeon_TexCoord1fv; - vfmt->TexCoord2f = radeon_TexCoord2f; - vfmt->TexCoord2fv = radeon_TexCoord2fv; - vfmt->TexCoord3f = radeon_TexCoord3f; - vfmt->TexCoord3fv = radeon_TexCoord3fv; - vfmt->TexCoord4f = radeon_TexCoord4f; - vfmt->TexCoord4fv = radeon_TexCoord4fv; - vfmt->Vertex2f = radeon_Vertex2f; - vfmt->Vertex2fv = radeon_Vertex2fv; - vfmt->Vertex3f = radeon_Vertex3f; - vfmt->Vertex3fv = radeon_Vertex3fv; - vfmt->Vertex4f = radeon_Vertex4f; - vfmt->Vertex4fv = radeon_Vertex4fv; + radeonVtxfmtInitChoosers( vfmt ); + /* Handled fully in supported states, but no codegen: + */ + vfmt->Materialfv = radeon_Materialfv; + vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */ + vfmt->Rectf = _mesa_noop_Rectf; /* generic helper */ vfmt->Begin = radeon_Begin; vfmt->End = radeon_End; - vfmt->Rectf = _mesa_noop_Rectf; /* generic helper */ - - vfmt->DrawArrays = NULL; - vfmt->DrawElements = NULL; - vfmt->DrawRangeElements = _mesa_noop_DrawRangeElements; /* discard range */ + /* Fallback for performance reasons: (Fix with cva/elt path here and + * dmatmp2.h style primitive-merging) + * + * These should call NotifyBegin(), as should _tnl_EvalMesh, to allow + * a driver-hook. + */ + vfmt->DrawArrays = radeon_fallback_DrawArrays; + vfmt->DrawElements = radeon_fallback_DrawElements; + vfmt->DrawRangeElements = radeon_fallback_DrawRangeElements; /* Not active in supported states; just keep ctx->Current uptodate: */ + vfmt->FogCoordfvEXT = _mesa_noop_FogCoordfvEXT; + vfmt->FogCoordfEXT = _mesa_noop_FogCoordfEXT; vfmt->EdgeFlag = _mesa_noop_EdgeFlag; vfmt->EdgeFlagv = _mesa_noop_EdgeFlagv; vfmt->Indexi = _mesa_noop_Indexi; @@ -609,10 +981,6 @@ void radeonInitTnlModule( GLcontext *ctx ) /* Active but unsupported -- fallback if we receive these: - * - * All of these fallbacks can be fixed with additional code, except - * CallList, unless we build a play_immediate_noop() command which - * turns an immediate back into glBegin/glEnd commands... */ vfmt->CallList = radeon_fallback_CallList; vfmt->EvalCoord1f = radeon_fallback_EvalCoord1f; @@ -623,132 +991,137 @@ void radeonInitTnlModule( GLcontext *ctx ) vfmt->EvalMesh2 = radeon_fallback_EvalMesh2; vfmt->EvalPoint1 = radeon_fallback_EvalPoint1; vfmt->EvalPoint2 = radeon_fallback_EvalPoint2; - - - rmesa->imm.prim = PRIM_OUTSIDE_BEGIN_END; - - /* THIS IS A HACK! - */ - _mesa_install_exec_vtxfmt( ctx, vfmt ); + vfmt->TexCoord3f = radeon_fallback_TexCoord3f; + vfmt->TexCoord3fv = radeon_fallback_TexCoord3fv; + vfmt->TexCoord4f = radeon_fallback_TexCoord4f; + vfmt->TexCoord4fv = radeon_fallback_TexCoord4fv; + vfmt->MultiTexCoord3fARB = radeon_fallback_MultiTexCoord3fARB; + vfmt->MultiTexCoord3fvARB = radeon_fallback_MultiTexCoord3fvARB; + vfmt->MultiTexCoord4fARB = radeon_fallback_MultiTexCoord4fARB; + vfmt->MultiTexCoord4fvARB = radeon_fallback_MultiTexCoord4fvARB; + vfmt->Vertex4f = radeon_fallback_Vertex4f; + vfmt->Vertex4fv = radeon_fallback_Vertex4fv; + + (void)radeon_fallback_vtxfmt; + + TNL_CONTEXT(ctx)->Driver.NotifyBegin = radeonNotifyBegin; + + vb.context = ctx; + rmesa->vb.enabled = 1; + rmesa->vb.prim = &ctx->Driver.CurrentExecPrimitive; + rmesa->vb.primflags = 0; + + make_empty_list( &rmesa->vb.dfn_cache.Vertex2f ); + make_empty_list( &rmesa->vb.dfn_cache.Vertex2fv ); + make_empty_list( &rmesa->vb.dfn_cache.Vertex3f ); + make_empty_list( &rmesa->vb.dfn_cache.Vertex3fv ); + make_empty_list( &rmesa->vb.dfn_cache.Color4ub ); + make_empty_list( &rmesa->vb.dfn_cache.Color4ubv ); + make_empty_list( &rmesa->vb.dfn_cache.Color3ub ); + make_empty_list( &rmesa->vb.dfn_cache.Color3ubv ); + make_empty_list( &rmesa->vb.dfn_cache.Color4f ); + make_empty_list( &rmesa->vb.dfn_cache.Color4fv ); + make_empty_list( &rmesa->vb.dfn_cache.Color3f ); + make_empty_list( &rmesa->vb.dfn_cache.Color3fv ); + make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3fEXT ); + make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3fvEXT ); + make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3ubEXT ); + make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3ubvEXT ); + make_empty_list( &rmesa->vb.dfn_cache.Normal3f ); + make_empty_list( &rmesa->vb.dfn_cache.Normal3fv ); + make_empty_list( &rmesa->vb.dfn_cache.TexCoord2f ); + make_empty_list( &rmesa->vb.dfn_cache.TexCoord2fv ); + make_empty_list( &rmesa->vb.dfn_cache.TexCoord1f ); + make_empty_list( &rmesa->vb.dfn_cache.TexCoord1fv ); + make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord2fARB ); + make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord2fvARB ); + make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord1fARB ); + make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord1fvARB ); + + radeonInitCodegen( &rmesa->vb.codegen ); } - - - - - -#if 0 - - - -static void radeon_Begin( GLenum prim ) +static void free_funcs( struct dynfn *l ) { - GET_CURRENT_CONTEXT(ctx); - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - radeon_prim *tab = &radeon_prim_tab[(int)prim]; - - if ( prim > GL_POLYGON ) { - gl_error( ctx, GL_INVALID_ENUM, "glBegin" ); - return; - } - - if ( rmesa->prim != PRIM_OUTSIDE_BEGIN_END ) { - gl_error( ctx, GL_INVALID_OPERATION, "glBegin" ); - return; - } - - if ( tab->fire_on_vertex ) { - rmesa->fire_on_vertex = tab->fire_on_vertex; - rmesa->fire_on_end = tab->fire_on_end; - rmesa->fire_on_fallback = tab->fire_on_fallback; - rmesa->vert = &(rmesa->cache[0]); - rmesa->prim = prim; - ctx->Driver.NeedFlush |= (FLUSH_INSIDE_BEGIN_END | - FLUSH_STORED_VERTICES); - } else { - radeon_fallback_vtxfmt( ctx ); + struct dynfn *f, *tmp; + foreach_s (f, tmp, l) { + remove_from_list( f ); + ALIGN_FREE( f->code ); + FREE( f ); } } -static void radeon_End( void ) +void radeonVtxfmtUnbindContext( GLcontext *ctx ) { - GET_CURRENT_CONTEXT(ctx); - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - - if ( rmesa->prim == PRIM_OUTSIDE_BEGIN_END ) { - gl_error( ctx, GL_INVALID_OPERATION, "glEnd" ); - return; + if (RADEON_CONTEXT(ctx)->vb.installed) { + assert(vb.context == ctx); + VFMT_FALLBACK_OUTSIDE_BEGIN_END( __FUNCTION__ ); } - rmesa->fire_on_end( ctx ); - rmesa->prim = PRIM_OUTSIDE_BEGIN_END; - - ctx->Exec->Vertex3fv = radeon_noop_Vertex3fv; - ctx->Exec->Vertex3f = radeon_noop_Vertex3f; - ctx->Exec->Vertex2f = radeon_noop_Vertex2f; - - ctx->Driver.NeedFlush &= ~(FLUSH_INSIDE_BEGIN_END | - FLUSH_STORED_VERTICES); + TNL_CONTEXT(ctx)->Driver.NotifyBegin = 0; } - - -static GLboolean radeon_flush_vtxfmt( GLcontext *ctx, GLuint flags ) +void radeonVtxfmtMakeCurrent( GLcontext *ctx ) { - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - - if ( fxMesa->prim != PRIM_OUTSIDE_BEGIN_END ) - return GL_FALSE; - - /* Outside begin/end. All vertices will already be flushed, just - * update ctx->Current. - */ - if ( flags & FLUSH_UPDATE_CURRENT ) { - radeonClipVertexPtr v = &(RADEON_CONTEXT(ctx)->Current); - COPY_2FV( ctx->Current.Texcoord[0], v->texcoord[0] ); - COPY_2FV( ctx->Current.Texcoord[1], v->texcoord[1] ); - if ( rmesa->accel_light == ACCEL_LIGHT ) { - COPY_3FV( ctx->Current.Normal, v->normal ); - } else { - ctx->Current.Color[RCOMP] = UBYTE_TO_CHAN( v->v.color.red ); - ctx->Current.Color[GCOMP] = UBYTE_TO_CHAN( v->v.color.green ); - ctx->Current.Color[BCOMP] = UBYTE_TO_CHAN( v->v.color.blue ); - ctx->Current.Color[ACOMP] = UBYTE_TO_CHAN( v->v.color.alpha ); + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + +#if defined(THREADS) + static GLboolean ThreadSafe = GL_FALSE; /* In thread-safe mode? */ + if (!ThreadSafe) { + static unsigned long knownID; + static GLboolean firstCall = GL_TRUE; + if (firstCall) { + knownID = _glthread_GetID(); + firstCall = GL_FALSE; + } + else if (knownID != _glthread_GetID()) { + ThreadSafe = GL_TRUE; - if ( ctx->Light.ColorMaterialEnabled ) - _mesa_update_color_material( ctx, ctx->Current.Color ); + if (RADEON_DEBUG & (DEBUG_DRI|DEBUG_VFMT)) + fprintf(stderr, "**** Multithread situation!\n"); } } + if (ThreadSafe) + return; +#endif - /* Could clear this flag and set it from each 'choose' function, - * maybe, but there isn't much of a penalty for leaving it set: - */ - ctx->Driver.NeedFlush = FLUSH_UPDATE_CURRENT; - return GL_TRUE; + if (rmesa->vb.enabled) { + TNL_CONTEXT(ctx)->Driver.NotifyBegin = radeonNotifyBegin; + } } -void radeon_update_lighting( GLcontext *ctx ) -{ - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - if ( !ctx->Light.Enabled ) { - rmesa->accel_light = ACCEL_NO_LIGHT; - } - else if ( !ctx->Light._NeedVertices && !ctx->Light.Model.TwoSide ) { - rmesa->accel_light = ACCEL_LIGHT; - radeon_recalc_basecolor( ctx ); - } - else { - radeon->accel_light = 0; - } +void radeonVtxfmtDestroy( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + + count_funcs( rmesa ); + free_funcs( &rmesa->vb.dfn_cache.Vertex2f ); + free_funcs( &rmesa->vb.dfn_cache.Vertex2fv ); + free_funcs( &rmesa->vb.dfn_cache.Vertex3f ); + free_funcs( &rmesa->vb.dfn_cache.Vertex3fv ); + free_funcs( &rmesa->vb.dfn_cache.Color4ub ); + free_funcs( &rmesa->vb.dfn_cache.Color4ubv ); + free_funcs( &rmesa->vb.dfn_cache.Color3ub ); + free_funcs( &rmesa->vb.dfn_cache.Color3ubv ); + free_funcs( &rmesa->vb.dfn_cache.Color4f ); + free_funcs( &rmesa->vb.dfn_cache.Color4fv ); + free_funcs( &rmesa->vb.dfn_cache.Color3f ); + free_funcs( &rmesa->vb.dfn_cache.Color3fv ); + free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3ubEXT ); + free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3ubvEXT ); + free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3fEXT ); + free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3fvEXT ); + free_funcs( &rmesa->vb.dfn_cache.Normal3f ); + free_funcs( &rmesa->vb.dfn_cache.Normal3fv ); + free_funcs( &rmesa->vb.dfn_cache.TexCoord2f ); + free_funcs( &rmesa->vb.dfn_cache.TexCoord2fv ); + free_funcs( &rmesa->vb.dfn_cache.TexCoord1f ); + free_funcs( &rmesa->vb.dfn_cache.TexCoord1fv ); + free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord2fARB ); + free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord2fvARB ); + free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord1fARB ); + free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord1fvARB ); } - -/* How to fallback: - * - install default vertex format - * - call glBegin - * - revive stalled vertices (may be reordered). - * - re-issue call that caused fallback. - */ -#endif diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.h b/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.h index b388d7364..9b82756be 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.h +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.h @@ -1,30 +1,36 @@ -/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.h,v 1.1 2002/02/22 21:45:01 dawes Exp $ */ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.h,v 1.3 2002/12/21 17:02:16 dawes Exp $ */ +/************************************************************************** + +Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and + Tungsten Graphics Inc., Cedar Park, Texas. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + /* - * Copyright 2000, 2001 VA Linux Systems Inc., Fremont, California. - * - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * * Authors: - * Gareth Hughes <gareth@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> + * */ #ifndef __RADEON_VTXFMT_H__ @@ -34,13 +40,89 @@ #include "radeon_context.h" -extern void radeonInitTnlModule( GLcontext *ctx ); -extern radeon_flush_func radeon_flush_tab_tiny[GL_POLYGON+1]; -extern radeon_flush_func radeon_flush_tab_notex[GL_POLYGON+1]; -extern radeon_flush_func radeon_flush_tab_tex0[GL_POLYGON+1]; -extern radeon_flush_func radeon_flush_tab_tex1[GL_POLYGON+1]; +extern struct radeon_vb vb; + + +extern void radeonVtxfmtUpdate( GLcontext *ctx ); +extern void radeonVtxfmtInit( GLcontext *ctx ); +extern void radeonVtxfmtInvalidate( GLcontext *ctx ); +extern void radeonVtxfmtDestroy( GLcontext *ctx ); +extern void radeonVtxfmtInitChoosers( GLvertexformat *vfmt ); + +extern void radeonVtxfmtMakeCurrent( GLcontext *ctx ); +extern void radeonVtxfmtUnbindContext( GLcontext *ctx ); + +extern void radeon_copy_to_current( GLcontext *ctx ); + +#define DFN( FUNC, CACHE) \ +do { \ + char *start = (char *)&FUNC; \ + char *end = (char *)&FUNC##_end; \ + insert_at_head( &CACHE, dfn ); \ + dfn->key = key; \ + dfn->code = ALIGN_MALLOC( end - start, 16 ); \ + memcpy (dfn->code, start, end - start); \ +} \ +while ( 0 ) + +#define FIXUP( CODE, OFFSET, CHECKVAL, NEWVAL ) \ +do { \ + int *icode = (int *)(CODE+OFFSET); \ + assert (*icode == CHECKVAL); \ + *icode = (int)NEWVAL; \ +} while (0) + + +/* Useful for figuring out the offsets: + */ +#define FIXUP2( CODE, OFFSET, CHECKVAL, NEWVAL ) \ +do { \ + while (*(int *)(CODE+OFFSET) != CHECKVAL) OFFSET++; \ + /* fprintf(stderr, "%s/%d CVAL %x OFFSET %d VAL %x\n", __FUNCTION__, */ \ +/* __LINE__, CHECKVAL, OFFSET, (int)(NEWVAL)); */ \ + *(int *)(CODE+OFFSET) = (int)(NEWVAL); \ + OFFSET += 4; \ +} while (0) + +/* + */ +void radeonInitCodegen( struct dfn_generators *gen ); +void radeonInitX86Codegen( struct dfn_generators *gen ); +void radeonInitSSECodegen( struct dfn_generators *gen ); + + + +/* Defined in radeon_vtxfmt_x86.c + */ +struct dynfn *radeon_makeX86Vertex2f( GLcontext *, int ); +struct dynfn *radeon_makeX86Vertex2fv( GLcontext *, int ); +struct dynfn *radeon_makeX86Vertex3f( GLcontext *, int ); +struct dynfn *radeon_makeX86Vertex3fv( GLcontext *, int ); +struct dynfn *radeon_makeX86Color4ub( GLcontext *, int ); +struct dynfn *radeon_makeX86Color4ubv( GLcontext *, int ); +struct dynfn *radeon_makeX86Color3ub( GLcontext *, int ); +struct dynfn *radeon_makeX86Color3ubv( GLcontext *, int ); +struct dynfn *radeon_makeX86Color4f( GLcontext *, int ); +struct dynfn *radeon_makeX86Color4fv( GLcontext *, int ); +struct dynfn *radeon_makeX86Color3f( GLcontext *, int ); +struct dynfn *radeon_makeX86Color3fv( GLcontext *, int ); +struct dynfn *radeon_makeX86SecondaryColor3ubEXT( GLcontext *, int ); +struct dynfn *radeon_makeX86SecondaryColor3ubvEXT( GLcontext *, int ); +struct dynfn *radeon_makeX86SecondaryColor3fEXT( GLcontext *, int ); +struct dynfn *radeon_makeX86SecondaryColor3fvEXT( GLcontext *, int ); +struct dynfn *radeon_makeX86Normal3f( GLcontext *, int ); +struct dynfn *radeon_makeX86Normal3fv( GLcontext *, int ); +struct dynfn *radeon_makeX86TexCoord2f( GLcontext *, int ); +struct dynfn *radeon_makeX86TexCoord2fv( GLcontext *, int ); +struct dynfn *radeon_makeX86TexCoord1f( GLcontext *, int ); +struct dynfn *radeon_makeX86TexCoord1fv( GLcontext *, int ); +struct dynfn *radeon_makeX86MultiTexCoord2fARB( GLcontext *, int ); +struct dynfn *radeon_makeX86MultiTexCoord2fvARB( GLcontext *, int ); +struct dynfn *radeon_makeX86MultiTexCoord1fARB( GLcontext *, int ); +struct dynfn *radeon_makeX86MultiTexCoord1fvARB( GLcontext *, int ); + #endif #endif diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt_c.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt_c.c new file mode 100644 index 000000000..fadfc3077 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt_c.c @@ -0,0 +1,801 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt_c.c,v 1.2 2002/12/16 16:18:59 dawes Exp $ */ +/************************************************************************** + +Copyright 2002 ATI Technologies Inc., Ontario, Canada, and + Tungsten Graphics Inc., Cedar Park, Texas. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ +#include "mtypes.h" +#include "colormac.h" +#include "simple_list.h" +#include "api_noop.h" +#include "vtxfmt.h" + +#include "radeon_vtxfmt.h" + +/* Fallback versions of all the entrypoints for situations where + * codegen isn't available. This is still a lot faster than the + * vb/pipeline implementation in Mesa. + */ +static void radeon_Vertex3f( GLfloat x, GLfloat y, GLfloat z ) +{ + int i; + + *vb.dmaptr++ = *(int *)&x; + *vb.dmaptr++ = *(int *)&y; + *vb.dmaptr++ = *(int *)&z; + + for (i = 3; i < vb.vertex_size; i++) + *vb.dmaptr++ = vb.vertex[i].i; + + if (--vb.counter == 0) + vb.notify(); +} + + +static void radeon_Vertex3fv( const GLfloat *v ) +{ + int i; + + *vb.dmaptr++ = *(int *)&v[0]; + *vb.dmaptr++ = *(int *)&v[1]; + *vb.dmaptr++ = *(int *)&v[2]; + + for (i = 3; i < vb.vertex_size; i++) + *vb.dmaptr++ = vb.vertex[i].i; + + if (--vb.counter == 0) + vb.notify(); +} + + +static void radeon_Vertex2f( GLfloat x, GLfloat y ) +{ + int i; + + *vb.dmaptr++ = *(int *)&x; + *vb.dmaptr++ = *(int *)&y; + *vb.dmaptr++ = 0; + + for (i = 3; i < vb.vertex_size; i++) + *vb.dmaptr++ = *(int *)&vb.vertex[i]; + + if (--vb.counter == 0) + vb.notify(); +} + + +static void radeon_Vertex2fv( const GLfloat *v ) +{ + int i; + + *vb.dmaptr++ = *(int *)&v[0]; + *vb.dmaptr++ = *(int *)&v[1]; + *vb.dmaptr++ = 0; + + for (i = 3; i < vb.vertex_size; i++) + *vb.dmaptr++ = vb.vertex[i].i; + + if (--vb.counter == 0) + vb.notify(); +} + + + +/* Color for ubyte (packed) color formats: + */ +static void radeon_Color3ub_ub( GLubyte r, GLubyte g, GLubyte b ) +{ + radeon_color_t *dest = vb.colorptr; + dest->red = r; + dest->green = g; + dest->blue = b; + dest->alpha = 0xff; +} + +static void radeon_Color3ubv_ub( const GLubyte *v ) +{ + radeon_color_t *dest = vb.colorptr; + dest->red = v[0]; + dest->green = v[1]; + dest->blue = v[2]; + dest->alpha = 0xff; +} + +static void radeon_Color4ub_ub( GLubyte r, GLubyte g, GLubyte b, GLubyte a ) +{ + radeon_color_t *dest = vb.colorptr; + dest->red = r; + dest->green = g; + dest->blue = b; + dest->alpha = a; +} + +static void radeon_Color4ubv_ub( const GLubyte *v ) +{ + *(GLuint *)vb.colorptr = LE32_TO_CPU(*(GLuint *)v); +} + + +static void radeon_Color3f_ub( GLfloat r, GLfloat g, GLfloat b ) +{ + radeon_color_t *dest = vb.colorptr; + UNCLAMPED_FLOAT_TO_UBYTE( dest->red, r ); + UNCLAMPED_FLOAT_TO_UBYTE( dest->green, g ); + UNCLAMPED_FLOAT_TO_UBYTE( dest->blue, b ); + dest->alpha = 255; +} + +static void radeon_Color3fv_ub( const GLfloat *v ) +{ + radeon_color_t *dest = vb.colorptr; + UNCLAMPED_FLOAT_TO_UBYTE( dest->red, v[0] ); + UNCLAMPED_FLOAT_TO_UBYTE( dest->green, v[1] ); + UNCLAMPED_FLOAT_TO_UBYTE( dest->blue, v[2] ); + dest->alpha = 255; +} + +static void radeon_Color4f_ub( GLfloat r, GLfloat g, GLfloat b, GLfloat a ) +{ + radeon_color_t *dest = vb.colorptr; + UNCLAMPED_FLOAT_TO_UBYTE( dest->red, r ); + UNCLAMPED_FLOAT_TO_UBYTE( dest->green, g ); + UNCLAMPED_FLOAT_TO_UBYTE( dest->blue, b ); + UNCLAMPED_FLOAT_TO_UBYTE( dest->alpha, a ); +} + +static void radeon_Color4fv_ub( const GLfloat *v ) +{ + radeon_color_t *dest = vb.colorptr; + UNCLAMPED_FLOAT_TO_UBYTE( dest->red, v[0] ); + UNCLAMPED_FLOAT_TO_UBYTE( dest->green, v[1] ); + UNCLAMPED_FLOAT_TO_UBYTE( dest->blue, v[2] ); + UNCLAMPED_FLOAT_TO_UBYTE( dest->alpha, v[3] ); +} + + +/* Color for float color+alpha formats: + */ +static void radeon_Color3ub_4f( GLubyte r, GLubyte g, GLubyte b ) +{ + GLfloat *dest = vb.floatcolorptr; + dest[0] = UBYTE_TO_FLOAT(r); + dest[1] = UBYTE_TO_FLOAT(g); + dest[2] = UBYTE_TO_FLOAT(b); + dest[3] = 1.0; +} + +static void radeon_Color3ubv_4f( const GLubyte *v ) +{ + GLfloat *dest = vb.floatcolorptr; + dest[0] = UBYTE_TO_FLOAT(v[0]); + dest[1] = UBYTE_TO_FLOAT(v[1]); + dest[2] = UBYTE_TO_FLOAT(v[2]); + dest[3] = 1.0; +} + +static void radeon_Color4ub_4f( GLubyte r, GLubyte g, GLubyte b, GLubyte a ) +{ + GLfloat *dest = vb.floatcolorptr; + dest[0] = UBYTE_TO_FLOAT(r); + dest[1] = UBYTE_TO_FLOAT(g); + dest[2] = UBYTE_TO_FLOAT(b); + dest[3] = UBYTE_TO_FLOAT(a); +} + +static void radeon_Color4ubv_4f( const GLubyte *v ) +{ + GLfloat *dest = vb.floatcolorptr; + dest[0] = UBYTE_TO_FLOAT(v[0]); + dest[1] = UBYTE_TO_FLOAT(v[1]); + dest[2] = UBYTE_TO_FLOAT(v[2]); + dest[3] = UBYTE_TO_FLOAT(v[3]); +} + + +static void radeon_Color3f_4f( GLfloat r, GLfloat g, GLfloat b ) +{ + GLfloat *dest = vb.floatcolorptr; + dest[0] = r; + dest[1] = g; + dest[2] = b; + dest[3] = 1.0; +} + +static void radeon_Color3fv_4f( const GLfloat *v ) +{ + GLfloat *dest = vb.floatcolorptr; + dest[0] = v[0]; + dest[1] = v[1]; + dest[2] = v[2]; + dest[3] = 1.0; +} + +static void radeon_Color4f_4f( GLfloat r, GLfloat g, GLfloat b, GLfloat a ) +{ + GLfloat *dest = vb.floatcolorptr; + dest[0] = r; + dest[1] = g; + dest[2] = b; + dest[3] = a; +} + +static void radeon_Color4fv_4f( const GLfloat *v ) +{ + GLfloat *dest = vb.floatcolorptr; + dest[0] = v[0]; + dest[1] = v[1]; + dest[2] = v[2]; + dest[3] = v[3]; +} + + +/* Color for float color formats: + */ +static void radeon_Color3ub_3f( GLubyte r, GLubyte g, GLubyte b ) +{ + GLfloat *dest = vb.floatcolorptr; + dest[0] = UBYTE_TO_FLOAT(r); + dest[1] = UBYTE_TO_FLOAT(g); + dest[2] = UBYTE_TO_FLOAT(b); +} + +static void radeon_Color3ubv_3f( const GLubyte *v ) +{ + GLfloat *dest = vb.floatcolorptr; + dest[0] = UBYTE_TO_FLOAT(v[0]); + dest[1] = UBYTE_TO_FLOAT(v[1]); + dest[2] = UBYTE_TO_FLOAT(v[2]); +} + +static void radeon_Color4ub_3f( GLubyte r, GLubyte g, GLubyte b, GLubyte a ) +{ + GLfloat *dest = vb.floatcolorptr; + dest[0] = UBYTE_TO_FLOAT(r); + dest[1] = UBYTE_TO_FLOAT(g); + dest[2] = UBYTE_TO_FLOAT(b); + vb.context->Current.Color[3] = UBYTE_TO_FLOAT(a); +} + +static void radeon_Color4ubv_3f( const GLubyte *v ) +{ + GLfloat *dest = vb.floatcolorptr; + dest[0] = UBYTE_TO_FLOAT(v[0]); + dest[1] = UBYTE_TO_FLOAT(v[1]); + dest[2] = UBYTE_TO_FLOAT(v[2]); + vb.context->Current.Color[3] = UBYTE_TO_FLOAT(v[3]); +} + + +static void radeon_Color3f_3f( GLfloat r, GLfloat g, GLfloat b ) +{ + GLfloat *dest = vb.floatcolorptr; + dest[0] = r; + dest[1] = g; + dest[2] = b; +} + +static void radeon_Color3fv_3f( const GLfloat *v ) +{ + GLfloat *dest = vb.floatcolorptr; + dest[0] = v[0]; + dest[1] = v[1]; + dest[2] = v[2]; +} + +static void radeon_Color4f_3f( GLfloat r, GLfloat g, GLfloat b, GLfloat a ) +{ + GLfloat *dest = vb.floatcolorptr; + dest[0] = r; + dest[1] = g; + dest[2] = b; + vb.context->Current.Color[3] = a; +} + +static void radeon_Color4fv_3f( const GLfloat *v ) +{ + GLfloat *dest = vb.floatcolorptr; + dest[0] = v[0]; + dest[1] = v[1]; + dest[2] = v[2]; + vb.context->Current.Color[3] = v[3]; +} + + +/* Secondary Color: + */ +static void radeon_SecondaryColor3ubEXT_ub( GLubyte r, GLubyte g, GLubyte b ) +{ + radeon_color_t *dest = vb.specptr; + dest->red = r; + dest->green = g; + dest->blue = b; + dest->alpha = 0xff; +} + +static void radeon_SecondaryColor3ubvEXT_ub( const GLubyte *v ) +{ + radeon_color_t *dest = vb.specptr; + dest->red = v[0]; + dest->green = v[1]; + dest->blue = v[2]; + dest->alpha = 0xff; +} + +static void radeon_SecondaryColor3fEXT_ub( GLfloat r, GLfloat g, GLfloat b ) +{ + radeon_color_t *dest = vb.specptr; + UNCLAMPED_FLOAT_TO_UBYTE( dest->red, r ); + UNCLAMPED_FLOAT_TO_UBYTE( dest->green, g ); + UNCLAMPED_FLOAT_TO_UBYTE( dest->blue, b ); + dest->alpha = 255; +} + +static void radeon_SecondaryColor3fvEXT_ub( const GLfloat *v ) +{ + radeon_color_t *dest = vb.specptr; + UNCLAMPED_FLOAT_TO_UBYTE( dest->red, v[0] ); + UNCLAMPED_FLOAT_TO_UBYTE( dest->green, v[1] ); + UNCLAMPED_FLOAT_TO_UBYTE( dest->blue, v[2] ); + dest->alpha = 255; +} + +static void radeon_SecondaryColor3ubEXT_3f( GLubyte r, GLubyte g, GLubyte b ) +{ + GLfloat *dest = vb.floatspecptr; + dest[0] = UBYTE_TO_FLOAT(r); + dest[1] = UBYTE_TO_FLOAT(g); + dest[2] = UBYTE_TO_FLOAT(b); + dest[3] = 1.0; +} + +static void radeon_SecondaryColor3ubvEXT_3f( const GLubyte *v ) +{ + GLfloat *dest = vb.floatspecptr; + dest[0] = UBYTE_TO_FLOAT(v[0]); + dest[1] = UBYTE_TO_FLOAT(v[1]); + dest[2] = UBYTE_TO_FLOAT(v[2]); + dest[3] = 1.0; +} + +static void radeon_SecondaryColor3fEXT_3f( GLfloat r, GLfloat g, GLfloat b ) +{ + GLfloat *dest = vb.floatspecptr; + dest[0] = r; + dest[1] = g; + dest[2] = b; + dest[3] = 1.0; +} + +static void radeon_SecondaryColor3fvEXT_3f( const GLfloat *v ) +{ + GLfloat *dest = vb.floatspecptr; + dest[0] = v[0]; + dest[1] = v[1]; + dest[2] = v[2]; + dest[3] = 1.0; +} + + +/* Normal + */ +static void radeon_Normal3f( GLfloat n0, GLfloat n1, GLfloat n2 ) +{ + GLfloat *dest = vb.normalptr; + dest[0] = n0; + dest[1] = n1; + dest[2] = n2; +} + +static void radeon_Normal3fv( const GLfloat *v ) +{ + GLfloat *dest = vb.normalptr; + dest[0] = v[0]; + dest[1] = v[1]; + dest[2] = v[2]; +} + + +/* TexCoord + */ +static void radeon_TexCoord1f( GLfloat s ) +{ + GLfloat *dest = vb.texcoordptr[0]; + dest[0] = s; + dest[1] = 0; +} + +static void radeon_TexCoord1fv( const GLfloat *v ) +{ + GLfloat *dest = vb.texcoordptr[0]; + dest[0] = v[0]; + dest[1] = 0; +} + +static void radeon_TexCoord2f( GLfloat s, GLfloat t ) +{ + GLfloat *dest = vb.texcoordptr[0]; + dest[0] = s; + dest[1] = t; +} + +static void radeon_TexCoord2fv( const GLfloat *v ) +{ + GLfloat *dest = vb.texcoordptr[0]; + dest[0] = v[0]; + dest[1] = v[1]; +} + + +/* MultiTexcoord + */ +static void radeon_MultiTexCoord1fARB( GLenum target, GLfloat s ) +{ + GLfloat *dest = vb.texcoordptr[(target - GL_TEXTURE0_ARB)&1]; + dest[0] = s; + dest[1] = 0; +} + +static void radeon_MultiTexCoord1fvARB( GLenum target, const GLfloat *v ) +{ + GLfloat *dest = vb.texcoordptr[(target - GL_TEXTURE0_ARB)&1]; + dest[0] = v[0]; + dest[1] = 0; +} + +static void radeon_MultiTexCoord2fARB( GLenum target, GLfloat s, GLfloat t ) +{ + GLfloat *dest = vb.texcoordptr[(target - GL_TEXTURE0_ARB)&1]; + dest[0] = s; + dest[1] = t; +} + +static void radeon_MultiTexCoord2fvARB( GLenum target, const GLfloat *v ) +{ + GLfloat *dest = vb.texcoordptr[(target - GL_TEXTURE0_ARB)&1]; + dest[0] = v[0]; + dest[1] = v[1]; +} + +static struct dynfn *lookup( struct dynfn *l, int key ) +{ + struct dynfn *f; + + foreach( f, l ) { + if (f->key == key) + return f; + } + + return 0; +} + +/* Can't use the loopback template for this: + */ + +#define CHOOSE(FN, FNTYPE, MASK, ACTIVE, ARGS1, ARGS2 ) \ +static void choose_##FN ARGS1 \ +{ \ + radeonContextPtr rmesa = RADEON_CONTEXT(vb.context); \ + int key = rmesa->vb.vertex_format & (MASK|ACTIVE); \ + struct dynfn *dfn = lookup( &rmesa->vb.dfn_cache.FN, key ); \ + \ + if (dfn == 0) \ + dfn = rmesa->vb.codegen.FN( vb.context, key ); \ + else if (RADEON_DEBUG & DEBUG_CODEGEN) \ + fprintf(stderr, "%s -- cached codegen\n", __FUNCTION__ ); \ + \ + if (dfn) \ + vb.context->Exec->FN = (FNTYPE)(dfn->code); \ + else { \ + if (RADEON_DEBUG & DEBUG_CODEGEN) \ + fprintf(stderr, "%s -- generic version\n", __FUNCTION__ ); \ + vb.context->Exec->FN = radeon_##FN; \ + } \ + \ + vb.context->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \ + vb.context->Exec->FN ARGS2; \ +} + + + +/* For the _3f case, only allow one color function to be hooked in at + * a time. Eventually, use a similar mechanism to allow selecting the + * color component of the vertex format based on client behaviour. + * + * Note: Perform these actions even if there is a codegen or cached + * codegen version of the chosen function. + */ +#define CHOOSE_COLOR(FN, FNTYPE, NR, MASK, ACTIVE, ARGS1, ARGS2 ) \ +static void choose_##FN ARGS1 \ +{ \ + GLcontext *ctx = vb.context; \ + radeonContextPtr rmesa = RADEON_CONTEXT(vb.context); \ + int key = rmesa->vb.vertex_format & (MASK|ACTIVE); \ + struct dynfn *dfn; \ + \ + if (rmesa->vb.vertex_format & ACTIVE_PKCOLOR) { \ + ctx->Exec->FN = radeon_##FN##_ub; \ + } \ + else if ((rmesa->vb.vertex_format & \ + (ACTIVE_FPCOLOR|ACTIVE_FPALPHA)) == ACTIVE_FPCOLOR) { \ + \ + if (rmesa->vb.installed_color_3f_sz != NR) { \ + rmesa->vb.installed_color_3f_sz = NR; \ + if (NR == 3) ctx->Current.Color[3] = 1.0; \ + if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) { \ + radeon_copy_to_current( ctx ); \ + _mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt ); \ + ctx->Exec->FN ARGS2; \ + return; \ + } \ + } \ + \ + ctx->Exec->FN = radeon_##FN##_3f; \ + } \ + else { \ + ctx->Exec->FN = radeon_##FN##_4f; \ + } \ + \ + \ + dfn = lookup( &rmesa->vb.dfn_cache.FN, key ); \ + if (!dfn) dfn = rmesa->vb.codegen.FN( ctx, key ); \ + \ + if (dfn) { \ + if (RADEON_DEBUG & DEBUG_CODEGEN) \ + fprintf(stderr, "%s -- codegen version\n", __FUNCTION__ ); \ + ctx->Exec->FN = (FNTYPE)dfn->code; \ + } \ + else if (RADEON_DEBUG & DEBUG_CODEGEN) \ + fprintf(stderr, "%s -- 'c' version\n", __FUNCTION__ ); \ + \ + ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \ + ctx->Exec->FN ARGS2; \ +} + + + +/* Right now there are both _ub and _3f versions of the secondary color + * functions. Currently, we only set-up the hardware to use the _ub versions. + * The _3f versions are needed for the cases where secondary color isn't used + * in the vertex format, but it still needs to be stored in the context + * state vector. + */ +#define CHOOSE_SECONDARY_COLOR(FN, FNTYPE, MASK, ACTIVE, ARGS1, ARGS2 ) \ +static void choose_##FN ARGS1 \ +{ \ + GLcontext *ctx = vb.context; \ + radeonContextPtr rmesa = RADEON_CONTEXT(vb.context); \ + int key = rmesa->vb.vertex_format & (MASK|ACTIVE); \ + struct dynfn *dfn = lookup( &rmesa->vb.dfn_cache.FN, key ); \ + \ + if (dfn == 0) \ + dfn = rmesa->vb.codegen.FN( vb.context, key ); \ + else if (RADEON_DEBUG & DEBUG_CODEGEN) \ + fprintf(stderr, "%s -- cached version\n", __FUNCTION__ ); \ + \ + if (dfn) \ + vb.context->Exec->FN = (FNTYPE)(dfn->code); \ + else { \ + if (RADEON_DEBUG & DEBUG_CODEGEN) \ + fprintf(stderr, "%s -- generic version\n", __FUNCTION__ ); \ + vb.context->Exec->FN = ((rmesa->vb.vertex_format & ACTIVE_PKSPEC) != 0) \ + ? radeon_##FN##_ub : radeon_##FN##_3f; \ + } \ + \ + ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \ + ctx->Exec->FN ARGS2; \ +} + + + + + +/* Shorthands + */ +#define ACTIVE_XYZW (RADEON_CP_VC_FRMT_W0|RADEON_CP_VC_FRMT_Z) +#define ACTIVE_NORM RADEON_CP_VC_FRMT_N0 + +#define ACTIVE_PKCOLOR RADEON_CP_VC_FRMT_PKCOLOR +#define ACTIVE_FPCOLOR RADEON_CP_VC_FRMT_FPCOLOR +#define ACTIVE_FPALPHA RADEON_CP_VC_FRMT_FPALPHA +#define ACTIVE_COLOR (ACTIVE_FPCOLOR|ACTIVE_PKCOLOR) + +#define ACTIVE_PKSPEC RADEON_CP_VC_FRMT_PKSPEC +#define ACTIVE_FPSPEC RADEON_CP_VC_FRMT_FPSPEC +#define ACTIVE_SPEC (ACTIVE_FPSPEC|ACTIVE_PKSPEC) + +#define ACTIVE_ST0 RADEON_CP_VC_FRMT_ST0 +#define ACTIVE_ST1 RADEON_CP_VC_FRMT_ST1 +#define ACTIVE_ST_ALL (RADEON_CP_VC_FRMT_ST1|RADEON_CP_VC_FRMT_ST0) + +/* Each codegen function should be able to be fully specified by a + * subsetted version of rmesa->vb.vertex_format. + */ +#define MASK_NORM (ACTIVE_XYZW) +#define MASK_COLOR (MASK_NORM|ACTIVE_NORM) +#define MASK_SPEC (MASK_COLOR|ACTIVE_COLOR) +#define MASK_ST0 (MASK_SPEC|ACTIVE_SPEC) +#define MASK_ST1 (MASK_ST0|ACTIVE_ST0) +#define MASK_ST_ALL (MASK_ST1|ACTIVE_ST1) +#define MASK_VERTEX (MASK_ST_ALL|ACTIVE_FPALPHA) + + +typedef void (*p4f)( GLfloat, GLfloat, GLfloat, GLfloat ); +typedef void (*p3f)( GLfloat, GLfloat, GLfloat ); +typedef void (*p2f)( GLfloat, GLfloat ); +typedef void (*p1f)( GLfloat ); +typedef void (*pe2f)( GLenum, GLfloat, GLfloat ); +typedef void (*pe1f)( GLenum, GLfloat ); +typedef void (*p4ub)( GLubyte, GLubyte, GLubyte, GLubyte ); +typedef void (*p3ub)( GLubyte, GLubyte, GLubyte ); +typedef void (*pfv)( const GLfloat * ); +typedef void (*pefv)( GLenum, const GLfloat * ); +typedef void (*pubv)( const GLubyte * ); + + +CHOOSE(Normal3f, p3f, MASK_NORM, ACTIVE_NORM, + (GLfloat a,GLfloat b,GLfloat c), (a,b,c)) +CHOOSE(Normal3fv, pfv, MASK_NORM, ACTIVE_NORM, + (const GLfloat *v), (v)) + +CHOOSE_COLOR(Color4ub, p4ub, 4, MASK_COLOR, ACTIVE_COLOR, + (GLubyte a,GLubyte b, GLubyte c, GLubyte d), (a,b,c,d)) +CHOOSE_COLOR(Color4ubv, pubv, 4, MASK_COLOR, ACTIVE_COLOR, + (const GLubyte *v), (v)) +CHOOSE_COLOR(Color3ub, p3ub, 3, MASK_COLOR, ACTIVE_COLOR, + (GLubyte a,GLubyte b, GLubyte c), (a,b,c)) +CHOOSE_COLOR(Color3ubv, pubv, 3, MASK_COLOR, ACTIVE_COLOR, + (const GLubyte *v), (v)) + +CHOOSE_COLOR(Color4f, p4f, 4, MASK_COLOR, ACTIVE_COLOR, + (GLfloat a,GLfloat b, GLfloat c, GLfloat d), (a,b,c,d)) +CHOOSE_COLOR(Color4fv, pfv, 4, MASK_COLOR, ACTIVE_COLOR, + (const GLfloat *v), (v)) +CHOOSE_COLOR(Color3f, p3f, 3, MASK_COLOR, ACTIVE_COLOR, + (GLfloat a,GLfloat b, GLfloat c), (a,b,c)) +CHOOSE_COLOR(Color3fv, pfv, 3, MASK_COLOR, ACTIVE_COLOR, + (const GLfloat *v), (v)) + + +CHOOSE_SECONDARY_COLOR(SecondaryColor3ubEXT, p3ub, MASK_SPEC, ACTIVE_SPEC, + (GLubyte a,GLubyte b, GLubyte c), (a,b,c)) +CHOOSE_SECONDARY_COLOR(SecondaryColor3ubvEXT, pubv, MASK_SPEC, ACTIVE_SPEC, + (const GLubyte *v), (v)) +CHOOSE_SECONDARY_COLOR(SecondaryColor3fEXT, p3f, MASK_SPEC, ACTIVE_SPEC, + (GLfloat a,GLfloat b, GLfloat c), (a,b,c)) +CHOOSE_SECONDARY_COLOR(SecondaryColor3fvEXT, pfv, MASK_SPEC, ACTIVE_SPEC, + (const GLfloat *v), (v)) + +CHOOSE(TexCoord2f, p2f, MASK_ST0, ACTIVE_ST0, + (GLfloat a,GLfloat b), (a,b)) +CHOOSE(TexCoord2fv, pfv, MASK_ST0, ACTIVE_ST0, + (const GLfloat *v), (v)) +CHOOSE(TexCoord1f, p1f, MASK_ST0, ACTIVE_ST0, + (GLfloat a), (a)) +CHOOSE(TexCoord1fv, pfv, MASK_ST0, ACTIVE_ST0, + (const GLfloat *v), (v)) + +CHOOSE(MultiTexCoord2fARB, pe2f, MASK_ST_ALL, ACTIVE_ST_ALL, + (GLenum u,GLfloat a,GLfloat b), (u,a,b)) +CHOOSE(MultiTexCoord2fvARB, pefv, MASK_ST_ALL, ACTIVE_ST_ALL, + (GLenum u,const GLfloat *v), (u,v)) +CHOOSE(MultiTexCoord1fARB, pe1f, MASK_ST_ALL, ACTIVE_ST_ALL, + (GLenum u,GLfloat a), (u,a)) +CHOOSE(MultiTexCoord1fvARB, pefv, MASK_ST_ALL, ACTIVE_ST_ALL, + (GLenum u,const GLfloat *v), (u,v)) + +CHOOSE(Vertex3f, p3f, MASK_VERTEX, MASK_VERTEX, + (GLfloat a,GLfloat b,GLfloat c), (a,b,c)) +CHOOSE(Vertex3fv, pfv, MASK_VERTEX, MASK_VERTEX, + (const GLfloat *v), (v)) +CHOOSE(Vertex2f, p2f, MASK_VERTEX, MASK_VERTEX, + (GLfloat a,GLfloat b), (a,b)) +CHOOSE(Vertex2fv, pfv, MASK_VERTEX, MASK_VERTEX, + (const GLfloat *v), (v)) + + + + + +void radeonVtxfmtInitChoosers( GLvertexformat *vfmt ) +{ + vfmt->Color3f = choose_Color3f; + vfmt->Color3fv = choose_Color3fv; + vfmt->Color3ub = choose_Color3ub; + vfmt->Color3ubv = choose_Color3ubv; + vfmt->Color4f = choose_Color4f; + vfmt->Color4fv = choose_Color4fv; + vfmt->Color4ub = choose_Color4ub; + vfmt->Color4ubv = choose_Color4ubv; + vfmt->SecondaryColor3fEXT = choose_SecondaryColor3fEXT; + vfmt->SecondaryColor3fvEXT = choose_SecondaryColor3fvEXT; + vfmt->SecondaryColor3ubEXT = choose_SecondaryColor3ubEXT; + vfmt->SecondaryColor3ubvEXT = choose_SecondaryColor3ubvEXT; + vfmt->MultiTexCoord1fARB = choose_MultiTexCoord1fARB; + vfmt->MultiTexCoord1fvARB = choose_MultiTexCoord1fvARB; + vfmt->MultiTexCoord2fARB = choose_MultiTexCoord2fARB; + vfmt->MultiTexCoord2fvARB = choose_MultiTexCoord2fvARB; + vfmt->Normal3f = choose_Normal3f; + vfmt->Normal3fv = choose_Normal3fv; + vfmt->TexCoord1f = choose_TexCoord1f; + vfmt->TexCoord1fv = choose_TexCoord1fv; + vfmt->TexCoord2f = choose_TexCoord2f; + vfmt->TexCoord2fv = choose_TexCoord2fv; + vfmt->Vertex2f = choose_Vertex2f; + vfmt->Vertex2fv = choose_Vertex2fv; + vfmt->Vertex3f = choose_Vertex3f; + vfmt->Vertex3fv = choose_Vertex3fv; +} + + +static struct dynfn *codegen_noop( GLcontext *ctx, int key ) +{ + (void) ctx; (void) key; + return 0; +} + +void radeonInitCodegen( struct dfn_generators *gen ) +{ + gen->Vertex3f = codegen_noop; + gen->Vertex3fv = codegen_noop; + gen->Color4ub = codegen_noop; + gen->Color4ubv = codegen_noop; + gen->Normal3f = codegen_noop; + gen->Normal3fv = codegen_noop; + gen->TexCoord2f = codegen_noop; + gen->TexCoord2fv = codegen_noop; + gen->MultiTexCoord2fARB = codegen_noop; + gen->MultiTexCoord2fvARB = codegen_noop; + gen->Vertex2f = codegen_noop; + gen->Vertex2fv = codegen_noop; + gen->Color3ub = codegen_noop; + gen->Color3ubv = codegen_noop; + gen->Color4f = codegen_noop; + gen->Color4fv = codegen_noop; + gen->Color3f = codegen_noop; + gen->Color3fv = codegen_noop; + gen->SecondaryColor3fEXT = codegen_noop; + gen->SecondaryColor3fvEXT = codegen_noop; + gen->SecondaryColor3ubEXT = codegen_noop; + gen->SecondaryColor3ubvEXT = codegen_noop; + gen->TexCoord1f = codegen_noop; + gen->TexCoord1fv = codegen_noop; + gen->MultiTexCoord1fARB = codegen_noop; + gen->MultiTexCoord1fvARB = codegen_noop; + + if (!getenv("RADEON_NO_CODEGEN")) { +#if defined(USE_X86_ASM) + radeonInitX86Codegen( gen ); +#endif + +#if defined(USE_SSE_ASM) + radeonInitSSECodegen( gen ); +#endif + } +} diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt_sse.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt_sse.c new file mode 100644 index 000000000..0df3062be --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt_sse.c @@ -0,0 +1,88 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt_sse.c,v 1.1 2002/10/30 12:51:58 alanh Exp $ */ +/************************************************************************** + +Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and + Tungsten Graphics Inc., Cedar Park, Texas. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include <stdio.h> +#include <assert.h> +#include "mem.h" +#include "simple_list.h" +#include "radeon_vtxfmt.h" + +#if defined(USE_SSE_ASM) +#include "X86/common_x86_asm.h" + +/* Build specialized versions of the immediate calls on the fly for + * the current state. ???P4 SSE2 versions??? + */ + + +static struct dynfn *makeSSENormal3fv( GLcontext *ctx, int key ) +{ + /* Requires P4 (sse2?) + */ + static unsigned char temp[] = { + 0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ + 0xba, 0x78, 0x56, 0x34, 0x12, /* mov $0x12345678,%edx */ + 0xf3, 0x0f, 0x7e, 0x00, /* movq (%eax),%xmm0 */ + 0x66, 0x0f, 0x6e, 0x48, 0x08, /* movd 0x8(%eax),%xmm1 */ + 0x66, 0x0f, 0xd6, 0x42, 0x0c, /* movq %xmm0,0xc(%edx) */ + 0x66, 0x0f, 0x7e, 0x4a, 0x14, /* movd %xmm1,0x14(%edx) */ + 0xc3, /* ret */ + }; + + + struct dynfn *dfn = MALLOC_STRUCT( dynfn ); + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + insert_at_head( &rmesa->vb.dfn_cache.Normal3fv, dfn ); + dfn->key = key; + + dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); + memcpy (dfn->code, temp, sizeof(temp)); + FIXUP(dfn->code, 5, 0x0, (int)vb.normalptr); + return dfn; +} + +void radeonInitSSECodegen( struct dfn_generators *gen ) +{ + if ( cpu_has_xmm && cpu_has_xmm2 ) + /*gen->Normal3fv = */ (void)makeSSENormal3fv; +} + +#else + +void radeonInitSSECodegen( struct dfn_generators *gen ) +{ + (void) gen; +} + +#endif diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt_x86.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt_x86.c new file mode 100644 index 000000000..ad7d9308e --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt_x86.c @@ -0,0 +1,463 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt_x86.c,v 1.2 2002/12/21 17:02:16 dawes Exp $ */ +/************************************************************************** + +Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and + Tungsten Graphics Inc., Cedar Park, Texas. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#include <stdio.h> +#include <assert.h> +#include "mem.h" +#include "mmath.h" +#include "simple_list.h" +#include "radeon_vtxfmt.h" + +#if defined(USE_X86_ASM) + +#define EXTERN( FUNC ) \ +extern const char *FUNC; \ +extern const char *FUNC##_end + +EXTERN ( _x86_Normal3fv ); +EXTERN ( _x86_Normal3f ); +EXTERN ( _x86_Vertex3fv_6 ); +EXTERN ( _x86_Vertex3fv_8 ); +EXTERN ( _x86_Vertex3fv ); +EXTERN ( _x86_Vertex3f_4 ); +EXTERN ( _x86_Vertex3f_6 ); +EXTERN ( _x86_Vertex3f ); +EXTERN ( _x86_Color4ubv_ub ); +EXTERN ( _x86_Color4ubv_4f ); +EXTERN ( _x86_Color4ub_ub ); +EXTERN ( _x86_Color3fv_3f ); +EXTERN ( _x86_Color3f_3f ); +EXTERN ( _x86_TexCoord2fv ); +EXTERN ( _x86_TexCoord2f ); +EXTERN ( _x86_MultiTexCoord2fvARB ); +EXTERN ( _x86_MultiTexCoord2fvARB_2 ); +EXTERN ( _x86_MultiTexCoord2fARB ); +EXTERN ( _x86_MultiTexCoord2fARB_2 ); + + +/* Build specialized versions of the immediate calls on the fly for + * the current state. Generic x86 versions. + */ + +struct dynfn *radeon_makeX86Vertex3f( GLcontext *ctx, int key ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + struct dynfn *dfn = MALLOC_STRUCT( dynfn ); + + if (RADEON_DEBUG & DEBUG_CODEGEN) + fprintf(stderr, "%s 0x%08x %d\n", __FUNCTION__, key, vb.vertex_size ); + + switch (vb.vertex_size) { + case 4: { + + DFN ( _x86_Vertex3f_4, rmesa->vb.dfn_cache.Vertex3f ); + FIXUP(dfn->code, 2, 0x0, (int)&vb.dmaptr); + FIXUP(dfn->code, 25, 0x0, (int)&vb.vertex[3]); + FIXUP(dfn->code, 36, 0x0, (int)&vb.counter); + FIXUP(dfn->code, 46, 0x0, (int)&vb.dmaptr); + FIXUP(dfn->code, 51, 0x0, (int)&vb.counter); + FIXUP(dfn->code, 60, 0x0, (int)&vb.notify); + break; + } + case 6: { + + DFN ( _x86_Vertex3f_6, rmesa->vb.dfn_cache.Vertex3f ); + FIXUP(dfn->code, 3, 0x0, (int)&vb.dmaptr); + FIXUP(dfn->code, 28, 0x0, (int)&vb.vertex[3]); + FIXUP(dfn->code, 34, 0x0, (int)&vb.vertex[4]); + FIXUP(dfn->code, 40, 0x0, (int)&vb.vertex[5]); + FIXUP(dfn->code, 57, 0x0, (int)&vb.counter); + FIXUP(dfn->code, 63, 0x0, (int)&vb.dmaptr); + FIXUP(dfn->code, 70, 0x0, (int)&vb.counter); + FIXUP(dfn->code, 79, 0x0, (int)&vb.notify); + break; + } + default: { + + DFN ( _x86_Vertex3f, rmesa->vb.dfn_cache.Vertex3f ); + FIXUP(dfn->code, 3, 0x0, (int)&vb.vertex[3]); + FIXUP(dfn->code, 9, 0x0, (int)&vb.dmaptr); + FIXUP(dfn->code, 37, 0x0, vb.vertex_size-3); + FIXUP(dfn->code, 44, 0x0, (int)&vb.counter); + FIXUP(dfn->code, 50, 0x0, (int)&vb.dmaptr); + FIXUP(dfn->code, 56, 0x0, (int)&vb.counter); + FIXUP(dfn->code, 67, 0x0, (int)&vb.notify); + break; + } + } + + return dfn; +} + + + +struct dynfn *radeon_makeX86Vertex3fv( GLcontext *ctx, int key ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + struct dynfn *dfn = MALLOC_STRUCT( dynfn ); + + if (RADEON_DEBUG & DEBUG_CODEGEN) + fprintf(stderr, "%s 0x%08x %d\n", __FUNCTION__, key, vb.vertex_size ); + + switch (vb.vertex_size) { + case 6: { + + DFN ( _x86_Vertex3fv_6, rmesa->vb.dfn_cache.Vertex3fv ); + FIXUP(dfn->code, 1, 0x00000000, (int)&vb.dmaptr); + FIXUP(dfn->code, 27, 0x0000001c, (int)&vb.vertex[3]); + FIXUP(dfn->code, 33, 0x00000020, (int)&vb.vertex[4]); + FIXUP(dfn->code, 45, 0x00000024, (int)&vb.vertex[5]); + FIXUP(dfn->code, 56, 0x00000000, (int)&vb.dmaptr); + FIXUP(dfn->code, 61, 0x00000004, (int)&vb.counter); + FIXUP(dfn->code, 67, 0x00000004, (int)&vb.counter); + FIXUP(dfn->code, 76, 0x00000008, (int)&vb.notify); + break; + } + + + case 8: { + + DFN ( _x86_Vertex3fv_8, rmesa->vb.dfn_cache.Vertex3fv ); + FIXUP(dfn->code, 1, 0x00000000, (int)&vb.dmaptr); + FIXUP(dfn->code, 27, 0x0000001c, (int)&vb.vertex[3]); + FIXUP(dfn->code, 33, 0x00000020, (int)&vb.vertex[4]); + FIXUP(dfn->code, 45, 0x0000001c, (int)&vb.vertex[5]); + FIXUP(dfn->code, 51, 0x00000020, (int)&vb.vertex[6]); + FIXUP(dfn->code, 63, 0x00000024, (int)&vb.vertex[7]); + FIXUP(dfn->code, 74, 0x00000000, (int)&vb.dmaptr); + FIXUP(dfn->code, 79, 0x00000004, (int)&vb.counter); + FIXUP(dfn->code, 85, 0x00000004, (int)&vb.counter); + FIXUP(dfn->code, 94, 0x00000008, (int)&vb.notify); + break; + } + + + + default: { + + DFN ( _x86_Vertex3fv, rmesa->vb.dfn_cache.Vertex3fv ); + FIXUP(dfn->code, 8, 0x01010101, (int)&vb.dmaptr); + FIXUP(dfn->code, 32, 0x00000006, vb.vertex_size-3); + FIXUP(dfn->code, 37, 0x00000058, (int)&vb.vertex[3]); + FIXUP(dfn->code, 45, 0x01010101, (int)&vb.dmaptr); + FIXUP(dfn->code, 50, 0x02020202, (int)&vb.counter); + FIXUP(dfn->code, 58, 0x02020202, (int)&vb.counter); + FIXUP(dfn->code, 67, 0x0, (int)&vb.notify); + break; + } + } + + return dfn; +} + +struct dynfn *radeon_makeX86Normal3fv( GLcontext *ctx, int key ) +{ + struct dynfn *dfn = MALLOC_STRUCT( dynfn ); + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + int i = 0; + + if (RADEON_DEBUG & DEBUG_CODEGEN) + fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key ); + + DFN ( _x86_Normal3fv, rmesa->vb.dfn_cache.Normal3fv ); + + FIXUP2(dfn->code, i, 0x0, (int)vb.normalptr); + FIXUP2(dfn->code, i, 0x4, 4+(int)vb.normalptr); + FIXUP2(dfn->code, i, 0x8, 8+(int)vb.normalptr); + /* fprintf(stderr, "%s done\n", __FUNCTION__); */ + return dfn; +} + +struct dynfn *radeon_makeX86Normal3f( GLcontext *ctx, int key ) +{ + struct dynfn *dfn = MALLOC_STRUCT( dynfn ); + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + + if (RADEON_DEBUG & DEBUG_CODEGEN) + fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key ); + + DFN ( _x86_Normal3f, rmesa->vb.dfn_cache.Normal3f ); + FIXUP(dfn->code, 1, 0x12345678, (int)vb.normalptr); + return dfn; +} + +struct dynfn *radeon_makeX86Color4ubv( GLcontext *ctx, int key ) +{ + struct dynfn *dfn = MALLOC_STRUCT( dynfn ); + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + + + if (RADEON_DEBUG & DEBUG_CODEGEN) + fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key ); + + if (key & RADEON_CP_VC_FRMT_PKCOLOR) { + DFN ( _x86_Color4ubv_ub, rmesa->vb.dfn_cache.Color4ubv); + FIXUP(dfn->code, 5, 0x12345678, (int)vb.colorptr); + return dfn; + } + else { + + DFN ( _x86_Color4ubv_4f, rmesa->vb.dfn_cache.Color4ubv); + FIXUP(dfn->code, 2, 0x00000000, (int)_mesa_ubyte_to_float_color_tab); + FIXUP(dfn->code, 27, 0xdeadbeaf, (int)vb.floatcolorptr); + FIXUP(dfn->code, 33, 0xdeadbeaf, (int)vb.floatcolorptr+4); + FIXUP(dfn->code, 55, 0xdeadbeaf, (int)vb.floatcolorptr+8); + FIXUP(dfn->code, 61, 0xdeadbeaf, (int)vb.floatcolorptr+12); + return dfn; + } +} + +struct dynfn *radeon_makeX86Color4ub( GLcontext *ctx, int key ) +{ + if (RADEON_DEBUG & DEBUG_CODEGEN) + fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key ); + + if (key & RADEON_CP_VC_FRMT_PKCOLOR) { + struct dynfn *dfn = MALLOC_STRUCT( dynfn ); + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + + DFN ( _x86_Color4ub_ub, rmesa->vb.dfn_cache.Color4ub ); + FIXUP(dfn->code, 18, 0x0, (int)vb.colorptr); + FIXUP(dfn->code, 24, 0x0, (int)vb.colorptr+1); + FIXUP(dfn->code, 30, 0x0, (int)vb.colorptr+2); + FIXUP(dfn->code, 36, 0x0, (int)vb.colorptr+3); + return dfn; + } + else + return 0; +} + + +struct dynfn *radeon_makeX86Color3fv( GLcontext *ctx, int key ) +{ + if (key & (RADEON_CP_VC_FRMT_PKCOLOR|RADEON_CP_VC_FRMT_FPALPHA)) + return 0; + else + { + struct dynfn *dfn = MALLOC_STRUCT( dynfn ); + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + + if (RADEON_DEBUG & DEBUG_CODEGEN) + fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key ); + + DFN ( _x86_Color3fv_3f, rmesa->vb.dfn_cache.Color3fv ); + FIXUP(dfn->code, 5, 0x0, (int)vb.floatcolorptr); + return dfn; + } +} + +struct dynfn *radeon_makeX86Color3f( GLcontext *ctx, int key ) +{ + if (key & (RADEON_CP_VC_FRMT_PKCOLOR|RADEON_CP_VC_FRMT_FPALPHA)) + return 0; + else + { + struct dynfn *dfn = MALLOC_STRUCT( dynfn ); + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + + if (RADEON_DEBUG & DEBUG_CODEGEN) + fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key ); + + DFN ( _x86_Color3f_3f, rmesa->vb.dfn_cache.Color3f ); + FIXUP(dfn->code, 1, 0x12345678, (int)vb.floatcolorptr); + return dfn; + } +} + + + +struct dynfn *radeon_makeX86TexCoord2fv( GLcontext *ctx, int key ) +{ + + struct dynfn *dfn = MALLOC_STRUCT( dynfn ); + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + + if (RADEON_DEBUG & DEBUG_CODEGEN) + fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key ); + + DFN ( _x86_TexCoord2fv, rmesa->vb.dfn_cache.TexCoord2fv ); + FIXUP(dfn->code, 5, 0x12345678, (int)vb.texcoordptr[0]); + return dfn; +} + +struct dynfn *radeon_makeX86TexCoord2f( GLcontext *ctx, int key ) +{ + + struct dynfn *dfn = MALLOC_STRUCT( dynfn ); + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + + if (RADEON_DEBUG & DEBUG_CODEGEN) + fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key ); + + DFN ( _x86_TexCoord2f, rmesa->vb.dfn_cache.TexCoord2f ); + FIXUP(dfn->code, 1, 0x12345678, (int)vb.texcoordptr[0]); + return dfn; +} + +struct dynfn *radeon_makeX86MultiTexCoord2fvARB( GLcontext *ctx, int key ) +{ +#if 0 + static char temp[] = { + 0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ + 0x8b, 0x4c, 0x24, 0x08, /* mov 0x8(%esp,1),%ecx */ + 0x2d, 0xc0, 0x84, 0x00, 0x00, /* sub $0x84c0,%eax */ + 0x83, 0xe0, 0x01, /* and $0x1,%eax */ + 0x8b, 0x11, /* mov (%ecx),%edx */ + 0xc1, 0xe0, 0x03, /* shl $0x3,%eax */ + 0x8b, 0x49, 0x04, /* mov 0x4(%ecx),%ecx */ + 0x89, 0x90, 0, 0, 0, 0,/* mov %edx,DEST(%eax) */ + 0x89, 0x88, 0, 0, 0, 0,/* mov %ecx,DEST+8(%eax) */ + 0xc3, /* ret */ + }; + static char temp2[] = { + 0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ + 0x8b, 0x4c, 0x24, 0x08, /* mov 0x8(%esp,1),%ecx */ + 0x2d, 0xc0, 0x84, 0x00, 0x00, /* sub $0x84c0,%eax */ + 0x83, 0xe0, 0x01, /* and $0x1,%eax */ + 0x8b, 0x14, 0x85, 0, 0, 0, 0, /* mov DEST(,%eax,4),%edx */ + 0x8b, 0x01, /* mov (%ecx),%eax */ + 0x89, 0x02, /* mov %eax,(%edx) */ + 0x8b, 0x41, 0x04, /* mov 0x4(%ecx),%eax */ + 0x89, 0x42, 0x04, /* mov %eax,0x4(%edx) */ + 0xc3, /* ret */ + }; +#endif + + struct dynfn *dfn = MALLOC_STRUCT( dynfn ); + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + + if (RADEON_DEBUG & DEBUG_CODEGEN) + fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key ); + + if ((key & (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) == + (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) { + DFN ( _x86_MultiTexCoord2fvARB, rmesa->vb.dfn_cache.MultiTexCoord2fvARB ); + FIXUP(dfn->code, 26, 0xdeadbeef, (int)vb.texcoordptr[0]); + FIXUP(dfn->code, 32, 0xdeadbeef, (int)vb.texcoordptr[0]+4); + } else { + DFN ( _x86_MultiTexCoord2fvARB_2, rmesa->vb.dfn_cache.MultiTexCoord2fvARB ); + FIXUP(dfn->code, 19, 0x0, (int)vb.texcoordptr); + } + return dfn; +} + +struct dynfn *radeon_makeX86MultiTexCoord2fARB( GLcontext *ctx, + int key ) +{ +#if 0 + static char temp[] = { + 0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ + 0x8b, 0x54, 0x24, 0x08, /* mov 0x8(%esp,1),%edx */ + 0x2d, 0xc0, 0x84, 0x00, 0x00, /* sub $0x84c0,%eax */ + 0x8b, 0x4c, 0x24, 0x0c, /* mov 0xc(%esp,1),%ecx */ + 0x83, 0xe0, 0x01, /* and $0x1,%eax */ + 0xc1, 0xe0, 0x03, /* shl $0x3,%eax */ + 0x89, 0x90, 0, 0, 0, 0, /* mov %edx,DEST(%eax) */ + 0x89, 0x88, 0, 0, 0, 0, /* mov %ecx,DEST+8(%eax) */ + 0xc3, /* ret */ + }; + + static char temp2[] = { + 0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ + 0x8b, 0x54, 0x24, 0x08, /* mov 0x8(%esp,1),%edx */ + 0x2d, 0xc0, 0x84, 0x00, 0x00, /* sub $0x84c0,%eax */ + 0x8b, 0x4c, 0x24, 0x0c, /* mov 0xc(%esp,1),%ecx */ + 0x83, 0xe0, 0x01, /* and $0x1,%eax */ + 0x8b, 0x04, 0x85, 0, 0, 0, 0, /* mov DEST(,%eax,4),%eax */ + 0x89, 0x10, /* mov %edx,(%eax) */ + 0x89, 0x48, 0x04, /* mov %ecx,0x4(%eax) */ + 0xc3, /* ret */ + }; +#endif + struct dynfn *dfn = MALLOC_STRUCT( dynfn ); + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + + if (RADEON_DEBUG & DEBUG_CODEGEN) + fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key ); + + if ((key & (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) == + (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) { + DFN ( _x86_MultiTexCoord2fARB, rmesa->vb.dfn_cache.MultiTexCoord2fARB ); + FIXUP(dfn->code, 25, 0xdeadbeef, (int)vb.texcoordptr[0]); + FIXUP(dfn->code, 31, 0xdeadbeef, (int)vb.texcoordptr[0]+4); + } + else { + /* Note: this might get generated multiple times, even though the + * actual emitted code is the same. + */ + DFN ( _x86_MultiTexCoord2fARB_2, rmesa->vb.dfn_cache.MultiTexCoord2fARB ); + FIXUP(dfn->code, 23, 0x0, (int)vb.texcoordptr); + } + return dfn; +} + + +void radeonInitX86Codegen( struct dfn_generators *gen ) +{ + gen->Vertex3f = radeon_makeX86Vertex3f; + gen->Vertex3fv = radeon_makeX86Vertex3fv; + gen->Color4ub = radeon_makeX86Color4ub; /* PKCOLOR only */ + gen->Color4ubv = radeon_makeX86Color4ubv; /* PKCOLOR only */ + gen->Normal3f = radeon_makeX86Normal3f; + gen->Normal3fv = radeon_makeX86Normal3fv; + gen->TexCoord2f = radeon_makeX86TexCoord2f; + gen->TexCoord2fv = radeon_makeX86TexCoord2fv; + gen->MultiTexCoord2fARB = radeon_makeX86MultiTexCoord2fARB; + gen->MultiTexCoord2fvARB = radeon_makeX86MultiTexCoord2fvARB; + gen->Color3f = radeon_makeX86Color3f; + gen->Color3fv = radeon_makeX86Color3fv; + + /* Not done: + */ +/* gen->Vertex2f = radeon_makeX86Vertex2f; */ +/* gen->Vertex2fv = radeon_makeX86Vertex2fv; */ +/* gen->Color3ub = radeon_makeX86Color3ub; */ +/* gen->Color3ubv = radeon_makeX86Color3ubv; */ +/* gen->Color4f = radeon_makeX86Color4f; */ +/* gen->Color4fv = radeon_makeX86Color4fv; */ +/* gen->TexCoord1f = radeon_makeX86TexCoord1f; */ +/* gen->TexCoord1fv = radeon_makeX86TexCoord1fv; */ +/* gen->MultiTexCoord1fARB = radeon_makeX86MultiTexCoord1fARB; */ +/* gen->MultiTexCoord1fvARB = radeon_makeX86MultiTexCoord1fvARB; */ +} + + +#else + +void radeonInitX86Codegen( struct dfn_generators *gen ) +{ + (void) gen; +} + +#endif diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxtmp_x86.S b/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxtmp_x86.S new file mode 100644 index 000000000..b9b1594a3 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxtmp_x86.S @@ -0,0 +1,410 @@ +/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_vtxtmp_x86.S,v 1.2 2002/11/07 18:32:00 tsi Exp $ */ +/************************************************************************** + +Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas. + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +on the rights to use, copy, modify, merge, publish, distribute, sub +license, and/or sell copies of the Software, and to permit persons to whom +the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#define GLOBL( x ) \ +.globl x; \ +x##: + +.data +.align 4 +GLOBL( _x86_Normal3fv) + movl 4(%esp), %eax /* load 'v' off stack */ + movl (%eax), %ecx /* load v[0] */ + movl 4(%eax), %edx /* load v[1] */ + movl 8(%eax), %eax /* load v[2] */ + movl %ecx, 0 /* store v[0] to current vertex */ + movl %edx, 4 /* store v[1] to current vertex */ + movl %eax, 8 /* store v[2] to current vertex */ + ret +GLOBL ( _x86_Normal3fv_end ) + +/* + vertex 3f vertex size 4 +*/ + +GLOBL ( _x86_Vertex3f_4 ) + movl (0), %ecx + movl 4(%esp), %eax + movl 8(%esp), %edx + movl %eax, (%ecx) + movl %edx, 4(%ecx) + movl 12(%esp), %eax + movl (0), %edx + movl %eax, 8(%ecx) + movl %edx, 12(%ecx) + movl (0), %eax + addl $16, %ecx + dec %eax + movl %ecx, (0) + movl %eax, (0) + je .1 + ret +.1: jmp *0 + +GLOBL ( _x86_Vertex3f_4_end ) + +/* + vertex 3f vertex size 6 +*/ +GLOBL ( _x86_Vertex3f_6 ) + push %edi + movl (0), %edi + movl 8(%esp), %eax + movl 12(%esp), %edx + movl 16(%esp), %ecx + movl %eax, (%edi) + movl %edx, 4(%edi) + movl %ecx, 8(%edi) + movl (0), %eax + movl (0), %edx + movl (0), %ecx + movl %eax, 12(%edi) + movl %edx, 16(%edi) + movl %ecx, 20(%edi) + addl $24, %edi + movl (0), %eax + movl %edi, (0) + dec %eax + pop %edi + movl %eax, (0) + je .2 + ret +.2: jmp *0 +GLOBL ( _x86_Vertex3f_6_end ) +/* + vertex 3f generic size +*/ +GLOBL ( _x86_Vertex3f ) + push %edi + push %esi + movl $0, %esi + movl (0), %edi + movl 12(%esp), %eax + movl 16(%esp), %edx + movl 20(%esp), %ecx + movl %eax, (%edi) + movl %edx, 4(%edi) + movl %ecx, 8(%edi) + addl $12, %edi + movl $0, %ecx + repz + movsl %ds:(%esi), %es:(%edi) + movl (0), %eax + movl %edi, (0) + dec %eax + movl %eax, (0) + pop %esi + pop %edi + je .3 + ret +.3: jmp *0 + +GLOBL ( _x86_Vertex3f_end ) + +/* + Vertex 3fv vertex size 6 +*/ +GLOBL ( _x86_Vertex3fv_6 ) + movl (0), %eax + movl 4(%esp), %ecx + movl (%ecx), %edx + movl %edx, (%eax) + movl 4(%ecx), %edx + movl 8(%ecx), %ecx + movl %edx, 4(%eax) + movl %ecx, 8(%eax) + movl (28), %edx + movl (32), %ecx + movl %edx, 12(%eax) + movl %ecx, 16(%eax) + movl (36), %edx + movl %edx, 20(%eax) + addl $24, %eax + movl %eax, 0 + movl 4, %eax + dec %eax + movl %eax, 4 + je .4 + ret +.4: jmp *8 + +GLOBL ( _x86_Vertex3fv_6_end ) + +/* + Vertex 3fv vertex size 8 +*/ +GLOBL ( _x86_Vertex3fv_8 ) + movl (0), %eax + movl 4(%esp), %ecx + movl (%ecx), %edx + movl %edx ,(%eax) + movl 4(%ecx) ,%edx + movl 8(%ecx) ,%ecx + movl %edx, 4(%eax) + movl %ecx, 8(%eax) + movl (28), %edx + movl (32), %ecx + movl %edx, 12(%eax) + movl %ecx, 16(%eax) + movl (28), %edx + movl (32), %ecx + movl %edx, 20(%eax) + movl %ecx, 24(%eax) + movl (36), %edx + movl %edx, 28(%eax) + addl $32, %eax + movl %eax, (0) + movl 4, %eax + dec %eax + movl %eax, (4) + je .5 + ret +.5: jmp *8 + +GLOBL ( _x86_Vertex3fv_8_end ) + +/* + Vertex 3fv generic vertex size +*/ +GLOBL ( _x86_Vertex3fv ) + movl 4(%esp), %edx + push %edi + push %esi + movl (0x1010101), %edi + movl (%edx), %eax + movl 4(%edx), %ecx + movl 8(%edx), %esi + movl %eax, (%edi) + movl %ecx, 4(%edi) + movl %esi, 8(%edi) + addl $12, %edi + movl $6, %ecx + movl $0x58, %esi + repz + movsl %ds:(%esi), %es:(%edi) + movl %edi, (0x1010101) + movl (0x2020202), %eax + pop %esi + pop %edi + dec %eax + movl %eax, (0x2020202) + je .6 + ret +.6: jmp *0 +GLOBL ( _x86_Vertex3fv_end ) + +/* + Normal 3f +*/ +GLOBL ( _x86_Normal3f ) + movl $0x12345678, %edx + movl 4(%esp), %eax + movl %eax, (%edx) + movl 8(%esp), %eax + movl %eax, 4(%edx) + movl 12(%esp), %eax + movl %eax, 8(%edx) + ret +GLOBL ( _x86_Normal3f_end ) + +/* + Color 4ubv_ub +*/ +GLOBL ( _x86_Color4ubv_ub ) + movl 4(%esp), %eax + movl $0x12345678, %edx + movl (%eax), %eax + movl %eax, (%edx) + ret +GLOBL ( _x86_Color4ubv_ub_end ) + +/* + Color 4ubv 4f +*/ +GLOBL ( _x86_Color4ubv_4f ) + push %ebx + movl $0, %edx + xor %eax, %eax + xor %ecx, %ecx + movl 8(%esp), %ebx + movl (%ebx), %ebx + mov %bl, %al + mov %bh, %cl + movl (%edx,%eax,4),%eax + movl (%edx,%ecx,4),%ecx + movl %eax, (0xdeadbeaf) + movl %ecx, (0xdeadbeaf) + xor %eax, %eax + xor %ecx, %ecx + shr $16, %ebx + mov %bl, %al + mov %bh, %cl + movl (%edx,%eax,4), %eax + movl (%edx,%ecx,4), %ecx + movl %eax, (0xdeadbeaf) + movl %ecx, (0xdeadbeaf) + pop %ebx + ret +GLOBL ( _x86_Color4ubv_4f_end ) + +/* + + Color4ub_ub +*/ +GLOBL( _x86_Color4ub_ub ) + push %ebx + movl 8(%esp), %eax + movl 12(%esp), %edx + movl 16(%esp), %ecx + movl 20(%esp), %ebx + mov %al, (0) + mov %dl, (0) + mov %cl, (0) + mov %bl, (0) + pop %ebx + ret +GLOBL( _x86_Color4ub_ub_end ) + +/* + Color3fv_3f +*/ +GLOBL( _x86_Color3fv_3f ) + movl 4(%esp), %eax + movl $0, %edx + movl (%eax), %ecx + movl %ecx, (%edx) + movl 4(%eax), %ecx + movl %ecx, 4(%edx) + movl 8(%eax), %ecx + movl %ecx, 8(%edx) + ret +GLOBL( _x86_Color3fv_3f_end ) + +/* + Color3f_3f +*/ +GLOBL( _x86_Color3f_3f ) + movl $0x12345678, %edx + movl 4(%esp), %eax + movl %eax, (%edx) + movl 8(%esp,1), %eax + movl %eax, 4(%edx) + movl 12(%esp), %eax + movl %eax, 8(%edx) + ret +GLOBL( _x86_Color3f_3f_end ) + +/* + TexCoord2fv +*/ + +GLOBL( _x86_TexCoord2fv ) + movl 4(%esp), %eax + movl $0x12345678, %edx + movl (%eax), %ecx + movl 4(%eax), %eax + movl %ecx, (%edx) + movl %eax, 4(%edx) + ret + +GLOBL( _x86_TexCoord2fv_end ) +/* + TexCoord2f +*/ +GLOBL( _x86_TexCoord2f ) + movl $0x12345678, %edx + movl 4(%esp), %eax + movl 8(%esp), %ecx + movl %eax, (%edx) + movl %ecx, 4(%edx) + ret +GLOBL( _x86_TexCoord2f_end ) + +/* + MultiTexCoord2fvARB st0/st1 +*/ +GLOBL( _x86_MultiTexCoord2fvARB ) + + movl 4(%esp), %eax + movl 8(%esp), %ecx + sub $0x84c0, %eax + and $1, %eax + movl (%ecx), %edx + shl $3, %eax + movl 4(%ecx), %ecx + movl %edx, 0xdeadbeef(%eax) + movl %ecx, 0xdeadbeef(%eax) + ret +GLOBL( _x86_MultiTexCoord2fvARB_end ) +/* + MultiTexCoord2fvARB +*/ + +GLOBL( _x86_MultiTexCoord2fvARB_2 ) + movl 4(%esp,1), %eax + movl 8(%esp,1), %ecx + sub $0x84c0, %eax + and $0x1, %eax + movl 0(,%eax,4), %edx + movl (%ecx), %eax + movl %eax, (%edx) + movl 4(%ecx), %eax + movl %eax, 4(%edx) + ret + +GLOBL( _x86_MultiTexCoord2fvARB_2_end ) + +/* + MultiTexCoord2fARB st0/st1 +*/ +GLOBL( _x86_MultiTexCoord2fARB ) + movl 4(%esp), %eax + movl 8(%esp), %edx + sub $0x84c0, %eax + movl 12(%esp), %ecx + and $1, %eax + shl $3, %eax + movl %edx, 0xdeadbeef(%eax) + movl %ecx, 0xdeadbeef(%eax) + ret +GLOBL( _x86_MultiTexCoord2fARB_end ) + +/* + MultiTexCoord2fARB +*/ +GLOBL( _x86_MultiTexCoord2fARB_2 ) + movl 4(%esp), %eax + movl 8(%esp), %edx + sub $0x84c0, %eax + movl 12(%esp,1), %ecx + and $1,%eax + movl 0(,%eax,4), %eax + movl %edx, (%eax) + movl %ecx, 4(%eax) + ret +GLOBL( _x86_MultiTexCoord2fARB_2_end ) |