| @@ -0,0 +1,134 @@ | |||
| # $Id: Makefile,v 1.1.2.1 2003/03/10 11:23:04 keithw Exp $ | |||
| # Mesa 3-D graphics library | |||
| # Version: 5.0 | |||
| # Copyright (C) 1995-2002 Brian Paul | |||
| MESA = ../../.. | |||
| default: r200_dri.so | |||
| include $(MESA)/Makefile.include | |||
| SHARED_INCLUDES= -I$(MESABUILDDIR) -I$(MESA)/include -I. -I../common -Iserver | |||
| MINIGLX_INCLUDES = -I$(MESABUILDDIR)/miniglx | |||
| DRI_INCLUDES = -I$(MESABUILDDIR)/dri | |||
| ifeq ($(FULL_DRIVER),true) | |||
| DEFINES = \ | |||
| -DGLX_DIRECT_RENDERING \ | |||
| -Dlinux -D__i386__ -D_POSIX_C_SOURCE=199309L -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE -D_GNU_SOURCE -DFUNCPROTO=15 -DNARROWPROTO -DXTHREADS -D_REENTRANT -DXUSE_MTSAFE_API -DMALLOC_0_RETURNS_NULL -DGLXEXT -DXF86DRI -DGLX_DIRECT_RENDERING -DGLX_USE_DLOPEN -DGLX_USE_MESA -DX_BYTE_ORDER=X_LITTLE_ENDIAN \ | |||
| -D_HAVE_SWRAST=1 \ | |||
| -D_HAVE_SWTNL=1 \ | |||
| -D_HAVE_SANITY=1 \ | |||
| -D_HAVE_CODEGEN=1 \ | |||
| -D_HAVE_LIGHTING=1 \ | |||
| -D_HAVE_TEXGEN=1 \ | |||
| -D_HAVE_USERCLIP=1 \ | |||
| -D_HAVE_FULL_GL=1 | |||
| else | |||
| DEFINES = \ | |||
| -D_HAVE_SWRAST=0 \ | |||
| -D_HAVE_SWTNL=0 \ | |||
| -D_HAVE_SANITY=0 \ | |||
| -D_HAVE_CODEGEN=0 \ | |||
| -D_HAVE_LIGHTING=0 \ | |||
| -D_HAVE_TEXGEN=0 \ | |||
| -D_HAVE_USERCLIP=0 \ | |||
| -D_HAVE_FULL_GL=0 | |||
| endif | |||
| # The .a files for each mesa module required by this driver: | |||
| # | |||
| FULL_MESA = $(MESABUILDDIR)/swrast_setup/swrast_setup.a \ | |||
| $(MESABUILDDIR)/tnl/tnl.a \ | |||
| $(MESABUILDDIR)/math/math.a \ | |||
| $(MESABUILDDIR)/array_cache/array_cache.a \ | |||
| $(MESABUILDDIR)/swrast/swrast.a \ | |||
| $(MESABUILDDIR)/mesa.a \ | |||
| $(MESABUILDDIR)/math/math.a #kludge | |||
| SUBSET_MESA = $(MESABUILDDIR)/mesa.a \ | |||
| $(MESABUILDDIR)/math/m_matrix.o | |||
| MINIGLX_SOURCES = server/radeon_dri.c | |||
| DRIVER_SOURCES = r200_context.c \ | |||
| r200_ioctl.c \ | |||
| r200_lock.c \ | |||
| r200_screen.c \ | |||
| r200_state.c \ | |||
| r200_state_init.c \ | |||
| ../common/mm.c | |||
| SUBSET_DRIVER_SOURCES = \ | |||
| r200_subset_bitmap.c \ | |||
| r200_subset_readpix.c \ | |||
| r200_subset_select.c \ | |||
| r200_subset_tex.c \ | |||
| r200_subset_vtx.c | |||
| FULL_DRIVER_SOURCES = \ | |||
| r200_cmdbuf.c \ | |||
| r200_pixel.c \ | |||
| r200_tex.c \ | |||
| r200_texmem.c \ | |||
| r200_texstate.c \ | |||
| r200_tcl.c \ | |||
| r200_swtcl.c \ | |||
| r200_span.c \ | |||
| r200_maos.c \ | |||
| r200_sanity.c \ | |||
| r200_vtxfmt.c \ | |||
| r200_vtxfmt_c.c \ | |||
| r200_vtxfmt_sse.c \ | |||
| r200_vtxfmt_x86.c | |||
| INCLUDES = $(MINIGLX_INCLUDES) \ | |||
| $(SHARED_INCLUDES) | |||
| ifeq ($(FULL_DRIVER),true) | |||
| C_SOURCES = $(DRIVER_SOURCES) \ | |||
| $(FULL_DRIVER_SOURCES) \ | |||
| $(MINIGLX_SOURCES) | |||
| MESA_MODULES = $(FULL_MESA) | |||
| else | |||
| C_SOURCES = $(DRIVER_SOURCES) \ | |||
| $(SUBSET_DRIVER_SOURCES) \ | |||
| $(MINIGLX_SOURCES) | |||
| MESA_MODULES = $(SUBSET_MESA) | |||
| endif | |||
| ifeq ($(WINDOW_SYSTEM),dri) | |||
| WINOBJ=$(MESABUILDDIR)/dri/dri.a | |||
| WINLIB= | |||
| else | |||
| WINOBJ= | |||
| WINLIB=-L$(MESA)/src/miniglx | |||
| endif | |||
| ASM_SOURCES = | |||
| OBJECTS = $(C_SOURCES:.c=.o) \ | |||
| $(ASM_SOURCES:.S=.o) | |||
| ##### TARGETS ##### | |||
| # Build the subset or full driver? | |||
| # | |||
| r200_dri.so: $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile | |||
| rm -f $@ && gcc -o $@ -shared $(OBJECTS) $(MESA_MODULES) $(WINOBJ) $(WINLIB) -lGL -lc -lm -Wl,-rpath,../../../lib | |||
| rm -f $(MESA)/lib/r200_dri.so && \ | |||
| install r200_dri.so $(MESA)/lib/r200_dri.so | |||
| ##### DEPENDENCIES ##### | |||
| -include $(C_SOURCES:.c=.d) | |||
| @@ -0,0 +1,344 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #include "glheader.h" | |||
| #include "imports.h" | |||
| #include "macros.h" | |||
| #include "context.h" | |||
| #include "swrast/swrast.h" | |||
| #include "simple_list.h" | |||
| #include "r200_context.h" | |||
| #include "r200_state.h" | |||
| #include "r200_ioctl.h" | |||
| #include "r200_tcl.h" | |||
| #include "r200_sanity.h" | |||
| #include "radeon_reg.h" | |||
| static void print_state_atom( struct r200_state_atom *state ) | |||
| { | |||
| int i; | |||
| fprintf(stderr, "emit %s/%d\n", state->name, state->cmd_size); | |||
| if (0 & R200_DEBUG & DEBUG_VERBOSE) | |||
| for (i = 0 ; i < state->cmd_size ; i++) | |||
| fprintf(stderr, "\t%s[%d]: %x\n", state->name, i, state->cmd[i]); | |||
| } | |||
| static void r200_emit_state_list( r200ContextPtr rmesa, | |||
| struct r200_state_atom *list ) | |||
| { | |||
| struct r200_state_atom *state, *tmp; | |||
| char *dest; | |||
| foreach_s( state, tmp, list ) { | |||
| if (state->check( rmesa->glCtx, state->idx )) { | |||
| dest = r200AllocCmdBuf( rmesa, state->cmd_size * 4, __FUNCTION__); | |||
| memcpy( dest, state->cmd, state->cmd_size * 4); | |||
| move_to_head( &(rmesa->hw.clean), state ); | |||
| if (R200_DEBUG & DEBUG_STATE) | |||
| print_state_atom( state ); | |||
| } | |||
| else if (R200_DEBUG & DEBUG_STATE) | |||
| fprintf(stderr, "skip state %s\n", state->name); | |||
| } | |||
| } | |||
| void r200EmitState( r200ContextPtr rmesa ) | |||
| { | |||
| struct r200_state_atom *state, *tmp; | |||
| if (R200_DEBUG & (DEBUG_STATE|DEBUG_PRIMS)) | |||
| fprintf(stderr, "%s\n", __FUNCTION__); | |||
| /* Somewhat overkill: | |||
| */ | |||
| if ( rmesa->lost_context) { | |||
| if (R200_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 { | |||
| move_to_tail( &rmesa->hw.dirty, &rmesa->hw.mtl[0] ); | |||
| /* odd bug? -- isosurf, cycle between reflect & lit */ | |||
| } | |||
| r200_emit_state_list( rmesa, &rmesa->hw.dirty ); | |||
| } | |||
| /* Fire a section of the retained (indexed_verts) buffer as a regular | |||
| * primtive. | |||
| */ | |||
| extern void r200EmitVbufPrim( r200ContextPtr rmesa, | |||
| GLuint primitive, | |||
| GLuint vertex_nr ) | |||
| { | |||
| drmRadeonCmdHeader *cmd; | |||
| assert(!(primitive & R200_VF_PRIM_WALK_IND)); | |||
| r200EmitState( rmesa ); | |||
| if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_PRIMS)) | |||
| fprintf(stderr, "%s cmd_used/4: %d prim %x nr %d\n", __FUNCTION__, | |||
| rmesa->store.cmd_used/4, primitive, vertex_nr); | |||
| cmd = (drmRadeonCmdHeader *)r200AllocCmdBuf( rmesa, 3 * sizeof(*cmd), | |||
| __FUNCTION__ ); | |||
| cmd[0].i = 0; | |||
| cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP; | |||
| cmd[1].i = R200_CP_CMD_3D_DRAW_VBUF_2; | |||
| cmd[2].i = (primitive | | |||
| R200_VF_PRIM_WALK_LIST | | |||
| R200_VF_COLOR_ORDER_RGBA | | |||
| (vertex_nr << R200_VF_VERTEX_NUMBER_SHIFT)); | |||
| if (R200_DEBUG & DEBUG_SYNC) { | |||
| fprintf(stderr, "\nSyncing\n\n"); | |||
| R200_FIREVERTICES( rmesa ); | |||
| r200Finish( rmesa->glCtx ); | |||
| } | |||
| } | |||
| void r200FlushElts( r200ContextPtr rmesa ) | |||
| { | |||
| int *cmd = (int *)(rmesa->store.cmd_buf + rmesa->store.elts_start); | |||
| int dwords; | |||
| int nr = (rmesa->store.cmd_used - (rmesa->store.elts_start + 12)) / 2; | |||
| if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_PRIMS)) | |||
| fprintf(stderr, "%s\n", __FUNCTION__); | |||
| assert( rmesa->dma.flush == r200FlushElts ); | |||
| rmesa->dma.flush = 0; | |||
| /* 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; | |||
| cmd[1] |= (dwords - 3) << 16; | |||
| cmd[2] |= nr << R200_VF_VERTEX_NUMBER_SHIFT; | |||
| if (R200_DEBUG & DEBUG_SYNC) { | |||
| fprintf(stderr, "\nSyncing in %s\n\n", __FUNCTION__); | |||
| R200_FIREVERTICES( rmesa ); | |||
| r200Finish( rmesa->glCtx ); | |||
| } | |||
| } | |||
| GLushort *r200AllocEltsOpenEnded( r200ContextPtr rmesa, | |||
| GLuint primitive, | |||
| GLuint min_nr ) | |||
| { | |||
| drmRadeonCmdHeader *cmd; | |||
| GLushort *retval; | |||
| if (R200_DEBUG & DEBUG_IOCTL) | |||
| fprintf(stderr, "%s %d prim %x\n", __FUNCTION__, min_nr, primitive); | |||
| assert((primitive & R200_VF_PRIM_WALK_IND)); | |||
| r200EmitState( rmesa ); | |||
| cmd = (drmRadeonCmdHeader *)r200AllocCmdBuf( rmesa, | |||
| 12 + min_nr*2, | |||
| __FUNCTION__ ); | |||
| cmd[0].i = 0; | |||
| cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP; | |||
| cmd[1].i = R200_CP_CMD_3D_DRAW_INDX_2; | |||
| cmd[2].i = (primitive | | |||
| R200_VF_PRIM_WALK_IND | | |||
| R200_VF_COLOR_ORDER_RGBA); | |||
| retval = (GLushort *)(cmd+3); | |||
| if (R200_DEBUG & DEBUG_PRIMS) | |||
| fprintf(stderr, "%s: header 0x%x prim %x \n", | |||
| __FUNCTION__, | |||
| cmd[1].i, primitive); | |||
| assert(!rmesa->dma.flush); | |||
| rmesa->dma.flush = r200FlushElts; | |||
| rmesa->store.elts_start = ((char *)cmd) - rmesa->store.cmd_buf; | |||
| return retval; | |||
| } | |||
| void r200EmitVertexAOS( r200ContextPtr rmesa, | |||
| GLuint vertex_size, | |||
| GLuint offset ) | |||
| { | |||
| drmRadeonCmdHeader *cmd; | |||
| if (R200_DEBUG & (DEBUG_PRIMS|DEBUG_IOCTL)) | |||
| fprintf(stderr, "%s: vertex_size 0x%x offset 0x%x \n", | |||
| __FUNCTION__, vertex_size, offset); | |||
| cmd = (drmRadeonCmdHeader *)r200AllocCmdBuf( rmesa, 5 * sizeof(int), | |||
| __FUNCTION__ ); | |||
| cmd[0].header.cmd_type = RADEON_CMD_PACKET3; | |||
| cmd[1].i = R200_CP_CMD_3D_LOAD_VBPNTR | (2 << 16); | |||
| cmd[2].i = 1; | |||
| cmd[3].i = vertex_size | (vertex_size << 8); | |||
| cmd[4].i = offset; | |||
| } | |||
| void r200EmitAOS( r200ContextPtr rmesa, | |||
| struct r200_dma_region **component, | |||
| GLuint nr, | |||
| GLuint offset ) | |||
| { | |||
| drmRadeonCmdHeader *cmd; | |||
| int sz = 3 + ((nr/2)*3) + ((nr&1)*2); | |||
| int i; | |||
| int *tmp; | |||
| if (R200_DEBUG & DEBUG_IOCTL) | |||
| fprintf(stderr, "%s nr arrays: %d\n", __FUNCTION__, nr); | |||
| cmd = (drmRadeonCmdHeader *)r200AllocCmdBuf( rmesa, sz * sizeof(int), | |||
| __FUNCTION__ ); | |||
| cmd[0].i = 0; | |||
| cmd[0].header.cmd_type = RADEON_CMD_PACKET3; | |||
| cmd[1].i = R200_CP_CMD_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); | |||
| } | |||
| } | |||
| if (R200_DEBUG & DEBUG_VERTS) { | |||
| fprintf(stderr, "%s:\n", __FUNCTION__); | |||
| for (i = 0 ; i < sz ; i++) | |||
| fprintf(stderr, " %d: %x\n", i, tmp[i]); | |||
| } | |||
| } | |||
| void r200EmitBlit( r200ContextPtr rmesa, | |||
| GLuint color_fmt, | |||
| GLuint src_pitch, | |||
| GLuint src_offset, | |||
| GLuint dst_pitch, | |||
| GLuint dst_offset, | |||
| GLint srcx, GLint srcy, | |||
| GLint dstx, GLint dsty, | |||
| GLuint w, GLuint h ) | |||
| { | |||
| drmRadeonCmdHeader *cmd; | |||
| if (R200_DEBUG & DEBUG_IOCTL) | |||
| fprintf(stderr, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n", | |||
| __FUNCTION__, | |||
| src_pitch, src_offset, srcx, srcy, | |||
| dst_pitch, dst_offset, dstx, dsty, | |||
| w, h); | |||
| assert( (src_pitch & 63) == 0 ); | |||
| assert( (dst_pitch & 63) == 0 ); | |||
| assert( (src_offset & 1023) == 0 ); | |||
| assert( (dst_offset & 1023) == 0 ); | |||
| assert( w < (1<<16) ); | |||
| assert( h < (1<<16) ); | |||
| cmd = (drmRadeonCmdHeader *)r200AllocCmdBuf( rmesa, 8 * sizeof(int), | |||
| __FUNCTION__ ); | |||
| cmd[0].header.cmd_type = RADEON_CMD_PACKET3; | |||
| cmd[1].i = R200_CP_CMD_BITBLT_MULTI | (5 << 16); | |||
| cmd[2].i = (RADEON_GMC_SRC_PITCH_OFFSET_CNTL | | |||
| RADEON_GMC_DST_PITCH_OFFSET_CNTL | | |||
| RADEON_GMC_BRUSH_NONE | | |||
| (color_fmt << 8) | | |||
| RADEON_GMC_SRC_DATATYPE_COLOR | | |||
| RADEON_ROP3_S | | |||
| RADEON_DP_SRC_SOURCE_MEMORY | | |||
| RADEON_GMC_CLR_CMP_CNTL_DIS | | |||
| RADEON_GMC_WR_MSK_DIS ); | |||
| cmd[3].i = ((src_pitch/64)<<22) | (src_offset >> 10); | |||
| cmd[4].i = ((dst_pitch/64)<<22) | (dst_offset >> 10); | |||
| cmd[5].i = (srcx << 16) | srcy; | |||
| cmd[6].i = (dstx << 16) | dsty; /* dst */ | |||
| cmd[7].i = (w << 16) | h; | |||
| } | |||
| void r200EmitWait( r200ContextPtr rmesa, GLuint flags ) | |||
| { | |||
| if (rmesa->dri.drmMinor >= 6) { | |||
| drmRadeonCmdHeader *cmd; | |||
| assert( !(flags & ~(RADEON_WAIT_2D|RADEON_WAIT_3D)) ); | |||
| cmd = (drmRadeonCmdHeader *)r200AllocCmdBuf( rmesa, 1 * sizeof(int), | |||
| __FUNCTION__ ); | |||
| cmd[0].i = 0; | |||
| cmd[0].wait.cmd_type = RADEON_CMD_WAIT; | |||
| cmd[0].wait.flags = flags; | |||
| } | |||
| } | |||
| @@ -0,0 +1,673 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #include "glheader.h" | |||
| #include "api_arrayelt.h" | |||
| #include "context.h" | |||
| #include "simple_list.h" | |||
| #include "imports.h" | |||
| #include "matrix.h" | |||
| #include "state.h" | |||
| #include "extensions.h" | |||
| #include "state.h" | |||
| #include "swrast/swrast.h" | |||
| #include "swrast_setup/swrast_setup.h" | |||
| #include "array_cache/acache.h" | |||
| #include "tnl/tnl.h" | |||
| #include "tnl/t_pipeline.h" | |||
| #include "r200_context.h" | |||
| #include "r200_ioctl.h" | |||
| #include "r200_state.h" | |||
| #include "r200_span.h" | |||
| #include "r200_pixel.h" | |||
| #include "r200_tex.h" | |||
| #include "r200_swtcl.h" | |||
| #include "r200_tcl.h" | |||
| #include "r200_vtxfmt.h" | |||
| #include "r200_maos.h" | |||
| #if defined(USE_X86_ASM) | |||
| #include "X86/common_x86_asm.h" | |||
| #endif | |||
| #define R200_DATE "20021125" | |||
| #ifndef R200_DEBUG | |||
| int R200_DEBUG = (0); | |||
| #endif | |||
| /* Return the width and height of the given buffer. | |||
| */ | |||
| static void r200GetBufferSize( GLframebuffer *buffer, | |||
| GLuint *width, GLuint *height ) | |||
| { | |||
| GET_CURRENT_CONTEXT(ctx); | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| LOCK_HARDWARE( rmesa ); | |||
| *width = rmesa->dri.drawable->w; | |||
| *height = rmesa->dri.drawable->h; | |||
| UNLOCK_HARDWARE( rmesa ); | |||
| } | |||
| /* Return various strings for glGetString(). | |||
| */ | |||
| static const GLubyte *r200GetString( GLcontext *ctx, GLenum name ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| static char buffer[128]; | |||
| switch ( name ) { | |||
| case GL_VENDOR: | |||
| return (GLubyte *)"Tungsten Graphics, Inc."; | |||
| case GL_RENDERER: | |||
| sprintf( buffer, "Mesa DRI R200 " R200_DATE); | |||
| /* Append any chipset-specific information. None yet. | |||
| */ | |||
| /* Append any AGP-specific information. | |||
| */ | |||
| switch ( rmesa->r200Screen->AGPMode ) { | |||
| case 1: | |||
| strncat( buffer, " AGP 1x", 7 ); | |||
| break; | |||
| case 2: | |||
| strncat( buffer, " AGP 2x", 7 ); | |||
| break; | |||
| case 4: | |||
| strncat( buffer, " AGP 4x", 7 ); | |||
| break; | |||
| } | |||
| /* Append any CPU-specific information. | |||
| */ | |||
| #ifdef USE_X86_ASM | |||
| if ( _mesa_x86_cpu_features ) { | |||
| strncat( buffer, " x86", 4 ); | |||
| } | |||
| #ifdef USE_MMX_ASM | |||
| if ( cpu_has_mmx ) { | |||
| strncat( buffer, "/MMX", 4 ); | |||
| } | |||
| #endif | |||
| #ifdef USE_3DNOW_ASM | |||
| if ( cpu_has_3dnow ) { | |||
| strncat( buffer, "/3DNow!", 7 ); | |||
| } | |||
| #endif | |||
| #ifdef USE_SSE_ASM | |||
| if ( cpu_has_xmm ) { | |||
| strncat( buffer, "/SSE", 4 ); | |||
| } | |||
| #endif | |||
| #endif | |||
| if ( !(rmesa->TclFallback & R200_TCL_FALLBACK_TCL_DISABLE) ) { | |||
| strncat( buffer, " TCL", 4 ); | |||
| } | |||
| else { | |||
| strncat( buffer, " NO-TCL", 7 ); | |||
| } | |||
| return (GLubyte *)buffer; | |||
| default: | |||
| return NULL; | |||
| } | |||
| } | |||
| /* Initialize the extensions supported by this driver. | |||
| */ | |||
| static void r200InitExtensions( GLcontext *ctx, r200ScreenPtr r200Screen ) | |||
| { | |||
| _mesa_enable_imaging_extensions( ctx ); | |||
| _mesa_enable_extension( ctx, "GL_ARB_multitexture" ); | |||
| if (r200Screen->drmSupportsCubeMaps) | |||
| _mesa_enable_extension( ctx, "GL_ARB_texture_cube_map" ); | |||
| _mesa_enable_extension( ctx, "GL_ARB_texture_env_add" ); | |||
| _mesa_enable_extension( ctx, "GL_ARB_texture_env_combine" ); | |||
| _mesa_enable_extension( ctx, "GL_ARB_texture_env_dot3" ); | |||
| _mesa_enable_extension( ctx, "GL_ARB_texture_mirrored_repeat" ); | |||
| _mesa_enable_extension( ctx, "GL_ARB_texture_border_clamp" ); | |||
| _mesa_enable_extension( ctx, "GL_ATI_texture_env_combine3" ); | |||
| _mesa_enable_extension( ctx, "GL_ATI_texture_mirror_once" ); | |||
| _mesa_enable_extension( ctx, "GL_EXT_blend_logic_op" ); | |||
| /*_mesa_enable_extension( ctx, "GL_EXT_fog_coord" );*/ | |||
| _mesa_enable_extension( ctx, "GL_EXT_stencil_wrap" ); | |||
| _mesa_enable_extension( ctx, "GL_EXT_texture_edge_clamp" ); | |||
| _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" ); | |||
| _mesa_enable_extension( ctx, "GL_EXT_secondary_color" ); | |||
| _mesa_enable_extension( ctx, "GL_EXT_blend_subtract" ); | |||
| _mesa_enable_extension( ctx, "GL_EXT_blend_minmax" ); | |||
| /* _mesa_enable_extension( ctx, "GL_EXT_fog_coord" ); */ | |||
| _mesa_enable_extension( ctx, "GL_MESA_pack_invert" ); | |||
| _mesa_enable_extension( ctx, "GL_MESA_ycbcr_texture" ); | |||
| _mesa_enable_extension( ctx, "GL_NV_texture_rectangle" ); | |||
| } | |||
| extern const struct gl_pipeline_stage _r200_render_stage; | |||
| extern const struct gl_pipeline_stage _r200_tcl_stage; | |||
| static const struct gl_pipeline_stage *r200_pipeline[] = { | |||
| /* Try and go straight to t&l | |||
| */ | |||
| &_r200_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, | |||
| /* 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. | |||
| */ | |||
| &_r200_render_stage, | |||
| &_tnl_render_stage, /* FALLBACK: */ | |||
| 0, | |||
| }; | |||
| /* Initialize the driver's misc functions. | |||
| */ | |||
| static void r200InitDriverFuncs( GLcontext *ctx ) | |||
| { | |||
| ctx->Driver.GetBufferSize = r200GetBufferSize; | |||
| ctx->Driver.ResizeBuffers = _swrast_alloc_buffers; | |||
| ctx->Driver.GetString = r200GetString; | |||
| ctx->Driver.Error = NULL; | |||
| ctx->Driver.DrawPixels = NULL; | |||
| ctx->Driver.Bitmap = NULL; | |||
| } | |||
| static void add_debug_flags( const char *debug ) | |||
| { | |||
| if (strstr(debug, "fall")) | |||
| R200_DEBUG |= DEBUG_FALLBACKS; | |||
| if (strstr(debug, "tex")) | |||
| R200_DEBUG |= DEBUG_TEXTURE; | |||
| if (strstr(debug, "ioctl")) | |||
| R200_DEBUG |= DEBUG_IOCTL; | |||
| if (strstr(debug, "prim")) | |||
| R200_DEBUG |= DEBUG_PRIMS; | |||
| if (strstr(debug, "vert")) | |||
| R200_DEBUG |= DEBUG_VERTS; | |||
| if (strstr(debug, "state")) | |||
| R200_DEBUG |= DEBUG_STATE; | |||
| if (strstr(debug, "code")) | |||
| R200_DEBUG |= DEBUG_CODEGEN; | |||
| if (strstr(debug, "vfmt") || strstr(debug, "vtxf")) | |||
| R200_DEBUG |= DEBUG_VFMT; | |||
| if (strstr(debug, "verb")) | |||
| R200_DEBUG |= DEBUG_VERBOSE; | |||
| if (strstr(debug, "dri")) | |||
| R200_DEBUG |= DEBUG_DRI; | |||
| if (strstr(debug, "dma")) | |||
| R200_DEBUG |= DEBUG_DMA; | |||
| if (strstr(debug, "san")) | |||
| R200_DEBUG |= DEBUG_SANITY; | |||
| if (strstr(debug, "sync")) | |||
| R200_DEBUG |= DEBUG_SYNC; | |||
| if (strstr(debug, "pix")) | |||
| R200_DEBUG |= DEBUG_PIXEL; | |||
| if (strstr(debug, "mem")) | |||
| R200_DEBUG |= DEBUG_MEMORY; | |||
| } | |||
| /* Create the device specific context. | |||
| */ | |||
| GLboolean r200CreateContext( const __GLcontextModes *glVisual, | |||
| __DRIcontextPrivate *driContextPriv, | |||
| void *sharedContextPrivate) | |||
| { | |||
| __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; | |||
| r200ScreenPtr r200Screen = (r200ScreenPtr)(sPriv->private); | |||
| r200ContextPtr rmesa; | |||
| GLcontext *ctx, *shareCtx; | |||
| int i, memPerUnit; | |||
| assert(glVisual); | |||
| assert(driContextPriv); | |||
| assert(r200Screen); | |||
| /* Allocate the R200 context */ | |||
| rmesa = (r200ContextPtr) CALLOC( sizeof(*rmesa) ); | |||
| if ( !rmesa ) | |||
| return GL_FALSE; | |||
| /* Allocate the Mesa context */ | |||
| if (sharedContextPrivate) | |||
| shareCtx = ((r200ContextPtr) sharedContextPrivate)->glCtx; | |||
| else | |||
| shareCtx = NULL; | |||
| rmesa->glCtx = _mesa_create_context(glVisual, shareCtx, (void *) rmesa, GL_TRUE); | |||
| if (!rmesa->glCtx) { | |||
| FREE(rmesa); | |||
| return GL_FALSE; | |||
| } | |||
| driContextPriv->driverPrivate = rmesa; | |||
| /* Init r200 context data */ | |||
| rmesa->dri.context = driContextPriv; | |||
| rmesa->dri.screen = sPriv; | |||
| rmesa->dri.drawable = NULL; /* Set by XMesaMakeCurrent */ | |||
| rmesa->dri.hwContext = driContextPriv->hHWContext; | |||
| rmesa->dri.hwLock = &sPriv->pSAREA->lock; | |||
| rmesa->dri.fd = sPriv->fd; | |||
| rmesa->dri.drmMinor = sPriv->drmMinor; | |||
| rmesa->r200Screen = r200Screen; | |||
| rmesa->sarea = (RADEONSAREAPrivPtr)((GLubyte *)sPriv->pSAREA + | |||
| r200Screen->sarea_priv_offset); | |||
| rmesa->dma.buf0_address = rmesa->r200Screen->buffers->list[0].address; | |||
| for ( i = 0 ; i < r200Screen->numTexHeaps ; i++ ) { | |||
| make_empty_list( &rmesa->texture.objects[i] ); | |||
| rmesa->texture.heap[i] = mmInit( 0, r200Screen->texSize[i] ); | |||
| rmesa->texture.age[i] = -1; | |||
| } | |||
| rmesa->texture.numHeaps = r200Screen->numTexHeaps; | |||
| make_empty_list( &rmesa->texture.swapped ); | |||
| 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 | |||
| * and have them both in on-card memory at once. | |||
| * Test for 2 textures * 4 bytes/texel * size * size. | |||
| */ | |||
| ctx = rmesa->glCtx; | |||
| memPerUnit = r200Screen->texSize[RADEON_CARD_HEAP] / 2; | |||
| /* XXX the following code could go into a utility file */ | |||
| if (memPerUnit >= 4 * 2048 * 2048) { | |||
| ctx->Const.MaxTextureLevels = 12; /* 2048x2048 */ | |||
| } | |||
| else if (memPerUnit >= 4 * 1024 * 1024) { | |||
| ctx->Const.MaxTextureLevels = 11; /* 1024x1024 */ | |||
| } | |||
| else if (memPerUnit >= 4 * 512 * 512) { | |||
| ctx->Const.MaxTextureLevels = 10; /* 512x512 */ | |||
| } | |||
| else { | |||
| ctx->Const.MaxTextureLevels = 9; /* 256x256 */ | |||
| } | |||
| #if ENABLE_HW_3D_TEXTURE | |||
| if (memPerUnit >= 4 * 256 * 256 * 256) { | |||
| ctx->Const.Max3DTextureLevels = 9; /* 256x256x256 */ | |||
| } | |||
| else if (memPerUnit >= 4 * 64 * 64 * 64) { | |||
| ctx->Const.Max3DTextureLevels = 8; /* 128x128x128 */ | |||
| } | |||
| else if (memPerUnit >= 4 * 32 * 32 * 32) { | |||
| ctx->Const.Max3DTextureLevels = 7; /* 64x64x64 */ | |||
| } | |||
| else { /* 256KBytes */ | |||
| ctx->Const.Max3DTextureLevels = 6; /* 32x32x32 */ | |||
| } | |||
| #endif | |||
| if (memPerUnit >= 4 * 6 * 2048 * 2048) { | |||
| ctx->Const.MaxCubeTextureLevels = 12; /* 2048x2048 */ | |||
| } | |||
| if (memPerUnit >= 4 * 6 * 1024 * 1024) { | |||
| ctx->Const.MaxCubeTextureLevels = 11; /* 1024x1024 */ | |||
| } | |||
| else if (memPerUnit >= 4 * 6 * 512 * 512) { | |||
| ctx->Const.MaxCubeTextureLevels = 10; /* 512x512 */ | |||
| } | |||
| else if (memPerUnit >= 4 * 6 * 256 * 256) { | |||
| ctx->Const.MaxCubeTextureLevels = 9; /* 256x256 */ | |||
| } | |||
| else { /* 393216 bytes */ | |||
| ctx->Const.MaxCubeTextureLevels = 8; /* 128x128 */ | |||
| } | |||
| ctx->Const.MaxTextureUnits = 2; | |||
| ctx->Const.MaxTextureMaxAnisotropy = 16.0; | |||
| /* No wide points. | |||
| */ | |||
| ctx->Const.MinPointSize = 1.0; | |||
| ctx->Const.MinPointSizeAA = 1.0; | |||
| ctx->Const.MaxPointSize = 1.0; | |||
| ctx->Const.MaxPointSizeAA = 1.0; | |||
| ctx->Const.MinLineWidth = 1.0; | |||
| ctx->Const.MinLineWidthAA = 1.0; | |||
| ctx->Const.MaxLineWidth = 10.0; | |||
| ctx->Const.MaxLineWidthAA = 10.0; | |||
| ctx->Const.LineWidthGranularity = 0.0625; | |||
| /* Initialize the software rasterizer and helper modules. | |||
| */ | |||
| _swrast_CreateContext( ctx ); | |||
| _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, r200_pipeline ); | |||
| ctx->Driver.FlushVertices = r200FlushVertices; | |||
| /* Try and keep materials and vertices separate: | |||
| */ | |||
| _tnl_isolate_materials( ctx, GL_TRUE ); | |||
| /* Configure swrast to match hardware characteristics: | |||
| */ | |||
| _swrast_allow_pixel_fog( ctx, GL_FALSE ); | |||
| _swrast_allow_vertex_fog( ctx, GL_TRUE ); | |||
| _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 ); | |||
| r200InitExtensions( ctx, r200Screen ); | |||
| r200InitDriverFuncs( ctx ); | |||
| r200InitIoctlFuncs( ctx ); | |||
| r200InitStateFuncs( ctx ); | |||
| r200InitSpanFuncs( ctx ); | |||
| r200InitPixelFuncs( ctx ); | |||
| r200InitTextureFuncs( ctx ); | |||
| r200InitState( rmesa ); | |||
| r200InitSwtcl( ctx ); | |||
| rmesa->iw.irq_seq = -1; | |||
| rmesa->irqsEmitted = 0; | |||
| rmesa->do_irqs = (rmesa->dri.drmMinor >= 6 && | |||
| !getenv("R200_NO_IRQS") && | |||
| rmesa->r200Screen->irq); | |||
| if (!rmesa->do_irqs) | |||
| fprintf(stderr, | |||
| "IRQ's not enabled, falling back to busy waits: %d %d %d\n", | |||
| rmesa->dri.drmMinor, | |||
| !!getenv("R200_NO_IRQS"), | |||
| rmesa->r200Screen->irq); | |||
| rmesa->do_usleeps = !getenv("R200_NO_USLEEPS"); | |||
| rmesa->prefer_agp_client_texturing = | |||
| (getenv("R200_AGP_CLIENT_TEXTURES") != 0); | |||
| #if DO_DEBUG | |||
| if (getenv("R200_DEBUG")) | |||
| add_debug_flags( getenv("R200_DEBUG") ); | |||
| if (getenv("RADEON_DEBUG")) | |||
| add_debug_flags( getenv("RADEON_DEBUG") ); | |||
| #endif | |||
| if (getenv("R200_NO_RAST")) { | |||
| fprintf(stderr, "disabling 3D acceleration\n"); | |||
| FALLBACK(rmesa, R200_FALLBACK_DISABLE, 1); | |||
| } | |||
| else if (getenv("R200_NO_TCL")) { | |||
| fprintf(stderr, "disabling TCL support\n"); | |||
| TCL_FALLBACK(rmesa->glCtx, R200_TCL_FALLBACK_TCL_DISABLE, 1); | |||
| } | |||
| else { | |||
| if (!getenv("R200_NO_VTXFMT")) { | |||
| r200VtxfmtInit( ctx ); | |||
| } | |||
| _tnl_need_dlist_norm_lengths( ctx, GL_FALSE ); | |||
| } | |||
| return GL_TRUE; | |||
| } | |||
| /* Destroy the device specific context. | |||
| */ | |||
| /* Destroy the Mesa and driver specific context data. | |||
| */ | |||
| void r200DestroyContext( __DRIcontextPrivate *driContextPriv ) | |||
| { | |||
| GET_CURRENT_CONTEXT(ctx); | |||
| r200ContextPtr rmesa = (r200ContextPtr) driContextPriv->driverPrivate; | |||
| r200ContextPtr current = ctx ? R200_CONTEXT(ctx) : NULL; | |||
| /* check if we're deleting the currently bound context */ | |||
| if (rmesa == current) { | |||
| R200_FIREVERTICES( rmesa ); | |||
| _mesa_make_current2(NULL, NULL, NULL); | |||
| } | |||
| /* Free r200 context resources */ | |||
| assert(rmesa); /* should never be null */ | |||
| if ( rmesa ) { | |||
| if (rmesa->glCtx->Shared->RefCount == 1) { | |||
| /* This share group is about to go away, free our private | |||
| * texture object data. | |||
| */ | |||
| r200TexObjPtr t, next_t; | |||
| int i; | |||
| for ( i = 0 ; i < rmesa->texture.numHeaps ; i++ ) { | |||
| foreach_s ( t, next_t, &rmesa->texture.objects[i] ) { | |||
| r200DestroyTexObj( rmesa, t ); | |||
| } | |||
| mmDestroy( rmesa->texture.heap[i] ); | |||
| rmesa->texture.heap[i] = NULL; | |||
| } | |||
| foreach_s ( t, next_t, &rmesa->texture.swapped ) { | |||
| r200DestroyTexObj( rmesa, t ); | |||
| } | |||
| } | |||
| _swsetup_DestroyContext( rmesa->glCtx ); | |||
| _tnl_DestroyContext( rmesa->glCtx ); | |||
| _ac_DestroyContext( rmesa->glCtx ); | |||
| _swrast_DestroyContext( rmesa->glCtx ); | |||
| r200DestroySwtcl( rmesa->glCtx ); | |||
| r200ReleaseArrays( rmesa->glCtx, ~0 ); | |||
| if (rmesa->dma.current.buf) { | |||
| r200ReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ ); | |||
| r200FlushCmdBuf( rmesa, __FUNCTION__ ); | |||
| } | |||
| if (!rmesa->TclFallback & R200_TCL_FALLBACK_TCL_DISABLE) | |||
| if (!getenv("R200_NO_VTXFMT")) | |||
| r200VtxfmtDestroy( 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 ); | |||
| } | |||
| } | |||
| void | |||
| r200SwapBuffers( __DRIdrawablePrivate *dPriv ) | |||
| { | |||
| if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { | |||
| r200ContextPtr rmesa; | |||
| GLcontext *ctx; | |||
| rmesa = (r200ContextPtr) dPriv->driContextPriv->driverPrivate; | |||
| ctx = rmesa->glCtx; | |||
| if (ctx->Visual.doubleBufferMode) { | |||
| _mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */ | |||
| if ( rmesa->doPageFlip ) { | |||
| r200PageFlip( dPriv ); | |||
| } | |||
| else { | |||
| r200CopyBuffer( dPriv ); | |||
| } | |||
| } | |||
| } | |||
| else { | |||
| /* XXX this shouldn't be an error but we can't handle it for now */ | |||
| _mesa_problem(NULL, "r200SwapBuffers: drawable has no context!\n"); | |||
| } | |||
| } | |||
| /* Force the context `c' to be the current context and associate with it | |||
| * buffer `b'. | |||
| */ | |||
| GLboolean | |||
| r200MakeCurrent( __DRIcontextPrivate *driContextPriv, | |||
| __DRIdrawablePrivate *driDrawPriv, | |||
| __DRIdrawablePrivate *driReadPriv ) | |||
| { | |||
| if ( driContextPriv ) { | |||
| r200ContextPtr newR200Ctx = | |||
| (r200ContextPtr) driContextPriv->driverPrivate; | |||
| if (R200_DEBUG & DEBUG_DRI) | |||
| fprintf(stderr, "%s ctx %p\n", __FUNCTION__, newR200Ctx->glCtx); | |||
| if ( newR200Ctx->dri.drawable != driDrawPriv ) { | |||
| newR200Ctx->dri.drawable = driDrawPriv; | |||
| r200UpdateWindow( newR200Ctx->glCtx ); | |||
| r200UpdateViewportOffset( newR200Ctx->glCtx ); | |||
| } | |||
| _mesa_make_current2( newR200Ctx->glCtx, | |||
| (GLframebuffer *) driDrawPriv->driverPrivate, | |||
| (GLframebuffer *) driReadPriv->driverPrivate ); | |||
| if ( !newR200Ctx->glCtx->Viewport.Width ) { | |||
| _mesa_set_viewport( newR200Ctx->glCtx, 0, 0, | |||
| driDrawPriv->w, driDrawPriv->h ); | |||
| } | |||
| if (newR200Ctx->vb.enabled) | |||
| r200VtxfmtMakeCurrent( newR200Ctx->glCtx ); | |||
| _mesa_update_state( newR200Ctx->glCtx ); | |||
| r200ValidateState( newR200Ctx->glCtx ); | |||
| } else { | |||
| if (R200_DEBUG & DEBUG_DRI) | |||
| fprintf(stderr, "%s ctx is null\n", __FUNCTION__); | |||
| _mesa_make_current( 0, 0 ); | |||
| } | |||
| if (R200_DEBUG & DEBUG_DRI) | |||
| fprintf(stderr, "End %s\n", __FUNCTION__); | |||
| return GL_TRUE; | |||
| } | |||
| /* Force the context `c' to be unbound from its buffer. | |||
| */ | |||
| GLboolean | |||
| r200UnbindContext( __DRIcontextPrivate *driContextPriv ) | |||
| { | |||
| r200ContextPtr rmesa = (r200ContextPtr) driContextPriv->driverPrivate; | |||
| if (R200_DEBUG & DEBUG_DRI) | |||
| fprintf(stderr, "%s ctx %p\n", __FUNCTION__, rmesa->glCtx); | |||
| r200VtxfmtUnbindContext( rmesa->glCtx ); | |||
| return GL_TRUE; | |||
| } | |||
| @@ -0,0 +1,944 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #ifndef __R200_CONTEXT_H__ | |||
| #define __R200_CONTEXT_H__ | |||
| #ifdef GLX_DIRECT_RENDERING | |||
| #include "dri_util.h" | |||
| #include "radeon_common.h" | |||
| #include "macros.h" | |||
| #include "mtypes.h" | |||
| #include "r200_reg.h" | |||
| #define ENABLE_HW_3D_TEXTURE 0 /* XXX this is temporary! */ | |||
| struct r200_context; | |||
| typedef struct r200_context r200ContextRec; | |||
| typedef struct r200_context *r200ContextPtr; | |||
| #include "r200_lock.h" | |||
| #include "r200_screen.h" | |||
| #include "mm.h" | |||
| /* Flags for software fallback cases */ | |||
| /* See correponding strings in r200_swtcl.c */ | |||
| #define R200_FALLBACK_TEXTURE 0x1 | |||
| #define R200_FALLBACK_DRAW_BUFFER 0x2 | |||
| #define R200_FALLBACK_STENCIL 0x4 | |||
| #define R200_FALLBACK_RENDER_MODE 0x8 | |||
| #define R200_FALLBACK_BLEND_EQ 0x10 | |||
| #define R200_FALLBACK_BLEND_FUNC 0x20 | |||
| #define R200_FALLBACK_DISABLE 0x40 | |||
| /* The blit width for texture uploads | |||
| */ | |||
| #define BLIT_WIDTH_BYTES 1024 | |||
| /* Use the templated vertex format: | |||
| */ | |||
| #define COLOR_IS_RGBA | |||
| #define TAG(x) r200##x | |||
| #include "tnl_dd/t_dd_vertex.h" | |||
| #undef TAG | |||
| typedef void (*r200_tri_func)( r200ContextPtr, | |||
| r200Vertex *, | |||
| r200Vertex *, | |||
| r200Vertex * ); | |||
| typedef void (*r200_line_func)( r200ContextPtr, | |||
| r200Vertex *, | |||
| r200Vertex * ); | |||
| typedef void (*r200_point_func)( r200ContextPtr, | |||
| r200Vertex * ); | |||
| struct r200_colorbuffer_state { | |||
| GLuint clear; | |||
| GLint drawOffset, drawPitch; | |||
| }; | |||
| struct r200_depthbuffer_state { | |||
| GLfloat scale; | |||
| }; | |||
| struct r200_pixel_state { | |||
| GLint readOffset, readPitch; | |||
| }; | |||
| struct r200_scissor_state { | |||
| XF86DRIClipRectRec rect; | |||
| GLboolean enabled; | |||
| GLuint numClipRects; /* Cliprects active */ | |||
| GLuint numAllocedClipRects; /* Cliprects available */ | |||
| XF86DRIClipRectPtr pClipRects; | |||
| }; | |||
| struct r200_stencilbuffer_state { | |||
| GLboolean hwBuffer; | |||
| GLuint clear; /* rb3d_stencilrefmask value */ | |||
| }; | |||
| struct r200_stipple_state { | |||
| GLuint mask[32]; | |||
| }; | |||
| #define TEX_0 0x1 | |||
| #define TEX_1 0x2 | |||
| #define TEX_ALL 0x3 | |||
| typedef struct r200_tex_obj r200TexObj, *r200TexObjPtr; | |||
| /* Texture object in locally shared texture space. | |||
| */ | |||
| struct r200_tex_obj { | |||
| r200TexObjPtr next, prev; | |||
| struct gl_texture_object *tObj; /* Mesa texture object */ | |||
| PMemBlock memBlock; /* Memory block containing texture */ | |||
| GLuint bufAddr; /* Offset to start of locally | |||
| shared texture block */ | |||
| GLuint dirty_images[6]; /* Flags for whether or not | |||
| images need to be uploaded to | |||
| local or AGP texture space. | |||
| Six cube faces. */ | |||
| 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[6][RADEON_MAX_TEXTURE_LEVELS]; | |||
| /* Six, for the cube faces */ | |||
| GLint totalSize; /* Total size of the texture | |||
| including all mipmap levels, | |||
| and all six cube faces */ | |||
| GLuint pp_txfilter; /* hardware register values */ | |||
| GLuint pp_txformat; | |||
| GLuint pp_txformat_x; | |||
| GLuint pp_txoffset; /* Image location in texmem. | |||
| All cube faces follow. */ | |||
| GLuint pp_txsize; /* npot only */ | |||
| GLuint pp_txpitch; /* npot only */ | |||
| GLuint pp_border_color; | |||
| GLuint pp_cubic_faces; /* cube face 1,2,3,4 log2 sizes */ | |||
| /* texObj->Image[firstLevel] through texObj->Image[lastLevel] are the | |||
| * images to upload. | |||
| */ | |||
| GLint firstLevel; | |||
| GLint lastLevel; | |||
| }; | |||
| struct r200_texture_env_state { | |||
| r200TexObjPtr texobj; | |||
| GLenum format; | |||
| GLenum envMode; | |||
| }; | |||
| #define R200_MAX_TEXTURE_UNITS 3 | |||
| struct r200_texture_state { | |||
| struct r200_texture_env_state unit[R200_MAX_TEXTURE_UNITS]; | |||
| }; | |||
| struct r200_state_atom { | |||
| struct r200_state_atom *next, *prev; | |||
| const char *name; /* for debug */ | |||
| int cmd_size; /* size in bytes */ | |||
| GLuint idx; | |||
| int *cmd; /* one or more cmd's */ | |||
| int *lastcmd; /* one or more cmd's */ | |||
| GLboolean (*check)( GLcontext *, int ); /* is this state active? */ | |||
| }; | |||
| /* Trying to keep these relatively short as the variables are becoming | |||
| * extravagently long. Drop the R200_ off the front of everything - | |||
| * I think we know we're in the r200 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 /* why */ | |||
| #define CTX_RB3D_COLORPITCH 13 /* why */ | |||
| #define CTX_STATE_SIZE 14 | |||
| #define SET_CMD_0 0 | |||
| #define SET_SE_CNTL 1 | |||
| #define SET_RE_CNTL 2 /* replace se_coord_fmt */ | |||
| #define SET_STATE_SIZE 3 | |||
| #define VTE_CMD_0 0 | |||
| #define VTE_SE_VTE_CNTL 1 | |||
| #define VTE_STATE_SIZE 2 | |||
| #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 ZBS_CMD_0 0 | |||
| #define ZBS_SE_ZBIAS_FACTOR 1 | |||
| #define ZBS_SE_ZBIAS_CONSTANT 2 | |||
| #define ZBS_STATE_SIZE 3 | |||
| #define MSC_CMD_0 0 | |||
| #define MSC_RE_MISC 1 | |||
| #define MSC_STATE_SIZE 2 | |||
| #define TAM_CMD_0 0 | |||
| #define TAM_DEBUG3 1 | |||
| #define TAM_STATE_SIZE 2 | |||
| #define TEX_CMD_0 0 | |||
| #define TEX_PP_TXFILTER 1 /*2c00*/ | |||
| #define TEX_PP_TXFORMAT 2 /*2c04*/ | |||
| #define TEX_PP_TXFORMAT_X 3 /*2c08*/ | |||
| #define TEX_PP_TXSIZE 4 /*2c0c*/ | |||
| #define TEX_PP_TXPITCH 5 /*2c10*/ | |||
| #define TEX_PP_BORDER_COLOR 6 /*2c14*/ | |||
| #define TEX_CMD_1 7 | |||
| #define TEX_PP_TXOFFSET 8 /*2d00 */ | |||
| #define TEX_STATE_SIZE 9 | |||
| #define CUBE_CMD_0 0 /* 1 register follows */ | |||
| #define CUBE_PP_CUBIC_FACES 1 /* 0x2c18 */ | |||
| #define CUBE_CMD_1 2 /* 5 registers follow */ | |||
| #define CUBE_PP_CUBIC_OFFSET_F1 3 /* 0x2d04 */ | |||
| #define CUBE_PP_CUBIC_OFFSET_F2 4 /* 0x2d08 */ | |||
| #define CUBE_PP_CUBIC_OFFSET_F3 5 /* 0x2d0c */ | |||
| #define CUBE_PP_CUBIC_OFFSET_F4 6 /* 0x2d10 */ | |||
| #define CUBE_PP_CUBIC_OFFSET_F5 7 /* 0x2d14 */ | |||
| #define CUBE_STATE_SIZE 8 | |||
| #define PIX_CMD_0 0 | |||
| #define PIX_PP_TXCBLEND 1 | |||
| #define PIX_PP_TXCBLEND2 2 | |||
| #define PIX_PP_TXABLEND 3 | |||
| #define PIX_PP_TXABLEND2 4 | |||
| #define PIX_STATE_SIZE 5 | |||
| #define TF_CMD_0 0 | |||
| #define TF_TFACTOR_0 1 | |||
| #define TF_TFACTOR_1 2 | |||
| #define TF_TFACTOR_2 3 | |||
| #define TF_TFACTOR_3 4 | |||
| #define TF_TFACTOR_4 5 | |||
| #define TF_TFACTOR_5 6 | |||
| #define TF_STATE_SIZE 7 | |||
| #define TCL_CMD_0 0 | |||
| #define TCL_LIGHT_MODEL_CTL_0 1 | |||
| #define TCL_LIGHT_MODEL_CTL_1 2 | |||
| #define TCL_PER_LIGHT_CTL_0 3 | |||
| #define TCL_PER_LIGHT_CTL_1 4 | |||
| #define TCL_PER_LIGHT_CTL_2 5 | |||
| #define TCL_PER_LIGHT_CTL_3 6 | |||
| #define TCL_CMD_1 7 | |||
| #define TCL_UCP_VERT_BLEND_CTL 8 | |||
| #define TCL_STATE_SIZE 9 | |||
| #define MSL_CMD_0 0 | |||
| #define MSL_MATRIX_SELECT_0 1 | |||
| #define MSL_MATRIX_SELECT_1 2 | |||
| #define MSL_MATRIX_SELECT_2 3 | |||
| #define MSL_MATRIX_SELECT_3 4 | |||
| #define MSL_MATRIX_SELECT_4 5 | |||
| #define MSL_STATE_SIZE 6 | |||
| #define TCG_CMD_0 0 | |||
| #define TCG_TEX_PROC_CTL_2 1 | |||
| #define TCG_TEX_PROC_CTL_3 2 | |||
| #define TCG_TEX_PROC_CTL_0 3 | |||
| #define TCG_TEX_PROC_CTL_1 4 | |||
| #define TCG_TEX_CYL_WRAP_CTL 5 | |||
| #define TCG_STATE_SIZE 6 | |||
| #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_CMD_1 17 | |||
| #define MTL_SHININESS 18 | |||
| #define MTL_STATE_SIZE 19 | |||
| #define VAP_CMD_0 0 | |||
| #define VAP_SE_VAP_CNTL 1 | |||
| #define VAP_STATE_SIZE 2 | |||
| /* Replaces a lot of packet info from radeon | |||
| */ | |||
| #define VTX_CMD_0 0 | |||
| #define VTX_VTXFMT_0 1 | |||
| #define VTX_VTXFMT_1 2 | |||
| #define VTX_TCL_OUTPUT_VTXFMT_0 3 | |||
| #define VTX_TCL_OUTPUT_VTXFMT_1 4 | |||
| #define VTX_CMD_1 5 | |||
| #define VTX_TCL_OUTPUT_COMPSEL 6 | |||
| #define VTX_CMD_2 7 | |||
| #define VTX_STATE_CNTL 8 | |||
| #define VTX_STATE_SIZE 9 | |||
| #define VTX_COLOR(v,n) (((v)>>(R200_VTX_COLOR_0_SHIFT+(n)*2))&\ | |||
| R200_VTX_COLOR_MASK) | |||
| #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_DCM 27 | |||
| #define LIT_SPOT_EXPONENT 28 | |||
| #define LIT_SPOT_CUTOFF 29 | |||
| #define LIT_SPECULAR_THRESH 30 | |||
| #define LIT_RANGE_CUTOFF 31 /* ? */ | |||
| #define LIT_RANGE_ATTEN 32 /* ? */ | |||
| #define LIT_STATE_SIZE 33 | |||
| /* 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 | |||
| /* CST - constant state | |||
| */ | |||
| #define CST_CMD_0 0 | |||
| #define CST_PP_CNTL_X 1 | |||
| #define CST_CMD_1 2 | |||
| #define CST_RB3D_DEPTHXY_OFFSET 3 | |||
| #define CST_CMD_2 4 | |||
| #define CST_RE_AUX_SCISSOR_CNTL 5 | |||
| #define CST_CMD_3 6 | |||
| #define CST_RE_SCISSOR_TL_0 7 | |||
| #define CST_RE_SCISSOR_BR_0 8 | |||
| #define CST_CMD_4 9 | |||
| #define CST_SE_VAP_CNTL_STATUS 10 | |||
| #define CST_CMD_5 11 | |||
| #define CST_RE_POINTSIZE 12 | |||
| #define CST_CMD_6 13 | |||
| #define CST_SE_TCL_INPUT_VTX_0 14 | |||
| #define CST_SE_TCL_INPUT_VTX_1 15 | |||
| #define CST_SE_TCL_INPUT_VTX_2 16 | |||
| #define CST_SE_TCL_INPUT_VTX_3 17 | |||
| #define CST_STATE_SIZE 18 | |||
| struct r200_hw_state { | |||
| /* All state should be on one of these lists: | |||
| */ | |||
| struct r200_state_atom dirty; /* dirty list head placeholder */ | |||
| struct r200_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 r200_state_atom ctx; | |||
| struct r200_state_atom set; | |||
| struct r200_state_atom vte; | |||
| struct r200_state_atom lin; | |||
| struct r200_state_atom msk; | |||
| struct r200_state_atom vpt; | |||
| struct r200_state_atom vap; | |||
| struct r200_state_atom vtx; | |||
| struct r200_state_atom tcl; | |||
| struct r200_state_atom msl; | |||
| struct r200_state_atom tcg; | |||
| struct r200_state_atom msc; | |||
| struct r200_state_atom cst; | |||
| struct r200_state_atom tam; | |||
| struct r200_state_atom tf; | |||
| struct r200_state_atom tex[2]; | |||
| struct r200_state_atom cube[2]; | |||
| struct r200_state_atom zbs; | |||
| struct r200_state_atom mtl[2]; | |||
| struct r200_state_atom mat[5]; | |||
| struct r200_state_atom lit[8]; /* includes vec, scl commands */ | |||
| struct r200_state_atom ucp[6]; | |||
| struct r200_state_atom pix[6]; /* pixshader stages */ | |||
| struct r200_state_atom eye; /* eye pos */ | |||
| struct r200_state_atom grd; /* guard band clipping */ | |||
| struct r200_state_atom fog; | |||
| struct r200_state_atom glt; | |||
| }; | |||
| struct r200_state { | |||
| /* Derived state for internal purposes: | |||
| */ | |||
| struct r200_colorbuffer_state color; | |||
| struct r200_depthbuffer_state depth; | |||
| struct r200_pixel_state pixel; | |||
| struct r200_scissor_state scissor; | |||
| struct r200_stencilbuffer_state stencil; | |||
| struct r200_stipple_state stipple; | |||
| struct r200_texture_state texture; | |||
| }; | |||
| struct r200_texture { | |||
| r200TexObj objects[R200_NR_TEX_HEAPS]; | |||
| r200TexObj swapped; | |||
| memHeap_t *heap[R200_NR_TEX_HEAPS]; | |||
| GLint age[R200_NR_TEX_HEAPS]; | |||
| GLint numHeaps; | |||
| }; | |||
| /* Need refcounting on dma buffers: | |||
| */ | |||
| struct r200_dma_buffer { | |||
| int refcount; /* the number of retained regions in buf */ | |||
| drmBufPtr buf; | |||
| }; | |||
| #define GET_START(rvb) (rmesa->r200Screen->agp_buffer_offset + \ | |||
| (rvb)->address - rmesa->dma.buf0_address + \ | |||
| (rvb)->start) | |||
| /* A retained region, eg vertices for indexed vertices. | |||
| */ | |||
| struct r200_dma_region { | |||
| struct r200_dma_buffer *buf; | |||
| char *address; /* == buf->address */ | |||
| int start, end, ptr; /* offsets from start of buf */ | |||
| int aos_start; | |||
| int aos_stride; | |||
| int aos_size; | |||
| }; | |||
| struct r200_dma { | |||
| /* Active dma region. Allocations for vertices and retained | |||
| * regions come from here. Also used for emitting random vertices, | |||
| * these may be flushed by calling flush_current(); | |||
| */ | |||
| struct r200_dma_region current; | |||
| void (*flush)( r200ContextPtr ); | |||
| char *buf0_address; /* start of buf[0], for index calcs */ | |||
| GLuint nr_released_bufs; /* flush after so many buffers released */ | |||
| }; | |||
| struct r200_dri_mirror { | |||
| __DRIcontextPrivate *context; /* DRI context */ | |||
| __DRIscreenPrivate *screen; /* DRI screen */ | |||
| __DRIdrawablePrivate *drawable; /* DRI drawable bound to this ctx */ | |||
| drmContext hwContext; | |||
| drmLock *hwLock; | |||
| int fd; | |||
| int drmMinor; | |||
| }; | |||
| #define R200_CMD_BUF_SZ (8*1024) | |||
| struct r200_store { | |||
| GLuint statenr; | |||
| GLuint primnr; | |||
| char cmd_buf[R200_CMD_BUF_SZ]; | |||
| int cmd_used; | |||
| int elts_start; | |||
| }; | |||
| /* r200_tcl.c | |||
| */ | |||
| struct r200_tcl_info { | |||
| GLuint vertex_format; | |||
| GLint last_offset; | |||
| GLuint hw_primitive; | |||
| struct r200_dma_region *aos_components[8]; | |||
| GLuint nr_aos_components; | |||
| GLuint *Elts; | |||
| struct r200_dma_region indexed_verts; | |||
| struct r200_dma_region obj; | |||
| struct r200_dma_region rgba; | |||
| struct r200_dma_region spec; | |||
| struct r200_dma_region fog; | |||
| struct r200_dma_region tex[R200_MAX_TEXTURE_UNITS]; | |||
| struct r200_dma_region norm; | |||
| }; | |||
| /* r200_swtcl.c | |||
| */ | |||
| struct r200_swtcl_info { | |||
| GLuint SetupIndex; | |||
| GLuint SetupNewInputs; | |||
| GLuint RenderIndex; | |||
| GLuint vertex_size; | |||
| GLuint vertex_stride_shift; | |||
| GLuint vertex_format; | |||
| char *verts; | |||
| /* Fallback rasterization functions | |||
| */ | |||
| r200_point_func draw_point; | |||
| r200_line_func draw_line; | |||
| r200_tri_func draw_tri; | |||
| GLuint hw_primitive; | |||
| GLenum render_primitive; | |||
| GLuint numverts; | |||
| struct r200_dma_region indexed_verts; | |||
| }; | |||
| struct r200_ioctl { | |||
| GLuint vertex_offset; | |||
| GLuint vertex_size; | |||
| }; | |||
| #define R200_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[2]; | |||
| 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 *, const int * ); | |||
| struct dynfn *(*Vertex2fv)( GLcontext *, const int * ); | |||
| struct dynfn *(*Vertex3f)( GLcontext *, const int * ); | |||
| struct dynfn *(*Vertex3fv)( GLcontext *, const int * ); | |||
| struct dynfn *(*Color4ub)( GLcontext *, const int * ); | |||
| struct dynfn *(*Color4ubv)( GLcontext *, const int * ); | |||
| struct dynfn *(*Color3ub)( GLcontext *, const int * ); | |||
| struct dynfn *(*Color3ubv)( GLcontext *, const int * ); | |||
| struct dynfn *(*Color4f)( GLcontext *, const int * ); | |||
| struct dynfn *(*Color4fv)( GLcontext *, const int * ); | |||
| struct dynfn *(*Color3f)( GLcontext *, const int * ); | |||
| struct dynfn *(*Color3fv)( GLcontext *, const int * ); | |||
| struct dynfn *(*SecondaryColor3ubEXT)( GLcontext *, const int * ); | |||
| struct dynfn *(*SecondaryColor3ubvEXT)( GLcontext *, const int * ); | |||
| struct dynfn *(*SecondaryColor3fEXT)( GLcontext *, const int * ); | |||
| struct dynfn *(*SecondaryColor3fvEXT)( GLcontext *, const int * ); | |||
| struct dynfn *(*Normal3f)( GLcontext *, const int * ); | |||
| struct dynfn *(*Normal3fv)( GLcontext *, const int * ); | |||
| struct dynfn *(*TexCoord2f)( GLcontext *, const int * ); | |||
| struct dynfn *(*TexCoord2fv)( GLcontext *, const int * ); | |||
| struct dynfn *(*TexCoord1f)( GLcontext *, const int * ); | |||
| struct dynfn *(*TexCoord1fv)( GLcontext *, const int * ); | |||
| struct dynfn *(*MultiTexCoord2fARB)( GLcontext *, const int * ); | |||
| struct dynfn *(*MultiTexCoord2fvARB)( GLcontext *, const int * ); | |||
| struct dynfn *(*MultiTexCoord1fARB)( GLcontext *, const int * ); | |||
| struct dynfn *(*MultiTexCoord1fvARB)( GLcontext *, const int * ); | |||
| }; | |||
| struct r200_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; r200_color_t color; } vertex[15]; | |||
| GLfloat *normalptr; | |||
| GLfloat *floatcolorptr; | |||
| r200_color_t *colorptr; | |||
| GLfloat *floatspecptr; | |||
| r200_color_t *specptr; | |||
| GLfloat *texcoordptr[2]; | |||
| GLcontext *context; /* current context : Single thread only! */ | |||
| }; | |||
| struct r200_prim { | |||
| GLuint start; | |||
| GLuint end; | |||
| GLuint prim; | |||
| }; | |||
| struct r200_vbinfo { | |||
| GLenum *prim; /* &ctx->Driver.CurrentExecPrimitive */ | |||
| GLuint primflags; | |||
| GLboolean enabled; /* R200_NO_VTXFMT//R200_NO_TCL env vars */ | |||
| GLboolean installed; | |||
| GLboolean fell_back; | |||
| GLboolean recheck; | |||
| GLint initial_counter; | |||
| GLint nrverts; | |||
| GLuint vtxfmt_0, vtxfmt_1; | |||
| GLuint installed_vertex_format; | |||
| GLuint installed_color_3f_sz; | |||
| struct r200_prim primlist[R200_MAX_PRIMS]; | |||
| int nrprims; | |||
| struct dfn_lists dfn_cache; | |||
| struct dfn_generators codegen; | |||
| GLvertexformat vtxfmt; | |||
| }; | |||
| struct r200_context { | |||
| GLcontext *glCtx; /* Mesa context */ | |||
| /* Driver and hardware state management | |||
| */ | |||
| struct r200_hw_state hw; | |||
| struct r200_state state; | |||
| /* Texture object bookkeeping | |||
| */ | |||
| struct r200_texture texture; | |||
| /* Rasterization and vertex state: | |||
| */ | |||
| GLuint TclFallback; | |||
| GLuint Fallback; | |||
| GLuint NewGLState; | |||
| /* Temporaries for translating away float colors: | |||
| */ | |||
| struct gl_client_array UbyteColor; | |||
| struct gl_client_array UbyteSecondaryColor; | |||
| /* Vertex buffers | |||
| */ | |||
| struct r200_ioctl ioctl; | |||
| struct r200_dma dma; | |||
| struct r200_store store; | |||
| /* Page flipping | |||
| */ | |||
| GLuint doPageFlip; | |||
| /* Busy waiting | |||
| */ | |||
| GLuint do_usleeps; | |||
| GLuint do_irqs; | |||
| GLuint irqsEmitted; | |||
| drmRadeonIrqWait iw; | |||
| /* Clientdata textures; | |||
| */ | |||
| GLuint prefer_agp_client_texturing; | |||
| /* Drawable, cliprect and scissor information | |||
| */ | |||
| GLuint numClipRects; /* Cliprects for the draw buffer */ | |||
| XF86DRIClipRectPtr pClipRects; | |||
| unsigned int lastStamp; | |||
| GLboolean lost_context; | |||
| r200ScreenPtr r200Screen; /* Screen private DRI data */ | |||
| RADEONSAREAPrivPtr sarea; /* Private SAREA data */ | |||
| /* TCL stuff | |||
| */ | |||
| GLmatrix TexGenMatrix[R200_MAX_TEXTURE_UNITS]; | |||
| GLboolean recheck_texgen[R200_MAX_TEXTURE_UNITS]; | |||
| GLboolean TexGenNeedNormals[R200_MAX_TEXTURE_UNITS]; | |||
| GLuint TexMatEnabled; | |||
| GLuint TexMatCompSel; | |||
| GLuint TexGenEnabled; | |||
| GLuint TexGenInputs; | |||
| GLuint TexGenCompSel; | |||
| GLmatrix tmpmat; | |||
| /* VBI | |||
| */ | |||
| GLuint vbl_seq; | |||
| /* r200_tcl.c | |||
| */ | |||
| struct r200_tcl_info tcl; | |||
| /* r200_swtcl.c | |||
| */ | |||
| struct r200_swtcl_info swtcl; | |||
| /* r200_vtxfmt.c | |||
| */ | |||
| struct r200_vbinfo vb; | |||
| /* Mirrors of some DRI state | |||
| */ | |||
| struct r200_dri_mirror dri; | |||
| }; | |||
| #define R200_CONTEXT(ctx) ((r200ContextPtr)(ctx->DriverCtx)) | |||
| static __inline GLuint r200PackColor( GLuint cpp, | |||
| GLubyte r, GLubyte g, | |||
| GLubyte b, GLubyte a ) | |||
| { | |||
| switch ( cpp ) { | |||
| case 2: | |||
| return PACK_COLOR_565( r, g, b ); | |||
| case 4: | |||
| return PACK_COLOR_8888( a, r, g, b ); | |||
| default: | |||
| return 0; | |||
| } | |||
| } | |||
| #define R200_OLD_PACKETS 0 | |||
| extern void r200DestroyContext( __DRIcontextPrivate *driContextPriv ); | |||
| extern GLboolean r200CreateContext( const __GLcontextModes *glVisual, | |||
| __DRIcontextPrivate *driContextPriv, | |||
| void *sharedContextPrivate); | |||
| extern void r200SwapBuffers( __DRIdrawablePrivate *dPriv ); | |||
| extern GLboolean r200MakeCurrent( __DRIcontextPrivate *driContextPriv, | |||
| __DRIdrawablePrivate *driDrawPriv, | |||
| __DRIdrawablePrivate *driReadPriv ); | |||
| extern GLboolean r200UnbindContext( __DRIcontextPrivate *driContextPriv ); | |||
| /* ================================================================ | |||
| * Debugging: | |||
| */ | |||
| #define DO_DEBUG 1 | |||
| #if DO_DEBUG | |||
| extern int R200_DEBUG; | |||
| #else | |||
| #define R200_DEBUG 0 | |||
| #endif | |||
| #define DEBUG_TEXTURE 0x001 | |||
| #define DEBUG_STATE 0x002 | |||
| #define DEBUG_IOCTL 0x004 | |||
| #define DEBUG_PRIMS 0x008 | |||
| #define DEBUG_VERTS 0x010 | |||
| #define DEBUG_FALLBACKS 0x020 | |||
| #define DEBUG_VFMT 0x040 | |||
| #define DEBUG_CODEGEN 0x080 | |||
| #define DEBUG_VERBOSE 0x100 | |||
| #define DEBUG_DRI 0x200 | |||
| #define DEBUG_DMA 0x400 | |||
| #define DEBUG_SANITY 0x800 | |||
| #define DEBUG_SYNC 0x1000 | |||
| #define DEBUG_PIXEL 0x2000 | |||
| #define DEBUG_MEMORY 0x4000 | |||
| #endif | |||
| #endif /* __R200_CONTEXT_H__ */ | |||
| @@ -0,0 +1,934 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #include "glheader.h" | |||
| #include "imports.h" | |||
| #include "macros.h" | |||
| #include "context.h" | |||
| #include "swrast/swrast.h" | |||
| #include "r200_context.h" | |||
| #include "r200_state.h" | |||
| #include "r200_ioctl.h" | |||
| #include "r200_tcl.h" | |||
| #include "r200_sanity.h" | |||
| #include "radeon_reg.h" | |||
| #include <unistd.h> /* for usleep() */ | |||
| #include <errno.h> | |||
| #define R200_TIMEOUT 512 | |||
| #define R200_IDLE_RETRY 16 | |||
| static void do_usleep( int nr, const char *caller ) | |||
| { | |||
| //if (1) fprintf(stderr, "usleep %d in %s\n", nr, caller ); | |||
| if (1) usleep( nr ); | |||
| } | |||
| static void r200WaitForIdle( r200ContextPtr rmesa ); | |||
| int r200FlushCmdBufLocked( r200ContextPtr rmesa, const char * caller ) | |||
| { | |||
| int ret, i; | |||
| drmRadeonCmdBuffer cmd; | |||
| if (R200_DEBUG & DEBUG_IOCTL) { | |||
| fprintf(stderr, "%s from %s\n", __FUNCTION__, caller); | |||
| if (0 & R200_DEBUG & DEBUG_VERBOSE) | |||
| for (i = 0 ; i < rmesa->store.cmd_used ; i += 4 ) | |||
| fprintf(stderr, "%d: %x\n", i/4, | |||
| *(int *)(&rmesa->store.cmd_buf[i])); | |||
| } | |||
| if (R200_DEBUG & DEBUG_DMA) | |||
| fprintf(stderr, "%s: Releasing %d buffers\n", __FUNCTION__, | |||
| rmesa->dma.nr_released_bufs); | |||
| if (R200_DEBUG & DEBUG_SANITY) { | |||
| if (rmesa->state.scissor.enabled) | |||
| ret = r200SanityCmdBuffer( rmesa, | |||
| rmesa->state.scissor.numClipRects, | |||
| rmesa->state.scissor.pClipRects); | |||
| else | |||
| ret = r200SanityCmdBuffer( rmesa, | |||
| rmesa->numClipRects, | |||
| rmesa->pClipRects); | |||
| if (ret) { | |||
| fprintf(stderr, "drmSanityCommandWrite: %d\n", ret); | |||
| goto out; | |||
| } | |||
| } | |||
| if (R200_DEBUG & DEBUG_MEMORY) { | |||
| if (!r200ValidateTexObjs( rmesa )) { | |||
| fprintf(stderr, " -- tex memory is inconsistent - expect mangled textures\n"); | |||
| } | |||
| } | |||
| cmd.bufsz = rmesa->store.cmd_used; | |||
| cmd.buf = rmesa->store.cmd_buf; | |||
| if (rmesa->state.scissor.enabled) { | |||
| cmd.nbox = rmesa->state.scissor.numClipRects; | |||
| cmd.boxes = (drmClipRect *)rmesa->state.scissor.pClipRects; | |||
| } else { | |||
| cmd.nbox = rmesa->numClipRects; | |||
| cmd.boxes = (drmClipRect *)rmesa->pClipRects; | |||
| } | |||
| ret = drmCommandWrite( rmesa->dri.fd, | |||
| DRM_RADEON_CMDBUF, | |||
| &cmd, sizeof(cmd) ); | |||
| if (ret) | |||
| fprintf(stderr, "drmCommandWrite: %d\n", ret); | |||
| if (R200_DEBUG & DEBUG_SYNC) { | |||
| fprintf(stderr, "\nSyncing in %s\n\n", __FUNCTION__); | |||
| r200WaitForIdleLocked( rmesa ); | |||
| } | |||
| out: | |||
| rmesa->store.primnr = 0; | |||
| rmesa->store.statenr = 0; | |||
| rmesa->store.cmd_used = 0; | |||
| rmesa->dma.nr_released_bufs = 0; | |||
| /* rmesa->lost_context = 0; */ | |||
| rmesa->lost_context = 1; | |||
| return ret; | |||
| } | |||
| /* Note: does not emit any commands to avoid recursion on | |||
| * r200AllocCmdBuf. | |||
| */ | |||
| void r200FlushCmdBuf( r200ContextPtr rmesa, const char *caller ) | |||
| { | |||
| int ret; | |||
| LOCK_HARDWARE( rmesa ); | |||
| ret = r200FlushCmdBufLocked( rmesa, caller ); | |||
| UNLOCK_HARDWARE( rmesa ); | |||
| if (ret) { | |||
| fprintf(stderr, "drmRadeonCmdBuffer: %d (exiting)\n", ret); | |||
| exit(ret); | |||
| } | |||
| } | |||
| /* ============================================================= | |||
| * Hardware vertex buffer handling | |||
| */ | |||
| void r200RefillCurrentDmaRegion( r200ContextPtr rmesa ) | |||
| { | |||
| struct r200_dma_buffer *dmabuf; | |||
| int fd = rmesa->dri.fd; | |||
| int index = 0; | |||
| int size = 0; | |||
| drmDMAReq dma; | |||
| int ret; | |||
| if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_DMA)) | |||
| fprintf(stderr, "%s\n", __FUNCTION__); | |||
| if (rmesa->dma.flush) { | |||
| rmesa->dma.flush( rmesa ); | |||
| } | |||
| if (rmesa->dma.current.buf) | |||
| r200ReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ ); | |||
| if (rmesa->dma.nr_released_bufs > 4) | |||
| r200FlushCmdBuf( rmesa, __FUNCTION__ ); | |||
| dma.context = rmesa->dri.hwContext; | |||
| dma.send_count = 0; | |||
| dma.send_list = NULL; | |||
| dma.send_sizes = NULL; | |||
| dma.flags = 0; | |||
| dma.request_count = 1; | |||
| dma.request_size = RADEON_BUFFER_SIZE; | |||
| dma.request_list = &index; | |||
| dma.request_sizes = &size; | |||
| dma.granted_count = 0; | |||
| LOCK_HARDWARE(rmesa); /* no need to validate */ | |||
| while (1) { | |||
| ret = drmDMA( fd, &dma ); | |||
| if (ret == 0) | |||
| break; | |||
| if (rmesa->dma.nr_released_bufs) { | |||
| r200FlushCmdBufLocked( rmesa, __FUNCTION__ ); | |||
| } | |||
| if (rmesa->do_usleeps) { | |||
| UNLOCK_HARDWARE( rmesa ); | |||
| do_usleep(1, __FUNCTION__); | |||
| LOCK_HARDWARE( rmesa ); | |||
| } | |||
| } | |||
| UNLOCK_HARDWARE(rmesa); | |||
| if (R200_DEBUG & DEBUG_DMA) | |||
| fprintf(stderr, "Allocated buffer %d\n", index); | |||
| dmabuf = CALLOC_STRUCT( r200_dma_buffer ); | |||
| dmabuf->buf = &rmesa->r200Screen->buffers->list[index]; | |||
| dmabuf->refcount = 1; | |||
| rmesa->dma.current.buf = dmabuf; | |||
| rmesa->dma.current.address = dmabuf->buf->address; | |||
| rmesa->dma.current.end = dmabuf->buf->total; | |||
| rmesa->dma.current.start = 0; | |||
| rmesa->dma.current.ptr = 0; | |||
| } | |||
| void r200ReleaseDmaRegion( r200ContextPtr rmesa, | |||
| struct r200_dma_region *region, | |||
| const char *caller ) | |||
| { | |||
| if (R200_DEBUG & DEBUG_IOCTL) | |||
| fprintf(stderr, "%s from %s\n", __FUNCTION__, caller); | |||
| if (!region->buf) | |||
| return; | |||
| if (rmesa->dma.flush) | |||
| rmesa->dma.flush( rmesa ); | |||
| if (--region->buf->refcount == 0) { | |||
| drmRadeonCmdHeader *cmd; | |||
| if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_DMA)) | |||
| fprintf(stderr, "%s -- DISCARD BUF %d\n", __FUNCTION__, | |||
| region->buf->buf->idx); | |||
| cmd = (drmRadeonCmdHeader *)r200AllocCmdBuf( rmesa, sizeof(*cmd), | |||
| __FUNCTION__ ); | |||
| cmd->dma.cmd_type = RADEON_CMD_DMA_DISCARD; | |||
| cmd->dma.buf_idx = region->buf->buf->idx; | |||
| FREE(region->buf); | |||
| rmesa->dma.nr_released_bufs++; | |||
| } | |||
| region->buf = 0; | |||
| region->start = 0; | |||
| } | |||
| /* Allocates a region from rmesa->dma.current. If there isn't enough | |||
| * space in current, grab a new buffer (and discard what was left of current) | |||
| */ | |||
| void r200AllocDmaRegion( r200ContextPtr rmesa, | |||
| struct r200_dma_region *region, | |||
| int bytes, | |||
| int alignment ) | |||
| { | |||
| if (R200_DEBUG & DEBUG_IOCTL) | |||
| fprintf(stderr, "%s %d\n", __FUNCTION__, bytes); | |||
| if (rmesa->dma.flush) | |||
| rmesa->dma.flush( rmesa ); | |||
| if (region->buf) | |||
| r200ReleaseDmaRegion( rmesa, region, __FUNCTION__ ); | |||
| alignment--; | |||
| rmesa->dma.current.start = rmesa->dma.current.ptr = | |||
| (rmesa->dma.current.ptr + alignment) & ~alignment; | |||
| if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end ) | |||
| r200RefillCurrentDmaRegion( rmesa ); | |||
| region->start = rmesa->dma.current.start; | |||
| region->ptr = rmesa->dma.current.start; | |||
| region->end = rmesa->dma.current.start + bytes; | |||
| region->address = rmesa->dma.current.address; | |||
| region->buf = rmesa->dma.current.buf; | |||
| region->buf->refcount++; | |||
| rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */ | |||
| rmesa->dma.current.start = | |||
| rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7; | |||
| } | |||
| void r200AllocDmaRegionVerts( r200ContextPtr rmesa, | |||
| struct r200_dma_region *region, | |||
| int numverts, | |||
| int vertsize, | |||
| int alignment ) | |||
| { | |||
| r200AllocDmaRegion( rmesa, region, vertsize * numverts, alignment ); | |||
| } | |||
| /* ================================================================ | |||
| * SwapBuffers with client-side throttling | |||
| */ | |||
| static GLuint r200GetLastFrame(r200ContextPtr rmesa) | |||
| { | |||
| drmRadeonGetParam gp; | |||
| int ret; | |||
| GLuint frame; | |||
| gp.param = RADEON_PARAM_LAST_FRAME; | |||
| gp.value = (int *)&frame; | |||
| ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_GETPARAM, | |||
| &gp, sizeof(gp) ); | |||
| if ( ret ) { | |||
| fprintf( stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, ret ); | |||
| exit(1); | |||
| } | |||
| return frame; | |||
| } | |||
| static void r200EmitIrqLocked( r200ContextPtr rmesa ) | |||
| { | |||
| 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); | |||
| } | |||
| } | |||
| static void r200WaitIrq( r200ContextPtr rmesa ) | |||
| { | |||
| int ret; | |||
| do { | |||
| ret = drmCommandWrite( rmesa->dri.fd, DRM_RADEON_IRQ_WAIT, | |||
| &rmesa->iw, sizeof(rmesa->iw) ); | |||
| } while (ret && (errno == EINTR || errno == EAGAIN)); | |||
| if ( ret ) { | |||
| fprintf( stderr, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__, ret ); | |||
| exit(1); | |||
| } | |||
| } | |||
| static void r200WaitForFrameCompletion( r200ContextPtr rmesa ) | |||
| { | |||
| RADEONSAREAPrivPtr sarea = rmesa->sarea; | |||
| if (rmesa->do_irqs) { | |||
| if (r200GetLastFrame(rmesa) < sarea->last_frame) { | |||
| if (!rmesa->irqsEmitted) { | |||
| while (r200GetLastFrame (rmesa) < sarea->last_frame) | |||
| ; | |||
| } | |||
| else { | |||
| UNLOCK_HARDWARE( rmesa ); | |||
| r200WaitIrq( rmesa ); | |||
| LOCK_HARDWARE( rmesa ); | |||
| } | |||
| rmesa->irqsEmitted = 10; | |||
| } | |||
| if (rmesa->irqsEmitted) { | |||
| r200EmitIrqLocked( rmesa ); | |||
| rmesa->irqsEmitted--; | |||
| } | |||
| } | |||
| else { | |||
| while (r200GetLastFrame (rmesa) < sarea->last_frame) { | |||
| UNLOCK_HARDWARE( rmesa ); | |||
| if (rmesa->do_usleeps) | |||
| do_usleep(1, __FUNCTION__); | |||
| LOCK_HARDWARE( rmesa ); | |||
| } | |||
| } | |||
| } | |||
| /* Copy the back color buffer to the front color buffer. | |||
| */ | |||
| void r200CopyBuffer( const __DRIdrawablePrivate *dPriv ) | |||
| { | |||
| r200ContextPtr rmesa; | |||
| GLint nbox, i, ret; | |||
| assert(dPriv); | |||
| assert(dPriv->driContextPriv); | |||
| assert(dPriv->driContextPriv->driverPrivate); | |||
| rmesa = (r200ContextPtr) dPriv->driContextPriv->driverPrivate; | |||
| if ( R200_DEBUG & DEBUG_IOCTL ) { | |||
| fprintf( stderr, "\n%s( %p )\n\n", __FUNCTION__, rmesa->glCtx ); | |||
| } | |||
| R200_FIREVERTICES( rmesa ); | |||
| LOCK_HARDWARE( rmesa ); | |||
| /* Throttle the frame rate -- only allow one pending swap buffers | |||
| * request at a time. | |||
| */ | |||
| r200WaitForFrameCompletion( rmesa ); | |||
| r200WaitForVBlank( rmesa ); | |||
| nbox = rmesa->dri.drawable->numClipRects; /* must be in locked region */ | |||
| for ( i = 0 ; i < nbox ; ) { | |||
| GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS , nbox ); | |||
| XF86DRIClipRectPtr box = rmesa->dri.drawable->pClipRects; | |||
| XF86DRIClipRectPtr b = rmesa->sarea->boxes; | |||
| GLint n = 0; | |||
| for ( ; i < nr ; i++ ) { | |||
| *b++ = box[i]; | |||
| n++; | |||
| } | |||
| rmesa->sarea->nbox = n; | |||
| ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_SWAP ); | |||
| if ( ret ) { | |||
| fprintf( stderr, "DRM_R200_SWAP_BUFFERS: return = %d\n", ret ); | |||
| UNLOCK_HARDWARE( rmesa ); | |||
| exit( 1 ); | |||
| } | |||
| } | |||
| UNLOCK_HARDWARE( rmesa ); | |||
| rmesa->lost_context = 1; | |||
| } | |||
| void r200PageFlip( const __DRIdrawablePrivate *dPriv ) | |||
| { | |||
| r200ContextPtr rmesa; | |||
| GLint ret; | |||
| assert(dPriv); | |||
| assert(dPriv->driContextPriv); | |||
| assert(dPriv->driContextPriv->driverPrivate); | |||
| rmesa = (r200ContextPtr) dPriv->driContextPriv->driverPrivate; | |||
| if ( R200_DEBUG & DEBUG_IOCTL ) { | |||
| fprintf(stderr, "%s: pfCurrentPage: %d\n", __FUNCTION__, | |||
| rmesa->sarea->pfCurrentPage); | |||
| } | |||
| R200_FIREVERTICES( rmesa ); | |||
| LOCK_HARDWARE( rmesa ); | |||
| if (!rmesa->dri.drawable->numClipRects) { | |||
| UNLOCK_HARDWARE( rmesa ); | |||
| usleep( 10000 ); /* throttle invisible client 10ms */ | |||
| return; | |||
| } | |||
| /* Need to do this for the perf box placement: | |||
| */ | |||
| { | |||
| XF86DRIClipRectPtr box = rmesa->dri.drawable->pClipRects; | |||
| XF86DRIClipRectPtr b = rmesa->sarea->boxes; | |||
| b[0] = box[0]; | |||
| rmesa->sarea->nbox = 1; | |||
| } | |||
| /* Throttle the frame rate -- only allow a few pending swap buffers | |||
| * request at a time. | |||
| */ | |||
| r200WaitForFrameCompletion( rmesa ); | |||
| r200WaitForVBlank( rmesa ); | |||
| ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_FLIP ); | |||
| UNLOCK_HARDWARE( rmesa ); | |||
| if ( ret ) { | |||
| fprintf( stderr, "DRM_R200_FLIP: return = %d\n", ret ); | |||
| exit( 1 ); | |||
| } | |||
| if ( rmesa->sarea->pfCurrentPage == 1 ) { | |||
| rmesa->state.color.drawOffset = rmesa->r200Screen->frontOffset; | |||
| rmesa->state.color.drawPitch = rmesa->r200Screen->frontPitch; | |||
| } else { | |||
| rmesa->state.color.drawOffset = rmesa->r200Screen->backOffset; | |||
| rmesa->state.color.drawPitch = rmesa->r200Screen->backPitch; | |||
| } | |||
| R200_STATECHANGE( rmesa, ctx ); | |||
| rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = rmesa->state.color.drawOffset; | |||
| rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch; | |||
| } | |||
| /* ================================================================ | |||
| * Buffer clear | |||
| */ | |||
| static void r200Clear( GLcontext *ctx, GLbitfield mask, GLboolean all, | |||
| GLint cx, GLint cy, GLint cw, GLint ch ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; | |||
| GLuint flags = 0; | |||
| GLuint color_mask = 0; | |||
| GLint ret, i; | |||
| if ( R200_DEBUG & DEBUG_IOCTL ) { | |||
| fprintf( stderr, "%s: all=%d cx=%d cy=%d cw=%d ch=%d\n", | |||
| __FUNCTION__, all, cx, cy, cw, ch ); | |||
| } | |||
| { | |||
| LOCK_HARDWARE( rmesa ); | |||
| UNLOCK_HARDWARE( rmesa ); | |||
| if ( dPriv->numClipRects == 0 ) | |||
| return; | |||
| } | |||
| r200EmitState( rmesa ); | |||
| /* Need to cope with lostcontext here as kernel relies on | |||
| * some residual state: | |||
| */ | |||
| R200_FIREVERTICES( rmesa ); | |||
| if ( mask & DD_FRONT_LEFT_BIT ) { | |||
| flags |= RADEON_FRONT; | |||
| 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->hw.msk.cmd[MSK_RB3D_PLANEMASK]; | |||
| mask &= ~DD_BACK_LEFT_BIT; | |||
| } | |||
| if ( mask & DD_DEPTH_BIT ) { | |||
| if ( ctx->Depth.Mask ) flags |= RADEON_DEPTH; /* FIXME: ??? */ | |||
| mask &= ~DD_DEPTH_BIT; | |||
| } | |||
| if ( (mask & DD_STENCIL_BIT) && rmesa->state.stencil.hwBuffer ) { | |||
| flags |= RADEON_STENCIL; | |||
| mask &= ~DD_STENCIL_BIT; | |||
| } | |||
| if ( mask ) | |||
| _swrast_Clear( ctx, mask, all, cx, cy, cw, ch ); | |||
| if ( !flags ) | |||
| return; | |||
| /* 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 ) { | |||
| drmRadeonGetParam gp; | |||
| int ret; | |||
| int clear; | |||
| gp.param = RADEON_PARAM_LAST_CLEAR; | |||
| gp.value = (int *)&clear; | |||
| ret = drmCommandWriteRead( rmesa->dri.fd, | |||
| DRM_RADEON_GETPARAM, &gp, sizeof(gp) ); | |||
| if ( ret ) { | |||
| fprintf( stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, ret ); | |||
| exit(1); | |||
| } | |||
| /* Clear throttling needs more thought. | |||
| */ | |||
| if ( rmesa->sarea->last_clear - clear <= 25 ) { | |||
| 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; | |||
| drmRadeonClearType clear; | |||
| drmRadeonClearRect depth_boxes[RADEON_NR_SAREA_CLIPRECTS]; | |||
| 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++; | |||
| } | |||
| } | |||
| rmesa->sarea->nbox = n; | |||
| clear.flags = flags; | |||
| clear.clear_color = rmesa->state.color.clear; | |||
| clear.clear_depth = 0; /* not used */ | |||
| 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] = ctx->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 ); | |||
| } | |||
| } | |||
| UNLOCK_HARDWARE( rmesa ); | |||
| rmesa->lost_context = 1; | |||
| } | |||
| void r200WaitForIdleLocked( r200ContextPtr rmesa ) | |||
| { | |||
| int ret; | |||
| int i = 0; | |||
| do { | |||
| ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_CP_IDLE); | |||
| if (ret) | |||
| do_usleep( 1, __FUNCTION__ ); | |||
| } while (ret && ++i < 100); | |||
| if ( ret < 0 ) { | |||
| UNLOCK_HARDWARE( rmesa ); | |||
| fprintf( stderr, "Error: R200 timed out... exiting\n" ); | |||
| exit( -1 ); | |||
| } | |||
| } | |||
| static void r200WaitForIdle( r200ContextPtr rmesa ) | |||
| { | |||
| LOCK_HARDWARE(rmesa); | |||
| r200WaitForIdleLocked( rmesa ); | |||
| UNLOCK_HARDWARE(rmesa); | |||
| } | |||
| void r200WaitForVBlank( r200ContextPtr rmesa ) | |||
| { | |||
| #if 0 | |||
| drmVBlank vbl; | |||
| int ret; | |||
| if ( !rmesa->r200Screen->irq ) | |||
| return; | |||
| if ( getenv("LIBGL_SYNC_REFRESH") ) { | |||
| /* Wait for until the next vertical blank */ | |||
| 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 (R200_DEBUG & DEBUG_IOCTL) | |||
| fprintf(stderr, "%s: drmWaitVBlank returned %d\n", __FUNCTION__, ret); | |||
| rmesa->vbl_seq = vbl.reply.sequence; | |||
| LOCK_HARDWARE( rmesa ); | |||
| #endif | |||
| } | |||
| void r200Flush( GLcontext *ctx ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT( ctx ); | |||
| if (R200_DEBUG & DEBUG_IOCTL) | |||
| fprintf(stderr, "%s\n", __FUNCTION__); | |||
| if (rmesa->dma.flush) | |||
| rmesa->dma.flush( rmesa ); | |||
| if (!is_empty_list(&rmesa->hw.dirty)) | |||
| r200EmitState( rmesa ); | |||
| if (rmesa->store.cmd_used) | |||
| r200FlushCmdBuf( rmesa, __FUNCTION__ ); | |||
| } | |||
| /* Make sure all commands have been sent to the hardware and have | |||
| * completed processing. | |||
| */ | |||
| void r200Finish( GLcontext *ctx ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| r200Flush( ctx ); | |||
| if (rmesa->do_irqs) { | |||
| LOCK_HARDWARE( rmesa ); | |||
| r200EmitIrqLocked( rmesa ); | |||
| UNLOCK_HARDWARE( rmesa ); | |||
| r200WaitIrq( rmesa ); | |||
| } | |||
| else | |||
| r200WaitForIdle( rmesa ); | |||
| } | |||
| /* This version of AllocateMemoryNV allocates only agp memory, and | |||
| * only does so after the point at which the driver has been | |||
| * initialized. | |||
| * | |||
| * Theoretically a valid context isn't required. However, in this | |||
| * implementation, it is, as I'm using the hardware lock to protect | |||
| * the kernel data structures, and the current context to get the | |||
| * device fd. | |||
| */ | |||
| void *r200AllocateMemoryNV(GLsizei size, GLfloat readfreq, | |||
| GLfloat writefreq, GLfloat priority) | |||
| { | |||
| GET_CURRENT_CONTEXT(ctx); | |||
| r200ContextPtr rmesa; | |||
| int region_offset; | |||
| drmRadeonMemAlloc alloc; | |||
| int ret; | |||
| if (R200_DEBUG & DEBUG_IOCTL) | |||
| fprintf(stderr, "%s sz %d %f/%f/%f\n", __FUNCTION__, size, readfreq, | |||
| writefreq, priority); | |||
| if (!ctx || !(rmesa = R200_CONTEXT(ctx)) || rmesa->r200Screen->IsPCI ) | |||
| return NULL; | |||
| if (getenv("R200_NO_ALLOC")) | |||
| return NULL; | |||
| if (rmesa->dri.drmMinor < 6) | |||
| return NULL; | |||
| alloc.region = RADEON_MEM_REGION_AGP; | |||
| alloc.alignment = 0; | |||
| alloc.size = size; | |||
| alloc.region_offset = ®ion_offset; | |||
| ret = drmCommandWriteRead( rmesa->r200Screen->driScreen->fd, | |||
| DRM_RADEON_ALLOC, | |||
| &alloc, sizeof(alloc)); | |||
| if (ret) { | |||
| fprintf(stderr, "%s: DRM_RADEON_ALLOC ret %d\n", __FUNCTION__, ret); | |||
| return NULL; | |||
| } | |||
| { | |||
| char *region_start = (char *)rmesa->r200Screen->agpTextures.map; | |||
| return (void *)(region_start + region_offset); | |||
| } | |||
| } | |||
| /* Called via glXFreeMemoryNV() */ | |||
| void r200FreeMemoryNV(GLvoid *pointer) | |||
| { | |||
| GET_CURRENT_CONTEXT(ctx); | |||
| r200ContextPtr rmesa; | |||
| int region_offset; | |||
| drmRadeonMemFree memfree; | |||
| int ret; | |||
| if (R200_DEBUG & DEBUG_IOCTL) | |||
| fprintf(stderr, "%s %p\n", __FUNCTION__, pointer); | |||
| if (!ctx || !(rmesa = R200_CONTEXT(ctx)) || rmesa->r200Screen->IsPCI ) { | |||
| fprintf(stderr, "%s: no context\n", __FUNCTION__); | |||
| return; | |||
| } | |||
| if (rmesa->dri.drmMinor < 6) | |||
| return; | |||
| region_offset = (char *)pointer - (char *)rmesa->r200Screen->agpTextures.map; | |||
| if (region_offset < 0 || | |||
| region_offset > rmesa->r200Screen->agpTextures.size) { | |||
| fprintf(stderr, "offset %d outside range 0..%d\n", region_offset, | |||
| rmesa->r200Screen->agpTextures.size); | |||
| return; | |||
| } | |||
| memfree.region = RADEON_MEM_REGION_AGP; | |||
| memfree.region_offset = region_offset; | |||
| ret = drmCommandWrite( rmesa->r200Screen->driScreen->fd, | |||
| DRM_RADEON_FREE, | |||
| &memfree, sizeof(memfree)); | |||
| if (ret) | |||
| fprintf(stderr, "%s: DRM_RADEON_FREE ret %d\n", __FUNCTION__, ret); | |||
| } | |||
| /* Called via glXGetAGPOffsetMESA() */ | |||
| GLuint r200GetAGPOffset(const GLvoid *pointer) | |||
| { | |||
| GET_CURRENT_CONTEXT(ctx); | |||
| r200ContextPtr rmesa; | |||
| GLuint card_offset; | |||
| if (!ctx || !(rmesa = R200_CONTEXT(ctx)) ) { | |||
| fprintf(stderr, "%s: no context\n", __FUNCTION__); | |||
| return ~0; | |||
| } | |||
| if (!r200IsAgpMemory( rmesa, pointer, 0 )) | |||
| return ~0; | |||
| if (rmesa->dri.drmMinor < 6) | |||
| return ~0; | |||
| card_offset = r200AgpOffsetFromVirtual( rmesa, pointer ); | |||
| return card_offset - rmesa->r200Screen->agp_base; | |||
| } | |||
| GLboolean r200IsAgpMemory( r200ContextPtr rmesa, const GLvoid *pointer, | |||
| GLint size ) | |||
| { | |||
| int offset = (char *)pointer - (char *)rmesa->r200Screen->agpTextures.map; | |||
| int valid = (size >= 0 && | |||
| offset >= 0 && | |||
| offset + size < rmesa->r200Screen->agpTextures.size); | |||
| if (R200_DEBUG & DEBUG_IOCTL) | |||
| fprintf(stderr, "r200IsAgpMemory( %p ) : %d\n", pointer, valid ); | |||
| return valid; | |||
| } | |||
| GLuint r200AgpOffsetFromVirtual( r200ContextPtr rmesa, const GLvoid *pointer ) | |||
| { | |||
| int offset = (char *)pointer - (char *)rmesa->r200Screen->agpTextures.map; | |||
| if (offset < 0 || offset > rmesa->r200Screen->agpTextures.size) | |||
| return ~0; | |||
| else | |||
| return rmesa->r200Screen->agp_texture_offset + offset; | |||
| } | |||
| void r200InitIoctlFuncs( GLcontext *ctx ) | |||
| { | |||
| ctx->Driver.Clear = r200Clear; | |||
| ctx->Driver.Finish = r200Finish; | |||
| ctx->Driver.Flush = r200Flush; | |||
| } | |||
| @@ -0,0 +1,188 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #ifndef __R200_IOCTL_H__ | |||
| #define __R200_IOCTL_H__ | |||
| #ifdef GLX_DIRECT_RENDERING | |||
| #include "simple_list.h" | |||
| #include "radeon_dri.h" | |||
| #include "r200_lock.h" | |||
| #include "xf86drm.h" | |||
| #include "radeon_common.h" | |||
| extern void r200EmitState( r200ContextPtr rmesa ); | |||
| extern void r200EmitVertexAOS( r200ContextPtr rmesa, | |||
| GLuint vertex_size, | |||
| GLuint offset ); | |||
| extern void r200EmitVbufPrim( r200ContextPtr rmesa, | |||
| GLuint primitive, | |||
| GLuint vertex_nr ); | |||
| extern void r200FlushElts( r200ContextPtr rmesa ); | |||
| extern GLushort *r200AllocEltsOpenEnded( r200ContextPtr rmesa, | |||
| GLuint primitive, | |||
| GLuint min_nr ); | |||
| extern void r200EmitAOS( r200ContextPtr rmesa, | |||
| struct r200_dma_region **regions, | |||
| GLuint n, | |||
| GLuint offset ); | |||
| extern void r200EmitBlit( r200ContextPtr rmesa, | |||
| GLuint color_fmt, | |||
| GLuint src_pitch, | |||
| GLuint src_offset, | |||
| GLuint dst_pitch, | |||
| GLuint dst_offset, | |||
| GLint srcx, GLint srcy, | |||
| GLint dstx, GLint dsty, | |||
| GLuint w, GLuint h ); | |||
| extern void r200EmitWait( r200ContextPtr rmesa, GLuint flags ); | |||
| extern void r200FlushCmdBuf( r200ContextPtr rmesa, const char * ); | |||
| extern int r200FlushCmdBufLocked( r200ContextPtr rmesa, const char * caller ); | |||
| extern void r200RefillCurrentDmaRegion( r200ContextPtr rmesa ); | |||
| extern void r200AllocDmaRegion( r200ContextPtr rmesa, | |||
| struct r200_dma_region *region, | |||
| int bytes, | |||
| int alignment ); | |||
| extern void r200AllocDmaRegionVerts( r200ContextPtr rmesa, | |||
| struct r200_dma_region *region, | |||
| int numverts, | |||
| int vertsize, | |||
| int alignment ); | |||
| extern void r200ReleaseDmaRegion( r200ContextPtr rmesa, | |||
| struct r200_dma_region *region, | |||
| const char *caller ); | |||
| extern void r200CopyBuffer( const __DRIdrawablePrivate *drawable ); | |||
| extern void r200PageFlip( const __DRIdrawablePrivate *drawable ); | |||
| extern void r200Flush( GLcontext *ctx ); | |||
| extern void r200Finish( GLcontext *ctx ); | |||
| extern void r200WaitForIdleLocked( r200ContextPtr rmesa ); | |||
| extern void r200WaitForVBlank( r200ContextPtr rmesa ); | |||
| extern void r200InitIoctlFuncs( GLcontext *ctx ); | |||
| extern void *r200AllocateMemoryNV( GLsizei size, GLfloat readfreq, | |||
| GLfloat writefreq, GLfloat priority ); | |||
| extern void r200FreeMemoryNV( GLvoid *pointer ); | |||
| extern GLuint r200GetAGPOffset( const GLvoid *pointer ); | |||
| extern GLboolean r200IsAgpMemory( r200ContextPtr rmesa, const GLvoid *pointer, | |||
| GLint size ); | |||
| extern GLuint r200AgpOffsetFromVirtual( r200ContextPtr rmesa, | |||
| const GLvoid *pointer ); | |||
| /* ================================================================ | |||
| * Helper macros: | |||
| */ | |||
| /* Close off the last primitive, if it exists. | |||
| */ | |||
| #define R200_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 R200_STATECHANGE( rmesa, ATOM ) \ | |||
| do { \ | |||
| R200_NEWPRIM( rmesa ); \ | |||
| move_to_head( &(rmesa->hw.dirty), &(rmesa->hw.ATOM)); \ | |||
| } while (0) | |||
| #define R200_DB_STATE( ATOM ) \ | |||
| memcpy( rmesa->hw.ATOM.lastcmd, rmesa->hw.ATOM.cmd, \ | |||
| rmesa->hw.ATOM.cmd_size * 4) | |||
| static __inline int R200_DB_STATECHANGE( | |||
| r200ContextPtr rmesa, | |||
| struct r200_state_atom *atom ) | |||
| { | |||
| if (memcmp(atom->cmd, atom->lastcmd, atom->cmd_size*4)) { | |||
| int *tmp; | |||
| R200_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 R200_FIREVERTICES( rmesa ) \ | |||
| do { \ | |||
| if ( rmesa->store.cmd_used || rmesa->dma.flush ) { \ | |||
| r200Flush( rmesa->glCtx ); \ | |||
| } \ | |||
| } while (0) | |||
| /* Alloc space in the command buffer | |||
| */ | |||
| static __inline char *r200AllocCmdBuf( r200ContextPtr rmesa, | |||
| int bytes, const char *where ) | |||
| { | |||
| if (rmesa->store.cmd_used + bytes > R200_CMD_BUF_SZ) | |||
| r200FlushCmdBuf( rmesa, __FUNCTION__ ); | |||
| { | |||
| char *head = rmesa->store.cmd_buf + rmesa->store.cmd_used; | |||
| rmesa->store.cmd_used += bytes; | |||
| return head; | |||
| } | |||
| } | |||
| #endif | |||
| #endif /* __R200_IOCTL_H__ */ | |||
| @@ -0,0 +1,118 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #include "r200_context.h" | |||
| #include "r200_lock.h" | |||
| #include "r200_tex.h" | |||
| #include "r200_state.h" | |||
| #include "r200_ioctl.h" | |||
| #if DEBUG_LOCKING | |||
| char *prevLockFile = NULL; | |||
| int prevLockLine = 0; | |||
| #endif | |||
| /* Turn on/off page flipping according to the flags in the sarea: | |||
| */ | |||
| static void | |||
| r200UpdatePageFlipping( r200ContextPtr rmesa ) | |||
| { | |||
| int use_back; | |||
| rmesa->doPageFlip = rmesa->sarea->pfAllowPageFlip; | |||
| use_back = (rmesa->glCtx->Color._DrawDestMask == BACK_LEFT_BIT); | |||
| use_back ^= (rmesa->sarea->pfCurrentPage == 1); | |||
| if (use_back) { | |||
| rmesa->state.color.drawOffset = rmesa->r200Screen->backOffset; | |||
| rmesa->state.color.drawPitch = rmesa->r200Screen->backPitch; | |||
| } else { | |||
| rmesa->state.color.drawOffset = rmesa->r200Screen->frontOffset; | |||
| rmesa->state.color.drawPitch = rmesa->r200Screen->frontPitch; | |||
| } | |||
| R200_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 | |||
| * function also updates the driver's window state after the X server | |||
| * moves, resizes or restacks a window -- the change will be reflected | |||
| * in the drawable position and clip rects. Since the X server grabs | |||
| * the hardware lock when it changes the window state, this routine will | |||
| * automatically be called after such a change. | |||
| */ | |||
| void r200GetLock( r200ContextPtr rmesa, GLuint flags ) | |||
| { | |||
| __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; | |||
| __DRIscreenPrivate *sPriv = rmesa->dri.screen; | |||
| RADEONSAREAPrivPtr sarea = rmesa->sarea; | |||
| int i; | |||
| drmGetLock( rmesa->dri.fd, rmesa->dri.hwContext, flags ); | |||
| /* The window might have moved, so we might need to get new clip | |||
| * rects. | |||
| * | |||
| * NOTE: This releases and regrabs the hw lock to allow the X server | |||
| * to respond to the DRI protocol request for new drawable info. | |||
| * Since the hardware state depends on having the latest drawable | |||
| * clip rects, all state checking must be done _after_ this call. | |||
| */ | |||
| DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv ); | |||
| if ( rmesa->lastStamp != dPriv->lastStamp ) { | |||
| r200UpdatePageFlipping( rmesa ); | |||
| if (rmesa->glCtx->Color._DrawDestMask == BACK_LEFT_BIT) | |||
| r200SetCliprects( rmesa, GL_BACK_LEFT ); | |||
| else | |||
| r200SetCliprects( rmesa, GL_FRONT_LEFT ); | |||
| r200UpdateViewportOffset( rmesa->glCtx ); | |||
| rmesa->lastStamp = dPriv->lastStamp; | |||
| } | |||
| if ( sarea->ctxOwner != rmesa->dri.hwContext ) { | |||
| sarea->ctxOwner = rmesa->dri.hwContext; | |||
| } | |||
| for ( i = 0 ; i < rmesa->texture.numHeaps ; i++ ) { | |||
| if ( sarea->texAge[i] != rmesa->texture.age[i] ) { | |||
| r200AgeTextures( rmesa, i ); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,111 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #ifndef __R200_LOCK_H__ | |||
| #define __R200_LOCK_H__ | |||
| #ifdef GLX_DIRECT_RENDERING | |||
| extern void r200GetLock( r200ContextPtr rmesa, GLuint flags ); | |||
| /* Turn DEBUG_LOCKING on to find locking conflicts. | |||
| */ | |||
| #define DEBUG_LOCKING 0 | |||
| #if DEBUG_LOCKING | |||
| extern char *prevLockFile; | |||
| extern int prevLockLine; | |||
| #define DEBUG_LOCK() \ | |||
| do { \ | |||
| prevLockFile = (__FILE__); \ | |||
| prevLockLine = (__LINE__); \ | |||
| } while (0) | |||
| #define DEBUG_RESET() \ | |||
| do { \ | |||
| prevLockFile = 0; \ | |||
| prevLockLine = 0; \ | |||
| } while (0) | |||
| #define DEBUG_CHECK_LOCK() \ | |||
| do { \ | |||
| if ( prevLockFile ) { \ | |||
| fprintf( stderr, \ | |||
| "LOCK SET!\n\tPrevious %s:%d\n\tCurrent: %s:%d\n", \ | |||
| prevLockFile, prevLockLine, __FILE__, __LINE__ ); \ | |||
| exit( 1 ); \ | |||
| } \ | |||
| } while (0) | |||
| #else | |||
| #define DEBUG_LOCK() | |||
| #define DEBUG_RESET() | |||
| #define DEBUG_CHECK_LOCK() | |||
| #endif | |||
| /* | |||
| * !!! We may want to separate locks from locks with validation. This | |||
| * could be used to improve performance for those things commands that | |||
| * do not do any drawing !!! | |||
| */ | |||
| /* Lock the hardware and validate our state. | |||
| */ | |||
| #define LOCK_HARDWARE( rmesa ) \ | |||
| do { \ | |||
| char __ret = 0; \ | |||
| DEBUG_CHECK_LOCK(); \ | |||
| DRM_CAS( rmesa->dri.hwLock, rmesa->dri.hwContext, \ | |||
| (DRM_LOCK_HELD | rmesa->dri.hwContext), __ret ); \ | |||
| if ( __ret ) \ | |||
| r200GetLock( rmesa, 0 ); \ | |||
| DEBUG_LOCK(); \ | |||
| } while (0) | |||
| /* Unlock the hardware. | |||
| */ | |||
| #define UNLOCK_HARDWARE( rmesa ) \ | |||
| do { \ | |||
| DRM_UNLOCK( rmesa->dri.fd, \ | |||
| rmesa->dri.hwLock, \ | |||
| rmesa->dri.hwContext ); \ | |||
| DEBUG_RESET(); \ | |||
| } while (0) | |||
| #endif | |||
| #endif /* __R200_LOCK_H__ */ | |||
| @@ -0,0 +1,12 @@ | |||
| /* If using new packets, can choose either verts or arrays. | |||
| * Otherwise, must use verts. | |||
| */ | |||
| #include "r200_context.h" | |||
| #define R200_MAOS_VERTS 0 | |||
| #if (R200_MAOS_VERTS) || (R200_OLD_PACKETS) | |||
| #include "r200_maos_verts.c" | |||
| #else | |||
| #include "r200_maos_arrays.c" | |||
| #endif | |||
| @@ -0,0 +1,46 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #ifndef __R200_MAOS_H__ | |||
| #define __R200_MAOS_H__ | |||
| #ifdef GLX_DIRECT_RENDERING | |||
| #include "r200_context.h" | |||
| extern void r200EmitArrays( GLcontext *ctx, GLuint inputs ); | |||
| extern void r200ReleaseArrays( GLcontext *ctx, GLuint newinputs ); | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,481 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #include "glheader.h" | |||
| #include "mtypes.h" | |||
| #include "colormac.h" | |||
| #include "imports.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 "r200_context.h" | |||
| #include "r200_ioctl.h" | |||
| #include "r200_state.h" | |||
| #include "r200_swtcl.h" | |||
| #include "r200_maos.h" | |||
| /* Usage: | |||
| * - from r200_tcl_render | |||
| * - call r200EmitArrays to ensure uptodate arrays in dma | |||
| * - emit primitives (new type?) which reference the data | |||
| * -- need to use elts for lineloop, quads, quadstrip/flat | |||
| * -- other primitives are all well-formed (need tristrip-1,fake-poly) | |||
| * | |||
| */ | |||
| static void emit_ubyte_rgba3( GLcontext *ctx, | |||
| struct r200_dma_region *rvb, | |||
| char *data, | |||
| int stride, | |||
| int count ) | |||
| { | |||
| int i; | |||
| r200_color_t *out = (r200_color_t *)(rvb->start + rvb->address); | |||
| if (R200_DEBUG & DEBUG_VERTS) | |||
| fprintf(stderr, "%s count %d stride %d out %p\n", | |||
| __FUNCTION__, count, stride, 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 r200_dma_region *rvb, | |||
| char *data, | |||
| int stride, | |||
| int count ) | |||
| { | |||
| int i; | |||
| int *out = (int *)(rvb->address + rvb->start); | |||
| if (R200_DEBUG & DEBUG_VERTS) | |||
| fprintf(stderr, "%s count %d stride %d\n", | |||
| __FUNCTION__, count, stride); | |||
| if (stride == 4) { | |||
| for (i = 0; i < count; i++) | |||
| ((int *)out)[i] = LE32_TO_CPU(((int *)data)[i]); | |||
| } else { | |||
| for (i = 0; i < count; i++) { | |||
| *(int *)out++ = LE32_TO_CPU(*(int *)data); | |||
| data += stride; | |||
| } | |||
| } | |||
| } | |||
| static void emit_ubyte_rgba( GLcontext *ctx, | |||
| struct r200_dma_region *rvb, | |||
| char *data, | |||
| int size, | |||
| int stride, | |||
| int count ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| if (R200_DEBUG & DEBUG_VERTS) | |||
| fprintf(stderr, "%s %d/%d\n", __FUNCTION__, count, size); | |||
| assert (!rvb->buf); | |||
| if (stride == 0) { | |||
| r200AllocDmaRegion( rmesa, rvb, 4, 4 ); | |||
| count = 1; | |||
| rvb->aos_start = GET_START(rvb); | |||
| rvb->aos_stride = 0; | |||
| rvb->aos_size = 1; | |||
| } | |||
| else { | |||
| r200AllocDmaRegion( rmesa, rvb, 4 * count, 4 ); /* alignment? */ | |||
| rvb->aos_start = GET_START(rvb); | |||
| rvb->aos_stride = 1; | |||
| rvb->aos_size = 1; | |||
| } | |||
| /* Emit the data | |||
| */ | |||
| switch (size) { | |||
| case 3: | |||
| emit_ubyte_rgba3( ctx, rvb, data, stride, count ); | |||
| break; | |||
| case 4: | |||
| emit_ubyte_rgba4( ctx, rvb, data, stride, count ); | |||
| break; | |||
| default: | |||
| assert(0); | |||
| exit(1); | |||
| break; | |||
| } | |||
| } | |||
| static void emit_vec8( GLcontext *ctx, | |||
| struct r200_dma_region *rvb, | |||
| char *data, | |||
| int stride, | |||
| int count ) | |||
| { | |||
| int i; | |||
| int *out = (int *)(rvb->address + rvb->start); | |||
| if (R200_DEBUG & DEBUG_VERTS) | |||
| fprintf(stderr, "%s count %d stride %d\n", | |||
| __FUNCTION__, count, stride); | |||
| if (stride == 8) | |||
| COPY_DWORDS( out, data, count*2 ); | |||
| else | |||
| for (i = 0; i < count; i++) { | |||
| out[0] = *(int *)data; | |||
| out[1] = *(int *)(data+4); | |||
| out += 2; | |||
| data += stride; | |||
| } | |||
| } | |||
| static void emit_vec12( GLcontext *ctx, | |||
| struct r200_dma_region *rvb, | |||
| char *data, | |||
| int stride, | |||
| int count ) | |||
| { | |||
| int i; | |||
| int *out = (int *)(rvb->address + rvb->start); | |||
| if (R200_DEBUG & DEBUG_VERTS) | |||
| fprintf(stderr, "%s count %d stride %d out %p data %p\n", | |||
| __FUNCTION__, count, stride, 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 r200_dma_region *rvb, | |||
| char *data, | |||
| int stride, | |||
| int count ) | |||
| { | |||
| int i; | |||
| int *out = (int *)(rvb->address + rvb->start); | |||
| if (R200_DEBUG & DEBUG_VERTS) | |||
| fprintf(stderr, "%s count %d stride %d\n", | |||
| __FUNCTION__, count, stride); | |||
| if (stride == 16) | |||
| COPY_DWORDS( out, data, count*4 ); | |||
| else | |||
| for (i = 0; i < count; i++) { | |||
| out[0] = *(int *)data; | |||
| out[1] = *(int *)(data+4); | |||
| out[2] = *(int *)(data+8); | |||
| out[3] = *(int *)(data+12); | |||
| out += 4; | |||
| data += stride; | |||
| } | |||
| } | |||
| static void emit_vector( GLcontext *ctx, | |||
| struct r200_dma_region *rvb, | |||
| char *data, | |||
| int size, | |||
| int stride, | |||
| int count ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| if (R200_DEBUG & DEBUG_VERTS) | |||
| fprintf(stderr, "%s count %d size %d stride %d\n", | |||
| __FUNCTION__, count, size, stride); | |||
| assert (!rvb->buf); | |||
| if (stride == 0) { | |||
| r200AllocDmaRegion( rmesa, rvb, size * 4, 4 ); | |||
| count = 1; | |||
| rvb->aos_start = GET_START(rvb); | |||
| rvb->aos_stride = 0; | |||
| rvb->aos_size = size; | |||
| } | |||
| else { | |||
| r200AllocDmaRegion( rmesa, rvb, size * count * 4, 4 ); /* alignment? */ | |||
| rvb->aos_start = GET_START(rvb); | |||
| rvb->aos_stride = size; | |||
| rvb->aos_size = size; | |||
| } | |||
| /* Emit the data | |||
| */ | |||
| switch (size) { | |||
| case 2: | |||
| emit_vec8( ctx, rvb, data, stride, count ); | |||
| break; | |||
| case 3: | |||
| emit_vec12( ctx, rvb, data, stride, count ); | |||
| break; | |||
| case 4: | |||
| emit_vec16( ctx, rvb, data, stride, count ); | |||
| break; | |||
| default: | |||
| assert(0); | |||
| exit(1); | |||
| break; | |||
| } | |||
| } | |||
| /* Emit any changed arrays to new agp memory, re-emit a packet to | |||
| * update the arrays. | |||
| */ | |||
| void r200EmitArrays( GLcontext *ctx, GLuint inputs ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT( ctx ); | |||
| struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb; | |||
| struct r200_dma_region **component = rmesa->tcl.aos_components; | |||
| GLuint nr = 0; | |||
| GLuint vfmt0 = 0, vfmt1 = 0; | |||
| GLuint count = VB->Count; | |||
| if (R200_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: vfmt0 |= R200_VTX_W0; | |||
| case 3: vfmt0 |= R200_VTX_Z0; | |||
| case 2: | |||
| default: | |||
| break; | |||
| } | |||
| component[nr++] = &rmesa->tcl.obj; | |||
| } | |||
| if (inputs & VERT_BIT_NORMAL) { | |||
| if (!rmesa->tcl.norm.buf) | |||
| emit_vector( ctx, | |||
| &(rmesa->tcl.norm), | |||
| (char *)VB->NormalPtr->data, | |||
| 3, | |||
| VB->NormalPtr->stride, | |||
| count); | |||
| vfmt0 |= R200_VTX_N0; | |||
| component[nr++] = &rmesa->tcl.norm; | |||
| } | |||
| if (inputs & VERT_BIT_COLOR0) { | |||
| 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); | |||
| vfmt0 |= R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT; | |||
| } | |||
| else { | |||
| int emitsize; | |||
| if (VB->ColorPtr[0]->Size == 4 && | |||
| (VB->ColorPtr[0]->StrideB != 0 || | |||
| ((GLfloat *)VB->ColorPtr[0]->Ptr)[3] != 1.0)) { | |||
| vfmt0 |= R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT; | |||
| emitsize = 4; | |||
| } | |||
| else { | |||
| vfmt0 |= R200_VTX_FP_RGB << R200_VTX_COLOR_0_SHIFT; | |||
| 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_BIT_COLOR1) { | |||
| if (!rmesa->tcl.spec.buf) { | |||
| if (VB->SecondaryColorPtr[0]->Type != GL_UNSIGNED_BYTE) | |||
| r200_import_float_spec_colors( ctx ); | |||
| emit_ubyte_rgba( ctx, | |||
| &rmesa->tcl.spec, | |||
| (char *)VB->SecondaryColorPtr[0]->Ptr, | |||
| 3, | |||
| VB->SecondaryColorPtr[0]->StrideB, | |||
| count); | |||
| } | |||
| /* How does this work? | |||
| */ | |||
| vfmt0 |= R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT; | |||
| component[nr++] = &rmesa->tcl.spec; | |||
| } | |||
| /* vtx = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] & */ | |||
| /* ~(R200_TCL_VTX_Q0|R200_TCL_VTX_Q1)); */ | |||
| if (inputs & VERT_BIT_TEX0) { | |||
| if (!rmesa->tcl.tex[0].buf) | |||
| emit_vector( ctx, | |||
| &(rmesa->tcl.tex[0]), | |||
| (char *)VB->TexCoordPtr[0]->data, | |||
| VB->TexCoordPtr[0]->size, | |||
| VB->TexCoordPtr[0]->stride, | |||
| count ); | |||
| vfmt1 |= VB->TexCoordPtr[0]->size << R200_VTX_TEX0_COMP_CNT_SHIFT; | |||
| component[nr++] = &rmesa->tcl.tex[0]; | |||
| } | |||
| if (inputs & VERT_BIT_TEX1) { | |||
| if (!rmesa->tcl.tex[1].buf) | |||
| emit_vector( ctx, | |||
| &(rmesa->tcl.tex[1]), | |||
| (char *)VB->TexCoordPtr[1]->data, | |||
| VB->TexCoordPtr[1]->size, | |||
| VB->TexCoordPtr[1]->stride, | |||
| count ); | |||
| vfmt1 |= VB->TexCoordPtr[1]->size << R200_VTX_TEX1_COMP_CNT_SHIFT; | |||
| component[nr++] = &rmesa->tcl.tex[1]; | |||
| } | |||
| if (vfmt0 != rmesa->hw.vtx.cmd[VTX_VTXFMT_0] || | |||
| vfmt1 != rmesa->hw.vtx.cmd[VTX_VTXFMT_1]) { | |||
| R200_STATECHANGE( rmesa, vtx ); | |||
| rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = vfmt0; | |||
| rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = vfmt1; | |||
| } | |||
| /* fprintf(stderr, "VTXFMT_0: %x VTXFMT_1: %x\n", vfmt0, vfmt1); */ | |||
| rmesa->tcl.nr_aos_components = nr; | |||
| rmesa->tcl.vertex_format = vfmt0; | |||
| } | |||
| void r200ReleaseArrays( GLcontext *ctx, GLuint newinputs ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT( ctx ); | |||
| if (R200_DEBUG & DEBUG_VERTS) | |||
| _tnl_print_vert_flags( __FUNCTION__, newinputs ); | |||
| if (newinputs & VERT_BIT_POS) | |||
| r200ReleaseDmaRegion( rmesa, &rmesa->tcl.obj, __FUNCTION__ ); | |||
| if (newinputs & VERT_BIT_NORMAL) | |||
| r200ReleaseDmaRegion( rmesa, &rmesa->tcl.norm, __FUNCTION__ ); | |||
| if (newinputs & VERT_BIT_COLOR0) | |||
| r200ReleaseDmaRegion( rmesa, &rmesa->tcl.rgba, __FUNCTION__ ); | |||
| if (newinputs & VERT_BIT_COLOR1) | |||
| r200ReleaseDmaRegion( rmesa, &rmesa->tcl.spec, __FUNCTION__ ); | |||
| if (newinputs & VERT_BIT_TEX0) | |||
| r200ReleaseDmaRegion( rmesa, &rmesa->tcl.tex[0], __FUNCTION__ ); | |||
| if (newinputs & VERT_BIT_TEX1) | |||
| r200ReleaseDmaRegion( rmesa, &rmesa->tcl.tex[1], __FUNCTION__ ); | |||
| } | |||
| @@ -0,0 +1,378 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #ifndef 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 (R200_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].ub[0] = spec[0][0]; | |||
| v[0].ub[1] = spec[0][1]; | |||
| v[0].ub[2] = spec[0][2]; | |||
| STRIDE_4UB(spec, spec_stride); | |||
| } | |||
| if (DO_FOG) { | |||
| v[0].ub[3] = 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].ub[0] = spec[i][0]; | |||
| v[0].ub[1] = spec[i][1]; | |||
| v[0].ub[2] = spec[i][2]; | |||
| } | |||
| if (DO_FOG) { | |||
| v[0].ub[3] = 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 | |||
| @@ -0,0 +1,338 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #include "glheader.h" | |||
| #include "imports.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" | |||
| #include "r200_context.h" | |||
| #include "r200_state.h" | |||
| #include "r200_ioctl.h" | |||
| #include "r200_tex.h" | |||
| #include "r200_tcl.h" | |||
| #include "r200_swtcl.h" | |||
| #include "r200_maos.h" | |||
| #define R200_TCL_MAX_SETUP 13 | |||
| union emit_union { float f; GLuint ui; GLubyte ub[4]; }; | |||
| static struct { | |||
| void (*emit)( GLcontext *, GLuint, GLuint, void * ); | |||
| GLuint vertex_size; | |||
| GLuint vertex_format; | |||
| } setup_tab[R200_TCL_MAX_SETUP]; | |||
| #define DO_W (IND & R200_CP_VC_FRMT_W0) | |||
| #define DO_RGBA (IND & R200_CP_VC_FRMT_PKCOLOR) | |||
| #define DO_SPEC (IND & R200_CP_VC_FRMT_PKSPEC) | |||
| #define DO_FOG (IND & R200_CP_VC_FRMT_PKSPEC) | |||
| #define DO_TEX0 (IND & R200_CP_VC_FRMT_ST0) | |||
| #define DO_TEX1 (IND & R200_CP_VC_FRMT_ST1) | |||
| #define DO_PTEX (IND & R200_CP_VC_FRMT_Q0) | |||
| #define DO_NORM (IND & R200_CP_VC_FRMT_N0) | |||
| #define DO_TEX2 0 | |||
| #define DO_TEX3 0 | |||
| #define GET_TEXSOURCE(n) n | |||
| #define GET_UBYTE_COLOR_STORE() &R200_CONTEXT(ctx)->UbyteColor | |||
| #define GET_UBYTE_SPEC_COLOR_STORE() &R200_CONTEXT(ctx)->UbyteSecondaryColor | |||
| #define IMPORT_FLOAT_COLORS r200_import_float_colors | |||
| #define IMPORT_FLOAT_SPEC_COLORS r200_import_float_spec_colors | |||
| /*********************************************************************** | |||
| * Generate vertex emit functions * | |||
| ***********************************************************************/ | |||
| /* Defined in order of increasing vertex size: | |||
| */ | |||
| #define IDX 0 | |||
| #define IND (R200_CP_VC_FRMT_XY| \ | |||
| R200_CP_VC_FRMT_Z| \ | |||
| R200_CP_VC_FRMT_PKCOLOR) | |||
| #define TAG(x) x##_rgba | |||
| #include "r200_maos_vbtmp.h" | |||
| #define IDX 1 | |||
| #define IND (R200_CP_VC_FRMT_XY| \ | |||
| R200_CP_VC_FRMT_Z| \ | |||
| R200_CP_VC_FRMT_N0) | |||
| #define TAG(x) x##_n | |||
| #include "r200_maos_vbtmp.h" | |||
| #define IDX 2 | |||
| #define IND (R200_CP_VC_FRMT_XY| \ | |||
| R200_CP_VC_FRMT_Z| \ | |||
| R200_CP_VC_FRMT_PKCOLOR| \ | |||
| R200_CP_VC_FRMT_ST0) | |||
| #define TAG(x) x##_rgba_st | |||
| #include "r200_maos_vbtmp.h" | |||
| #define IDX 3 | |||
| #define IND (R200_CP_VC_FRMT_XY| \ | |||
| R200_CP_VC_FRMT_Z| \ | |||
| R200_CP_VC_FRMT_PKCOLOR| \ | |||
| R200_CP_VC_FRMT_N0) | |||
| #define TAG(x) x##_rgba_n | |||
| #include "r200_maos_vbtmp.h" | |||
| #define IDX 4 | |||
| #define IND (R200_CP_VC_FRMT_XY| \ | |||
| R200_CP_VC_FRMT_Z| \ | |||
| R200_CP_VC_FRMT_ST0| \ | |||
| R200_CP_VC_FRMT_N0) | |||
| #define TAG(x) x##_st_n | |||
| #include "r200_maos_vbtmp.h" | |||
| #define IDX 5 | |||
| #define IND (R200_CP_VC_FRMT_XY| \ | |||
| R200_CP_VC_FRMT_Z| \ | |||
| R200_CP_VC_FRMT_PKCOLOR| \ | |||
| R200_CP_VC_FRMT_ST0| \ | |||
| R200_CP_VC_FRMT_ST1) | |||
| #define TAG(x) x##_rgba_st_st | |||
| #include "r200_maos_vbtmp.h" | |||
| #define IDX 6 | |||
| #define IND (R200_CP_VC_FRMT_XY| \ | |||
| R200_CP_VC_FRMT_Z| \ | |||
| R200_CP_VC_FRMT_PKCOLOR| \ | |||
| R200_CP_VC_FRMT_ST0| \ | |||
| R200_CP_VC_FRMT_N0) | |||
| #define TAG(x) x##_rgba_st_n | |||
| #include "r200_maos_vbtmp.h" | |||
| #define IDX 7 | |||
| #define IND (R200_CP_VC_FRMT_XY| \ | |||
| R200_CP_VC_FRMT_Z| \ | |||
| R200_CP_VC_FRMT_PKCOLOR| \ | |||
| R200_CP_VC_FRMT_PKSPEC| \ | |||
| R200_CP_VC_FRMT_ST0| \ | |||
| R200_CP_VC_FRMT_ST1) | |||
| #define TAG(x) x##_rgba_spec_st_st | |||
| #include "r200_maos_vbtmp.h" | |||
| #define IDX 8 | |||
| #define IND (R200_CP_VC_FRMT_XY| \ | |||
| R200_CP_VC_FRMT_Z| \ | |||
| R200_CP_VC_FRMT_ST0| \ | |||
| R200_CP_VC_FRMT_ST1| \ | |||
| R200_CP_VC_FRMT_N0) | |||
| #define TAG(x) x##_st_st_n | |||
| #include "r200_maos_vbtmp.h" | |||
| #define IDX 9 | |||
| #define IND (R200_CP_VC_FRMT_XY| \ | |||
| R200_CP_VC_FRMT_Z| \ | |||
| R200_CP_VC_FRMT_PKCOLOR| \ | |||
| R200_CP_VC_FRMT_PKSPEC| \ | |||
| R200_CP_VC_FRMT_ST0| \ | |||
| R200_CP_VC_FRMT_ST1| \ | |||
| R200_CP_VC_FRMT_N0) | |||
| #define TAG(x) x##_rgpa_spec_st_st_n | |||
| #include "r200_maos_vbtmp.h" | |||
| #define IDX 10 | |||
| #define IND (R200_CP_VC_FRMT_XY| \ | |||
| R200_CP_VC_FRMT_Z| \ | |||
| R200_CP_VC_FRMT_PKCOLOR| \ | |||
| R200_CP_VC_FRMT_ST0| \ | |||
| R200_CP_VC_FRMT_Q0) | |||
| #define TAG(x) x##_rgba_stq | |||
| #include "r200_maos_vbtmp.h" | |||
| #define IDX 11 | |||
| #define IND (R200_CP_VC_FRMT_XY| \ | |||
| R200_CP_VC_FRMT_Z| \ | |||
| R200_CP_VC_FRMT_PKCOLOR| \ | |||
| R200_CP_VC_FRMT_ST1| \ | |||
| R200_CP_VC_FRMT_Q1| \ | |||
| R200_CP_VC_FRMT_ST0| \ | |||
| R200_CP_VC_FRMT_Q0) | |||
| #define TAG(x) x##_rgba_stq_stq | |||
| #include "r200_maos_vbtmp.h" | |||
| #define IDX 12 | |||
| #define IND (R200_CP_VC_FRMT_XY| \ | |||
| R200_CP_VC_FRMT_Z| \ | |||
| R200_CP_VC_FRMT_W0| \ | |||
| R200_CP_VC_FRMT_PKCOLOR| \ | |||
| R200_CP_VC_FRMT_PKSPEC| \ | |||
| R200_CP_VC_FRMT_ST0| \ | |||
| R200_CP_VC_FRMT_Q0| \ | |||
| R200_CP_VC_FRMT_ST1| \ | |||
| R200_CP_VC_FRMT_Q1| \ | |||
| R200_CP_VC_FRMT_N0) | |||
| #define TAG(x) x##_w_rgpa_spec_stq_stq_n | |||
| #include "r200_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 r200EmitArrays( GLcontext *ctx, GLuint inputs ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; | |||
| GLuint req = 0; | |||
| GLuint vtx = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] & | |||
| ~(R200_TCL_VTX_Q0|R200_TCL_VTX_Q1)); | |||
| int i; | |||
| static int firsttime = 1; | |||
| if (firsttime) { | |||
| init_tcl_verts(); | |||
| firsttime = 0; | |||
| } | |||
| if (1) { | |||
| req |= R200_CP_VC_FRMT_Z; | |||
| if (VB->ObjPtr->size == 4) { | |||
| req |= R200_CP_VC_FRMT_W0; | |||
| } | |||
| } | |||
| if (inputs & VERT_BIT_NORMAL) { | |||
| req |= R200_CP_VC_FRMT_N0; | |||
| } | |||
| if (inputs & VERT_BIT_COLOR0) { | |||
| req |= R200_CP_VC_FRMT_PKCOLOR; | |||
| } | |||
| if (inputs & VERT_BIT_COLOR1) { | |||
| req |= R200_CP_VC_FRMT_PKSPEC; | |||
| } | |||
| if (inputs & VERT_BIT_TEX0) { | |||
| req |= R200_CP_VC_FRMT_ST0; | |||
| if (VB->TexCoordPtr[0]->size == 4) { | |||
| req |= R200_CP_VC_FRMT_Q0; | |||
| vtx |= R200_TCL_VTX_Q0; | |||
| } | |||
| } | |||
| if (inputs & VERT_BIT_TEX1) { | |||
| req |= R200_CP_VC_FRMT_ST1; | |||
| if (VB->TexCoordPtr[1]->size == 4) { | |||
| req |= R200_CP_VC_FRMT_Q1; | |||
| vtx |= R200_TCL_VTX_Q1; | |||
| } | |||
| } | |||
| if (vtx != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT]) { | |||
| R200_STATECHANGE( rmesa, tcl ); | |||
| rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] = vtx; | |||
| } | |||
| for (i = 0 ; i < R200_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) | |||
| r200ReleaseArrays( ctx, ~0 ); | |||
| r200AllocDmaRegionVerts( 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 r200ReleaseArrays( GLcontext *ctx, GLuint newinputs ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT( ctx ); | |||
| if (R200_DEBUG & DEBUG_VERTS) | |||
| _tnl_print_vert_flags( __FUNCTION__, newinputs ); | |||
| if (newinputs) | |||
| r200ReleaseDmaRegion( rmesa, &rmesa->tcl.indexed_verts, __FUNCTION__ ); | |||
| } | |||
| @@ -0,0 +1,494 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #include "glheader.h" | |||
| #include "enums.h" | |||
| #include "mtypes.h" | |||
| #include "macros.h" | |||
| #include "texutil.h" | |||
| #include "swrast/swrast.h" | |||
| #include "r200_context.h" | |||
| #include "r200_ioctl.h" | |||
| #include "r200_pixel.h" | |||
| #include "r200_swtcl.h" | |||
| static GLboolean | |||
| check_color( const GLcontext *ctx, GLenum type, GLenum format, | |||
| const struct gl_pixelstore_attrib *packing, | |||
| const void *pixels, GLint sz, GLint pitch ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| GLuint cpp = rmesa->r200Screen->cpp; | |||
| if (R200_DEBUG & DEBUG_PIXEL) | |||
| fprintf(stderr, "%s\n", __FUNCTION__); | |||
| if ( (pitch & 63) || | |||
| ctx->_ImageTransferState || | |||
| packing->SwapBytes || | |||
| packing->LsbFirst) { | |||
| if (R200_DEBUG & DEBUG_PIXEL) | |||
| fprintf(stderr, "%s: failed 1\n", __FUNCTION__); | |||
| return GL_FALSE; | |||
| } | |||
| if ( type == GL_UNSIGNED_INT_8_8_8_8_REV && | |||
| cpp == 4 && | |||
| format == GL_BGRA ) { | |||
| if (R200_DEBUG & DEBUG_PIXEL) | |||
| fprintf(stderr, "%s: passed 2\n", __FUNCTION__); | |||
| return GL_TRUE; | |||
| } | |||
| if (R200_DEBUG & DEBUG_PIXEL) | |||
| fprintf(stderr, "%s: failed\n", __FUNCTION__); | |||
| return GL_FALSE; | |||
| } | |||
| static GLboolean | |||
| check_color_per_fragment_ops( const GLcontext *ctx ) | |||
| { | |||
| int result; | |||
| result = (!( ctx->Color.AlphaEnabled || | |||
| ctx->Depth.Test || | |||
| ctx->Fog.Enabled || | |||
| ctx->Scissor.Enabled || | |||
| ctx->Stencil.Enabled || | |||
| !ctx->Color.ColorMask[0] || | |||
| !ctx->Color.ColorMask[1] || | |||
| !ctx->Color.ColorMask[2] || | |||
| !ctx->Color.ColorMask[3] || | |||
| ctx->Color.ColorLogicOpEnabled || | |||
| ctx->Texture._EnabledUnits || | |||
| ctx->Depth.OcclusionTest | |||
| ) && | |||
| ctx->Current.RasterPosValid); | |||
| return result; | |||
| } | |||
| static GLboolean | |||
| clip_pixelrect( const GLcontext *ctx, | |||
| const GLframebuffer *buffer, | |||
| GLint *x, GLint *y, | |||
| GLsizei *width, GLsizei *height, | |||
| GLint *size ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| /* left clipping */ | |||
| if (*x < buffer->_Xmin) { | |||
| *width -= (buffer->_Xmin - *x); | |||
| *x = buffer->_Xmin; | |||
| } | |||
| /* right clipping */ | |||
| if (*x + *width > buffer->_Xmax) | |||
| *width -= (*x + *width - buffer->_Xmax - 1); | |||
| if (*width <= 0) | |||
| return GL_FALSE; | |||
| /* bottom clipping */ | |||
| if (*y < buffer->_Ymin) { | |||
| *height -= (buffer->_Ymin - *y); | |||
| *y = buffer->_Ymin; | |||
| } | |||
| /* top clipping */ | |||
| if (*y + *height > buffer->_Ymax) | |||
| *height -= (*y + *height - buffer->_Ymax - 1); | |||
| if (*height <= 0) | |||
| return GL_FALSE; | |||
| *size = ((*y + *height - 1) * rmesa->r200Screen->frontPitch + | |||
| (*x + *width - 1) * rmesa->r200Screen->cpp); | |||
| return GL_TRUE; | |||
| } | |||
| static GLboolean | |||
| r200TryReadPixels( GLcontext *ctx, | |||
| GLint x, GLint y, GLsizei width, GLsizei height, | |||
| GLenum format, GLenum type, | |||
| const struct gl_pixelstore_attrib *pack, | |||
| GLvoid *pixels ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| GLint size; | |||
| GLint pitch = pack->RowLength ? pack->RowLength : width; | |||
| GLint blit_format; | |||
| if (R200_DEBUG & DEBUG_PIXEL) | |||
| fprintf(stderr, "%s\n", __FUNCTION__); | |||
| /* Only accelerate reading to agp buffers. | |||
| */ | |||
| if ( !r200IsAgpMemory(rmesa, pixels, | |||
| pitch * height * rmesa->r200Screen->cpp ) ) { | |||
| if (R200_DEBUG & DEBUG_PIXEL) | |||
| fprintf(stderr, "%s: dest not agp\n", __FUNCTION__); | |||
| return GL_FALSE; | |||
| } | |||
| /* Need GL_PACK_INVERT_MESA to cope with upsidedown results from | |||
| * blitter: | |||
| */ | |||
| if (!pack->Invert) { | |||
| if (R200_DEBUG & DEBUG_PIXEL) | |||
| fprintf(stderr, "%s: MESA_PACK_INVERT not set\n", __FUNCTION__); | |||
| return GL_FALSE; | |||
| } | |||
| if (!check_color(ctx, type, format, pack, pixels, size, pitch)) | |||
| return GL_FALSE; | |||
| switch ( rmesa->r200Screen->cpp ) { | |||
| case 4: | |||
| blit_format = R200_CP_COLOR_FORMAT_ARGB8888; | |||
| break; | |||
| default: | |||
| return GL_FALSE; | |||
| } | |||
| /* Although the blits go on the command buffer, need to do this and | |||
| * fire with lock held to guarentee cliprects and drawOffset are | |||
| * correct. | |||
| * | |||
| * This is an unusual situation however, as the code which flushes | |||
| * a full command buffer expects to be called unlocked. As a | |||
| * workaround, immediately flush the buffer on aquiring the lock. | |||
| */ | |||
| LOCK_HARDWARE( rmesa ); | |||
| if (rmesa->store.cmd_used) | |||
| r200FlushCmdBufLocked( rmesa, __FUNCTION__ ); | |||
| if (!clip_pixelrect(ctx, ctx->ReadBuffer, &x, &y, &width, &height, | |||
| &size)) { | |||
| UNLOCK_HARDWARE( rmesa ); | |||
| if (R200_DEBUG & DEBUG_PIXEL) | |||
| fprintf(stderr, "%s totally clipped -- nothing to do\n", | |||
| __FUNCTION__); | |||
| return GL_TRUE; | |||
| } | |||
| { | |||
| __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; | |||
| int nbox = dPriv->numClipRects; | |||
| int src_offset = rmesa->state.color.drawOffset; | |||
| int src_pitch = rmesa->state.color.drawPitch * rmesa->r200Screen->cpp; | |||
| int dst_offset = r200AgpOffsetFromVirtual( rmesa, pixels); | |||
| int dst_pitch = pitch * rmesa->r200Screen->cpp; | |||
| XF86DRIClipRectRec *box = dPriv->pClipRects; | |||
| int i; | |||
| r200EmitWait( rmesa, RADEON_WAIT_3D ); | |||
| y = dPriv->h - y - height; | |||
| x += dPriv->x; | |||
| y += dPriv->y; | |||
| if (R200_DEBUG & DEBUG_PIXEL) | |||
| fprintf(stderr, "readpixel blit src_pitch %d dst_pitch %d\n", | |||
| src_pitch, dst_pitch); | |||
| for (i = 0 ; i < nbox ; i++) | |||
| { | |||
| GLint bx = box[i].x1; | |||
| GLint by = box[i].y1; | |||
| GLint bw = box[i].x2 - bx; | |||
| GLint bh = box[i].y2 - by; | |||
| if (bx < x) bw -= x - bx, bx = x; | |||
| if (by < y) bh -= y - by, by = y; | |||
| if (bx + bw > x + width) bw = x + width - bx; | |||
| if (by + bh > y + height) bh = y + height - by; | |||
| if (bw <= 0) continue; | |||
| if (bh <= 0) continue; | |||
| r200EmitBlit( rmesa, | |||
| blit_format, | |||
| src_pitch, src_offset, | |||
| dst_pitch, dst_offset, | |||
| bx, by, | |||
| bx - x, by - y, | |||
| bw, bh ); | |||
| } | |||
| r200FlushCmdBufLocked( rmesa, __FUNCTION__ ); | |||
| } | |||
| UNLOCK_HARDWARE( rmesa ); | |||
| r200Finish( ctx ); /* required by GL */ | |||
| return GL_TRUE; | |||
| } | |||
| static void | |||
| r200ReadPixels( GLcontext *ctx, | |||
| GLint x, GLint y, GLsizei width, GLsizei height, | |||
| GLenum format, GLenum type, | |||
| const struct gl_pixelstore_attrib *pack, | |||
| GLvoid *pixels ) | |||
| { | |||
| if (R200_DEBUG & DEBUG_PIXEL) | |||
| fprintf(stderr, "%s\n", __FUNCTION__); | |||
| if (!r200TryReadPixels( ctx, x, y, width, height, format, type, pack, | |||
| pixels)) | |||
| _swrast_ReadPixels( ctx, x, y, width, height, format, type, pack, | |||
| pixels); | |||
| } | |||
| static void do_draw_pix( GLcontext *ctx, | |||
| GLint x, GLint y, GLsizei width, GLsizei height, | |||
| GLint pitch, | |||
| const void *pixels, | |||
| GLuint dest, GLuint planemask) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; | |||
| XF86DRIClipRectPtr box = dPriv->pClipRects; | |||
| int nbox = dPriv->numClipRects; | |||
| int i; | |||
| int blit_format; | |||
| int size; | |||
| int src_offset = r200AgpOffsetFromVirtual( rmesa, pixels); | |||
| int src_pitch = pitch * rmesa->r200Screen->cpp; | |||
| if (R200_DEBUG & DEBUG_PIXEL) | |||
| fprintf(stderr, "%s\n", __FUNCTION__); | |||
| switch ( rmesa->r200Screen->cpp ) { | |||
| case 2: | |||
| blit_format = R200_CP_COLOR_FORMAT_RGB565; | |||
| break; | |||
| case 4: | |||
| blit_format = R200_CP_COLOR_FORMAT_ARGB8888; | |||
| break; | |||
| default: | |||
| return; | |||
| } | |||
| LOCK_HARDWARE( rmesa ); | |||
| if (rmesa->store.cmd_used) | |||
| r200FlushCmdBufLocked( rmesa, __FUNCTION__ ); | |||
| y -= height; /* cope with pixel zoom */ | |||
| if (!clip_pixelrect(ctx, ctx->DrawBuffer, | |||
| &x, &y, &width, &height, | |||
| &size)) { | |||
| UNLOCK_HARDWARE( rmesa ); | |||
| return; | |||
| } | |||
| y = dPriv->h - y - height; /* convert from gl to hardware coords */ | |||
| x += dPriv->x; | |||
| y += dPriv->y; | |||
| r200EmitWait( rmesa, RADEON_WAIT_3D ); | |||
| for (i = 0 ; i < nbox ; i++ ) | |||
| { | |||
| GLint bx = box[i].x1; | |||
| GLint by = box[i].y1; | |||
| GLint bw = box[i].x2 - bx; | |||
| GLint bh = box[i].y2 - by; | |||
| if (bx < x) bw -= x - bx, bx = x; | |||
| if (by < y) bh -= y - by, by = y; | |||
| if (bx + bw > x + width) bw = x + width - bx; | |||
| if (by + bh > y + height) bh = y + height - by; | |||
| if (bw <= 0) continue; | |||
| if (bh <= 0) continue; | |||
| r200EmitBlit( rmesa, | |||
| blit_format, | |||
| src_pitch, src_offset, | |||
| rmesa->state.color.drawPitch * rmesa->r200Screen->cpp, | |||
| rmesa->state.color.drawOffset, | |||
| bx - x, by - y, | |||
| bx, by, | |||
| bw, bh ); | |||
| } | |||
| r200FlushCmdBufLocked( rmesa, __FUNCTION__ ); | |||
| r200WaitForIdleLocked( rmesa ); /* required by GL */ | |||
| UNLOCK_HARDWARE( rmesa ); | |||
| } | |||
| static GLboolean | |||
| r200TryDrawPixels( GLcontext *ctx, | |||
| GLint x, GLint y, GLsizei width, GLsizei height, | |||
| GLenum format, GLenum type, | |||
| const struct gl_pixelstore_attrib *unpack, | |||
| const GLvoid *pixels ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| GLint pitch = unpack->RowLength ? unpack->RowLength : width; | |||
| GLuint dest, planemask; | |||
| GLuint cpp = rmesa->r200Screen->cpp; | |||
| GLint size = width * pitch * cpp; | |||
| if (R200_DEBUG & DEBUG_PIXEL) | |||
| fprintf(stderr, "%s\n", __FUNCTION__); | |||
| switch (format) { | |||
| case GL_RGB: | |||
| case GL_RGBA: | |||
| case GL_BGRA: | |||
| dest = rmesa->state.color.drawOffset; | |||
| planemask = r200PackColor(cpp, | |||
| ctx->Color.ColorMask[RCOMP], | |||
| ctx->Color.ColorMask[GCOMP], | |||
| ctx->Color.ColorMask[BCOMP], | |||
| ctx->Color.ColorMask[ACOMP]); | |||
| if (cpp == 2) | |||
| planemask |= planemask << 16; | |||
| if (planemask != ~0) | |||
| return GL_FALSE; /* fix me -- should be possible */ | |||
| /* Can't do conversions on agp reads/draws. | |||
| */ | |||
| if ( !r200IsAgpMemory( rmesa, pixels, size ) ) { | |||
| if (R200_DEBUG & DEBUG_PIXEL) | |||
| fprintf(stderr, "%s: not agp memory\n", __FUNCTION__); | |||
| return GL_FALSE; | |||
| } | |||
| if (!check_color(ctx, type, format, unpack, pixels, size, pitch)) { | |||
| return GL_FALSE; | |||
| } | |||
| if (!check_color_per_fragment_ops(ctx)) { | |||
| return GL_FALSE; | |||
| } | |||
| if (ctx->Pixel.ZoomX != 1.0F || | |||
| ctx->Pixel.ZoomY != -1.0F) | |||
| return GL_FALSE; | |||
| break; | |||
| default: | |||
| return GL_FALSE; | |||
| } | |||
| if ( r200IsAgpMemory(rmesa, pixels, size) ) | |||
| { | |||
| do_draw_pix( ctx, x, y, width, height, pitch, pixels, | |||
| dest, planemask ); | |||
| return GL_TRUE; | |||
| } | |||
| else if (0) | |||
| { | |||
| /* Pixels is in regular memory -- get dma buffers and perform | |||
| * upload through them. | |||
| */ | |||
| } | |||
| else | |||
| return GL_FALSE; | |||
| } | |||
| static void | |||
| r200DrawPixels( GLcontext *ctx, | |||
| GLint x, GLint y, GLsizei width, GLsizei height, | |||
| GLenum format, GLenum type, | |||
| const struct gl_pixelstore_attrib *unpack, | |||
| const GLvoid *pixels ) | |||
| { | |||
| if (R200_DEBUG & DEBUG_PIXEL) | |||
| fprintf(stderr, "%s\n", __FUNCTION__); | |||
| if (!r200TryDrawPixels( ctx, x, y, width, height, format, type, | |||
| unpack, pixels )) | |||
| _swrast_DrawPixels( ctx, x, y, width, height, format, type, | |||
| unpack, pixels ); | |||
| } | |||
| static void | |||
| r200Bitmap( GLcontext *ctx, GLint px, GLint py, | |||
| GLsizei width, GLsizei height, | |||
| const struct gl_pixelstore_attrib *unpack, | |||
| const GLubyte *bitmap ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| if (rmesa->Fallback) | |||
| _swrast_Bitmap( ctx, px, py, width, height, unpack, bitmap ); | |||
| else | |||
| r200PointsBitmap( ctx, px, py, width, height, unpack, bitmap ); | |||
| } | |||
| void r200InitPixelFuncs( GLcontext *ctx ) | |||
| { | |||
| /* Pixel path fallbacks. | |||
| */ | |||
| ctx->Driver.Accum = _swrast_Accum; | |||
| ctx->Driver.Bitmap = _swrast_Bitmap; | |||
| ctx->Driver.CopyPixels = _swrast_CopyPixels; | |||
| ctx->Driver.DrawPixels = _swrast_DrawPixels; | |||
| ctx->Driver.ReadPixels = _swrast_ReadPixels; | |||
| if (!getenv("R200_NO_BLITS") && R200_CONTEXT(ctx)->dri.drmMinor >= 6) { | |||
| ctx->Driver.ReadPixels = r200ReadPixels; | |||
| ctx->Driver.DrawPixels = r200DrawPixels; | |||
| if (getenv("R200_HW_BITMAP")) | |||
| ctx->Driver.Bitmap = r200Bitmap; | |||
| } | |||
| } | |||
| @@ -0,0 +1,43 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #ifndef __R200_PIXEL_H__ | |||
| #define __R200_PIXEL_H__ | |||
| #ifdef GLX_DIRECT_RENDERING | |||
| extern void r200InitPixelFuncs( GLcontext *ctx ); | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,11 @@ | |||
| #ifndef R200_SANITY_H | |||
| #define R200_SANITY_H | |||
| extern int r200SanityCmdBuffer( r200ContextPtr rmesa, | |||
| int nbox, | |||
| XF86DRIClipRectRec *boxes ); | |||
| extern int r200ValidateTexObjs( r200ContextPtr rmesa ); | |||
| #endif | |||
| @@ -0,0 +1,434 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #include <dlfcn.h> | |||
| #include "glheader.h" | |||
| #include "imports.h" | |||
| #include "context.h" | |||
| #include "r200_screen.h" | |||
| #include "r200_context.h" | |||
| #include "r200_ioctl.h" | |||
| #if 1 | |||
| /* Including xf86PciInfo.h introduces a bunch of errors... | |||
| */ | |||
| #define PCI_CHIP_R200_QD 0x5144 | |||
| #define PCI_CHIP_R200_QE 0x5145 | |||
| #define PCI_CHIP_R200_QF 0x5146 | |||
| #define PCI_CHIP_R200_QG 0x5147 | |||
| #define PCI_CHIP_R200_QY 0x5159 | |||
| #define PCI_CHIP_R200_QZ 0x515A | |||
| #define PCI_CHIP_R200_LW 0x4C57 | |||
| #define PCI_CHIP_R200_LY 0x4C59 | |||
| #define PCI_CHIP_R200_LZ 0x4C5A | |||
| #define PCI_CHIP_RV200_QW 0x5157 | |||
| #endif | |||
| static r200ScreenPtr __r200Screen; | |||
| /* Create the device specific screen private data struct. | |||
| */ | |||
| static r200ScreenPtr | |||
| r200CreateScreen( __DRIscreenPrivate *sPriv ) | |||
| { | |||
| r200ScreenPtr r200Screen; | |||
| RADEONDRIPtr r200DRIPriv = (RADEONDRIPtr)sPriv->pDevPriv; | |||
| /* Check the DRI extension version */ | |||
| if ( sPriv->driMajor != 4 || sPriv->driMinor < 0 ) { | |||
| __driUtilMessage( "R200 DRI driver expected DRI version 4.0.x " | |||
| "but got version %d.%d.%d", | |||
| sPriv->driMajor, sPriv->driMinor, sPriv->driPatch ); | |||
| return NULL; | |||
| } | |||
| /* Check that the DDX driver version is compatible */ | |||
| if ( sPriv->ddxMajor != 4 || | |||
| sPriv->ddxMinor < 0 ) { | |||
| __driUtilMessage( "R200 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 | |||
| * -- R200 support added at 1.5.0. | |||
| */ | |||
| if ( sPriv->drmMajor != 1 || | |||
| sPriv->drmMinor < 5) { | |||
| __driUtilMessage( "R200 DRI driver expected DRM driver version 1.5.x " | |||
| "but got version %d.%d.%d", | |||
| sPriv->drmMajor, sPriv->drmMinor, sPriv->drmPatch ); | |||
| return NULL; | |||
| } | |||
| /* Allocate the private area */ | |||
| r200Screen = (r200ScreenPtr) CALLOC( sizeof(*r200Screen) ); | |||
| if ( !r200Screen ) { | |||
| __driUtilMessage("%s: CALLOC r200Screen struct failed", | |||
| __FUNCTION__); | |||
| return NULL; | |||
| } | |||
| /* Check if kernel module is new enough to support cube maps */ | |||
| if (sPriv->drmMajor * 100 + sPriv->drmMinor >= 107) | |||
| r200Screen->drmSupportsCubeMaps = GL_TRUE; | |||
| else | |||
| r200Screen->drmSupportsCubeMaps = GL_FALSE; | |||
| switch ( r200DRIPriv->deviceID ) { | |||
| case PCI_CHIP_R200_QD: | |||
| case PCI_CHIP_R200_QE: | |||
| case PCI_CHIP_R200_QF: | |||
| case PCI_CHIP_R200_QG: | |||
| case PCI_CHIP_R200_QY: | |||
| case PCI_CHIP_R200_QZ: | |||
| case PCI_CHIP_RV200_QW: | |||
| case PCI_CHIP_R200_LW: | |||
| case PCI_CHIP_R200_LY: | |||
| case PCI_CHIP_R200_LZ: | |||
| __driUtilMessage("r200CreateScreen(): Device isn't an r200!\n"); | |||
| FREE( r200Screen ); | |||
| return NULL; | |||
| default: | |||
| r200Screen->chipset = R200_CHIPSET_R200; | |||
| break; | |||
| } | |||
| /* This is first since which regions we map depends on whether or | |||
| * not we are using a PCI card. | |||
| */ | |||
| r200Screen->IsPCI = r200DRIPriv->IsPCI; | |||
| { | |||
| int ret; | |||
| drmRadeonGetParam gp; | |||
| gp.param = RADEON_PARAM_AGP_BUFFER_OFFSET; | |||
| gp.value = &r200Screen->agp_buffer_offset; | |||
| ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM, | |||
| &gp, sizeof(gp)); | |||
| if (ret) { | |||
| FREE( r200Screen ); | |||
| fprintf(stderr, "drmR200GetParam: %d\n", ret); | |||
| return NULL; | |||
| } | |||
| r200Screen->agp_texture_offset = | |||
| r200Screen->agp_buffer_offset + 2*1024*1024; | |||
| if (sPriv->drmMinor >= 6) { | |||
| gp.param = RADEON_PARAM_AGP_BASE; | |||
| gp.value = &r200Screen->agp_base; | |||
| ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM, | |||
| &gp, sizeof(gp)); | |||
| if (ret) { | |||
| FREE( r200Screen ); | |||
| fprintf(stderr, "drmR200GetParam (RADEON_PARAM_AGP_BUFFER_OFFSET): %d\n", ret); | |||
| return NULL; | |||
| } | |||
| } | |||
| if (sPriv->drmMinor >= 6) { | |||
| gp.param = RADEON_PARAM_IRQ_NR; | |||
| gp.value = &r200Screen->irq; | |||
| ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM, | |||
| &gp, sizeof(gp)); | |||
| if (ret) { | |||
| FREE( r200Screen ); | |||
| fprintf(stderr, "drmR200GetParam (RADEON_PARAM_IRQ_NR): %d\n", ret); | |||
| return NULL; | |||
| } | |||
| } | |||
| } | |||
| r200Screen->mmio.handle = r200DRIPriv->registerHandle; | |||
| r200Screen->mmio.size = r200DRIPriv->registerSize; | |||
| if ( drmMap( sPriv->fd, | |||
| r200Screen->mmio.handle, | |||
| r200Screen->mmio.size, | |||
| &r200Screen->mmio.map ) ) { | |||
| FREE( r200Screen ); | |||
| __driUtilMessage("r200CreateScreen(): drmMap failed\n"); | |||
| return NULL; | |||
| } | |||
| r200Screen->status.handle = r200DRIPriv->statusHandle; | |||
| r200Screen->status.size = r200DRIPriv->statusSize; | |||
| if ( drmMap( sPriv->fd, | |||
| r200Screen->status.handle, | |||
| r200Screen->status.size, | |||
| &r200Screen->status.map ) ) { | |||
| drmUnmap( r200Screen->mmio.map, r200Screen->mmio.size ); | |||
| FREE( r200Screen ); | |||
| __driUtilMessage("r200CreateScreen(): drmMap (2) failed\n"); | |||
| return NULL; | |||
| } | |||
| r200Screen->scratch = (__volatile__ GLuint *) | |||
| ((GLubyte *)r200Screen->status.map + RADEON_SCRATCH_REG_OFFSET); | |||
| r200Screen->buffers = drmMapBufs( sPriv->fd ); | |||
| if ( !r200Screen->buffers ) { | |||
| drmUnmap( r200Screen->status.map, r200Screen->status.size ); | |||
| drmUnmap( r200Screen->mmio.map, r200Screen->mmio.size ); | |||
| FREE( r200Screen ); | |||
| __driUtilMessage("r200CreateScreen(): drmMapBufs failed\n"); | |||
| return NULL; | |||
| } | |||
| if ( !r200Screen->IsPCI ) { | |||
| r200Screen->agpTextures.handle = r200DRIPriv->agpTexHandle; | |||
| r200Screen->agpTextures.size = r200DRIPriv->agpTexMapSize; | |||
| if ( drmMap( sPriv->fd, | |||
| r200Screen->agpTextures.handle, | |||
| r200Screen->agpTextures.size, | |||
| (drmAddressPtr)&r200Screen->agpTextures.map ) ) { | |||
| drmUnmapBufs( r200Screen->buffers ); | |||
| drmUnmap( r200Screen->status.map, r200Screen->status.size ); | |||
| drmUnmap( r200Screen->mmio.map, r200Screen->mmio.size ); | |||
| FREE( r200Screen ); | |||
| __driUtilMessage("r200CreateScreen(): IsPCI failed\n"); | |||
| return NULL; | |||
| } | |||
| } | |||
| r200Screen->cpp = r200DRIPriv->bpp / 8; | |||
| r200Screen->AGPMode = r200DRIPriv->AGPMode; | |||
| r200Screen->frontOffset = r200DRIPriv->frontOffset; | |||
| r200Screen->frontPitch = r200DRIPriv->frontPitch; | |||
| r200Screen->backOffset = r200DRIPriv->backOffset; | |||
| r200Screen->backPitch = r200DRIPriv->backPitch; | |||
| r200Screen->depthOffset = r200DRIPriv->depthOffset; | |||
| r200Screen->depthPitch = r200DRIPriv->depthPitch; | |||
| r200Screen->texOffset[RADEON_CARD_HEAP] = r200DRIPriv->textureOffset; | |||
| r200Screen->texSize[RADEON_CARD_HEAP] = r200DRIPriv->textureSize; | |||
| r200Screen->logTexGranularity[RADEON_CARD_HEAP] = | |||
| r200DRIPriv->log2TexGran; | |||
| if ( r200Screen->IsPCI ) { | |||
| r200Screen->numTexHeaps = RADEON_NR_TEX_HEAPS - 1; | |||
| r200Screen->texOffset[RADEON_AGP_HEAP] = 0; | |||
| r200Screen->texSize[RADEON_AGP_HEAP] = 0; | |||
| r200Screen->logTexGranularity[RADEON_AGP_HEAP] = 0; | |||
| } else { | |||
| r200Screen->numTexHeaps = RADEON_NR_TEX_HEAPS; | |||
| r200Screen->texOffset[RADEON_AGP_HEAP] = | |||
| r200DRIPriv->agpTexOffset + R200_AGP_TEX_OFFSET; | |||
| r200Screen->texSize[RADEON_AGP_HEAP] = r200DRIPriv->agpTexMapSize; | |||
| r200Screen->logTexGranularity[RADEON_AGP_HEAP] = | |||
| r200DRIPriv->log2AGPTexGran; | |||
| } | |||
| r200Screen->driScreen = sPriv; | |||
| r200Screen->sarea_priv_offset = r200DRIPriv->sarea_priv_offset; | |||
| return r200Screen; | |||
| } | |||
| /* Destroy the device specific screen private data struct. | |||
| */ | |||
| static void | |||
| r200DestroyScreen( __DRIscreenPrivate *sPriv ) | |||
| { | |||
| r200ScreenPtr r200Screen = (r200ScreenPtr)sPriv->private; | |||
| if (!r200Screen) | |||
| return; | |||
| if ( !r200Screen->IsPCI ) { | |||
| drmUnmap( r200Screen->agpTextures.map, | |||
| r200Screen->agpTextures.size ); | |||
| } | |||
| drmUnmapBufs( r200Screen->buffers ); | |||
| drmUnmap( r200Screen->status.map, r200Screen->status.size ); | |||
| drmUnmap( r200Screen->mmio.map, r200Screen->mmio.size ); | |||
| FREE( r200Screen ); | |||
| sPriv->private = NULL; | |||
| } | |||
| /* Initialize the driver specific screen private data. | |||
| */ | |||
| static GLboolean | |||
| r200InitDriver( __DRIscreenPrivate *sPriv ) | |||
| { | |||
| __r200Screen = r200CreateScreen( sPriv ); | |||
| sPriv->private = (void *) __r200Screen; | |||
| return sPriv->private ? GL_TRUE : GL_FALSE; | |||
| } | |||
| /* Create and initialize the Mesa and driver specific pixmap buffer | |||
| * data. | |||
| */ | |||
| static GLboolean | |||
| r200CreateBuffer( __DRIscreenPrivate *driScrnPriv, | |||
| __DRIdrawablePrivate *driDrawPriv, | |||
| const __GLcontextModes *mesaVis, | |||
| GLboolean isPixmap ) | |||
| { | |||
| if (isPixmap) { | |||
| return GL_FALSE; /* not implemented */ | |||
| } | |||
| else { | |||
| const GLboolean swDepth = GL_FALSE; | |||
| const GLboolean swAlpha = GL_FALSE; | |||
| const GLboolean swAccum = mesaVis->accumRedBits > 0; | |||
| const GLboolean swStencil = mesaVis->stencilBits > 0 && | |||
| mesaVis->depthBits != 24; | |||
| driDrawPriv->driverPrivate = (void *) | |||
| _mesa_create_framebuffer( mesaVis, | |||
| swDepth, | |||
| swStencil, | |||
| swAccum, | |||
| swAlpha ); | |||
| return (driDrawPriv->driverPrivate != NULL); | |||
| } | |||
| } | |||
| static void | |||
| r200DestroyBuffer(__DRIdrawablePrivate *driDrawPriv) | |||
| { | |||
| _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate)); | |||
| } | |||
| /* 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 | |||
| r200OpenCloseFullScreen( __DRIcontextPrivate *driContextPriv ) | |||
| { | |||
| return GL_TRUE; | |||
| } | |||
| static struct __DriverAPIRec r200API = { | |||
| r200InitDriver, | |||
| r200DestroyScreen, | |||
| r200CreateContext, | |||
| r200DestroyContext, | |||
| r200CreateBuffer, | |||
| r200DestroyBuffer, | |||
| r200SwapBuffers, | |||
| r200MakeCurrent, | |||
| r200UnbindContext, | |||
| r200OpenCloseFullScreen, | |||
| r200OpenCloseFullScreen | |||
| }; | |||
| /* | |||
| * This is the bootstrap function for the driver. | |||
| * The __driCreateScreen name is the symbol that libGL.so fetches. | |||
| * Return: pointer to a __DRIscreenPrivate. | |||
| * | |||
| */ | |||
| void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc, | |||
| int numConfigs, __GLXvisualConfig *config) | |||
| { | |||
| __DRIscreenPrivate *psp; | |||
| psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &r200API); | |||
| return (void *) psp; | |||
| } | |||
| /* This function is called by libGL.so to allow the driver to dynamically | |||
| * extend libGL. We can add new GLX functions and/or new GL functions. | |||
| * Note that _mesa_create_context() will probably add most of the newer | |||
| * OpenGL extension functions into the dispatcher. | |||
| */ | |||
| void | |||
| __driRegisterExtensions( void ) | |||
| { | |||
| /* dlopen ourself */ | |||
| void *dll = dlopen(NULL, RTLD_GLOBAL); | |||
| if (dll) { | |||
| typedef void *(*registerFunc)(const char *funcName, void *funcAddr); | |||
| typedef void (*registerString)(const char *extName); | |||
| /* Get pointers to libGL's __glXRegisterGLXFunction | |||
| * and __glXRegisterGLXExtensionString, if they exist. | |||
| */ | |||
| registerFunc regFunc = (registerFunc) dlsym(dll, "__glXRegisterGLXFunction"); | |||
| registerString regString = (registerString) dlsym(dll, "__glXRegisterGLXExtensionString"); | |||
| if (regFunc) { | |||
| /* register our GLX extensions with libGL */ | |||
| void *p; | |||
| p = regFunc("glXAllocateMemoryNV", (void *) r200AllocateMemoryNV); | |||
| if (p) | |||
| ; /* XXX already registered - what to do, wrap? */ | |||
| p = regFunc("glXFreeMemoryNV", (void *) r200FreeMemoryNV); | |||
| if (p) | |||
| ; /* XXX already registered - what to do, wrap? */ | |||
| p = regFunc("glXGetAGPOffsetMESA", (void *) r200GetAGPOffset); | |||
| if (p) | |||
| ; /* XXX already registered - what to do, wrap? */ | |||
| } | |||
| if (regString) { | |||
| regString("GLX_NV_vertex_array_range"); | |||
| regString("GLX_MESA_agp_offset"); | |||
| } | |||
| dlclose(dll); | |||
| } | |||
| } | |||
| @@ -0,0 +1,96 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #ifndef __R200_SCREEN_H__ | |||
| #define __R200_SCREEN_H__ | |||
| #ifdef GLX_DIRECT_RENDERING | |||
| #include "dri_util.h" | |||
| #include "radeon_common.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 */ | |||
| } r200RegionRec, *r200RegionPtr; | |||
| #define R200_CHIPSET_R200 1 | |||
| #define R200_CHIPSET_MOBILITY 2 | |||
| #define R200_NR_TEX_HEAPS 2 | |||
| 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; | |||
| unsigned int backOffset; | |||
| unsigned int backPitch; | |||
| unsigned int depthOffset; | |||
| unsigned int depthPitch; | |||
| /* Shared texture data */ | |||
| int numTexHeaps; | |||
| int texOffset[R200_NR_TEX_HEAPS]; | |||
| int texSize[R200_NR_TEX_HEAPS]; | |||
| int logTexGranularity[R200_NR_TEX_HEAPS]; | |||
| r200RegionRec mmio; | |||
| r200RegionRec status; | |||
| r200RegionRec agpTextures; | |||
| drmBufMapPtr buffers; | |||
| __volatile__ GLuint *scratch; | |||
| __DRIscreenPrivate *driScreen; | |||
| unsigned int sarea_priv_offset; | |||
| unsigned int agp_buffer_offset; /* offset in card memory space */ | |||
| unsigned int agp_texture_offset; /* offset in card memory space */ | |||
| unsigned int agp_base; | |||
| GLboolean drmSupportsCubeMaps; /* need radeon kernel module >=1.7 */ | |||
| } r200ScreenRec, *r200ScreenPtr; | |||
| #endif | |||
| #endif /* __R200_SCREEN_H__ */ | |||
| @@ -0,0 +1,430 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #include "glheader.h" | |||
| #include "imports.h" | |||
| #include "swrast/swrast.h" | |||
| #include "r200_context.h" | |||
| #include "r200_ioctl.h" | |||
| #include "r200_state.h" | |||
| #include "r200_span.h" | |||
| #include "r200_tex.h" | |||
| #define DBG 0 | |||
| #define LOCAL_VARS \ | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); \ | |||
| r200ScreenPtr r200Screen = rmesa->r200Screen; \ | |||
| __DRIscreenPrivate *sPriv = rmesa->dri.screen; \ | |||
| __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; \ | |||
| GLuint pitch = r200Screen->frontPitch * r200Screen->cpp; \ | |||
| GLuint height = dPriv->h; \ | |||
| char *buf = (char *)(sPriv->pFB + \ | |||
| rmesa->state.color.drawOffset + \ | |||
| (dPriv->x * r200Screen->cpp) + \ | |||
| (dPriv->y * pitch)); \ | |||
| char *read_buf = (char *)(sPriv->pFB + \ | |||
| rmesa->state.pixel.readOffset + \ | |||
| (dPriv->x * r200Screen->cpp) + \ | |||
| (dPriv->y * pitch)); \ | |||
| GLuint p; \ | |||
| (void) read_buf; (void) buf; (void) p | |||
| #define LOCAL_DEPTH_VARS \ | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); \ | |||
| r200ScreenPtr r200Screen = rmesa->r200Screen; \ | |||
| __DRIscreenPrivate *sPriv = rmesa->dri.screen; \ | |||
| __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; \ | |||
| GLuint height = dPriv->h; \ | |||
| GLuint xo = dPriv->x; \ | |||
| GLuint yo = dPriv->y; \ | |||
| char *buf = (char *)(sPriv->pFB + r200Screen->depthOffset); \ | |||
| (void) buf | |||
| #define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS | |||
| #define CLIPPIXEL( _x, _y ) \ | |||
| ((_x >= minx) && (_x < maxx) && (_y >= miny) && (_y < maxy)) | |||
| #define CLIPSPAN( _x, _y, _n, _x1, _n1, _i ) \ | |||
| if ( _y < miny || _y >= maxy ) { \ | |||
| _n1 = 0, _x1 = x; \ | |||
| } else { \ | |||
| _n1 = _n; \ | |||
| _x1 = _x; \ | |||
| if ( _x1 < minx ) _i += (minx-_x1), n1 -= (minx-_x1), _x1 = minx; \ | |||
| if ( _x1 + _n1 >= maxx ) n1 -= (_x1 + n1 - maxx); \ | |||
| } | |||
| #define Y_FLIP( _y ) (height - _y - 1) | |||
| #define HW_LOCK() | |||
| #define HW_CLIPLOOP() \ | |||
| do { \ | |||
| __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; \ | |||
| int _nc = dPriv->numClipRects; \ | |||
| \ | |||
| while ( _nc-- ) { \ | |||
| int minx = dPriv->pClipRects[_nc].x1 - dPriv->x; \ | |||
| int miny = dPriv->pClipRects[_nc].y1 - dPriv->y; \ | |||
| int maxx = dPriv->pClipRects[_nc].x2 - dPriv->x; \ | |||
| int maxy = dPriv->pClipRects[_nc].y2 - dPriv->y; | |||
| #define HW_ENDCLIPLOOP() \ | |||
| } \ | |||
| } while (0) | |||
| #define HW_UNLOCK() | |||
| /* ================================================================ | |||
| * Color buffer | |||
| */ | |||
| /* 16 bit, RGB565 color spanline and pixel functions | |||
| */ | |||
| #define INIT_MONO_PIXEL(p, color) \ | |||
| p = PACK_COLOR_565( color[0], color[1], color[2] ) | |||
| #define WRITE_RGBA( _x, _y, r, g, b, a ) \ | |||
| *(GLushort *)(buf + _x*2 + _y*pitch) = ((((int)r & 0xf8) << 8) | \ | |||
| (((int)g & 0xfc) << 3) | \ | |||
| (((int)b & 0xf8) >> 3)) | |||
| #define WRITE_PIXEL( _x, _y, p ) \ | |||
| *(GLushort *)(buf + _x*2 + _y*pitch) = p | |||
| #define READ_RGBA( rgba, _x, _y ) \ | |||
| do { \ | |||
| GLushort p = *(GLushort *)(read_buf + _x*2 + _y*pitch); \ | |||
| rgba[0] = ((p >> 8) & 0xf8) * 255 / 0xf8; \ | |||
| rgba[1] = ((p >> 3) & 0xfc) * 255 / 0xfc; \ | |||
| rgba[2] = ((p << 3) & 0xf8) * 255 / 0xf8; \ | |||
| rgba[3] = 0xff; \ | |||
| } while (0) | |||
| #define TAG(x) r200##x##_RGB565 | |||
| #include "spantmp.h" | |||
| /* 32 bit, ARGB8888 color spanline and pixel functions | |||
| */ | |||
| #undef INIT_MONO_PIXEL | |||
| #define INIT_MONO_PIXEL(p, color) \ | |||
| p = PACK_COLOR_8888( color[3], color[0], color[1], color[2] ) | |||
| #define WRITE_RGBA( _x, _y, r, g, b, a ) \ | |||
| do { \ | |||
| *(GLuint *)(buf + _x*4 + _y*pitch) = ((b << 0) | \ | |||
| (g << 8) | \ | |||
| (r << 16) | \ | |||
| (a << 24) ); \ | |||
| } while (0) | |||
| #define WRITE_PIXEL( _x, _y, p ) \ | |||
| do { \ | |||
| *(GLuint *)(buf + _x*4 + _y*pitch) = p; \ | |||
| } while (0) | |||
| #define READ_RGBA( rgba, _x, _y ) \ | |||
| do { \ | |||
| volatile GLuint *ptr = (volatile GLuint *)(read_buf + _x*4 + _y*pitch); \ | |||
| GLuint p = *ptr; \ | |||
| rgba[0] = (p >> 16) & 0xff; \ | |||
| rgba[1] = (p >> 8) & 0xff; \ | |||
| rgba[2] = (p >> 0) & 0xff; \ | |||
| rgba[3] = (p >> 24) & 0xff; \ | |||
| } while (0) | |||
| #define TAG(x) r200##x##_ARGB8888 | |||
| #include "spantmp.h" | |||
| /* ================================================================ | |||
| * Depth buffer | |||
| */ | |||
| /* The R200 has depth tiling on all the time, so we have to convert | |||
| * the x,y coordinates into the memory bus address (mba) in the same | |||
| * manner as the engine. In each case, the linear block address (ba) | |||
| * is calculated, and then wired with x and y to produce the final | |||
| * memory address. | |||
| */ | |||
| #define BIT(x,b) ((x & (1<<b))>>b) | |||
| static GLuint r200_mba_z32( r200ContextPtr rmesa, | |||
| GLint x, GLint y ) | |||
| { | |||
| GLuint pitch = rmesa->r200Screen->frontPitch; | |||
| GLuint b = ((y & 0x3FF) >> 4) * ((pitch & 0xFFF) >> 5) + ((x & 0x3FF) >> 5); | |||
| GLuint a = | |||
| (BIT(x,0) << 2) | | |||
| (BIT(y,0) << 3) | | |||
| (BIT(x,1) << 4) | | |||
| (BIT(y,1) << 5) | | |||
| (BIT(x,3) << 6) | | |||
| (BIT(x,4) << 7) | | |||
| (BIT(x,2) << 8) | | |||
| (BIT(y,2) << 9) | | |||
| (BIT(y,3) << 10) | | |||
| (((pitch & 0x20) ? (b & 0x01) : ((b & 0x01) ^ (BIT(y,4)))) << 11) | | |||
| ((b >> 1) << 12); | |||
| return a; | |||
| } | |||
| static GLuint r200_mba_z16( r200ContextPtr rmesa, GLint x, GLint y ) | |||
| { | |||
| GLuint pitch = rmesa->r200Screen->frontPitch; | |||
| GLuint b = ((y & 0x3FF) >> 4) * ((pitch & 0xFFF) >> 6) + ((x & 0x3FF) >> 6); | |||
| GLuint a = | |||
| (BIT(x,0) << 1) | | |||
| (BIT(y,0) << 2) | | |||
| (BIT(x,1) << 3) | | |||
| (BIT(y,1) << 4) | | |||
| (BIT(x,2) << 5) | | |||
| (BIT(x,4) << 6) | | |||
| (BIT(x,5) << 7) | | |||
| (BIT(x,3) << 8) | | |||
| (BIT(y,2) << 9) | | |||
| (BIT(y,3) << 10) | | |||
| (((pitch & 0x40) ? (b & 0x01) : ((b & 0x01) ^ (BIT(y,4)))) << 11) | | |||
| ((b >> 1) << 12); | |||
| return a; | |||
| } | |||
| /* 16-bit depth buffer functions | |||
| */ | |||
| #define WRITE_DEPTH( _x, _y, d ) \ | |||
| *(GLushort *)(buf + r200_mba_z16( rmesa, _x + xo, _y + yo )) = d; | |||
| #define READ_DEPTH( d, _x, _y ) \ | |||
| d = *(GLushort *)(buf + r200_mba_z16( rmesa, _x + xo, _y + yo )); | |||
| #define TAG(x) r200##x##_16 | |||
| #include "depthtmp.h" | |||
| /* 24 bit depth, 8 bit stencil depthbuffer functions | |||
| */ | |||
| #define WRITE_DEPTH( _x, _y, d ) \ | |||
| do { \ | |||
| GLuint offset = r200_mba_z32( rmesa, _x + xo, _y + yo ); \ | |||
| GLuint tmp = *(GLuint *)(buf + offset); \ | |||
| tmp &= 0xff000000; \ | |||
| tmp |= ((d) & 0x00ffffff); \ | |||
| *(GLuint *)(buf + offset) = tmp; \ | |||
| } while (0) | |||
| #define READ_DEPTH( d, _x, _y ) \ | |||
| d = *(GLuint *)(buf + r200_mba_z32( rmesa, _x + xo, \ | |||
| _y + yo )) & 0x00ffffff; | |||
| #define TAG(x) r200##x##_24_8 | |||
| #include "depthtmp.h" | |||
| /* ================================================================ | |||
| * Stencil buffer | |||
| */ | |||
| /* 24 bit depth, 8 bit stencil depthbuffer functions | |||
| */ | |||
| #define WRITE_STENCIL( _x, _y, d ) \ | |||
| do { \ | |||
| GLuint offset = r200_mba_z32( rmesa, _x + xo, _y + yo ); \ | |||
| GLuint tmp = *(GLuint *)(buf + offset); \ | |||
| tmp &= 0x00ffffff; \ | |||
| tmp |= (((d) & 0xff) << 24); \ | |||
| *(GLuint *)(buf + offset) = tmp; \ | |||
| } while (0) | |||
| #define READ_STENCIL( d, _x, _y ) \ | |||
| do { \ | |||
| GLuint offset = r200_mba_z32( rmesa, _x + xo, _y + yo ); \ | |||
| GLuint tmp = *(GLuint *)(buf + offset); \ | |||
| tmp &= 0xff000000; \ | |||
| d = tmp >> 24; \ | |||
| } while (0) | |||
| #define TAG(x) r200##x##_24_8 | |||
| #include "stenciltmp.h" | |||
| /* | |||
| * This function is called to specify which buffer to read and write | |||
| * for software rasterization (swrast) fallbacks. This doesn't necessarily | |||
| * correspond to glDrawBuffer() or glReadBuffer() calls. | |||
| */ | |||
| static void r200SetBuffer( GLcontext *ctx, | |||
| GLframebuffer *colorBuffer, | |||
| GLuint bufferBit ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| switch ( bufferBit ) { | |||
| case FRONT_LEFT_BIT: | |||
| if ( rmesa->doPageFlip && rmesa->sarea->pfCurrentPage == 1 ) { | |||
| rmesa->state.pixel.readOffset = rmesa->r200Screen->backOffset; | |||
| rmesa->state.pixel.readPitch = rmesa->r200Screen->backPitch; | |||
| rmesa->state.color.drawOffset = rmesa->r200Screen->backOffset; | |||
| rmesa->state.color.drawPitch = rmesa->r200Screen->backPitch; | |||
| } else { | |||
| rmesa->state.pixel.readOffset = rmesa->r200Screen->frontOffset; | |||
| rmesa->state.pixel.readPitch = rmesa->r200Screen->frontPitch; | |||
| rmesa->state.color.drawOffset = rmesa->r200Screen->frontOffset; | |||
| rmesa->state.color.drawPitch = rmesa->r200Screen->frontPitch; | |||
| } | |||
| break; | |||
| case BACK_LEFT_BIT: | |||
| if ( rmesa->doPageFlip && rmesa->sarea->pfCurrentPage == 1 ) { | |||
| rmesa->state.pixel.readOffset = rmesa->r200Screen->frontOffset; | |||
| rmesa->state.pixel.readPitch = rmesa->r200Screen->frontPitch; | |||
| rmesa->state.color.drawOffset = rmesa->r200Screen->frontOffset; | |||
| rmesa->state.color.drawPitch = rmesa->r200Screen->frontPitch; | |||
| } else { | |||
| rmesa->state.pixel.readOffset = rmesa->r200Screen->backOffset; | |||
| rmesa->state.pixel.readPitch = rmesa->r200Screen->backPitch; | |||
| rmesa->state.color.drawOffset = rmesa->r200Screen->backOffset; | |||
| rmesa->state.color.drawPitch = rmesa->r200Screen->backPitch; | |||
| } | |||
| break; | |||
| default: | |||
| _mesa_problem(ctx, "Bad bufferBit in r200SetBuffer()"); | |||
| break; | |||
| } | |||
| } | |||
| /* Move locking out to get reasonable span performance (10x better | |||
| * than doing this in HW_LOCK above). WaitForIdle() is the main | |||
| * culprit. | |||
| */ | |||
| static void r200SpanRenderStart( GLcontext *ctx ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT( ctx ); | |||
| R200_FIREVERTICES( rmesa ); | |||
| LOCK_HARDWARE( rmesa ); | |||
| r200WaitForIdleLocked( rmesa ); | |||
| /* Read & rewrite the first pixel in the frame buffer. This should | |||
| * be a noop, right? In fact without this conform fails as reading | |||
| * from the framebuffer sometimes produces old results -- the | |||
| * on-card read cache gets mixed up and doesn't notice that the | |||
| * framebuffer has been updated. | |||
| * | |||
| * In the worst case this is buggy too as p might get the wrong | |||
| * value first time, so really need a hidden pixel somewhere for this. | |||
| */ | |||
| { | |||
| int p; | |||
| volatile int *read_buf = (volatile int *)(rmesa->dri.screen->pFB + | |||
| rmesa->state.pixel.readOffset); | |||
| p = *read_buf; | |||
| *read_buf = p; | |||
| } | |||
| } | |||
| static void r200SpanRenderFinish( GLcontext *ctx ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT( ctx ); | |||
| _swrast_flush( ctx ); | |||
| UNLOCK_HARDWARE( rmesa ); | |||
| } | |||
| void r200InitSpanFuncs( GLcontext *ctx ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx); | |||
| swdd->SetBuffer = r200SetBuffer; | |||
| switch ( rmesa->r200Screen->cpp ) { | |||
| case 2: | |||
| swdd->WriteRGBASpan = r200WriteRGBASpan_RGB565; | |||
| swdd->WriteRGBSpan = r200WriteRGBSpan_RGB565; | |||
| swdd->WriteMonoRGBASpan = r200WriteMonoRGBASpan_RGB565; | |||
| swdd->WriteRGBAPixels = r200WriteRGBAPixels_RGB565; | |||
| swdd->WriteMonoRGBAPixels = r200WriteMonoRGBAPixels_RGB565; | |||
| swdd->ReadRGBASpan = r200ReadRGBASpan_RGB565; | |||
| swdd->ReadRGBAPixels = r200ReadRGBAPixels_RGB565; | |||
| break; | |||
| case 4: | |||
| swdd->WriteRGBASpan = r200WriteRGBASpan_ARGB8888; | |||
| swdd->WriteRGBSpan = r200WriteRGBSpan_ARGB8888; | |||
| swdd->WriteMonoRGBASpan = r200WriteMonoRGBASpan_ARGB8888; | |||
| swdd->WriteRGBAPixels = r200WriteRGBAPixels_ARGB8888; | |||
| swdd->WriteMonoRGBAPixels = r200WriteMonoRGBAPixels_ARGB8888; | |||
| swdd->ReadRGBASpan = r200ReadRGBASpan_ARGB8888; | |||
| swdd->ReadRGBAPixels = r200ReadRGBAPixels_ARGB8888; | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| switch ( rmesa->glCtx->Visual.depthBits ) { | |||
| case 16: | |||
| swdd->ReadDepthSpan = r200ReadDepthSpan_16; | |||
| swdd->WriteDepthSpan = r200WriteDepthSpan_16; | |||
| swdd->ReadDepthPixels = r200ReadDepthPixels_16; | |||
| swdd->WriteDepthPixels = r200WriteDepthPixels_16; | |||
| break; | |||
| case 24: | |||
| swdd->ReadDepthSpan = r200ReadDepthSpan_24_8; | |||
| swdd->WriteDepthSpan = r200WriteDepthSpan_24_8; | |||
| swdd->ReadDepthPixels = r200ReadDepthPixels_24_8; | |||
| swdd->WriteDepthPixels = r200WriteDepthPixels_24_8; | |||
| swdd->ReadStencilSpan = r200ReadStencilSpan_24_8; | |||
| swdd->WriteStencilSpan = r200WriteStencilSpan_24_8; | |||
| swdd->ReadStencilPixels = r200ReadStencilPixels_24_8; | |||
| swdd->WriteStencilPixels = r200WriteStencilPixels_24_8; | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| swdd->SpanRenderStart = r200SpanRenderStart; | |||
| swdd->SpanRenderFinish = r200SpanRenderFinish; | |||
| } | |||
| @@ -0,0 +1,43 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #ifndef __R200_SPAN_H__ | |||
| #define __R200_SPAN_H__ | |||
| #ifdef GLX_DIRECT_RENDERING | |||
| extern void r200InitSpanFuncs( GLcontext *ctx ); | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,68 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #ifndef __R200_STATE_H__ | |||
| #define __R200_STATE_H__ | |||
| #ifdef GLX_DIRECT_RENDERING | |||
| #include "r200_context.h" | |||
| extern void r200InitState( r200ContextPtr rmesa ); | |||
| extern void r200InitStateFuncs( GLcontext *ctx ); | |||
| extern void r200UpdateMaterial( GLcontext *ctx ); | |||
| extern void r200SetCliprects( r200ContextPtr rmesa, GLenum mode ); | |||
| extern void r200RecalcScissorRects( r200ContextPtr rmesa ); | |||
| extern void r200UpdateViewportOffset( GLcontext *ctx ); | |||
| extern void r200UpdateWindow( GLcontext *ctx ); | |||
| extern void r200ValidateState( GLcontext *ctx ); | |||
| extern void r200PrintDirty( r200ContextPtr rmesa, | |||
| const char *msg ); | |||
| extern void r200Fallback( GLcontext *ctx, GLuint bit, GLboolean mode ); | |||
| #define FALLBACK( rmesa, bit, mode ) do { \ | |||
| if ( 0 ) fprintf( stderr, "FALLBACK in %s: #%d=%d\n", \ | |||
| __FUNCTION__, bit, mode ); \ | |||
| r200Fallback( rmesa->glCtx, bit, mode ); \ | |||
| } while (0) | |||
| extern void r200LightingSpaceChange( GLcontext *ctx ); | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,692 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #include "glheader.h" | |||
| #include "imports.h" | |||
| #include "mmath.h" | |||
| #include "enums.h" | |||
| #include "colormac.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" | |||
| #include "r200_context.h" | |||
| #include "r200_ioctl.h" | |||
| #include "r200_state.h" | |||
| #include "r200_tcl.h" | |||
| #include "r200_tex.h" | |||
| #include "r200_swtcl.h" | |||
| #include "r200_vtxfmt.h" | |||
| /* ============================================================= | |||
| * State initialization | |||
| */ | |||
| void r200PrintDirty( r200ContextPtr rmesa, const char *msg ) | |||
| { | |||
| struct r200_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; | |||
| } | |||
| static int cmdscl2( int offset, int stride, int count ) | |||
| { | |||
| drmRadeonCmdHeader h; | |||
| h.i = 0; | |||
| h.scalars.cmd_type = RADEON_CMD_SCALARS2; | |||
| h.scalars.offset = offset - 0x100; | |||
| h.scalars.stride = stride; | |||
| h.scalars.count = count; | |||
| return h.i; | |||
| } | |||
| #define CHECK( NM, FLAG ) \ | |||
| static GLboolean check_##NM( GLcontext *ctx, int idx ) \ | |||
| { \ | |||
| (void) idx; \ | |||
| return FLAG; \ | |||
| } | |||
| #define TCL_CHECK( NM, FLAG ) \ | |||
| static GLboolean check_##NM( GLcontext *ctx, int idx ) \ | |||
| { \ | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); \ | |||
| (void) idx; \ | |||
| return !rmesa->TclFallback && (FLAG); \ | |||
| } | |||
| CHECK( always, GL_TRUE ) | |||
| CHECK( tex_any, ctx->Texture._EnabledUnits ) | |||
| CHECK( tex, ctx->Texture.Unit[idx]._ReallyEnabled ) | |||
| CHECK( fog, ctx->Fog.Enabled ) | |||
| TCL_CHECK( tcl, GL_TRUE ) | |||
| TCL_CHECK( tcl_tex_any, ctx->Texture._EnabledUnits ) | |||
| TCL_CHECK( tcl_tex, ctx->Texture.Unit[idx]._ReallyEnabled ) | |||
| TCL_CHECK( tcl_lighting, ctx->Light.Enabled ) | |||
| TCL_CHECK( tcl_eyespace_or_lighting, ctx->_NeedEyeCoords || ctx->Light.Enabled ) | |||
| TCL_CHECK( tcl_light, ctx->Light.Enabled && ctx->Light.Light[idx].Enabled ) | |||
| TCL_CHECK( tcl_ucp, (ctx->Transform.ClipPlanesEnabled & (1 << idx)) ) | |||
| /* TCL_CHECK( tcl_eyespace_or_fog, ctx->_NeedEyeCoords || ctx->Fog.Enabled ) */ | |||
| static GLboolean check_tcl_eyespace_or_fog( GLcontext *ctx, int idx ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| int res; | |||
| (void) idx; | |||
| res = !rmesa->TclFallback && (ctx->_NeedEyeCoords || ctx->Fog.Enabled); | |||
| fprintf(stderr, "%s: %d\n", __FUNCTION__, res); | |||
| return res; | |||
| } | |||
| /* Initialize the context's hardware state. | |||
| */ | |||
| void r200InitState( r200ContextPtr rmesa ) | |||
| { | |||
| GLcontext *ctx = rmesa->glCtx; | |||
| GLuint color_fmt, depth_fmt, i; | |||
| switch ( rmesa->r200Screen->cpp ) { | |||
| case 2: | |||
| color_fmt = R200_COLOR_FORMAT_RGB565; | |||
| break; | |||
| case 4: | |||
| color_fmt = R200_COLOR_FORMAT_ARGB8888; | |||
| break; | |||
| default: | |||
| fprintf( stderr, "Error: Unsupported pixel depth... exiting\n" ); | |||
| exit( -1 ); | |||
| } | |||
| rmesa->state.color.clear = 0x00000000; | |||
| switch ( ctx->Visual.depthBits ) { | |||
| case 16: | |||
| rmesa->state.depth.scale = 1.0 / (GLfloat)0xffff; | |||
| depth_fmt = R200_DEPTH_FORMAT_16BIT_INT_Z; | |||
| rmesa->state.stencil.clear = 0x00000000; | |||
| break; | |||
| case 24: | |||
| rmesa->state.depth.scale = 1.0 / (GLfloat)0xffffff; | |||
| depth_fmt = R200_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->r200Screen->backOffset; | |||
| rmesa->state.color.drawPitch = rmesa->r200Screen->backPitch; | |||
| } else { | |||
| rmesa->state.color.drawOffset = rmesa->r200Screen->frontOffset; | |||
| rmesa->state.color.drawPitch = rmesa->r200Screen->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)); rmesa->hw.dirty.name = "DIRTY"; | |||
| make_empty_list(&(rmesa->hw.clean)); rmesa->hw.clean.name = "CLEAN"; | |||
| #define ALLOC_STATE( ATOM, CHK, SZ, NM, IDX ) \ | |||
| do { \ | |||
| rmesa->hw.ATOM.cmd_size = SZ; \ | |||
| rmesa->hw.ATOM.cmd = (int *)CALLOC(SZ * sizeof(int)); \ | |||
| rmesa->hw.ATOM.lastcmd = (int *)CALLOC(SZ * sizeof(int)); \ | |||
| rmesa->hw.ATOM.name = NM; \ | |||
| rmesa->hw.ATOM.idx = IDX; \ | |||
| 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( set, always, SET_STATE_SIZE, "SET/setup", 0 ); | |||
| ALLOC_STATE( lin, always, LIN_STATE_SIZE, "LIN/line", 0 ); | |||
| ALLOC_STATE( msk, always, MSK_STATE_SIZE, "MSK/mask", 0 ); | |||
| ALLOC_STATE( vpt, always, VPT_STATE_SIZE, "VPT/viewport", 0 ); | |||
| ALLOC_STATE( vtx, always, VTX_STATE_SIZE, "VTX/vertex", 0 ); | |||
| ALLOC_STATE( vap, always, VAP_STATE_SIZE, "VAP/vap", 0 ); | |||
| ALLOC_STATE( vte, always, VTE_STATE_SIZE, "VTE/vte", 0 ); | |||
| ALLOC_STATE( msc, always, MSC_STATE_SIZE, "MSC/misc", 0 ); | |||
| ALLOC_STATE( cst, always, CST_STATE_SIZE, "CST/constant", 0 ); | |||
| ALLOC_STATE( zbs, always, ZBS_STATE_SIZE, "ZBS/zbias", 0 ); | |||
| ALLOC_STATE( tam, tex_any, TAM_STATE_SIZE, "TAM/tam", 0 ); | |||
| ALLOC_STATE( tf, tex_any, TF_STATE_SIZE, "TF/tfactor", 0 ); | |||
| ALLOC_STATE( tex[0], tex_any, TEX_STATE_SIZE, "TEX/tex-0", 0 ); | |||
| ALLOC_STATE( tex[1], tex_any, TEX_STATE_SIZE, "TEX/tex-1", 1 ); | |||
| ALLOC_STATE( cube[0], tex_any, CUBE_STATE_SIZE, "CUBE/tex-0", 0 ); | |||
| ALLOC_STATE( cube[1], tex_any, CUBE_STATE_SIZE, "CUBE/tex-1", 1 ); | |||
| ALLOC_STATE( tcl, tcl, TCL_STATE_SIZE, "TCL/tcl", 0 ); | |||
| ALLOC_STATE( msl, tcl, MSL_STATE_SIZE, "MSL/matrix-select", 0 ); | |||
| ALLOC_STATE( tcg, tcl, TCG_STATE_SIZE, "TCG/texcoordgen", 0 ); | |||
| ALLOC_STATE( mtl[0], tcl_lighting, MTL_STATE_SIZE, "MTL0/material0", 0 ); | |||
| ALLOC_STATE( grd, tcl, GRD_STATE_SIZE, "GRD/guard-band", 0 ); | |||
| ALLOC_STATE( fog, fog, FOG_STATE_SIZE, "FOG/fog", 0 ); | |||
| ALLOC_STATE( glt, tcl_lighting, GLT_STATE_SIZE, "GLT/light-global", 0 ); | |||
| ALLOC_STATE( eye, tcl_lighting, EYE_STATE_SIZE, "EYE/eye-vector", 0 ); | |||
| ALLOC_STATE( mat[R200_MTX_MV], tcl, MAT_STATE_SIZE, "MAT/modelview", 0 ); | |||
| ALLOC_STATE( mat[R200_MTX_IMV], tcl, MAT_STATE_SIZE, "MAT/it-modelview", 0 ); | |||
| ALLOC_STATE( mat[R200_MTX_MVP], tcl, MAT_STATE_SIZE, "MAT/modelproject", 0 ); | |||
| ALLOC_STATE( mat[R200_MTX_TEX0], tcl_tex, MAT_STATE_SIZE, "MAT/texmat0", 0 ); | |||
| ALLOC_STATE( mat[R200_MTX_TEX1], tcl_tex, MAT_STATE_SIZE, "MAT/texmat1", 1 ); | |||
| ALLOC_STATE( ucp[0], tcl_ucp, UCP_STATE_SIZE, "UCP/userclip-0", 0 ); | |||
| ALLOC_STATE( ucp[1], tcl_ucp, UCP_STATE_SIZE, "UCP/userclip-1", 1 ); | |||
| ALLOC_STATE( ucp[2], tcl_ucp, UCP_STATE_SIZE, "UCP/userclip-2", 2 ); | |||
| ALLOC_STATE( ucp[3], tcl_ucp, UCP_STATE_SIZE, "UCP/userclip-3", 3 ); | |||
| ALLOC_STATE( ucp[4], tcl_ucp, UCP_STATE_SIZE, "UCP/userclip-4", 4 ); | |||
| ALLOC_STATE( ucp[5], tcl_ucp, UCP_STATE_SIZE, "UCP/userclip-5", 5 ); | |||
| ALLOC_STATE( lit[0], tcl_light, LIT_STATE_SIZE, "LIT/light-0", 0 ); | |||
| ALLOC_STATE( lit[1], tcl_light, LIT_STATE_SIZE, "LIT/light-1", 1 ); | |||
| ALLOC_STATE( lit[2], tcl_light, LIT_STATE_SIZE, "LIT/light-2", 2 ); | |||
| ALLOC_STATE( lit[3], tcl_light, LIT_STATE_SIZE, "LIT/light-3", 3 ); | |||
| ALLOC_STATE( lit[4], tcl_light, LIT_STATE_SIZE, "LIT/light-4", 4 ); | |||
| ALLOC_STATE( lit[5], tcl_light, LIT_STATE_SIZE, "LIT/light-5", 5 ); | |||
| ALLOC_STATE( lit[6], tcl_light, LIT_STATE_SIZE, "LIT/light-6", 6 ); | |||
| ALLOC_STATE( lit[7], tcl_light, LIT_STATE_SIZE, "LIT/light-7", 7 ); | |||
| ALLOC_STATE( pix[0], always, PIX_STATE_SIZE, "PIX/pixstage-0", 0 ); | |||
| ALLOC_STATE( pix[1], tex, PIX_STATE_SIZE, "PIX/pixstage-1", 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.msc.cmd[MSC_CMD_0] = cmdpkt(RADEON_EMIT_RE_MISC); | |||
| rmesa->hw.cst.cmd[CST_CMD_0] = cmdpkt(R200_EMIT_PP_CNTL_X); | |||
| rmesa->hw.cst.cmd[CST_CMD_1] = cmdpkt(R200_EMIT_RB3D_DEPTHXY_OFFSET); | |||
| rmesa->hw.cst.cmd[CST_CMD_2] = cmdpkt(R200_EMIT_RE_AUX_SCISSOR_CNTL); | |||
| rmesa->hw.cst.cmd[CST_CMD_3] = cmdpkt(R200_EMIT_RE_SCISSOR_TL_0); | |||
| rmesa->hw.cst.cmd[CST_CMD_4] = cmdpkt(R200_EMIT_SE_VAP_CNTL_STATUS); | |||
| rmesa->hw.cst.cmd[CST_CMD_5] = cmdpkt(R200_EMIT_RE_POINTSIZE); | |||
| rmesa->hw.cst.cmd[CST_CMD_6] = cmdpkt(R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0); | |||
| rmesa->hw.tam.cmd[TAM_CMD_0] = cmdpkt(R200_EMIT_PP_TAM_DEBUG3); | |||
| rmesa->hw.tf.cmd[TF_CMD_0] = cmdpkt(R200_EMIT_TFACTOR_0); | |||
| rmesa->hw.tex[0].cmd[TEX_CMD_0] = cmdpkt(R200_EMIT_PP_TXFILTER_0); | |||
| rmesa->hw.tex[0].cmd[TEX_CMD_1] = cmdpkt(R200_EMIT_PP_TXOFFSET_0); | |||
| rmesa->hw.tex[1].cmd[TEX_CMD_0] = cmdpkt(R200_EMIT_PP_TXFILTER_1); | |||
| rmesa->hw.tex[1].cmd[TEX_CMD_1] = cmdpkt(R200_EMIT_PP_TXOFFSET_1); | |||
| rmesa->hw.cube[0].cmd[CUBE_CMD_0] = cmdpkt(R200_EMIT_PP_CUBIC_FACES_0); | |||
| rmesa->hw.cube[0].cmd[CUBE_CMD_1] = cmdpkt(R200_EMIT_PP_CUBIC_OFFSETS_0); | |||
| rmesa->hw.cube[1].cmd[CUBE_CMD_0] = cmdpkt(R200_EMIT_PP_CUBIC_FACES_1); | |||
| rmesa->hw.cube[1].cmd[CUBE_CMD_1] = cmdpkt(R200_EMIT_PP_CUBIC_OFFSETS_1); | |||
| rmesa->hw.pix[0].cmd[PIX_CMD_0] = cmdpkt(R200_EMIT_PP_TXCBLEND_0); | |||
| rmesa->hw.pix[1].cmd[PIX_CMD_0] = cmdpkt(R200_EMIT_PP_TXCBLEND_1); | |||
| rmesa->hw.zbs.cmd[ZBS_CMD_0] = cmdpkt(RADEON_EMIT_SE_ZBIAS_FACTOR); | |||
| rmesa->hw.tcl.cmd[TCL_CMD_0] = cmdpkt(R200_EMIT_TCL_LIGHT_MODEL_CTL_0); | |||
| rmesa->hw.tcl.cmd[TCL_CMD_1] = cmdpkt(R200_EMIT_TCL_UCP_VERT_BLEND_CTL); | |||
| rmesa->hw.tcg.cmd[TCG_CMD_0] = cmdpkt(R200_EMIT_TEX_PROC_CTL_2); | |||
| rmesa->hw.msl.cmd[MSL_CMD_0] = cmdpkt(R200_EMIT_MATRIX_SELECT_0); | |||
| rmesa->hw.vap.cmd[VAP_CMD_0] = cmdpkt(R200_EMIT_VAP_CTL); | |||
| rmesa->hw.vtx.cmd[VTX_CMD_0] = cmdpkt(R200_EMIT_VTX_FMT_0); | |||
| rmesa->hw.vtx.cmd[VTX_CMD_1] = cmdpkt(R200_EMIT_OUTPUT_VTX_COMP_SEL); | |||
| rmesa->hw.vtx.cmd[VTX_CMD_2] = cmdpkt(R200_EMIT_SE_VTX_STATE_CNTL); | |||
| rmesa->hw.vte.cmd[VTE_CMD_0] = cmdpkt(R200_EMIT_VTE_CNTL); | |||
| rmesa->hw.mtl[0].cmd[MTL_CMD_0] = | |||
| cmdvec( R200_VS_MAT_0_EMISS, 1, 16 ); | |||
| rmesa->hw.mtl[0].cmd[MTL_CMD_1] = | |||
| cmdscl2( R200_SS_MAT_0_SHININESS, 1, 1 ); | |||
| rmesa->hw.grd.cmd[GRD_CMD_0] = | |||
| cmdscl( R200_SS_VERT_GUARD_CLIP_ADJ_ADDR, 1, 4 ); | |||
| rmesa->hw.fog.cmd[FOG_CMD_0] = | |||
| cmdvec( R200_VS_FOG_PARAM_ADDR, 1, 4 ); | |||
| rmesa->hw.glt.cmd[GLT_CMD_0] = | |||
| cmdvec( R200_VS_GLOBAL_AMBIENT_ADDR, 1, 4 ); | |||
| rmesa->hw.eye.cmd[EYE_CMD_0] = | |||
| cmdvec( R200_VS_EYE_VECTOR_ADDR, 1, 4 ); | |||
| rmesa->hw.mat[R200_MTX_MV].cmd[MAT_CMD_0] = | |||
| cmdvec( R200_VS_MATRIX_0_MV, 1, 16); | |||
| rmesa->hw.mat[R200_MTX_IMV].cmd[MAT_CMD_0] = | |||
| cmdvec( R200_VS_MATRIX_1_INV_MV, 1, 16); | |||
| rmesa->hw.mat[R200_MTX_MVP].cmd[MAT_CMD_0] = | |||
| cmdvec( R200_VS_MATRIX_2_MVP, 1, 16); | |||
| rmesa->hw.mat[R200_MTX_TEX0].cmd[MAT_CMD_0] = | |||
| cmdvec( R200_VS_MATRIX_3_TEX0, 1, 16); | |||
| rmesa->hw.mat[R200_MTX_TEX1].cmd[MAT_CMD_0] = | |||
| cmdvec( R200_VS_MATRIX_4_TEX1, 1, 16); | |||
| for (i = 0 ; i < 8; i++) { | |||
| rmesa->hw.lit[i].cmd[LIT_CMD_0] = | |||
| cmdvec( R200_VS_LIGHT_AMBIENT_ADDR + i, 8, 24 ); | |||
| rmesa->hw.lit[i].cmd[LIT_CMD_1] = | |||
| cmdscl( R200_SS_LIGHT_DCD_ADDR + i, 8, 7 ); | |||
| } | |||
| for (i = 0 ; i < 6; i++) { | |||
| rmesa->hw.ucp[i].cmd[UCP_CMD_0] = | |||
| cmdvec( R200_VS_UCP_ADDR + i, 1, 4 ); | |||
| } | |||
| /* Initial Harware state: | |||
| */ | |||
| rmesa->hw.ctx.cmd[CTX_PP_MISC] = (R200_ALPHA_TEST_PASS | |||
| /* | R200_RIGHT_HAND_CUBE_OGL*/); | |||
| rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = (R200_FOG_VERTEX | | |||
| R200_FOG_USE_SPEC_ALPHA); | |||
| rmesa->hw.ctx.cmd[CTX_RE_SOLID_COLOR] = 0x00000000; | |||
| rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = (R200_COMB_FCN_ADD_CLAMP | | |||
| R200_SRC_BLEND_GL_ONE | | |||
| R200_DST_BLEND_GL_ZERO ); | |||
| rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHOFFSET] = | |||
| rmesa->r200Screen->depthOffset; | |||
| rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHPITCH] = | |||
| ((rmesa->r200Screen->depthPitch & | |||
| R200_DEPTHPITCH_MASK) | | |||
| R200_DEPTH_ENDIAN_NO_SWAP); | |||
| rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] = (depth_fmt | | |||
| R200_Z_TEST_LESS | | |||
| R200_STENCIL_TEST_ALWAYS | | |||
| R200_STENCIL_FAIL_KEEP | | |||
| R200_STENCIL_ZPASS_KEEP | | |||
| R200_STENCIL_ZFAIL_KEEP | | |||
| R200_Z_WRITE_ENABLE); | |||
| rmesa->hw.ctx.cmd[CTX_PP_CNTL] = (R200_ANTI_ALIAS_NONE | |||
| | R200_TEX_BLEND_0_ENABLE); | |||
| rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = color_fmt; | |||
| rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_ENABLE; | |||
| rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = (rmesa->state.color.drawOffset & | |||
| R200_COLOROFFSET_MASK); | |||
| rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = ((rmesa->state.color.drawPitch & | |||
| R200_COLORPITCH_MASK) | | |||
| R200_COLOR_ENDIAN_NO_SWAP); | |||
| rmesa->hw.set.cmd[SET_SE_CNTL] = (R200_FFACE_CULL_CCW | | |||
| R200_BFACE_SOLID | | |||
| R200_FFACE_SOLID | | |||
| R200_FLAT_SHADE_VTX_LAST | | |||
| R200_DIFFUSE_SHADE_GOURAUD | | |||
| R200_ALPHA_SHADE_GOURAUD | | |||
| R200_SPECULAR_SHADE_GOURAUD | | |||
| R200_FOG_SHADE_GOURAUD | | |||
| R200_VTX_PIX_CENTER_OGL | | |||
| R200_ROUND_MODE_TRUNC | | |||
| R200_ROUND_PREC_8TH_PIX); | |||
| rmesa->hw.set.cmd[SET_RE_CNTL] = (R200_PERSPECTIVE_ENABLE | | |||
| R200_SCISSOR_ENABLE); | |||
| rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] = ((1 << 16) | 0xffff); | |||
| rmesa->hw.lin.cmd[LIN_RE_LINE_STATE] = | |||
| ((0 << R200_LINE_CURRENT_PTR_SHIFT) | | |||
| (1 << R200_LINE_CURRENT_COUNT_SHIFT)); | |||
| rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] = (1 << 4); | |||
| rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] = | |||
| ((0x00 << R200_STENCIL_REF_SHIFT) | | |||
| (0xff << R200_STENCIL_MASK_SHIFT) | | |||
| (0xff << R200_STENCIL_WRITEMASK_SHIFT)); | |||
| rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = R200_ROP_COPY; | |||
| rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = 0xffffffff; | |||
| rmesa->hw.tam.cmd[TAM_DEBUG3] = 0; | |||
| rmesa->hw.msc.cmd[MSC_RE_MISC] = | |||
| ((0 << R200_STIPPLE_X_OFFSET_SHIFT) | | |||
| (0 << R200_STIPPLE_Y_OFFSET_SHIFT) | | |||
| R200_STIPPLE_BIG_BIT_ORDER); | |||
| rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0; | |||
| rmesa->hw.cst.cmd[CST_RB3D_DEPTHXY_OFFSET] = 0; | |||
| rmesa->hw.cst.cmd[CST_RE_AUX_SCISSOR_CNTL] = 0x0; | |||
| rmesa->hw.cst.cmd[CST_RE_SCISSOR_TL_0] = 0; | |||
| rmesa->hw.cst.cmd[CST_RE_SCISSOR_BR_0] = 0; | |||
| rmesa->hw.cst.cmd[CST_SE_VAP_CNTL_STATUS] = | |||
| #ifdef MESA_BIG_ENDIAN | |||
| R200_VC_32BIT_SWAP; | |||
| #else | |||
| R200_VC_NO_SWAP; | |||
| #endif | |||
| rmesa->hw.cst.cmd[CST_RE_POINTSIZE] = 0x100010; | |||
| rmesa->hw.cst.cmd[CST_SE_TCL_INPUT_VTX_0] = | |||
| (0x0 << R200_VERTEX_POSITION_ADDR__SHIFT); | |||
| rmesa->hw.cst.cmd[CST_SE_TCL_INPUT_VTX_1] = | |||
| (0x02 << R200_VTX_COLOR_0_ADDR__SHIFT) | | |||
| (0x03 << R200_VTX_COLOR_1_ADDR__SHIFT); | |||
| rmesa->hw.cst.cmd[CST_SE_TCL_INPUT_VTX_2] = | |||
| (0x06 << R200_VTX_TEX_0_ADDR__SHIFT) | | |||
| (0x07 << R200_VTX_TEX_1_ADDR__SHIFT) | | |||
| (0x08 << R200_VTX_TEX_2_ADDR__SHIFT) | | |||
| (0x09 << R200_VTX_TEX_3_ADDR__SHIFT); | |||
| rmesa->hw.cst.cmd[CST_SE_TCL_INPUT_VTX_3] = | |||
| (0x0A << R200_VTX_TEX_4_ADDR__SHIFT) | | |||
| (0x0B << R200_VTX_TEX_5_ADDR__SHIFT); | |||
| 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; | |||
| for (i = 0; i < 2; i++) { /* 2 texture units for now */ | |||
| rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] = R200_BORDER_MODE_OGL; | |||
| rmesa->hw.tex[i].cmd[TEX_PP_TXFORMAT] = | |||
| ((i << R200_TXFORMAT_ST_ROUTE_SHIFT) | /* <-- note i */ | |||
| (2 << R200_TXFORMAT_WIDTH_SHIFT) | | |||
| (2 << R200_TXFORMAT_HEIGHT_SHIFT)); | |||
| rmesa->hw.tex[i].cmd[TEX_PP_TXOFFSET] = 0; | |||
| rmesa->hw.tex[i].cmd[TEX_PP_BORDER_COLOR] = 0; | |||
| rmesa->hw.tex[i].cmd[TEX_PP_TXFORMAT_X] = | |||
| (/* R200_TEXCOORD_PROJ | */ | |||
| 0x100000); /* Small default bias */ | |||
| rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_FACES] = 0; | |||
| rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_F1] = 0; | |||
| rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_F2] = 0; | |||
| rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_F3] = 0; | |||
| rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_F4] = 0; | |||
| rmesa->hw.cube[i].cmd[CUBE_PP_CUBIC_OFFSET_F5] = 0; | |||
| } | |||
| rmesa->hw.pix[0].cmd[PIX_PP_TXCBLEND] = | |||
| (R200_TXC_ARG_A_ZERO | | |||
| R200_TXC_ARG_B_ZERO | | |||
| R200_TXC_ARG_C_DIFFUSE_COLOR | | |||
| R200_TXC_OP_MADD); | |||
| rmesa->hw.pix[0].cmd[PIX_PP_TXCBLEND2] = | |||
| ((0 << R200_TXC_TFACTOR_SEL_SHIFT) | | |||
| R200_TXC_SCALE_1X | | |||
| R200_TXC_CLAMP_0_1 | | |||
| R200_TXC_OUTPUT_REG_R0); | |||
| rmesa->hw.pix[0].cmd[PIX_PP_TXABLEND] = | |||
| (R200_TXA_ARG_A_ZERO | | |||
| R200_TXA_ARG_B_ZERO | | |||
| R200_TXA_ARG_C_DIFFUSE_ALPHA | | |||
| R200_TXA_OP_MADD); | |||
| rmesa->hw.pix[0].cmd[PIX_PP_TXABLEND2] = | |||
| ((0 << R200_TXA_TFACTOR_SEL_SHIFT) | | |||
| R200_TXA_SCALE_1X | | |||
| R200_TXA_CLAMP_0_1 | | |||
| R200_TXA_OUTPUT_REG_R0); | |||
| rmesa->hw.pix[1].cmd[PIX_PP_TXCBLEND] = | |||
| (R200_TXC_ARG_A_ZERO | | |||
| R200_TXC_ARG_B_ZERO | | |||
| R200_TXC_ARG_C_DIFFUSE_COLOR | | |||
| R200_TXC_OP_MADD); | |||
| rmesa->hw.pix[1].cmd[PIX_PP_TXCBLEND2] = | |||
| ((0 << R200_TXC_TFACTOR_SEL_SHIFT) | | |||
| R200_TXC_SCALE_1X | | |||
| R200_TXC_CLAMP_0_1 | | |||
| R200_TXC_OUTPUT_REG_R0); | |||
| rmesa->hw.pix[1].cmd[PIX_PP_TXABLEND] = | |||
| (R200_TXA_ARG_A_ZERO | | |||
| R200_TXA_ARG_B_ZERO | | |||
| R200_TXA_ARG_C_DIFFUSE_ALPHA | | |||
| R200_TXA_OP_MADD); | |||
| rmesa->hw.pix[1].cmd[PIX_PP_TXABLEND2] = | |||
| ((0 << R200_TXA_TFACTOR_SEL_SHIFT) | | |||
| R200_TXA_SCALE_1X | | |||
| R200_TXA_CLAMP_0_1 | | |||
| R200_TXA_OUTPUT_REG_R0); | |||
| rmesa->hw.tf.cmd[TF_TFACTOR_0] = 0; | |||
| rmesa->hw.tf.cmd[TF_TFACTOR_1] = 0; | |||
| rmesa->hw.tf.cmd[TF_TFACTOR_2] = 0; | |||
| rmesa->hw.tf.cmd[TF_TFACTOR_3] = 0; | |||
| rmesa->hw.tf.cmd[TF_TFACTOR_4] = 0; | |||
| rmesa->hw.tf.cmd[TF_TFACTOR_5] = 0; | |||
| rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] = | |||
| (R200_VAP_TCL_ENABLE | | |||
| (0x9 << R200_VAP_VF_MAX_VTX_NUM__SHIFT)); | |||
| rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = | |||
| (R200_VPORT_X_SCALE_ENA | | |||
| R200_VPORT_Y_SCALE_ENA | | |||
| R200_VPORT_Z_SCALE_ENA | | |||
| R200_VPORT_X_OFFSET_ENA | | |||
| R200_VPORT_Y_OFFSET_ENA | | |||
| R200_VPORT_Z_OFFSET_ENA | | |||
| /* FIXME: Turn on for tex rect only */ | |||
| R200_VTX_ST_DENORMALIZED | | |||
| R200_VTX_W0_FMT); | |||
| rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = 0; | |||
| rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = 0; | |||
| rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] = | |||
| ((R200_VTX_Z0 | R200_VTX_W0 | | |||
| (R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT))); | |||
| rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] = 0; | |||
| rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = (R200_OUTPUT_XYZW); | |||
| rmesa->hw.vtx.cmd[VTX_STATE_CNTL] = R200_VSC_UPDATE_USER_COLOR_0_ENABLE; | |||
| /* Matrix selection */ | |||
| rmesa->hw.msl.cmd[MSL_MATRIX_SELECT_0] = | |||
| (R200_MTX_MV << R200_MODELVIEW_0_SHIFT); | |||
| rmesa->hw.msl.cmd[MSL_MATRIX_SELECT_1] = | |||
| (R200_MTX_IMV << R200_IT_MODELVIEW_0_SHIFT); | |||
| rmesa->hw.msl.cmd[MSL_MATRIX_SELECT_2] = | |||
| (R200_MTX_MVP << R200_MODELPROJECT_0_SHIFT); | |||
| rmesa->hw.msl.cmd[MSL_MATRIX_SELECT_3] = | |||
| ((R200_MTX_TEX0 << R200_TEXMAT_0_SHIFT) | | |||
| (R200_MTX_TEX1 << R200_TEXMAT_1_SHIFT) | | |||
| (R200_MTX_TEX2 << R200_TEXMAT_2_SHIFT) | | |||
| (R200_MTX_TEX3 << R200_TEXMAT_3_SHIFT)); | |||
| rmesa->hw.msl.cmd[MSL_MATRIX_SELECT_4] = | |||
| ((R200_MTX_TEX4 << R200_TEXMAT_4_SHIFT) | | |||
| (R200_MTX_TEX5 << R200_TEXMAT_5_SHIFT)); | |||
| /* General TCL state */ | |||
| rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] = | |||
| (R200_SPECULAR_LIGHTS | | |||
| R200_DIFFUSE_SPECULAR_COMBINE | | |||
| R200_LOCAL_LIGHT_VEC_GL); | |||
| rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] = | |||
| ((R200_LM1_SOURCE_LIGHT_PREMULT << R200_FRONT_EMISSIVE_SOURCE_SHIFT) | | |||
| (R200_LM1_SOURCE_LIGHT_PREMULT << R200_FRONT_AMBIENT_SOURCE_SHIFT) | | |||
| (R200_LM1_SOURCE_LIGHT_PREMULT << R200_FRONT_DIFFUSE_SOURCE_SHIFT) | | |||
| (R200_LM1_SOURCE_LIGHT_PREMULT << R200_FRONT_SPECULAR_SOURCE_SHIFT) | | |||
| (R200_LM1_SOURCE_LIGHT_PREMULT << R200_BACK_EMISSIVE_SOURCE_SHIFT) | | |||
| (R200_LM1_SOURCE_LIGHT_PREMULT << R200_BACK_AMBIENT_SOURCE_SHIFT) | | |||
| (R200_LM1_SOURCE_LIGHT_PREMULT << R200_BACK_DIFFUSE_SOURCE_SHIFT) | | |||
| (R200_LM1_SOURCE_LIGHT_PREMULT << R200_BACK_SPECULAR_SOURCE_SHIFT)); | |||
| rmesa->hw.tcl.cmd[TCL_PER_LIGHT_CTL_0] = 0; /* filled in via callbacks */ | |||
| rmesa->hw.tcl.cmd[TCL_PER_LIGHT_CTL_1] = 0; | |||
| rmesa->hw.tcl.cmd[TCL_PER_LIGHT_CTL_2] = 0; | |||
| rmesa->hw.tcl.cmd[TCL_PER_LIGHT_CTL_3] = 0; | |||
| rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = | |||
| (R200_UCP_IN_CLIP_SPACE | | |||
| R200_CULL_FRONT_IS_CCW); | |||
| /* Texgen/Texmat state */ | |||
| rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2] = 0x0; /* masks??? */ | |||
| rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_3] = | |||
| ((0 << R200_TEXGEN_0_INPUT_TEX_SHIFT) | | |||
| (1 << R200_TEXGEN_1_INPUT_TEX_SHIFT) | | |||
| (2 << R200_TEXGEN_2_INPUT_TEX_SHIFT) | | |||
| (3 << R200_TEXGEN_3_INPUT_TEX_SHIFT) | | |||
| (4 << R200_TEXGEN_4_INPUT_TEX_SHIFT) | | |||
| (5 << R200_TEXGEN_5_INPUT_TEX_SHIFT)); | |||
| rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] = 0; | |||
| rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] = | |||
| ((0 << R200_TEXGEN_0_INPUT_SHIFT) | | |||
| (1 << R200_TEXGEN_1_INPUT_SHIFT) | | |||
| (2 << R200_TEXGEN_2_INPUT_SHIFT) | | |||
| (3 << R200_TEXGEN_3_INPUT_SHIFT) | | |||
| (4 << R200_TEXGEN_4_INPUT_SHIFT) | | |||
| (5 << R200_TEXGEN_5_INPUT_SHIFT)); | |||
| rmesa->hw.tcg.cmd[TCG_TEX_CYL_WRAP_CTL] = 0; | |||
| rmesa->TexGenInputs = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1]; | |||
| 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 ); | |||
| 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; | |||
| r200LightingSpaceChange( ctx ); | |||
| rmesa->lost_context = 1; | |||
| } | |||
| @@ -0,0 +1,80 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #ifndef __R200_SWTCL_H__ | |||
| #define __R200_SWTCL_H__ | |||
| #include "mtypes.h" | |||
| #include "swrast/swrast.h" | |||
| #include "r200_context.h" | |||
| extern void r200InitSwtcl( GLcontext *ctx ); | |||
| extern void r200DestroySwtcl( GLcontext *ctx ); | |||
| extern void r200FlushVertices( GLcontext *ctx, GLuint flags ); | |||
| extern void r200ChooseRenderState( GLcontext *ctx ); | |||
| extern void r200ChooseVertexState( GLcontext *ctx ); | |||
| extern void r200CheckTexSizes( GLcontext *ctx ); | |||
| extern void r200BuildVertices( GLcontext *ctx, GLuint start, GLuint count, | |||
| GLuint newinputs ); | |||
| extern void r200PrintSetupFlags(char *msg, GLuint flags ); | |||
| extern void r200_emit_contiguous_verts( GLcontext *ctx, | |||
| GLuint start, | |||
| GLuint count ); | |||
| extern void r200_emit_indexed_verts( GLcontext *ctx, | |||
| GLuint start, | |||
| GLuint count ); | |||
| extern void r200_translate_vertex( GLcontext *ctx, | |||
| const r200Vertex *src, | |||
| SWvertex *dst ); | |||
| extern void r200_print_vertex( GLcontext *ctx, const r200Vertex *v ); | |||
| extern void r200_import_float_colors( GLcontext *ctx ); | |||
| extern void r200_import_float_spec_colors( GLcontext *ctx ); | |||
| extern void r200PointsBitmap( GLcontext *ctx, GLint px, GLint py, | |||
| GLsizei width, GLsizei height, | |||
| const struct gl_pixelstore_attrib *unpack, | |||
| const GLubyte *bitmap ); | |||
| #endif | |||
| @@ -0,0 +1,555 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #include "glheader.h" | |||
| #include "imports.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 "r200_context.h" | |||
| #include "r200_state.h" | |||
| #include "r200_ioctl.h" | |||
| #include "r200_tex.h" | |||
| #include "r200_tcl.h" | |||
| #include "r200_swtcl.h" | |||
| #include "r200_maos.h" | |||
| #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 /* hw quad verts in wrong order??? */ | |||
| #define HAVE_QUAD_STRIPS 1 | |||
| #define HAVE_POLYGONS 1 | |||
| #define HAVE_ELTS 1 | |||
| #define HW_POINTS R200_VF_PRIM_POINTS | |||
| #define HW_LINES R200_VF_PRIM_LINES | |||
| #define HW_LINE_LOOP 0 | |||
| #define HW_LINE_STRIP R200_VF_PRIM_LINE_STRIP | |||
| #define HW_TRIANGLES R200_VF_PRIM_TRIANGLES | |||
| #define HW_TRIANGLE_STRIP_0 R200_VF_PRIM_TRIANGLE_STRIP | |||
| #define HW_TRIANGLE_STRIP_1 0 | |||
| #define HW_TRIANGLE_FAN R200_VF_PRIM_TRIANGLE_FAN | |||
| #define HW_QUADS R200_VF_PRIM_QUADS | |||
| #define HW_QUAD_STRIP R200_VF_PRIM_QUAD_STRIP | |||
| #define HW_POLYGON R200_VF_PRIM_POLYGON | |||
| static GLboolean discrete_prim[0x10] = { | |||
| 0, /* 0 none */ | |||
| 1, /* 1 points */ | |||
| 1, /* 2 lines */ | |||
| 0, /* 3 line_strip */ | |||
| 1, /* 4 tri_list */ | |||
| 0, /* 5 tri_fan */ | |||
| 0, /* 6 tri_strip */ | |||
| 0, /* 7 tri_w_flags */ | |||
| 1, /* 8 rect list (unused) */ | |||
| 1, /* 9 3vert point */ | |||
| 1, /* a 3vert line */ | |||
| 0, /* b point sprite */ | |||
| 0, /* c line loop */ | |||
| 1, /* d quads */ | |||
| 0, /* e quad strip */ | |||
| 0, /* f polygon */ | |||
| }; | |||
| #define LOCAL_VARS r200ContextPtr rmesa = R200_CONTEXT(ctx) | |||
| #define ELTS_VARS GLushort *dest | |||
| #define ELT_INIT(prim, hw_prim) \ | |||
| r200TclPrimitive( ctx, prim, hw_prim | R200_VF_PRIM_WALK_IND ) | |||
| #define GET_ELTS() rmesa->tcl.Elts | |||
| #define NEW_PRIMITIVE() R200_NEWPRIM( rmesa ) | |||
| #define NEW_BUFFER() r200RefillCurrentDmaRegion( 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() \ | |||
| ((R200_CMD_BUF_SZ - (rmesa->store.cmd_used + 16)) / 2) | |||
| #define GET_SUBSEQUENT_VB_MAX_ELTS() ((R200_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 { \ | |||
| R200_STATECHANGE( rmesa, lin ); \ | |||
| r200EmitState( rmesa ); \ | |||
| } while (0) | |||
| #define AUTO_STIPPLE( mode ) do { \ | |||
| R200_STATECHANGE( rmesa, lin ); \ | |||
| if (mode) \ | |||
| rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] |= \ | |||
| R200_LINE_PATTERN_AUTO_RESET; \ | |||
| else \ | |||
| rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] &= \ | |||
| ~R200_LINE_PATTERN_AUTO_RESET; \ | |||
| r200EmitState( rmesa ); \ | |||
| } while (0) | |||
| /* How do you extend an existing primitive? | |||
| */ | |||
| #define ALLOC_ELTS(nr) \ | |||
| do { \ | |||
| if (rmesa->dma.flush == r200FlushElts && \ | |||
| rmesa->store.cmd_used + nr*2 < R200_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 ); \ | |||
| \ | |||
| r200EmitAOS( rmesa, \ | |||
| rmesa->tcl.aos_components, \ | |||
| rmesa->tcl.nr_aos_components, \ | |||
| 0 ); \ | |||
| \ | |||
| dest = r200AllocEltsOpenEnded( rmesa, \ | |||
| rmesa->tcl.hw_primitive, \ | |||
| nr ); \ | |||
| } \ | |||
| } while (0) | |||
| /* TODO: Try to extend existing primitive if both are identical, | |||
| * discrete 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) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT( ctx ); | |||
| r200TclPrimitive( ctx, prim, hwprim ); | |||
| r200EmitAOS( rmesa, | |||
| rmesa->tcl.aos_components, | |||
| rmesa->tcl.nr_aos_components, | |||
| start ); | |||
| /* Why couldn't this packet have taken an offset param? | |||
| */ | |||
| r200EmitVbufPrim( rmesa, | |||
| 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| \ | |||
| R200_VF_TCL_OUTPUT_VTX_ENABLE| \ | |||
| R200_VF_PRIM_WALK_IND))) | |||
| #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() \ | |||
| r200ReleaseArrays( ctx, ~0 ) | |||
| #define TAG(x) tcl_##x | |||
| #include "tnl_dd/t_dd_dmatmp2.h" | |||
| /**********************************************************************/ | |||
| /* External entrypoints */ | |||
| /**********************************************************************/ | |||
| void r200EmitPrimitive( GLcontext *ctx, | |||
| GLuint first, | |||
| GLuint last, | |||
| GLuint flags ) | |||
| { | |||
| tcl_render_tab_verts[flags&PRIM_MODE_MASK]( ctx, first, last, flags ); | |||
| } | |||
| void r200EmitEltPrimitive( GLcontext *ctx, | |||
| GLuint first, | |||
| GLuint last, | |||
| GLuint flags ) | |||
| { | |||
| tcl_render_tab_elts[flags&PRIM_MODE_MASK]( ctx, first, last, flags ); | |||
| } | |||
| void r200TclPrimitive( GLcontext *ctx, | |||
| GLenum prim, | |||
| int hw_prim ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| GLuint newprim = hw_prim | R200_VF_TCL_OUTPUT_VTX_ENABLE; | |||
| if (newprim != rmesa->tcl.hw_primitive || | |||
| !discrete_prim[hw_prim&0xf]) { | |||
| R200_NEWPRIM( rmesa ); | |||
| rmesa->tcl.hw_primitive = newprim; | |||
| } | |||
| } | |||
| /**********************************************************************/ | |||
| /* Render pipeline stage */ | |||
| /**********************************************************************/ | |||
| /* TCL render. | |||
| */ | |||
| static GLboolean r200_run_tcl_render( GLcontext *ctx, | |||
| struct gl_pipeline_stage *stage ) | |||
| { | |||
| r200ContextPtr rmesa = R200_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 (R200_DEBUG & DEBUG_PRIMS) | |||
| fprintf(stderr, "%s\n", __FUNCTION__); | |||
| if (VB->Count == 0) | |||
| return GL_FALSE; | |||
| r200ReleaseArrays( ctx, stage->changed_inputs ); | |||
| r200EmitArrays( 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 (R200_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) | |||
| r200EmitEltPrimitive( ctx, i, i+length, flags ); | |||
| else | |||
| r200EmitPrimitive( ctx, i, i+length, flags ); | |||
| } | |||
| return GL_FALSE; /* finished the pipe */ | |||
| } | |||
| static void r200_check_tcl_render( GLcontext *ctx, | |||
| struct gl_pipeline_stage *stage ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| GLuint inputs = VERT_BIT_POS; | |||
| /* Validate state: | |||
| */ | |||
| if (rmesa->NewGLState) | |||
| r200ValidateState( ctx ); | |||
| if (0) | |||
| fprintf(stderr, "%s: RE %d TGE %d NN %d\n", | |||
| __FUNCTION__, | |||
| ctx->Texture.Unit[0]._ReallyEnabled, | |||
| ctx->Texture.Unit[0].TexGenEnabled, | |||
| rmesa->TexGenNeedNormals[0]); | |||
| if (ctx->RenderMode == GL_RENDER) { | |||
| /* Make all this event-driven: | |||
| */ | |||
| if (ctx->Light.Enabled) { | |||
| inputs |= VERT_BIT_NORMAL; | |||
| if (ctx->Light.ColorMaterialEnabled) { | |||
| inputs |= VERT_BIT_COLOR0; | |||
| } | |||
| } | |||
| else { | |||
| inputs |= VERT_BIT_COLOR0; | |||
| if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) { | |||
| inputs |= VERT_BIT_COLOR1; | |||
| } | |||
| } | |||
| if (ctx->Texture.Unit[0]._ReallyEnabled) { | |||
| if (ctx->Texture.Unit[0].TexGenEnabled) { | |||
| if (rmesa->TexGenNeedNormals[0]) { | |||
| inputs |= VERT_BIT_NORMAL; | |||
| } | |||
| } else { | |||
| inputs |= VERT_BIT_TEX0; | |||
| } | |||
| } | |||
| if (ctx->Texture.Unit[1]._ReallyEnabled) { | |||
| if (ctx->Texture.Unit[1].TexGenEnabled) { | |||
| if (rmesa->TexGenNeedNormals[1]) { | |||
| inputs |= VERT_BIT_NORMAL; | |||
| } | |||
| } else { | |||
| inputs |= VERT_BIT_TEX1; | |||
| } | |||
| } | |||
| stage->inputs = inputs; | |||
| stage->active = 1; | |||
| } | |||
| else | |||
| stage->active = 0; | |||
| } | |||
| static void r200_init_tcl_render( GLcontext *ctx, | |||
| struct gl_pipeline_stage *stage ) | |||
| { | |||
| stage->check = r200_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 _r200_tcl_stage = | |||
| { | |||
| "r200 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 */ | |||
| r200_init_tcl_render, /* check - initially set to alloc data */ | |||
| r200_run_tcl_render /* run */ | |||
| }; | |||
| /**********************************************************************/ | |||
| /* Validate state at pipeline start */ | |||
| /**********************************************************************/ | |||
| /*----------------------------------------------------------------------- | |||
| * Manage TCL fallbacks | |||
| */ | |||
| static void transition_to_swtnl( GLcontext *ctx ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| TNLcontext *tnl = TNL_CONTEXT(ctx); | |||
| R200_NEWPRIM( rmesa ); | |||
| rmesa->swtcl.vertex_format = 0; | |||
| r200ChooseVertexState( ctx ); | |||
| r200ChooseRenderState( ctx ); | |||
| _mesa_validate_all_lighting_tables( ctx ); | |||
| tnl->Driver.NotifyMaterialChange = | |||
| _mesa_validate_all_lighting_tables; | |||
| r200ReleaseArrays( ctx, ~0 ); | |||
| /* Still using the D3D based hardware-rasterizer from the radeon; | |||
| * need to put the card into D3D mode to make it work: | |||
| */ | |||
| R200_STATECHANGE( rmesa, vap ); | |||
| rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_TCL_ENABLE; | |||
| rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_D3D_TEX_DEFAULT; | |||
| R200_STATECHANGE( rmesa, vte ); | |||
| rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] &= ~R200_VTX_W0_FMT; | |||
| R200_STATECHANGE( rmesa, set ); | |||
| rmesa->hw.set.cmd[SET_RE_CNTL] |= (R200_VTX_STQ0_D3D | | |||
| R200_VTX_STQ1_D3D); | |||
| } | |||
| static void transition_to_hwtnl( GLcontext *ctx ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| TNLcontext *tnl = TNL_CONTEXT(ctx); | |||
| _tnl_need_projected_coords( ctx, GL_FALSE ); | |||
| r200UpdateMaterial( ctx ); | |||
| tnl->Driver.NotifyMaterialChange = r200UpdateMaterial; | |||
| if ( rmesa->dma.flush ) | |||
| rmesa->dma.flush( rmesa ); | |||
| rmesa->dma.flush = 0; | |||
| rmesa->swtcl.vertex_format = 0; | |||
| if (rmesa->swtcl.indexed_verts.buf) | |||
| r200ReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, | |||
| __FUNCTION__ ); | |||
| R200_STATECHANGE( rmesa, vap ); | |||
| rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_TCL_ENABLE; | |||
| rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~(R200_VAP_FORCE_W_TO_ONE | | |||
| R200_VAP_D3D_TEX_DEFAULT); | |||
| R200_STATECHANGE( rmesa, vte ); | |||
| rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] &= ~(R200_VTX_XY_FMT|R200_VTX_Z_FMT); | |||
| rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] |= R200_VTX_W0_FMT; | |||
| R200_STATECHANGE( rmesa, set ); | |||
| rmesa->hw.set.cmd[SET_RE_CNTL] &= ~(R200_VTX_STQ0_D3D | | |||
| R200_VTX_STQ1_D3D); | |||
| if (R200_DEBUG & DEBUG_FALLBACKS) | |||
| fprintf(stderr, "R200 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 r200TclFallback( GLcontext *ctx, GLuint bit, GLboolean mode ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| GLuint oldfallback = rmesa->TclFallback; | |||
| if (mode) { | |||
| rmesa->TclFallback |= bit; | |||
| if (oldfallback == 0) { | |||
| if (R200_DEBUG & DEBUG_FALLBACKS) | |||
| fprintf(stderr, "R200 begin tcl fallback %s\n", | |||
| getFallbackString( bit )); | |||
| transition_to_swtnl( ctx ); | |||
| } | |||
| } | |||
| else { | |||
| rmesa->TclFallback &= ~bit; | |||
| if (oldfallback == bit) { | |||
| if (R200_DEBUG & DEBUG_FALLBACKS) | |||
| fprintf(stderr, "R200 end tcl fallback %s\n", | |||
| getFallbackString( bit )); | |||
| transition_to_hwtnl( ctx ); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,66 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #ifndef __R200_TCL_H__ | |||
| #define __R200_TCL_H__ | |||
| #ifdef GLX_DIRECT_RENDERING | |||
| #include "r200_context.h" | |||
| extern void r200TclPrimitive( GLcontext *ctx, GLenum prim, int hw_prim ); | |||
| extern void r200EmitEltPrimitive( GLcontext *ctx, GLuint first, GLuint last, | |||
| GLuint flags ); | |||
| extern void r200EmitPrimitive( GLcontext *ctx, GLuint first, GLuint last, | |||
| GLuint flags ); | |||
| extern void r200TclFallback( GLcontext *ctx, GLuint bit, GLboolean mode ); | |||
| #define R200_TCL_FALLBACK_RASTER 0x1 /* rasterization */ | |||
| #define R200_TCL_FALLBACK_UNFILLED 0x2 /* unfilled tris */ | |||
| #define R200_TCL_FALLBACK_LIGHT_TWOSIDE 0x4 /* twoside tris */ | |||
| #define R200_TCL_FALLBACK_MATERIAL 0x8 /* material in vb */ | |||
| #define R200_TCL_FALLBACK_TEXGEN_0 0x10 /* texgen, unit 0 */ | |||
| #define R200_TCL_FALLBACK_TEXGEN_1 0x20 /* texgen, unit 1 */ | |||
| #define R200_TCL_FALLBACK_TEXGEN_2 0x40 /* texgen, unit 2 */ | |||
| #define R200_TCL_FALLBACK_TCL_DISABLE 0x80 /* user disable */ | |||
| #define R200_TCL_FALLBACK_BITMAP 0x100 /* draw bitmap with points */ | |||
| #define R200_MAX_TCL_VERTSIZE (4*4) /* using maos now... */ | |||
| #define TCL_FALLBACK( ctx, bit, mode ) r200TclFallback( ctx, bit, mode ) | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,988 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #include "glheader.h" | |||
| #include "imports.h" | |||
| #include "colormac.h" | |||
| #include "context.h" | |||
| #include "enums.h" | |||
| #include "image.h" | |||
| #include "mmath.h" | |||
| #include "simple_list.h" | |||
| #include "texformat.h" | |||
| #include "texstore.h" | |||
| #include "texutil.h" | |||
| #include "r200_context.h" | |||
| #include "r200_state.h" | |||
| #include "r200_ioctl.h" | |||
| #include "r200_swtcl.h" | |||
| #include "r200_tex.h" | |||
| /* ============================================================= | |||
| * Utility functions: | |||
| */ | |||
| static void r200SetTexWrap( r200TexObjPtr t, GLenum swrap, GLenum twrap, GLenum rwrap ) | |||
| { | |||
| t->pp_txfilter &= ~(R200_CLAMP_S_MASK | R200_CLAMP_T_MASK); | |||
| switch ( swrap ) { | |||
| case GL_REPEAT: | |||
| t->pp_txfilter |= R200_CLAMP_S_WRAP; | |||
| break; | |||
| case GL_CLAMP: | |||
| t->pp_txfilter |= R200_CLAMP_S_CLAMP_LAST; | |||
| break; | |||
| case GL_CLAMP_TO_EDGE: | |||
| t->pp_txfilter |= R200_CLAMP_S_CLAMP_LAST; | |||
| break; | |||
| case GL_CLAMP_TO_BORDER: | |||
| t->pp_txfilter |= R200_CLAMP_S_CLAMP_BORDER; | |||
| break; | |||
| case GL_MIRRORED_REPEAT_ARB: | |||
| t->pp_txfilter |= R200_CLAMP_S_MIRROR; | |||
| break; | |||
| case GL_MIRROR_CLAMP_ATI: | |||
| t->pp_txfilter |= R200_CLAMP_S_MIRROR_CLAMP_BORDER; | |||
| break; | |||
| case GL_MIRROR_CLAMP_TO_EDGE_ATI: | |||
| t->pp_txfilter |= R200_CLAMP_S_MIRROR_CLAMP_LAST; | |||
| break; | |||
| default: | |||
| _mesa_problem(NULL, "bad S wrap mode in r200SetTexWrap"); | |||
| } | |||
| switch ( twrap ) { | |||
| case GL_REPEAT: | |||
| t->pp_txfilter |= R200_CLAMP_T_WRAP; | |||
| break; | |||
| case GL_CLAMP: | |||
| t->pp_txfilter |= R200_CLAMP_T_CLAMP_LAST; | |||
| break; | |||
| case GL_CLAMP_TO_EDGE: | |||
| t->pp_txfilter |= R200_CLAMP_T_CLAMP_LAST; | |||
| break; | |||
| case GL_CLAMP_TO_BORDER: | |||
| t->pp_txfilter |= R200_CLAMP_T_CLAMP_BORDER; | |||
| break; | |||
| case GL_MIRRORED_REPEAT_ARB: | |||
| t->pp_txfilter |= R200_CLAMP_T_MIRROR; | |||
| break; | |||
| case GL_MIRROR_CLAMP_ATI: | |||
| t->pp_txfilter |= R200_CLAMP_T_MIRROR_CLAMP_BORDER; | |||
| break; | |||
| case GL_MIRROR_CLAMP_TO_EDGE_ATI: | |||
| t->pp_txfilter |= R200_CLAMP_T_MIRROR_CLAMP_LAST; | |||
| break; | |||
| default: | |||
| _mesa_problem(NULL, "bad S wrap mode in r200SetTexWrap"); | |||
| } | |||
| t->pp_txformat_x &= ~R200_CLAMP_Q_MASK; | |||
| switch ( rwrap ) { | |||
| case GL_REPEAT: | |||
| t->pp_txformat_x |= R200_CLAMP_Q_WRAP; | |||
| break; | |||
| case GL_CLAMP: | |||
| t->pp_txformat_x |= R200_CLAMP_Q_CLAMP_LAST; | |||
| break; | |||
| case GL_CLAMP_TO_EDGE: | |||
| t->pp_txformat_x |= R200_CLAMP_Q_CLAMP_LAST; | |||
| break; | |||
| case GL_CLAMP_TO_BORDER: | |||
| t->pp_txformat_x |= R200_CLAMP_Q_CLAMP_BORDER; | |||
| break; | |||
| case GL_MIRRORED_REPEAT_ARB: | |||
| t->pp_txformat_x |= R200_CLAMP_Q_MIRROR; | |||
| break; | |||
| case GL_MIRROR_CLAMP_ATI: | |||
| t->pp_txformat_x |= R200_CLAMP_Q_MIRROR_CLAMP_BORDER; | |||
| break; | |||
| case GL_MIRROR_CLAMP_TO_EDGE_ATI: | |||
| t->pp_txformat_x |= R200_CLAMP_Q_MIRROR_CLAMP_LAST; | |||
| break; | |||
| default: | |||
| _mesa_problem(NULL, "bad R wrap mode in r200SetTexWrap"); | |||
| } | |||
| } | |||
| static void r200SetTexMaxAnisotropy( r200TexObjPtr t, GLfloat max ) | |||
| { | |||
| t->pp_txfilter &= ~R200_MAX_ANISO_MASK; | |||
| if ( max == 1.0 ) { | |||
| t->pp_txfilter |= R200_MAX_ANISO_1_TO_1; | |||
| } else if ( max <= 2.0 ) { | |||
| t->pp_txfilter |= R200_MAX_ANISO_2_TO_1; | |||
| } else if ( max <= 4.0 ) { | |||
| t->pp_txfilter |= R200_MAX_ANISO_4_TO_1; | |||
| } else if ( max <= 8.0 ) { | |||
| t->pp_txfilter |= R200_MAX_ANISO_8_TO_1; | |||
| } else { | |||
| t->pp_txfilter |= R200_MAX_ANISO_16_TO_1; | |||
| } | |||
| } | |||
| static void r200SetTexFilter( r200TexObjPtr t, GLenum minf, GLenum magf ) | |||
| { | |||
| GLuint anisotropy = (t->pp_txfilter & R200_MAX_ANISO_MASK); | |||
| t->pp_txfilter &= ~(R200_MIN_FILTER_MASK | R200_MAG_FILTER_MASK); | |||
| t->pp_txformat_x &= ~R200_VOLUME_FILTER_MASK; | |||
| if ( anisotropy == R200_MAX_ANISO_1_TO_1 ) { | |||
| switch ( minf ) { | |||
| case GL_NEAREST: | |||
| t->pp_txfilter |= R200_MIN_FILTER_NEAREST; | |||
| break; | |||
| case GL_LINEAR: | |||
| t->pp_txfilter |= R200_MIN_FILTER_LINEAR; | |||
| break; | |||
| case GL_NEAREST_MIPMAP_NEAREST: | |||
| t->pp_txfilter |= R200_MIN_FILTER_NEAREST_MIP_NEAREST; | |||
| break; | |||
| case GL_NEAREST_MIPMAP_LINEAR: | |||
| t->pp_txfilter |= R200_MIN_FILTER_LINEAR_MIP_NEAREST; | |||
| break; | |||
| case GL_LINEAR_MIPMAP_NEAREST: | |||
| t->pp_txfilter |= R200_MIN_FILTER_NEAREST_MIP_LINEAR; | |||
| break; | |||
| case GL_LINEAR_MIPMAP_LINEAR: | |||
| t->pp_txfilter |= R200_MIN_FILTER_LINEAR_MIP_LINEAR; | |||
| break; | |||
| } | |||
| } else { | |||
| switch ( minf ) { | |||
| case GL_NEAREST: | |||
| t->pp_txfilter |= R200_MIN_FILTER_ANISO_NEAREST; | |||
| break; | |||
| case GL_LINEAR: | |||
| t->pp_txfilter |= R200_MIN_FILTER_ANISO_LINEAR; | |||
| break; | |||
| case GL_NEAREST_MIPMAP_NEAREST: | |||
| case GL_LINEAR_MIPMAP_NEAREST: | |||
| t->pp_txfilter |= R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST; | |||
| break; | |||
| case GL_NEAREST_MIPMAP_LINEAR: | |||
| case GL_LINEAR_MIPMAP_LINEAR: | |||
| t->pp_txfilter |= R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR; | |||
| break; | |||
| } | |||
| } | |||
| /* Note we don't have 3D mipmaps so only use the mag filter setting | |||
| * to set the 3D texture filter mode. | |||
| */ | |||
| switch ( magf ) { | |||
| case GL_NEAREST: | |||
| t->pp_txfilter |= R200_MAG_FILTER_NEAREST; | |||
| t->pp_txformat_x |= R200_VOLUME_FILTER_NEAREST; | |||
| break; | |||
| case GL_LINEAR: | |||
| t->pp_txfilter |= R200_MAG_FILTER_LINEAR; | |||
| t->pp_txformat_x |= R200_VOLUME_FILTER_LINEAR; | |||
| break; | |||
| } | |||
| } | |||
| static void r200SetTexBorderColor( r200TexObjPtr t, GLubyte c[4] ) | |||
| { | |||
| t->pp_border_color = r200PackColor( 4, c[0], c[1], c[2], c[3] ); | |||
| } | |||
| static r200TexObjPtr r200AllocTexObj( struct gl_texture_object *texObj ) | |||
| { | |||
| r200TexObjPtr t; | |||
| t = CALLOC_STRUCT( r200_tex_obj ); | |||
| if (!t) | |||
| return NULL; | |||
| if ( R200_DEBUG & DEBUG_TEXTURE ) { | |||
| fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, texObj, t ); | |||
| } | |||
| t->tObj = texObj; | |||
| make_empty_list( t ); | |||
| /* Initialize non-image-dependent parts of the state: | |||
| */ | |||
| r200SetTexWrap( t, texObj->WrapS, texObj->WrapT, texObj->WrapR ); | |||
| r200SetTexMaxAnisotropy( t, texObj->MaxAnisotropy ); | |||
| r200SetTexFilter( t, texObj->MinFilter, texObj->MagFilter ); | |||
| r200SetTexBorderColor( t, texObj->_BorderChan ); | |||
| return t; | |||
| } | |||
| static const struct gl_texture_format * | |||
| r200ChooseTextureFormat( GLcontext *ctx, GLint internalFormat, | |||
| GLenum format, GLenum type ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| const GLboolean do32bpt = ( rmesa->r200Screen->cpp == 4 ); | |||
| switch ( internalFormat ) { | |||
| case 4: | |||
| case GL_RGBA: | |||
| if ( format == GL_BGRA ) { | |||
| if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) { | |||
| return &_mesa_texformat_argb8888; | |||
| } | |||
| else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) { | |||
| return &_mesa_texformat_argb4444; | |||
| } | |||
| else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) { | |||
| return &_mesa_texformat_argb1555; | |||
| } | |||
| } | |||
| return do32bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_argb4444; | |||
| case 3: | |||
| case GL_RGB: | |||
| if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) { | |||
| return &_mesa_texformat_rgb565; | |||
| } | |||
| return do32bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_rgb565; | |||
| case GL_RGBA8: | |||
| case GL_RGB10_A2: | |||
| case GL_RGBA12: | |||
| case GL_RGBA16: | |||
| return do32bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_argb4444; | |||
| case GL_RGBA4: | |||
| case GL_RGBA2: | |||
| return &_mesa_texformat_argb4444; | |||
| case GL_RGB5_A1: | |||
| return &_mesa_texformat_argb1555; | |||
| case GL_RGB8: | |||
| case GL_RGB10: | |||
| case GL_RGB12: | |||
| case GL_RGB16: | |||
| return do32bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_rgb565; | |||
| case GL_RGB5: | |||
| case GL_RGB4: | |||
| case GL_R3_G3_B2: | |||
| return &_mesa_texformat_rgb565; | |||
| case GL_ALPHA: | |||
| case GL_ALPHA4: | |||
| case GL_ALPHA8: | |||
| case GL_ALPHA12: | |||
| case GL_ALPHA16: | |||
| return &_mesa_texformat_al88; | |||
| case 1: | |||
| case GL_LUMINANCE: | |||
| case GL_LUMINANCE4: | |||
| case GL_LUMINANCE8: | |||
| case GL_LUMINANCE12: | |||
| case GL_LUMINANCE16: | |||
| return &_mesa_texformat_al88; | |||
| case 2: | |||
| case GL_LUMINANCE_ALPHA: | |||
| case GL_LUMINANCE4_ALPHA4: | |||
| case GL_LUMINANCE6_ALPHA2: | |||
| case GL_LUMINANCE8_ALPHA8: | |||
| case GL_LUMINANCE12_ALPHA4: | |||
| case GL_LUMINANCE12_ALPHA12: | |||
| case GL_LUMINANCE16_ALPHA16: | |||
| return &_mesa_texformat_al88; | |||
| case GL_INTENSITY: | |||
| case GL_INTENSITY4: | |||
| case GL_INTENSITY8: | |||
| case GL_INTENSITY12: | |||
| case GL_INTENSITY16: | |||
| /* At the moment, glean & conform both fail using the i8 internal | |||
| * format. | |||
| */ | |||
| return &_mesa_texformat_al88; | |||
| /* return &_mesa_texformat_i8; */ | |||
| case GL_YCBCR_MESA: | |||
| if (type == GL_UNSIGNED_SHORT_8_8_APPLE || | |||
| type == GL_UNSIGNED_BYTE) | |||
| return &_mesa_texformat_ycbcr; | |||
| else | |||
| return &_mesa_texformat_ycbcr_rev; | |||
| default: | |||
| _mesa_problem(ctx, "unexpected texture format in r200ChoosTexFormat"); | |||
| return NULL; | |||
| } | |||
| return NULL; /* never get here */ | |||
| } | |||
| static GLboolean | |||
| r200ValidateClientStorage( GLcontext *ctx, GLenum target, | |||
| GLint internalFormat, | |||
| GLint srcWidth, GLint srcHeight, | |||
| GLenum format, GLenum type, const void *pixels, | |||
| const struct gl_pixelstore_attrib *packing, | |||
| struct gl_texture_object *texObj, | |||
| struct gl_texture_image *texImage) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| int texelBytes; | |||
| if (0) | |||
| fprintf(stderr, "intformat %s format %s type %s\n", | |||
| _mesa_lookup_enum_by_nr( internalFormat ), | |||
| _mesa_lookup_enum_by_nr( format ), | |||
| _mesa_lookup_enum_by_nr( type )); | |||
| if (!ctx->Unpack.ClientStorage) | |||
| return 0; | |||
| if (ctx->_ImageTransferState || | |||
| texImage->IsCompressed || | |||
| texObj->GenerateMipmap) | |||
| return 0; | |||
| /* This list is incomplete, may be different on ppc??? | |||
| */ | |||
| switch ( internalFormat ) { | |||
| case GL_RGBA: | |||
| if ( format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV ) { | |||
| texImage->TexFormat = &_mesa_texformat_argb8888; | |||
| texelBytes = 4; | |||
| } | |||
| else | |||
| return 0; | |||
| break; | |||
| case GL_YCBCR_MESA: | |||
| if ( format == GL_YCBCR_MESA && | |||
| type == GL_UNSIGNED_SHORT_8_8_REV_APPLE ) { | |||
| texImage->TexFormat = &_mesa_texformat_ycbcr_rev; | |||
| texelBytes = 2; | |||
| } | |||
| else if ( format == GL_YCBCR_MESA && | |||
| (type == GL_UNSIGNED_SHORT_8_8_APPLE || | |||
| type == GL_UNSIGNED_BYTE)) { | |||
| texImage->TexFormat = &_mesa_texformat_ycbcr; | |||
| texelBytes = 2; | |||
| } | |||
| else | |||
| return 0; | |||
| break; | |||
| default: | |||
| return 0; | |||
| } | |||
| /* Could deal with these packing issues, but currently don't: | |||
| */ | |||
| if (packing->SkipPixels || | |||
| packing->SkipRows || | |||
| packing->SwapBytes || | |||
| packing->LsbFirst) { | |||
| return 0; | |||
| } | |||
| { | |||
| GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth, | |||
| format, type); | |||
| if (0) | |||
| fprintf(stderr, "%s: srcRowStride %d/%x\n", | |||
| __FUNCTION__, srcRowStride, srcRowStride); | |||
| /* Could check this later in upload, pitch restrictions could be | |||
| * relaxed, but would need to store the image pitch somewhere, | |||
| * as packing details might change before image is uploaded: | |||
| */ | |||
| if (!r200IsAgpMemory( rmesa, pixels, srcHeight * srcRowStride ) || | |||
| (srcRowStride & 63)) | |||
| return 0; | |||
| /* Have validated that _mesa_transfer_teximage would be a straight | |||
| * memcpy at this point. NOTE: future calls to TexSubImage will | |||
| * overwrite the client data. This is explicitly mentioned in the | |||
| * extension spec. | |||
| */ | |||
| texImage->Data = (void *)pixels; | |||
| texImage->IsClientData = GL_TRUE; | |||
| texImage->RowStride = srcRowStride / texelBytes; | |||
| return 1; | |||
| } | |||
| } | |||
| static void r200TexImage1D( GLcontext *ctx, GLenum target, GLint level, | |||
| GLint internalFormat, | |||
| GLint width, GLint border, | |||
| GLenum format, GLenum type, const GLvoid *pixels, | |||
| const struct gl_pixelstore_attrib *packing, | |||
| struct gl_texture_object *texObj, | |||
| struct gl_texture_image *texImage ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| r200TexObjPtr t = (r200TexObjPtr) texObj->DriverData; | |||
| if ( t ) { | |||
| r200SwapOutTexObj( rmesa, t ); | |||
| } | |||
| else { | |||
| t = r200AllocTexObj( texObj ); | |||
| if (!t) { | |||
| _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); | |||
| return; | |||
| } | |||
| texObj->DriverData = t; | |||
| } | |||
| /* Note, this will call r200ChooseTextureFormat */ | |||
| _mesa_store_teximage1d(ctx, target, level, internalFormat, | |||
| width, border, format, type, pixels, | |||
| &ctx->Unpack, texObj, texImage); | |||
| t->dirty_images[0] |= (1 << level); | |||
| } | |||
| static void r200TexSubImage1D( GLcontext *ctx, GLenum target, GLint level, | |||
| GLint xoffset, | |||
| GLsizei width, | |||
| GLenum format, GLenum type, | |||
| const GLvoid *pixels, | |||
| const struct gl_pixelstore_attrib *packing, | |||
| struct gl_texture_object *texObj, | |||
| struct gl_texture_image *texImage ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| r200TexObjPtr t = (r200TexObjPtr)texObj->DriverData; | |||
| assert( t ); /* this _should_ be true */ | |||
| if ( t ) { | |||
| r200SwapOutTexObj( rmesa, t ); | |||
| t->dirty_images[0] |= (1 << level); | |||
| } | |||
| else { | |||
| t = r200AllocTexObj(texObj); | |||
| if (!t) { | |||
| _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D"); | |||
| return; | |||
| } | |||
| texObj->DriverData = t; | |||
| } | |||
| _mesa_store_texsubimage1d(ctx, target, level, xoffset, width, | |||
| format, type, pixels, packing, texObj, | |||
| texImage); | |||
| t->dirty_images[0] |= (1 << level); | |||
| } | |||
| static void r200TexImage2D( GLcontext *ctx, GLenum target, GLint level, | |||
| GLint internalFormat, | |||
| GLint width, GLint height, GLint border, | |||
| GLenum format, GLenum type, const GLvoid *pixels, | |||
| const struct gl_pixelstore_attrib *packing, | |||
| struct gl_texture_object *texObj, | |||
| struct gl_texture_image *texImage ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| r200TexObjPtr t = (r200TexObjPtr)texObj->DriverData; | |||
| GLuint face; | |||
| /* which cube face or ordinary 2D image */ | |||
| switch (target) { | |||
| case GL_TEXTURE_CUBE_MAP_POSITIVE_X: | |||
| case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: | |||
| case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: | |||
| case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: | |||
| case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: | |||
| case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: | |||
| face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; | |||
| ASSERT(face < 6); | |||
| break; | |||
| default: | |||
| face = 0; | |||
| } | |||
| if ( t ) { | |||
| r200SwapOutTexObj( rmesa, t ); | |||
| } | |||
| else { | |||
| t = r200AllocTexObj( texObj ); | |||
| if (!t) { | |||
| _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); | |||
| return; | |||
| } | |||
| texObj->DriverData = t; | |||
| } | |||
| texImage->IsClientData = GL_FALSE; | |||
| if (r200ValidateClientStorage( ctx, target, | |||
| internalFormat, | |||
| width, height, | |||
| format, type, pixels, | |||
| packing, texObj, texImage)) { | |||
| if (R200_DEBUG & DEBUG_TEXTURE) | |||
| fprintf(stderr, "%s: Using client storage\n", __FUNCTION__); | |||
| } | |||
| else { | |||
| if (R200_DEBUG & DEBUG_TEXTURE) | |||
| fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__); | |||
| /* Normal path: copy (to cached memory) and eventually upload | |||
| * via another copy to agp memory and then a blit... Could | |||
| * eliminate one copy by going straight to (permanent) agp. | |||
| * | |||
| * Note, this will call r200ChooseTextureFormat. | |||
| */ | |||
| _mesa_store_teximage2d(ctx, target, level, internalFormat, | |||
| width, height, border, format, type, pixels, | |||
| &ctx->Unpack, texObj, texImage); | |||
| t->dirty_images[face] |= (1 << level); | |||
| } | |||
| } | |||
| static void r200TexSubImage2D( GLcontext *ctx, GLenum target, GLint level, | |||
| GLint xoffset, GLint yoffset, | |||
| GLsizei width, GLsizei height, | |||
| GLenum format, GLenum type, | |||
| const GLvoid *pixels, | |||
| const struct gl_pixelstore_attrib *packing, | |||
| struct gl_texture_object *texObj, | |||
| struct gl_texture_image *texImage ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| r200TexObjPtr t = (r200TexObjPtr) texObj->DriverData; | |||
| GLuint face; | |||
| /* fprintf(stderr, "%s\n", __FUNCTION__); */ | |||
| /* which cube face or ordinary 2D image */ | |||
| switch (target) { | |||
| case GL_TEXTURE_CUBE_MAP_POSITIVE_X: | |||
| case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: | |||
| case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: | |||
| case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: | |||
| case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: | |||
| case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: | |||
| face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; | |||
| ASSERT(face < 6); | |||
| break; | |||
| default: | |||
| face = 0; | |||
| } | |||
| assert( t ); /* this _should_ be true */ | |||
| if ( t ) { | |||
| r200SwapOutTexObj( rmesa, t ); | |||
| } | |||
| else { | |||
| t = r200AllocTexObj(texObj); | |||
| if (!t) { | |||
| _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D"); | |||
| return; | |||
| } | |||
| texObj->DriverData = t; | |||
| } | |||
| _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width, | |||
| height, format, type, pixels, packing, texObj, | |||
| texImage); | |||
| t->dirty_images[face] |= (1 << level); | |||
| } | |||
| static void r200TexImage3D( GLcontext *ctx, GLenum target, GLint level, | |||
| GLint internalFormat, | |||
| GLint width, GLint height, GLint depth, | |||
| GLint border, | |||
| GLenum format, GLenum type, const GLvoid *pixels, | |||
| const struct gl_pixelstore_attrib *packing, | |||
| struct gl_texture_object *texObj, | |||
| struct gl_texture_image *texImage ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| r200TexObjPtr t = (r200TexObjPtr)texObj->DriverData; | |||
| if ( t ) { | |||
| r200SwapOutTexObj( rmesa, t ); | |||
| } | |||
| else { | |||
| t = r200AllocTexObj( texObj ); | |||
| if (!t) { | |||
| _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); | |||
| return; | |||
| } | |||
| texObj->DriverData = t; | |||
| } | |||
| texImage->IsClientData = GL_FALSE; | |||
| #if 0 | |||
| if (r200ValidateClientStorage( ctx, target, | |||
| internalFormat, | |||
| width, height, | |||
| format, type, pixels, | |||
| packing, texObj, texImage)) { | |||
| if (R200_DEBUG & DEBUG_TEXTURE) | |||
| fprintf(stderr, "%s: Using client storage\n", __FUNCTION__); | |||
| } | |||
| else | |||
| #endif | |||
| { | |||
| if (R200_DEBUG & DEBUG_TEXTURE) | |||
| fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__); | |||
| /* Normal path: copy (to cached memory) and eventually upload | |||
| * via another copy to agp memory and then a blit... Could | |||
| * eliminate one copy by going straight to (permanent) agp. | |||
| * | |||
| * Note, this will call r200ChooseTextureFormat. | |||
| */ | |||
| _mesa_store_teximage3d(ctx, target, level, internalFormat, | |||
| width, height, depth, border, | |||
| format, type, pixels, | |||
| &ctx->Unpack, texObj, texImage); | |||
| t->dirty_images[0] |= (1 << level); | |||
| } | |||
| } | |||
| static void | |||
| r200TexSubImage3D( GLcontext *ctx, GLenum target, GLint level, | |||
| GLint xoffset, GLint yoffset, GLint zoffset, | |||
| GLsizei width, GLsizei height, GLsizei depth, | |||
| GLenum format, GLenum type, | |||
| const GLvoid *pixels, | |||
| const struct gl_pixelstore_attrib *packing, | |||
| struct gl_texture_object *texObj, | |||
| struct gl_texture_image *texImage ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| r200TexObjPtr t = (r200TexObjPtr) texObj->DriverData; | |||
| /* fprintf(stderr, "%s\n", __FUNCTION__); */ | |||
| assert( t ); /* this _should_ be true */ | |||
| if ( t ) { | |||
| r200SwapOutTexObj( rmesa, t ); | |||
| } | |||
| else { | |||
| t = r200AllocTexObj(texObj); | |||
| if (!t) { | |||
| _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D"); | |||
| return; | |||
| } | |||
| texObj->DriverData = t; | |||
| } | |||
| _mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset, | |||
| width, height, depth, | |||
| format, type, pixels, packing, texObj, texImage); | |||
| t->dirty_images[0] |= (1 << level); | |||
| } | |||
| static void r200TexEnv( GLcontext *ctx, GLenum target, | |||
| GLenum pname, const GLfloat *param ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| GLuint unit = ctx->Texture.CurrentUnit; | |||
| struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; | |||
| if ( R200_DEBUG & DEBUG_STATE ) { | |||
| fprintf( stderr, "%s( %s )\n", | |||
| __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) ); | |||
| } | |||
| /* This is incorrect: Need to maintain this data for each of | |||
| * GL_TEXTURE_{123}D, GL_TEXTURE_RECTANGLE_NV, etc, and switch | |||
| * between them according to _ReallyEnabled. | |||
| */ | |||
| switch ( pname ) { | |||
| case GL_TEXTURE_ENV_COLOR: { | |||
| GLubyte c[4]; | |||
| GLuint envColor; | |||
| UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor ); | |||
| envColor = r200PackColor( 4, c[0], c[1], c[2], c[3] ); | |||
| if ( rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] != envColor ) { | |||
| R200_STATECHANGE( rmesa, tf ); | |||
| rmesa->hw.tf.cmd[TF_TFACTOR_0 + unit] = envColor; | |||
| } | |||
| break; | |||
| } | |||
| case GL_TEXTURE_LOD_BIAS_EXT: { | |||
| GLfloat bias; | |||
| GLuint b; | |||
| const int fixed_one = 0x8000000; | |||
| /* The R200's LOD bias is a signed 2's complement value with a | |||
| * range of -16.0 <= bias < 16.0. | |||
| * | |||
| * NOTE: Add a small bias to the bias for conform mipsel.c test. | |||
| */ | |||
| bias = *param + .01; | |||
| bias = CLAMP( bias, -16.0, 16.0 ); | |||
| b = (int)(bias * fixed_one) & R200_LOD_BIAS_MASK; | |||
| if ( (rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] & R200_LOD_BIAS_MASK) != b ) { | |||
| R200_STATECHANGE( rmesa, tex[unit] ); | |||
| rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] &= ~R200_LOD_BIAS_MASK; | |||
| rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT_X] |= b; | |||
| } | |||
| break; | |||
| } | |||
| default: | |||
| return; | |||
| } | |||
| } | |||
| static void r200TexParameter( GLcontext *ctx, GLenum target, | |||
| struct gl_texture_object *texObj, | |||
| GLenum pname, const GLfloat *params ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| r200TexObjPtr t = (r200TexObjPtr) texObj->DriverData; | |||
| if ( R200_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) { | |||
| fprintf( stderr, "%s( %s )\n", __FUNCTION__, | |||
| _mesa_lookup_enum_by_nr( pname ) ); | |||
| } | |||
| if (!t) | |||
| return; | |||
| switch ( pname ) { | |||
| case GL_TEXTURE_MIN_FILTER: | |||
| case GL_TEXTURE_MAG_FILTER: | |||
| case GL_TEXTURE_MAX_ANISOTROPY_EXT: | |||
| r200SetTexMaxAnisotropy( t, texObj->MaxAnisotropy ); | |||
| r200SetTexFilter( t, texObj->MinFilter, texObj->MagFilter ); | |||
| break; | |||
| case GL_TEXTURE_WRAP_S: | |||
| case GL_TEXTURE_WRAP_T: | |||
| case GL_TEXTURE_WRAP_R: | |||
| r200SetTexWrap( t, texObj->WrapS, texObj->WrapT, texObj->WrapR ); | |||
| break; | |||
| case GL_TEXTURE_BORDER_COLOR: | |||
| r200SetTexBorderColor( t, texObj->_BorderChan ); | |||
| break; | |||
| case GL_TEXTURE_BASE_LEVEL: | |||
| case GL_TEXTURE_MAX_LEVEL: | |||
| case GL_TEXTURE_MIN_LOD: | |||
| case GL_TEXTURE_MAX_LOD: | |||
| /* This isn't the most efficient solution but there doesn't appear to | |||
| * be a nice alternative for R200. Since there's no LOD clamping, | |||
| * we just have to rely on loading the right subset of mipmap levels | |||
| * to simulate a clamped LOD. | |||
| */ | |||
| r200SwapOutTexObj( rmesa, t ); | |||
| break; | |||
| default: | |||
| return; | |||
| } | |||
| /* Mark this texobj as dirty (one bit per tex unit) | |||
| */ | |||
| t->dirty_state = TEX_ALL; | |||
| } | |||
| static void r200BindTexture( GLcontext *ctx, GLenum target, | |||
| struct gl_texture_object *texObj ) | |||
| { | |||
| r200TexObjPtr t = (r200TexObjPtr) texObj->DriverData; | |||
| GLuint unit = ctx->Texture.CurrentUnit; | |||
| if ( R200_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) { | |||
| fprintf( stderr, "%s( %p ) unit=%d\n", __FUNCTION__, texObj, unit ); | |||
| } | |||
| if ( target == GL_TEXTURE_2D || target == GL_TEXTURE_1D ) { | |||
| if ( !t ) { | |||
| t = r200AllocTexObj( texObj ); | |||
| texObj->DriverData = t; | |||
| } | |||
| } | |||
| } | |||
| static void r200DeleteTexture( GLcontext *ctx, | |||
| struct gl_texture_object *texObj ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| r200TexObjPtr t = (r200TexObjPtr) texObj->DriverData; | |||
| if ( R200_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) { | |||
| fprintf( stderr, "%s( %p )\n", __FUNCTION__, texObj ); | |||
| } | |||
| if ( t ) { | |||
| if ( rmesa ) { | |||
| R200_FIREVERTICES( rmesa ); | |||
| } | |||
| r200DestroyTexObj( rmesa, t ); | |||
| texObj->DriverData = NULL; | |||
| } | |||
| } | |||
| static GLboolean r200IsTextureResident( GLcontext *ctx, | |||
| struct gl_texture_object *texObj ) | |||
| { | |||
| r200TexObjPtr t = (r200TexObjPtr) texObj->DriverData; | |||
| return ( t && t->memBlock ); | |||
| } | |||
| static void r200InitTextureObjects( GLcontext *ctx ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| struct gl_texture_object *texObj; | |||
| GLuint tmp = ctx->Texture.CurrentUnit; | |||
| ctx->Texture.CurrentUnit = 0; | |||
| texObj = ctx->Texture.Unit[0].Current1D; | |||
| r200BindTexture( ctx, GL_TEXTURE_1D, texObj ); | |||
| move_to_tail( &rmesa->texture.swapped, | |||
| (r200TexObjPtr)texObj->DriverData ); | |||
| texObj = ctx->Texture.Unit[0].Current2D; | |||
| r200BindTexture( ctx, GL_TEXTURE_2D, texObj ); | |||
| move_to_tail( &rmesa->texture.swapped, | |||
| (r200TexObjPtr)texObj->DriverData ); | |||
| ctx->Texture.CurrentUnit = 1; | |||
| texObj = ctx->Texture.Unit[1].Current1D; | |||
| r200BindTexture( ctx, GL_TEXTURE_1D, texObj ); | |||
| move_to_tail( &rmesa->texture.swapped, | |||
| (r200TexObjPtr)texObj->DriverData ); | |||
| texObj = ctx->Texture.Unit[1].Current2D; | |||
| r200BindTexture( ctx, GL_TEXTURE_2D, texObj ); | |||
| move_to_tail( &rmesa->texture.swapped, | |||
| (r200TexObjPtr)texObj->DriverData ); | |||
| 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 r200TexGen( GLcontext *ctx, | |||
| GLenum coord, | |||
| GLenum pname, | |||
| const GLfloat *params ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| GLuint unit = ctx->Texture.CurrentUnit; | |||
| rmesa->recheck_texgen[unit] = GL_TRUE; | |||
| } | |||
| void r200InitTextureFuncs( GLcontext *ctx ) | |||
| { | |||
| ctx->Driver.ChooseTextureFormat = r200ChooseTextureFormat; | |||
| ctx->Driver.TexImage1D = r200TexImage1D; | |||
| ctx->Driver.TexImage2D = r200TexImage2D; | |||
| #if ENABLE_HW_3D_TEXTURE | |||
| ctx->Driver.TexImage3D = r200TexImage3D; | |||
| #else | |||
| ctx->Driver.TexImage3D = _mesa_store_teximage3d; | |||
| #endif | |||
| ctx->Driver.TexSubImage1D = r200TexSubImage1D; | |||
| ctx->Driver.TexSubImage2D = r200TexSubImage2D; | |||
| #if ENABLE_HW_3D_TEXTURE | |||
| ctx->Driver.TexSubImage3D = r200TexSubImage3D; | |||
| #else | |||
| ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d; | |||
| #endif | |||
| ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d; | |||
| ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d; | |||
| ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d; | |||
| ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d; | |||
| ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d; | |||
| ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage; | |||
| ctx->Driver.BindTexture = r200BindTexture; | |||
| ctx->Driver.CreateTexture = NULL; /* FIXME: Is this used??? */ | |||
| ctx->Driver.DeleteTexture = r200DeleteTexture; | |||
| ctx->Driver.IsTextureResident = r200IsTextureResident; | |||
| ctx->Driver.PrioritizeTexture = NULL; | |||
| ctx->Driver.ActiveTexture = NULL; | |||
| ctx->Driver.UpdateTexturePalette = NULL; | |||
| ctx->Driver.TexEnv = r200TexEnv; | |||
| ctx->Driver.TexParameter = r200TexParameter; | |||
| ctx->Driver.TexGen = r200TexGen; | |||
| r200InitTextureObjects( ctx ); | |||
| } | |||
| @@ -0,0 +1,55 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #ifndef __R200_TEX_H__ | |||
| #define __R200_TEX_H__ | |||
| #ifdef GLX_DIRECT_RENDERING | |||
| extern void r200UpdateTextureState( GLcontext *ctx ); | |||
| extern int r200UploadTexImages( r200ContextPtr rmesa, r200TexObjPtr t, GLuint face ); | |||
| extern void r200AgeTextures( r200ContextPtr rmesa, int heap ); | |||
| extern void r200DestroyTexObj( r200ContextPtr rmesa, r200TexObjPtr t ); | |||
| extern void r200SwapOutTexObj( r200ContextPtr rmesa, r200TexObjPtr t ); | |||
| extern void r200PrintLocalLRU( r200ContextPtr rmesa, int heap ); | |||
| extern void r200PrintGlobalLRU( r200ContextPtr rmesa, int heap ); | |||
| extern void r200UpdateTexLRU( r200ContextPtr rmesa, r200TexObjPtr t ); | |||
| extern void r200InitTextureFuncs( GLcontext *ctx ); | |||
| #endif | |||
| #endif /* __R200_TEX_H__ */ | |||
| @@ -0,0 +1,811 @@ | |||
| /* $XFree86$ */ | |||
| /************************************************************************** | |||
| Copyright (C) Tungsten Graphics 2002. All Rights Reserved. | |||
| The Weather Channel, Inc. funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 | |||
| license. This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation on the rights to use, copy, modify, merge, publish, | |||
| distribute, sub license, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
| NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR THEIR | |||
| SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | |||
| IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR | |||
| IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| SOFTWARE. | |||
| **************************************************************************/ | |||
| /* | |||
| * Authors: | |||
| * Kevin E. Martin <martin@valinux.com> | |||
| * Gareth Hughes <gareth@valinux.com> | |||
| * | |||
| */ | |||
| #include "glheader.h" | |||
| #include "imports.h" | |||
| #include "context.h" | |||
| #include "colormac.h" | |||
| #include "mmath.h" | |||
| #include "macros.h" | |||
| #include "simple_list.h" | |||
| #include "radeon_reg.h" /* gets definition for usleep */ | |||
| #include "r200_context.h" | |||
| #include "r200_state.h" | |||
| #include "r200_ioctl.h" | |||
| #include "r200_swtcl.h" | |||
| #include "r200_tex.h" | |||
| #include <unistd.h> /* for usleep() */ | |||
| #include <errno.h> | |||
| /* Destroy hardware state associated with texture `t'. | |||
| */ | |||
| void r200DestroyTexObj( r200ContextPtr rmesa, r200TexObjPtr t ) | |||
| { | |||
| if ( !t ) | |||
| return; | |||
| if ( R200_DEBUG & DEBUG_TEXTURE ) { | |||
| fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, t, t->tObj ); | |||
| } | |||
| if ( t->memBlock ) { | |||
| mmFreeMem( t->memBlock ); | |||
| t->memBlock = NULL; | |||
| } | |||
| if ( t->tObj ) | |||
| t->tObj->DriverData = NULL; | |||
| if ( rmesa ) { | |||
| if ( t == rmesa->state.texture.unit[0].texobj ) { | |||
| rmesa->state.texture.unit[0].texobj = NULL; | |||
| remove_from_list( &rmesa->hw.tex[0] ); | |||
| make_empty_list( &rmesa->hw.tex[0] ); | |||
| remove_from_list( &rmesa->hw.cube[0] ); | |||
| make_empty_list( &rmesa->hw.cube[0] ); | |||
| } | |||
| if ( t == rmesa->state.texture.unit[1].texobj ) { | |||
| rmesa->state.texture.unit[1].texobj = NULL; | |||
| remove_from_list( &rmesa->hw.tex[1] ); | |||
| make_empty_list( &rmesa->hw.tex[1] ); | |||
| remove_from_list( &rmesa->hw.cube[1] ); | |||
| make_empty_list( &rmesa->hw.cube[1] ); | |||
| } | |||
| } | |||
| remove_from_list( t ); | |||
| FREE( t ); | |||
| } | |||
| /* Keep track of swapped out texture objects. | |||
| */ | |||
| void r200SwapOutTexObj( r200ContextPtr rmesa, r200TexObjPtr t ) | |||
| { | |||
| GLuint face; | |||
| if ( R200_DEBUG & DEBUG_TEXTURE ) { | |||
| fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, t, t->tObj ); | |||
| } | |||
| if (t->memBlock) { | |||
| mmFreeMem( t->memBlock ); | |||
| t->memBlock = NULL; | |||
| } | |||
| if (!t->tObj) { | |||
| remove_from_list( t ); | |||
| FREE( t ); | |||
| } | |||
| else { | |||
| for (face = 0; face < 6; face++) | |||
| t->dirty_images[face] = ~0; | |||
| move_to_tail( &rmesa->texture.swapped, t ); | |||
| } | |||
| } | |||
| /* Print out debugging information about texture LRU. | |||
| */ | |||
| void r200PrintLocalLRU( r200ContextPtr rmesa, int heap ) | |||
| { | |||
| r200TexObjPtr t; | |||
| int sz = 1 << (rmesa->r200Screen->logTexGranularity[heap]); | |||
| fprintf( stderr, "\nLocal LRU, heap %d:\n", heap ); | |||
| foreach ( t, &rmesa->texture.objects[heap] ) { | |||
| if (!t->memBlock) | |||
| continue; | |||
| if (!t->tObj) { | |||
| fprintf( stderr, "Placeholder %d at 0x%x sz 0x%x\n", | |||
| t->memBlock->ofs / sz, | |||
| t->memBlock->ofs, | |||
| t->memBlock->size ); | |||
| } else { | |||
| fprintf( stderr, "Texture at 0x%x sz 0x%x\n", | |||
| t->memBlock->ofs, | |||
| t->memBlock->size ); | |||
| } | |||
| } | |||
| fprintf( stderr, "\n" ); | |||
| } | |||
| void r200PrintGlobalLRU( r200ContextPtr 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, 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", | |||
| j, list[j].age, list[j].next, list[j].prev ); | |||
| j = list[j].next; | |||
| if ( j == RADEON_NR_TEX_REGIONS ) break; | |||
| } | |||
| if ( j != RADEON_NR_TEX_REGIONS ) { | |||
| fprintf( stderr, "Loop detected in global LRU\n" ); | |||
| for ( i = 0 ; i < RADEON_NR_TEX_REGIONS ; i++ ) { | |||
| fprintf( stderr, "list[%d] age %d next %d prev %d\n", | |||
| i, list[i].age, list[i].next, list[i].prev ); | |||
| } | |||
| } | |||
| fprintf( stderr, "\n" ); | |||
| } | |||
| /* Reset the global texture LRU. | |||
| */ | |||
| static void r200ResetGlobalLRU( r200ContextPtr rmesa, int heap ) | |||
| { | |||
| radeon_tex_region_t *list = rmesa->sarea->texList[heap]; | |||
| int sz = 1 << rmesa->r200Screen->logTexGranularity[heap]; | |||
| int i; | |||
| /* | |||
| * (Re)initialize the global circular LRU list. The last element in | |||
| * the array (RADEON_NR_TEX_REGIONS) is the sentinal. Keeping it at | |||
| * the end of the array allows it to be addressed rationally when | |||
| * looking up objects at a particular location in texture memory. | |||
| */ | |||
| for ( i = 0 ; (i+1) * sz <= rmesa->r200Screen->texSize[heap] ; i++ ) { | |||
| list[i].prev = i-1; | |||
| list[i].next = i+1; | |||
| list[i].age = 0; | |||
| } | |||
| i--; | |||
| list[0].prev = RADEON_NR_TEX_REGIONS; | |||
| list[i].prev = i-1; | |||
| list[i].next = RADEON_NR_TEX_REGIONS; | |||
| list[RADEON_NR_TEX_REGIONS].prev = i; | |||
| list[RADEON_NR_TEX_REGIONS].next = 0; | |||
| rmesa->sarea->texAge[heap] = 0; | |||
| } | |||
| /* Update the local and glock texture LRUs. | |||
| */ | |||
| void r200UpdateTexLRU(r200ContextPtr rmesa, r200TexObjPtr t ) | |||
| { | |||
| int heap = t->heap; | |||
| radeon_tex_region_t *list = rmesa->sarea->texList[heap]; | |||
| int sz = rmesa->r200Screen->logTexGranularity[heap]; | |||
| int i, start, end; | |||
| rmesa->texture.age[heap] = ++rmesa->sarea->texAge[heap]; | |||
| if ( !t->memBlock ) | |||
| return; | |||
| start = t->memBlock->ofs >> sz; | |||
| end = (t->memBlock->ofs + t->memBlock->size-1) >> sz; | |||
| /* Update our local LRU */ | |||
| move_to_head( &rmesa->texture.objects[heap], t ); | |||
| /* Update the global LRU */ | |||
| for ( i = start ; i <= end ; i++ ) { | |||
| list[i].in_use = 1; | |||
| list[i].age = rmesa->texture.age[heap]; | |||
| /* remove_from_list(i) */ | |||
| list[(GLuint)list[i].next].prev = list[i].prev; | |||
| list[(GLuint)list[i].prev].next = list[i].next; | |||
| /* insert_at_head(list, i) */ | |||
| list[i].prev = RADEON_NR_TEX_REGIONS; | |||
| list[i].next = list[RADEON_NR_TEX_REGIONS].next; | |||
| list[(GLuint)list[RADEON_NR_TEX_REGIONS].next].prev = i; | |||
| list[RADEON_NR_TEX_REGIONS].next = i; | |||
| } | |||
| if ( 0 ) { | |||
| r200PrintGlobalLRU( rmesa, t->heap ); | |||
| r200PrintLocalLRU( rmesa, t->heap ); | |||
| } | |||
| } | |||
| /* Update our notion of what textures have been changed since we last | |||
| * held the lock. This pertains to both our local textures and the | |||
| * textures belonging to other clients. Keep track of other client's | |||
| * textures by pushing a placeholder texture onto the LRU list -- these | |||
| * are denoted by (tObj == NULL). | |||
| */ | |||
| static void r200TexturesGone( r200ContextPtr rmesa, int heap, | |||
| int offset, int size, int in_use ) | |||
| { | |||
| r200TexObjPtr t, tmp; | |||
| foreach_s ( t, tmp, &rmesa->texture.objects[heap] ) { | |||
| if ( !t->memBlock || | |||
| t->memBlock->ofs >= offset + size || | |||
| t->memBlock->ofs + t->memBlock->size <= offset ) | |||
| continue; | |||
| /* It overlaps - kick it out. Need to hold onto the currently | |||
| * bound objects, however. | |||
| */ | |||
| r200SwapOutTexObj( rmesa, t ); | |||
| } | |||
| if ( in_use ) { | |||
| t = (r200TexObjPtr) CALLOC( sizeof(*t) ); | |||
| if ( !t ) return; | |||
| t->memBlock = mmAllocMem( rmesa->texture.heap[heap], size, 0, offset ); | |||
| if ( !t->memBlock ) { | |||
| fprintf( stderr, "Couldn't alloc placeholder sz %x ofs %x\n", | |||
| (int)size, (int)offset ); | |||
| mmDumpMemInfo( rmesa->texture.heap[heap] ); | |||
| return; | |||
| } | |||
| insert_at_head( &rmesa->texture.objects[heap], t ); | |||
| } | |||
| } | |||
| /* Update our client's shared texture state. If another client has | |||
| * modified a region in which we have textures, then we need to figure | |||
| * out which of our textures has been removed, and update our global | |||
| * LRU. | |||
| */ | |||
| void r200AgeTextures( r200ContextPtr rmesa, int heap ) | |||
| { | |||
| RADEONSAREAPrivPtr sarea = rmesa->sarea; | |||
| if ( R200_DEBUG & DEBUG_TEXTURE ) { | |||
| fprintf(stderr, "%s %d\n", __FUNCTION__, heap); | |||
| } | |||
| if ( sarea->texAge[heap] != rmesa->texture.age[heap] ) { | |||
| int sz = 1 << rmesa->r200Screen->logTexGranularity[heap]; | |||
| int nr = 0; | |||
| int idx; | |||
| for ( idx = sarea->texList[heap][RADEON_NR_TEX_REGIONS].prev ; | |||
| idx != RADEON_NR_TEX_REGIONS && nr < RADEON_NR_TEX_REGIONS ; | |||
| idx = sarea->texList[heap][idx].prev, nr++ ) | |||
| { | |||
| /* If switching texturing schemes, then the SAREA might not | |||
| * have been properly cleared, so we need to reset the | |||
| * global texture LRU. | |||
| */ | |||
| if ( idx * sz > rmesa->r200Screen->texSize[heap] ) { | |||
| nr = RADEON_NR_TEX_REGIONS; | |||
| break; | |||
| } | |||
| if ( sarea->texList[heap][idx].age > rmesa->texture.age[heap] ) { | |||
| r200TexturesGone( rmesa, heap, idx * sz, sz, | |||
| sarea->texList[heap][idx].in_use ); | |||
| } | |||
| } | |||
| if ( nr == RADEON_NR_TEX_REGIONS ) { | |||
| r200TexturesGone( rmesa, heap, 0, | |||
| rmesa->r200Screen->texSize[heap], 0 ); | |||
| r200ResetGlobalLRU( rmesa, heap ); | |||
| } | |||
| rmesa->texture.age[heap] = sarea->texAge[heap]; | |||
| } | |||
| } | |||
| /* ------------------------------------------------------------ | |||
| * Texture image conversions | |||
| */ | |||
| static void r200UploadAGPClientSubImage( r200ContextPtr rmesa, | |||
| r200TexObjPtr t, | |||
| struct gl_texture_image *texImage, | |||
| GLint hwlevel, | |||
| GLint x, GLint y, | |||
| GLint width, GLint height ) | |||
| { | |||
| const struct gl_texture_format *texFormat = texImage->TexFormat; | |||
| GLuint srcPitch, dstPitch; | |||
| int blit_format; | |||
| int srcOffset; | |||
| /* | |||
| * XXX it appears that we always upload the full image, not a subimage. | |||
| * I.e. x==0, y==0, width=texWidth, height=texWidth. If this is ever | |||
| * changed, the src pitch will have to change. | |||
| */ | |||
| switch ( texFormat->TexelBytes ) { | |||
| case 1: | |||
| blit_format = R200_CP_COLOR_FORMAT_CI8; | |||
| srcPitch = t->image[0][0].width * texFormat->TexelBytes; | |||
| dstPitch = t->image[0][0].width * texFormat->TexelBytes; | |||
| break; | |||
| case 2: | |||
| blit_format = R200_CP_COLOR_FORMAT_RGB565; | |||
| srcPitch = t->image[0][0].width * texFormat->TexelBytes; | |||
| dstPitch = t->image[0][0].width * texFormat->TexelBytes; | |||
| break; | |||
| case 4: | |||
| blit_format = R200_CP_COLOR_FORMAT_ARGB8888; | |||
| srcPitch = t->image[0][0].width * texFormat->TexelBytes; | |||
| dstPitch = t->image[0][0].width * texFormat->TexelBytes; | |||
| break; | |||
| default: | |||
| return; | |||
| } | |||
| t->image[0][hwlevel].data = texImage->Data; | |||
| srcOffset = r200AgpOffsetFromVirtual( rmesa, texImage->Data ); | |||
| assert( srcOffset != ~0 ); | |||
| /* Don't currently need to cope with small pitches? | |||
| */ | |||
| width = texImage->Width; | |||
| height = texImage->Height; | |||
| r200EmitWait( rmesa, RADEON_WAIT_3D ); | |||
| r200EmitBlit( rmesa, blit_format, | |||
| srcPitch, | |||
| srcOffset, | |||
| dstPitch, | |||
| t->bufAddr, | |||
| x, | |||
| y, | |||
| t->image[0][hwlevel].x + x, | |||
| t->image[0][hwlevel].y + y, | |||
| width, | |||
| height ); | |||
| r200EmitWait( rmesa, RADEON_WAIT_2D ); | |||
| } | |||
| static void r200UploadRectSubImage( r200ContextPtr rmesa, | |||
| r200TexObjPtr t, | |||
| struct gl_texture_image *texImage, | |||
| GLint x, GLint y, | |||
| GLint width, GLint height ) | |||
| { | |||
| const struct gl_texture_format *texFormat = texImage->TexFormat; | |||
| int blit_format, dstPitch, done; | |||
| switch ( texFormat->TexelBytes ) { | |||
| case 1: | |||
| blit_format = R200_CP_COLOR_FORMAT_CI8; | |||
| break; | |||
| case 2: | |||
| blit_format = R200_CP_COLOR_FORMAT_RGB565; | |||
| break; | |||
| case 4: | |||
| blit_format = R200_CP_COLOR_FORMAT_ARGB8888; | |||
| break; | |||
| default: | |||
| return; | |||
| } | |||
| t->image[0][0].data = texImage->Data; | |||
| /* Currently don't need to cope with small pitches. | |||
| */ | |||
| width = texImage->Width; | |||
| height = texImage->Height; | |||
| dstPitch = t->pp_txpitch + 32; | |||
| if (rmesa->prefer_agp_client_texturing && texImage->IsClientData) { | |||
| /* In this case, could also use agp texturing. This is | |||
| * currently disabled, but has been tested & works. | |||
| */ | |||
| t->pp_txoffset = r200AgpOffsetFromVirtual( rmesa, texImage->Data ); | |||
| t->pp_txpitch = texImage->RowStride * texFormat->TexelBytes - 32; | |||
| if (R200_DEBUG & DEBUG_TEXTURE) | |||
| fprintf(stderr, | |||
| "Using agp texturing for rectangular client texture\n"); | |||
| /* Release FB memory allocated for this image: | |||
| */ | |||
| if ( t->memBlock ) { | |||
| mmFreeMem( t->memBlock ); | |||
| t->memBlock = NULL; | |||
| } | |||
| } | |||
| else if (texImage->IsClientData) { | |||
| /* Data already in agp memory, with usable pitch. | |||
| */ | |||
| GLuint srcPitch; | |||
| srcPitch = texImage->RowStride * texFormat->TexelBytes; | |||
| r200EmitBlit( rmesa, | |||
| blit_format, | |||
| srcPitch, | |||
| r200AgpOffsetFromVirtual( rmesa, texImage->Data ), | |||
| dstPitch, t->bufAddr, | |||
| 0, 0, | |||
| 0, 0, | |||
| width, height ); | |||
| } | |||
| else { | |||
| /* Data not in agp memory, or bad pitch. | |||
| */ | |||
| for (done = 0; done < height ; ) { | |||
| struct r200_dma_region region; | |||
| int lines = MIN2( height - done, RADEON_BUFFER_SIZE / dstPitch ); | |||
| int src_pitch; | |||
| char *tex; | |||
| src_pitch = texImage->RowStride * texFormat->TexelBytes; | |||
| tex = (char *)texImage->Data + done * src_pitch; | |||
| memset(®ion, 0, sizeof(region)); | |||
| r200AllocDmaRegion( rmesa, ®ion, lines * dstPitch, 64 ); | |||
| /* Copy texdata to dma: | |||
| */ | |||
| if (0) | |||
| fprintf(stderr, "%s: src_pitch %d dst_pitch %d\n", | |||
| __FUNCTION__, src_pitch, dstPitch); | |||
| if (src_pitch == dstPitch) { | |||
| memcpy( region.address, tex, lines * src_pitch ); | |||
| } | |||
| else { | |||
| char *buf = region.address; | |||
| int i; | |||
| for (i = 0 ; i < lines ; i++) { | |||
| memcpy( buf, tex, src_pitch ); | |||
| buf += dstPitch; | |||
| tex += src_pitch; | |||
| } | |||
| } | |||
| r200EmitWait( rmesa, RADEON_WAIT_3D ); | |||
| /* Blit to framebuffer | |||
| */ | |||
| r200EmitBlit( rmesa, | |||
| blit_format, | |||
| dstPitch, GET_START( ®ion ), | |||
| dstPitch, t->bufAddr, | |||
| 0, 0, | |||
| 0, done, | |||
| width, lines ); | |||
| r200EmitWait( rmesa, RADEON_WAIT_2D ); | |||
| r200ReleaseDmaRegion( rmesa, ®ion, __FUNCTION__ ); | |||
| done += lines; | |||
| } | |||
| } | |||
| } | |||
| /* Upload the texture image associated with texture `t' at level `level' | |||
| * at the address relative to `start'. | |||
| */ | |||
| static void r200UploadSubImage( r200ContextPtr rmesa, | |||
| r200TexObjPtr t, | |||
| GLint hwlevel, | |||
| GLint x, GLint y, GLint width, GLint height, | |||
| GLuint face ) | |||
| { | |||
| struct gl_texture_image *texImage = NULL; | |||
| const struct gl_texture_format *texFormat; | |||
| GLint texelsPerDword = 0; | |||
| GLuint format, pitch, offset; | |||
| GLint imageWidth, imageHeight; | |||
| GLint ret; | |||
| drmRadeonTexture tex; | |||
| drmRadeonTexImage tmp; | |||
| int level = hwlevel + t->firstLevel; | |||
| if ( R200_DEBUG & DEBUG_TEXTURE ) { | |||
| fprintf( stderr, "%s level %d %dx%d\n", __FUNCTION__, | |||
| level, width, height); | |||
| } | |||
| ASSERT(face < 6); | |||
| /* Ensure we have a valid texture to upload */ | |||
| if ( ( hwlevel < 0 ) || ( hwlevel >= RADEON_MAX_TEXTURE_LEVELS ) ) { | |||
| _mesa_problem(NULL, "bad texture level in r200UploadSubimage"); | |||
| return; | |||
| } | |||
| switch (face) { | |||
| case 0: | |||
| texImage = t->tObj->Image[level]; | |||
| break; | |||
| case 1: | |||
| texImage = t->tObj->NegX[level]; | |||
| break; | |||
| case 2: | |||
| texImage = t->tObj->PosY[level]; | |||
| break; | |||
| case 3: | |||
| texImage = t->tObj->NegY[level]; | |||
| break; | |||
| case 4: | |||
| texImage = t->tObj->PosZ[level]; | |||
| break; | |||
| case 5: | |||
| texImage = t->tObj->NegZ[level]; | |||
| break; | |||
| } | |||
| if ( !texImage ) { | |||
| if ( R200_DEBUG & DEBUG_TEXTURE ) | |||
| fprintf( stderr, "%s: texImage %d is NULL!\n", __FUNCTION__, level ); | |||
| return; | |||
| } | |||
| if ( !texImage->Data ) { | |||
| if ( R200_DEBUG & DEBUG_TEXTURE ) | |||
| fprintf( stderr, "%s: image data is NULL!\n", __FUNCTION__ ); | |||
| return; | |||
| } | |||
| if (t->tObj->Target == GL_TEXTURE_RECTANGLE_NV) { | |||
| assert(level == 0); | |||
| assert(hwlevel == 0); | |||
| if ( R200_DEBUG & DEBUG_TEXTURE ) | |||
| fprintf( stderr, "%s: image data is rectangular\n", __FUNCTION__); | |||
| r200UploadRectSubImage( rmesa, t, texImage, x, y, width, height ); | |||
| return; | |||
| } | |||
| else if (texImage->IsClientData) { | |||
| if ( R200_DEBUG & DEBUG_TEXTURE ) | |||
| fprintf( stderr, "%s: image data is in agp client storage\n", | |||
| __FUNCTION__); | |||
| r200UploadAGPClientSubImage( rmesa, t, texImage, hwlevel, | |||
| x, y, width, height ); | |||
| return; | |||
| } | |||
| else if ( R200_DEBUG & DEBUG_TEXTURE ) | |||
| fprintf( stderr, "%s: image data is in normal memory\n", | |||
| __FUNCTION__); | |||
| texFormat = texImage->TexFormat; | |||
| switch ( texFormat->TexelBytes ) { | |||
| case 1: | |||
| texelsPerDword = 4; | |||
| break; | |||
| case 2: | |||
| texelsPerDword = 2; | |||
| break; | |||
| case 4: | |||
| texelsPerDword = 1; | |||
| break; | |||
| } | |||
| format = t->pp_txformat & R200_TXFORMAT_FORMAT_MASK; | |||
| imageWidth = texImage->Width; | |||
| imageHeight = texImage->Height; | |||
| offset = t->bufAddr; | |||
| if (texFormat->TexelBytes == 0) | |||
| pitch = (t->image[face][0].width * 1) / 64; | |||
| else | |||
| pitch = (t->image[face][0].width * texFormat->TexelBytes) / 64; | |||
| if ( R200_DEBUG & (DEBUG_TEXTURE|DEBUG_IOCTL) ) | |||
| { | |||
| GLint imageX = 0; | |||
| GLint imageY = 0; | |||
| GLint blitX = t->image[face][hwlevel].x; | |||
| GLint blitY = t->image[face][hwlevel].y; | |||
| GLint blitWidth = t->image[face][hwlevel].width; | |||
| GLint blitHeight = t->image[face][hwlevel].height; | |||
| fprintf( stderr, " upload image: %d,%d at %d,%d\n", | |||
| imageWidth, imageHeight, imageX, imageY ); | |||
| fprintf( stderr, " upload blit: %d,%d at %d,%d\n", | |||
| blitWidth, blitHeight, blitX, blitY ); | |||
| fprintf( stderr, " blit ofs: 0x%07x pitch: 0x%x " | |||
| "level: %d/%d format: %x\n", | |||
| (GLuint)offset, (GLuint)pitch, hwlevel, level, format ); | |||
| } | |||
| t->image[face][hwlevel].data = texImage->Data; | |||
| /* Init the DRM_RADEON_TEXTURE command / drmRadeonTexture struct. | |||
| * NOTE: we're always use a 1KB-wide blit and I8 texture format. | |||
| * We used to use 1, 2 and 4-byte texels and used to use the texture | |||
| * width to dictate the blit width - but that won't work for compressed | |||
| * textures. (Brian) | |||
| */ | |||
| tex.offset = offset; | |||
| tex.pitch = BLIT_WIDTH_BYTES / 64; | |||
| tex.format = R200_TXFORMAT_I8; /* any 1-byte texel format */ | |||
| if (texImage->TexFormat->TexelBytes) { | |||
| tex.width = imageWidth * texImage->TexFormat->TexelBytes; /* in bytes */ | |||
| tex.height = imageHeight; | |||
| } | |||
| else { | |||
| tex.width = imageWidth; /* compressed */ | |||
| tex.height = imageHeight; | |||
| if (tex.height < 4) | |||
| tex.height = 4; | |||
| } | |||
| tex.image = &tmp; | |||
| /* copy (x,y,width,height,data) */ | |||
| memcpy( &tmp, &t->image[face][hwlevel], sizeof(drmRadeonTexImage) ); | |||
| LOCK_HARDWARE( rmesa ); | |||
| do { | |||
| ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_TEXTURE, | |||
| &tex, sizeof(drmRadeonTexture) ); | |||
| if (ret) { | |||
| if (R200_DEBUG & DEBUG_IOCTL) | |||
| fprintf(stderr, "DRM_RADEON_TEXTURE: again!\n"); | |||
| usleep(1); | |||
| } | |||
| } while ( ret && errno == EAGAIN ); | |||
| UNLOCK_HARDWARE( rmesa ); | |||
| if ( ret ) { | |||
| fprintf( stderr, "DRM_R200_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", | |||
| imageWidth, imageHeight ); | |||
| fprintf( stderr, " blit width=%d height=%d data=%p\n", | |||
| t->image[face][hwlevel].width, t->image[face][hwlevel].height, | |||
| t->image[face][hwlevel].data ); | |||
| exit( 1 ); | |||
| } | |||
| } | |||
| /* Upload the texture images associated with texture `t'. This might | |||
| * require removing our own and/or other client's texture objects to | |||
| * make room for these images. | |||
| */ | |||
| int r200UploadTexImages( r200ContextPtr rmesa, r200TexObjPtr t, GLuint face ) | |||
| { | |||
| const int numLevels = t->lastLevel - t->firstLevel + 1; | |||
| int heap; | |||
| r200TexObjPtr t0 = rmesa->state.texture.unit[0].texobj; | |||
| r200TexObjPtr t1 = rmesa->state.texture.unit[1].texobj; | |||
| if ( R200_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 ); | |||
| } | |||
| if ( !t || t->totalSize == 0 ) | |||
| return 0; | |||
| if (R200_DEBUG & DEBUG_SYNC) { | |||
| fprintf(stderr, "\nSyncing\n\n"); | |||
| R200_FIREVERTICES( rmesa ); | |||
| r200Finish( rmesa->glCtx ); | |||
| } | |||
| LOCK_HARDWARE( rmesa ); | |||
| /* Choose the heap appropriately */ | |||
| heap = t->heap = RADEON_CARD_HEAP; | |||
| /* Do we need to eject LRU texture objects? */ | |||
| if ( !t->memBlock ) { | |||
| /* Allocate a memory block on a 1k boundary (1<<10 == 1024) */ | |||
| t->memBlock = mmAllocMem( rmesa->texture.heap[heap], | |||
| t->totalSize, 10, 0 ); | |||
| /* Kick out textures until the requested texture fits */ | |||
| while ( !t->memBlock ) { | |||
| if ( rmesa->texture.objects[heap].prev == t0 || | |||
| rmesa->texture.objects[heap].prev == t1 ) { | |||
| fprintf( stderr, | |||
| "r200UploadTexImages: ran into bound texture\n" ); | |||
| UNLOCK_HARDWARE( rmesa ); | |||
| return -1; | |||
| } | |||
| if ( rmesa->texture.objects[heap].prev == | |||
| &rmesa->texture.objects[heap] ) { | |||
| if ( rmesa->r200Screen->IsPCI ) { | |||
| fprintf( stderr, "r200UploadTexImages: upload texture " | |||
| "failure on local texture heaps, sz=%d\n", | |||
| t->totalSize ); | |||
| UNLOCK_HARDWARE( rmesa ); | |||
| return -1; | |||
| } else { | |||
| fprintf( stderr, "r200UploadTexImages: upload texture " | |||
| "failure on both local and AGP texture heaps, " | |||
| "sz=%d\n", | |||
| t->totalSize ); | |||
| UNLOCK_HARDWARE( rmesa ); | |||
| return -1; | |||
| } | |||
| } | |||
| r200SwapOutTexObj( rmesa, rmesa->texture.objects[heap].prev ); | |||
| t->memBlock = mmAllocMem( rmesa->texture.heap[heap], | |||
| t->totalSize, 12, 0 ); | |||
| } | |||
| /* Set the base offset of the texture image */ | |||
| t->bufAddr = rmesa->r200Screen->texOffset[heap] + t->memBlock->ofs; | |||
| t->pp_txoffset = t->bufAddr; | |||
| /* Mark this texobj as dirty on all units: | |||
| */ | |||
| t->dirty_state = TEX_ALL; | |||
| } | |||
| /* Let the world know we've used this memory recently */ | |||
| r200UpdateTexLRU( rmesa, t ); | |||
| UNLOCK_HARDWARE( rmesa ); | |||
| /* Upload any images that are new */ | |||
| if (t->dirty_images[face]) { | |||
| int hwlevel; | |||
| for ( hwlevel = 0 ; hwlevel < numLevels ; hwlevel++ ) { | |||
| if ( t->dirty_images[face] & (1 << (hwlevel+t->firstLevel)) ) { | |||
| r200UploadSubImage( rmesa, t, hwlevel, | |||
| 0, 0, | |||
| t->image[face][hwlevel].width, | |||
| t->image[face][hwlevel].height, face ); | |||
| } | |||
| } | |||
| t->dirty_images[face] = 0; | |||
| } | |||
| if (R200_DEBUG & DEBUG_SYNC) { | |||
| fprintf(stderr, "\nSyncing\n\n"); | |||
| r200Finish( rmesa->glCtx ); | |||
| } | |||
| return 0; | |||
| } | |||
| @@ -0,0 +1,128 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #ifndef __R200_VTXFMT_H__ | |||
| #define __R200_VTXFMT_H__ | |||
| #ifdef GLX_DIRECT_RENDERING | |||
| #include "r200_context.h" | |||
| extern struct r200_vb vb; | |||
| extern void r200VtxfmtUpdate( GLcontext *ctx ); | |||
| extern void r200VtxfmtInit( GLcontext *ctx ); | |||
| extern void r200VtxfmtInvalidate( GLcontext *ctx ); | |||
| extern void r200VtxfmtDestroy( GLcontext *ctx ); | |||
| extern void r200VtxfmtInitChoosers( GLvertexformat *vfmt ); | |||
| extern void r200VtxfmtMakeCurrent( GLcontext *ctx ); | |||
| extern void r200VtxfmtUnbindContext( GLcontext *ctx ); | |||
| extern void r200_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[0] = key[0]; \ | |||
| dfn->key[1] = key[1]; \ | |||
| 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 r200InitCodegen( struct dfn_generators *gen ); | |||
| void r200InitX86Codegen( struct dfn_generators *gen ); | |||
| void r200InitSSECodegen( struct dfn_generators *gen ); | |||
| /* Defined in r200_vtxfmt_x86.c | |||
| */ | |||
| struct dynfn *r200_makeX86Vertex2f( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86Vertex2fv( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86Vertex3f( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86Vertex3fv( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86Color4ub( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86Color4ubv( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86Color3ub( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86Color3ubv( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86Color4f( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86Color4fv( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86Color3f( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86Color3fv( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86SecondaryColor3ubEXT( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86SecondaryColor3ubvEXT( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86SecondaryColor3fEXT( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86SecondaryColor3fvEXT( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86Normal3f( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86Normal3fv( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86TexCoord2f( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86TexCoord2fv( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86TexCoord1f( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86TexCoord1fv( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86MultiTexCoord2fARB( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86MultiTexCoord2fvARB( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86MultiTexCoord1fARB( GLcontext *, const int * ); | |||
| struct dynfn *r200_makeX86MultiTexCoord1fvARB( GLcontext *, const int * ); | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,797 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #include "glheader.h" | |||
| #include "imports.h" | |||
| #include "mtypes.h" | |||
| #include "colormac.h" | |||
| #include "simple_list.h" | |||
| #include "api_noop.h" | |||
| #include "vtxfmt.h" | |||
| #include "r200_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 r200_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 r200_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 r200_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++ = vb.vertex[i].i; | |||
| if (--vb.counter == 0) | |||
| vb.notify(); | |||
| } | |||
| static void r200_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 r200_Color3ub_ub( GLubyte r, GLubyte g, GLubyte b ) | |||
| { | |||
| r200_color_t *dest = vb.colorptr; | |||
| dest->red = r; | |||
| dest->green = g; | |||
| dest->blue = b; | |||
| dest->alpha = 0xff; | |||
| } | |||
| static void r200_Color3ubv_ub( const GLubyte *v ) | |||
| { | |||
| r200_color_t *dest = vb.colorptr; | |||
| dest->red = v[0]; | |||
| dest->green = v[1]; | |||
| dest->blue = v[2]; | |||
| dest->alpha = 0xff; | |||
| } | |||
| static void r200_Color4ub_ub( GLubyte r, GLubyte g, GLubyte b, GLubyte a ) | |||
| { | |||
| r200_color_t *dest = vb.colorptr; | |||
| dest->red = r; | |||
| dest->green = g; | |||
| dest->blue = b; | |||
| dest->alpha = a; | |||
| } | |||
| static void r200_Color4ubv_ub( const GLubyte *v ) | |||
| { | |||
| *(GLuint *)vb.colorptr = LE32_TO_CPU(*(GLuint *)v); | |||
| } | |||
| static void r200_Color3f_ub( GLfloat r, GLfloat g, GLfloat b ) | |||
| { | |||
| r200_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 r200_Color3fv_ub( const GLfloat *v ) | |||
| { | |||
| r200_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 r200_Color4f_ub( GLfloat r, GLfloat g, GLfloat b, GLfloat a ) | |||
| { | |||
| r200_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 r200_Color4fv_ub( const GLfloat *v ) | |||
| { | |||
| r200_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 r200_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 r200_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 r200_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 r200_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 r200_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 r200_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 r200_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 r200_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 r200_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 r200_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 r200_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.Attrib[VERT_ATTRIB_COLOR0][3] = UBYTE_TO_FLOAT(a); | |||
| } | |||
| static void r200_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.Attrib[VERT_ATTRIB_COLOR0][3] = UBYTE_TO_FLOAT(v[3]); | |||
| } | |||
| static void r200_Color3f_3f( GLfloat r, GLfloat g, GLfloat b ) | |||
| { | |||
| GLfloat *dest = vb.floatcolorptr; | |||
| dest[0] = r; | |||
| dest[1] = g; | |||
| dest[2] = b; | |||
| } | |||
| static void r200_Color3fv_3f( const GLfloat *v ) | |||
| { | |||
| GLfloat *dest = vb.floatcolorptr; | |||
| dest[0] = v[0]; | |||
| dest[1] = v[1]; | |||
| dest[2] = v[2]; | |||
| } | |||
| static void r200_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.Attrib[VERT_ATTRIB_COLOR0][3] = a; | |||
| } | |||
| static void r200_Color4fv_3f( const GLfloat *v ) | |||
| { | |||
| GLfloat *dest = vb.floatcolorptr; | |||
| dest[0] = v[0]; | |||
| dest[1] = v[1]; | |||
| dest[2] = v[2]; | |||
| vb.context->Current.Attrib[VERT_ATTRIB_COLOR0][3] = v[3]; | |||
| } | |||
| /* Secondary Color: | |||
| */ | |||
| static void r200_SecondaryColor3ubEXT_ub( GLubyte r, GLubyte g, GLubyte b ) | |||
| { | |||
| r200_color_t *dest = vb.specptr; | |||
| dest->red = r; | |||
| dest->green = g; | |||
| dest->blue = b; | |||
| dest->alpha = 0xff; | |||
| } | |||
| static void r200_SecondaryColor3ubvEXT_ub( const GLubyte *v ) | |||
| { | |||
| r200_color_t *dest = vb.specptr; | |||
| dest->red = v[0]; | |||
| dest->green = v[1]; | |||
| dest->blue = v[2]; | |||
| dest->alpha = 0xff; | |||
| } | |||
| static void r200_SecondaryColor3fEXT_ub( GLfloat r, GLfloat g, GLfloat b ) | |||
| { | |||
| r200_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 r200_SecondaryColor3fvEXT_ub( const GLfloat *v ) | |||
| { | |||
| r200_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 r200_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 r200_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 r200_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 r200_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 r200_Normal3f( GLfloat n0, GLfloat n1, GLfloat n2 ) | |||
| { | |||
| GLfloat *dest = vb.normalptr; | |||
| dest[0] = n0; | |||
| dest[1] = n1; | |||
| dest[2] = n2; | |||
| } | |||
| static void r200_Normal3fv( const GLfloat *v ) | |||
| { | |||
| GLfloat *dest = vb.normalptr; | |||
| dest[0] = v[0]; | |||
| dest[1] = v[1]; | |||
| dest[2] = v[2]; | |||
| } | |||
| /* TexCoord | |||
| */ | |||
| static void r200_TexCoord1f( GLfloat s ) | |||
| { | |||
| GLfloat *dest = vb.texcoordptr[0]; | |||
| dest[0] = s; | |||
| dest[1] = 0; | |||
| } | |||
| static void r200_TexCoord1fv( const GLfloat *v ) | |||
| { | |||
| GLfloat *dest = vb.texcoordptr[0]; | |||
| dest[0] = v[0]; | |||
| dest[1] = 0; | |||
| } | |||
| static void r200_TexCoord2f( GLfloat s, GLfloat t ) | |||
| { | |||
| GLfloat *dest = vb.texcoordptr[0]; | |||
| dest[0] = s; | |||
| dest[1] = t; | |||
| } | |||
| static void r200_TexCoord2fv( const GLfloat *v ) | |||
| { | |||
| GLfloat *dest = vb.texcoordptr[0]; | |||
| dest[0] = v[0]; | |||
| dest[1] = v[1]; | |||
| } | |||
| /* MultiTexcoord | |||
| */ | |||
| static void r200_MultiTexCoord1fARB( GLenum target, GLfloat s ) | |||
| { | |||
| GLfloat *dest = vb.texcoordptr[(target - GL_TEXTURE0_ARB)&1]; | |||
| dest[0] = s; | |||
| dest[1] = 0; | |||
| } | |||
| static void r200_MultiTexCoord1fvARB( GLenum target, const GLfloat *v ) | |||
| { | |||
| GLfloat *dest = vb.texcoordptr[(target - GL_TEXTURE0_ARB)&1]; | |||
| dest[0] = v[0]; | |||
| dest[1] = 0; | |||
| } | |||
| static void r200_MultiTexCoord2fARB( GLenum target, GLfloat s, GLfloat t ) | |||
| { | |||
| GLfloat *dest = vb.texcoordptr[(target - GL_TEXTURE0_ARB)&1]; | |||
| dest[0] = s; | |||
| dest[1] = t; | |||
| } | |||
| static void r200_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, const int *key ) | |||
| { | |||
| struct dynfn *f; | |||
| foreach( f, l ) { | |||
| if (f->key[0] == key[0] && f->key[1] == key[1]) | |||
| return f; | |||
| } | |||
| return 0; | |||
| } | |||
| /* Can't use the loopback template for this: | |||
| */ | |||
| #define CHOOSE(FN, FNTYPE, MASK0, MASK1, ARGS1, ARGS2 ) \ | |||
| static void choose_##FN ARGS1 \ | |||
| { \ | |||
| r200ContextPtr rmesa = R200_CONTEXT(vb.context); \ | |||
| int key[2]; \ | |||
| struct dynfn *dfn; \ | |||
| \ | |||
| key[0] = rmesa->vb.vtxfmt_0 & MASK0; \ | |||
| key[1] = rmesa->vb.vtxfmt_1 & MASK1; \ | |||
| \ | |||
| dfn = lookup( &rmesa->vb.dfn_cache.FN, key ); \ | |||
| if (dfn == 0) \ | |||
| dfn = rmesa->vb.codegen.FN( vb.context, key ); \ | |||
| else if (R200_DEBUG & DEBUG_CODEGEN) \ | |||
| fprintf(stderr, "%s -- cached codegen\n", __FUNCTION__ ); \ | |||
| \ | |||
| if (dfn) \ | |||
| vb.context->Exec->FN = (FNTYPE)(dfn->code); \ | |||
| else { \ | |||
| if (R200_DEBUG & DEBUG_CODEGEN) \ | |||
| fprintf(stderr, "%s -- generic version\n", __FUNCTION__ ); \ | |||
| vb.context->Exec->FN = r200_##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, MASK0, MASK1, ARGS1, ARGS2 ) \ | |||
| static void choose_##FN ARGS1 \ | |||
| { \ | |||
| GLcontext *ctx = vb.context; \ | |||
| r200ContextPtr rmesa = R200_CONTEXT(vb.context); \ | |||
| int key[2]; \ | |||
| struct dynfn *dfn; \ | |||
| \ | |||
| key[0] = rmesa->vb.vtxfmt_0 & MASK0; \ | |||
| key[1] = rmesa->vb.vtxfmt_1 & MASK1; \ | |||
| \ | |||
| if (VTX_COLOR(rmesa->vb.vtxfmt_0,0) == R200_VTX_PK_RGBA) { \ | |||
| ctx->Exec->FN = r200_##FN##_ub; \ | |||
| } \ | |||
| else if (VTX_COLOR(rmesa->vb.vtxfmt_0,0) == R200_VTX_FP_RGB) { \ | |||
| \ | |||
| if (rmesa->vb.installed_color_3f_sz != NR) { \ | |||
| rmesa->vb.installed_color_3f_sz = NR; \ | |||
| if (NR == 3) ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] = 1.0; \ | |||
| if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) { \ | |||
| r200_copy_to_current( ctx ); \ | |||
| _mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt ); \ | |||
| ctx->Exec->FN ARGS2; \ | |||
| return; \ | |||
| } \ | |||
| } \ | |||
| \ | |||
| ctx->Exec->FN = r200_##FN##_3f; \ | |||
| } \ | |||
| else { \ | |||
| ctx->Exec->FN = r200_##FN##_4f; \ | |||
| } \ | |||
| \ | |||
| \ | |||
| dfn = lookup( &rmesa->vb.dfn_cache.FN, key ); \ | |||
| if (!dfn) dfn = rmesa->vb.codegen.FN( ctx, key ); \ | |||
| \ | |||
| if (dfn) { \ | |||
| if (R200_DEBUG & DEBUG_CODEGEN) \ | |||
| fprintf(stderr, "%s -- codegen version\n", __FUNCTION__ ); \ | |||
| ctx->Exec->FN = (FNTYPE)dfn->code; \ | |||
| } \ | |||
| else if (R200_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, MASK0, MASK1, ARGS1, ARGS2 ) \ | |||
| static void choose_##FN ARGS1 \ | |||
| { \ | |||
| r200ContextPtr rmesa = R200_CONTEXT(vb.context); \ | |||
| int key[2]; \ | |||
| struct dynfn *dfn; \ | |||
| \ | |||
| key[0] = rmesa->vb.vtxfmt_0 & MASK0; \ | |||
| key[1] = rmesa->vb.vtxfmt_1 & MASK1; \ | |||
| \ | |||
| dfn = lookup( &rmesa->vb.dfn_cache.FN, key ); \ | |||
| if (dfn == 0) \ | |||
| dfn = rmesa->vb.codegen.FN( vb.context, key ); \ | |||
| else if (R200_DEBUG & DEBUG_CODEGEN) \ | |||
| fprintf(stderr, "%s -- cached version\n", __FUNCTION__ ); \ | |||
| \ | |||
| if (dfn) \ | |||
| vb.context->Exec->FN = (FNTYPE)(dfn->code); \ | |||
| else { \ | |||
| if (R200_DEBUG & DEBUG_CODEGEN) \ | |||
| fprintf(stderr, "%s -- generic version\n", __FUNCTION__ ); \ | |||
| vb.context->Exec->FN = (VTX_COLOR(rmesa->vb.vtxfmt_0,1) == R200_VTX_PK_RGBA) \ | |||
| ? r200_##FN##_ub : r200_##FN##_3f; \ | |||
| } \ | |||
| \ | |||
| vb.context->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \ | |||
| vb.context->Exec->FN ARGS2; \ | |||
| } | |||
| /* VTXFMT_0 | |||
| */ | |||
| #define MASK_XYZW (R200_VTX_W0|R200_VTX_Z0) | |||
| #define MASK_NORM (MASK_XYZW|R200_VTX_N0) | |||
| #define MASK_COLOR (MASK_NORM |(R200_VTX_COLOR_MASK<<R200_VTX_COLOR_0_SHIFT)) | |||
| #define MASK_SPEC (MASK_COLOR|(R200_VTX_COLOR_MASK<<R200_VTX_COLOR_1_SHIFT)) | |||
| /* VTXFMT_1 | |||
| */ | |||
| #define MASK_ST0 (0x7 << R200_VTX_TEX0_COMP_CNT_SHIFT) | |||
| 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, 0, | |||
| (GLfloat a,GLfloat b,GLfloat c), (a,b,c)) | |||
| CHOOSE(Normal3fv, pfv, MASK_NORM, 0, | |||
| (const GLfloat *v), (v)) | |||
| CHOOSE_COLOR(Color4ub, p4ub, 4, MASK_COLOR, 0, | |||
| (GLubyte a,GLubyte b, GLubyte c, GLubyte d), (a,b,c,d)) | |||
| CHOOSE_COLOR(Color4ubv, pubv, 4, MASK_COLOR, 0, | |||
| (const GLubyte *v), (v)) | |||
| CHOOSE_COLOR(Color3ub, p3ub, 3, MASK_COLOR, 0, | |||
| (GLubyte a,GLubyte b, GLubyte c), (a,b,c)) | |||
| CHOOSE_COLOR(Color3ubv, pubv, 3, MASK_COLOR, 0, | |||
| (const GLubyte *v), (v)) | |||
| CHOOSE_COLOR(Color4f, p4f, 4, MASK_COLOR, 0, | |||
| (GLfloat a,GLfloat b, GLfloat c, GLfloat d), (a,b,c,d)) | |||
| CHOOSE_COLOR(Color4fv, pfv, 4, MASK_COLOR, 0, | |||
| (const GLfloat *v), (v)) | |||
| CHOOSE_COLOR(Color3f, p3f, 3, MASK_COLOR, 0, | |||
| (GLfloat a,GLfloat b, GLfloat c), (a,b,c)) | |||
| CHOOSE_COLOR(Color3fv, pfv, 3, MASK_COLOR, 0, | |||
| (const GLfloat *v), (v)) | |||
| CHOOSE_SECONDARY_COLOR(SecondaryColor3ubEXT, p3ub, MASK_SPEC, 0, | |||
| (GLubyte a,GLubyte b, GLubyte c), (a,b,c)) | |||
| CHOOSE_SECONDARY_COLOR(SecondaryColor3ubvEXT, pubv, MASK_SPEC, 0, | |||
| (const GLubyte *v), (v)) | |||
| CHOOSE_SECONDARY_COLOR(SecondaryColor3fEXT, p3f, MASK_SPEC, 0, | |||
| (GLfloat a,GLfloat b, GLfloat c), (a,b,c)) | |||
| CHOOSE_SECONDARY_COLOR(SecondaryColor3fvEXT, pfv, MASK_SPEC, 0, | |||
| (const GLfloat *v), (v)) | |||
| CHOOSE(TexCoord2f, p2f, ~0, MASK_ST0, | |||
| (GLfloat a,GLfloat b), (a,b)) | |||
| CHOOSE(TexCoord2fv, pfv, ~0, MASK_ST0, | |||
| (const GLfloat *v), (v)) | |||
| CHOOSE(TexCoord1f, p1f, ~0, MASK_ST0, | |||
| (GLfloat a), (a)) | |||
| CHOOSE(TexCoord1fv, pfv, ~0, MASK_ST0, | |||
| (const GLfloat *v), (v)) | |||
| CHOOSE(MultiTexCoord2fARB, pe2f, ~0, ~0, | |||
| (GLenum u,GLfloat a,GLfloat b), (u,a,b)) | |||
| CHOOSE(MultiTexCoord2fvARB, pefv, ~0, ~0, | |||
| (GLenum u,const GLfloat *v), (u,v)) | |||
| CHOOSE(MultiTexCoord1fARB, pe1f, ~0, ~0, | |||
| (GLenum u,GLfloat a), (u,a)) | |||
| CHOOSE(MultiTexCoord1fvARB, pefv, ~0, ~0, | |||
| (GLenum u,const GLfloat *v), (u,v)) | |||
| CHOOSE(Vertex3f, p3f, ~0, ~0, | |||
| (GLfloat a,GLfloat b,GLfloat c), (a,b,c)) | |||
| CHOOSE(Vertex3fv, pfv, ~0, ~0, | |||
| (const GLfloat *v), (v)) | |||
| CHOOSE(Vertex2f, p2f, ~0, ~0, | |||
| (GLfloat a,GLfloat b), (a,b)) | |||
| CHOOSE(Vertex2fv, pfv, ~0, ~0, | |||
| (const GLfloat *v), (v)) | |||
| void r200VtxfmtInitChoosers( 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, const int *key ) | |||
| { | |||
| (void) ctx; (void) key; | |||
| return 0; | |||
| } | |||
| void r200InitCodegen( 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("R200_NO_CODEGEN")) { | |||
| #if defined(USE_X86_ASM) | |||
| r200InitX86Codegen( gen ); | |||
| #endif | |||
| #if defined(USE_SSE_ASM) | |||
| r200InitSSECodegen( gen ); | |||
| #endif | |||
| } | |||
| } | |||
| @@ -0,0 +1,95 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #include "glheader.h" | |||
| #include "imports.h" | |||
| #include "simple_list.h" | |||
| #include "r200_vtxfmt.h" | |||
| #if defined(USE_SSE_ASM) | |||
| /* Build specialized versions of the immediate calls on the fly for | |||
| * the current state. ???P4 SSE2 versions??? | |||
| */ | |||
| static struct dynfn *makeSSENormal3fv( GLcontext *ctx, const 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 ); | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| insert_at_head( &rmesa->vb.dfn_cache.Normal3fv, dfn ); | |||
| dfn->key[0] = key[0]; | |||
| dfn->key[1] = key[1]; | |||
| dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); | |||
| memcpy (dfn->code, temp, sizeof(temp)); | |||
| FIXUP(dfn->code, 5, 0x0, (int)vb.normalptr); | |||
| return dfn; | |||
| } | |||
| void r200InitSSECodegen( struct dfn_generators *gen ) | |||
| { | |||
| /* Need to: | |||
| * - check kernel sse support | |||
| * - check p4/sse2 | |||
| */ | |||
| (void) makeSSENormal3fv; | |||
| } | |||
| #else | |||
| void r200InitSSECodegen( struct dfn_generators *gen ) | |||
| { | |||
| (void) gen; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,462 @@ | |||
| /* $XFree86$ */ | |||
| /* | |||
| Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | |||
| The Weather Channel (TM) funded Tungsten Graphics to develop the | |||
| initial release of the Radeon 8500 driver under the XFree86 license. | |||
| This notice must be preserved. | |||
| Permission is hereby granted, free of charge, to any person obtaining | |||
| a copy of this software and associated documentation files (the | |||
| "Software"), to deal in the Software without restriction, including | |||
| without limitation the rights to use, copy, modify, merge, publish, | |||
| distribute, sublicense, and/or sell copies of the Software, and to | |||
| permit persons to whom the Software is furnished to do so, subject to | |||
| the following conditions: | |||
| The above copyright notice and this permission notice (including the | |||
| next paragraph) shall be included in all copies or substantial | |||
| portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||
| IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE | |||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #include "glheader.h" | |||
| #include "imports.h" | |||
| #include "mmath.h" | |||
| #include "simple_list.h" | |||
| #include "r200_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 *r200_makeX86Vertex3f( GLcontext *ctx, const int *key ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| struct dynfn *dfn = MALLOC_STRUCT( dynfn ); | |||
| if (R200_DEBUG & DEBUG_CODEGEN) | |||
| fprintf(stderr, "%s 0x%08x 0x%08x %d\n", __FUNCTION__, | |||
| key[0], key[1], 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 *r200_makeX86Vertex3fv( GLcontext *ctx, const int *key ) | |||
| { | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| struct dynfn *dfn = MALLOC_STRUCT( dynfn ); | |||
| if (R200_DEBUG & DEBUG_CODEGEN) | |||
| fprintf(stderr, "%s 0x%08x 0x%08x %d\n", __FUNCTION__, | |||
| key[0], key[1], 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 *r200_makeX86Normal3fv( GLcontext *ctx, const int *key ) | |||
| { | |||
| struct dynfn *dfn = MALLOC_STRUCT( dynfn ); | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| int i = 0; | |||
| if (R200_DEBUG & DEBUG_CODEGEN) | |||
| fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key[0] ); | |||
| 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 *r200_makeX86Normal3f( GLcontext *ctx, const int *key ) | |||
| { | |||
| struct dynfn *dfn = MALLOC_STRUCT( dynfn ); | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| if (R200_DEBUG & DEBUG_CODEGEN) | |||
| fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key[0] ); | |||
| DFN ( _x86_Normal3f, rmesa->vb.dfn_cache.Normal3f ); | |||
| FIXUP(dfn->code, 1, 0x12345678, (int)vb.normalptr); | |||
| return dfn; | |||
| } | |||
| struct dynfn *r200_makeX86Color4ubv( GLcontext *ctx, const int *key ) | |||
| { | |||
| struct dynfn *dfn = MALLOC_STRUCT( dynfn ); | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| if (R200_DEBUG & DEBUG_CODEGEN) | |||
| fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key[0] ); | |||
| if (VTX_COLOR(key[0],0) == R200_VTX_PK_RGBA) { | |||
| 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 *r200_makeX86Color4ub( GLcontext *ctx, const int *key ) | |||
| { | |||
| if (R200_DEBUG & DEBUG_CODEGEN) | |||
| fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key[0] ); | |||
| if (VTX_COLOR(key[0],0) == R200_VTX_PK_RGBA) { | |||
| struct dynfn *dfn = MALLOC_STRUCT( dynfn ); | |||
| r200ContextPtr rmesa = R200_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 *r200_makeX86Color3fv( GLcontext *ctx, const int *key ) | |||
| { | |||
| if (VTX_COLOR(key[0],0) != R200_VTX_FP_RGB) | |||
| return 0; | |||
| else | |||
| { | |||
| struct dynfn *dfn = MALLOC_STRUCT( dynfn ); | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| if (R200_DEBUG & DEBUG_CODEGEN) | |||
| fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key[0] ); | |||
| DFN ( _x86_Color3fv_3f, rmesa->vb.dfn_cache.Color3fv ); | |||
| FIXUP(dfn->code, 5, 0x0, (int)vb.floatcolorptr); | |||
| return dfn; | |||
| } | |||
| } | |||
| struct dynfn *r200_makeX86Color3f( GLcontext *ctx, const int *key ) | |||
| { | |||
| if (VTX_COLOR(key[0],0) != R200_VTX_FP_RGB) | |||
| return 0; | |||
| else | |||
| { | |||
| struct dynfn *dfn = MALLOC_STRUCT( dynfn ); | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| if (R200_DEBUG & DEBUG_CODEGEN) | |||
| fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key[0] ); | |||
| DFN ( _x86_Color3f_3f, rmesa->vb.dfn_cache.Color3f ); | |||
| FIXUP(dfn->code, 1, 0x12345678, (int)vb.floatcolorptr); | |||
| return dfn; | |||
| } | |||
| } | |||
| struct dynfn *r200_makeX86TexCoord2fv( GLcontext *ctx, const int *key ) | |||
| { | |||
| struct dynfn *dfn = MALLOC_STRUCT( dynfn ); | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| if (R200_DEBUG & DEBUG_CODEGEN) | |||
| fprintf(stderr, "%s 0x%08x 0x%08x\n", __FUNCTION__, key[0], key[1] ); | |||
| DFN ( _x86_TexCoord2fv, rmesa->vb.dfn_cache.TexCoord2fv ); | |||
| FIXUP(dfn->code, 5, 0x12345678, (int)vb.texcoordptr[0]); | |||
| return dfn; | |||
| } | |||
| struct dynfn *r200_makeX86TexCoord2f( GLcontext *ctx, const int *key ) | |||
| { | |||
| struct dynfn *dfn = MALLOC_STRUCT( dynfn ); | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| if (R200_DEBUG & DEBUG_CODEGEN) | |||
| fprintf(stderr, "%s 0x%08x 0x%08x\n", __FUNCTION__, key[0], key[1] ); | |||
| DFN ( _x86_TexCoord2f, rmesa->vb.dfn_cache.TexCoord2f ); | |||
| FIXUP(dfn->code, 1, 0x12345678, (int)vb.texcoordptr[0]); | |||
| return dfn; | |||
| } | |||
| struct dynfn *r200_makeX86MultiTexCoord2fvARB( GLcontext *ctx, const 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 ); | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| if (R200_DEBUG & DEBUG_CODEGEN) | |||
| fprintf(stderr, "%s 0x%08x 0x%08x\n", __FUNCTION__, key[0], key[1] ); | |||
| if (vb.texcoordptr[1] == vb.texcoordptr[0]+4) { | |||
| 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 *r200_makeX86MultiTexCoord2fARB( GLcontext *ctx, | |||
| const 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 ); | |||
| r200ContextPtr rmesa = R200_CONTEXT(ctx); | |||
| if (R200_DEBUG & DEBUG_CODEGEN) | |||
| fprintf(stderr, "%s 0x%08x 0x%08x\n", __FUNCTION__, key[0], key[1] ); | |||
| if (vb.texcoordptr[1] == vb.texcoordptr[0]+4) { | |||
| 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 r200InitX86Codegen( struct dfn_generators *gen ) | |||
| { | |||
| gen->Vertex3f = r200_makeX86Vertex3f; | |||
| gen->Vertex3fv = r200_makeX86Vertex3fv; | |||
| gen->Color4ub = r200_makeX86Color4ub; /* PKCOLOR only */ | |||
| gen->Color4ubv = r200_makeX86Color4ubv; /* PKCOLOR only */ | |||
| gen->Normal3f = r200_makeX86Normal3f; | |||
| gen->Normal3fv = r200_makeX86Normal3fv; | |||
| gen->TexCoord2f = r200_makeX86TexCoord2f; | |||
| gen->TexCoord2fv = r200_makeX86TexCoord2fv; | |||
| gen->MultiTexCoord2fARB = r200_makeX86MultiTexCoord2fARB; | |||
| gen->MultiTexCoord2fvARB = r200_makeX86MultiTexCoord2fvARB; | |||
| gen->Color3f = r200_makeX86Color3f; | |||
| gen->Color3fv = r200_makeX86Color3fv; | |||
| /* Not done: | |||
| */ | |||
| /* gen->Vertex2f = r200_makeX86Vertex2f; */ | |||
| /* gen->Vertex2fv = r200_makeX86Vertex2fv; */ | |||
| /* gen->Color3ub = r200_makeX86Color3ub; */ | |||
| /* gen->Color3ubv = r200_makeX86Color3ubv; */ | |||
| /* gen->Color4f = r200_makeX86Color4f; */ | |||
| /* gen->Color4fv = r200_makeX86Color4fv; */ | |||
| /* gen->TexCoord1f = r200_makeX86TexCoord1f; */ | |||
| /* gen->TexCoord1fv = r200_makeX86TexCoord1fv; */ | |||
| /* gen->MultiTexCoord1fARB = r200_makeX86MultiTexCoord1fARB; */ | |||
| /* gen->MultiTexCoord1fvARB = r200_makeX86MultiTexCoord1fvARB; */ | |||
| } | |||
| #else | |||
| void r200InitX86Codegen( struct dfn_generators *gen ) | |||
| { | |||
| (void) gen; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,410 @@ | |||
| /* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_vtxtmp_x86.S,v 1.1 2002/10/30 12:51:53 alanh 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 ) | |||