Browse Source

r200 driver, brought over by Jon Smirl

tags/embedded-1-20030324
Keith Whitwell 23 years ago
parent
commit
ed1b6e98e2
39 changed files with 20725 additions and 0 deletions
  1. 134
    0
      src/mesa/drivers/dri/r200/Makefile
  2. 344
    0
      src/mesa/drivers/dri/r200/r200_cmdbuf.c
  3. 673
    0
      src/mesa/drivers/dri/r200/r200_context.c
  4. 944
    0
      src/mesa/drivers/dri/r200/r200_context.h
  5. 934
    0
      src/mesa/drivers/dri/r200/r200_ioctl.c
  6. 188
    0
      src/mesa/drivers/dri/r200/r200_ioctl.h
  7. 118
    0
      src/mesa/drivers/dri/r200/r200_lock.c
  8. 111
    0
      src/mesa/drivers/dri/r200/r200_lock.h
  9. 12
    0
      src/mesa/drivers/dri/r200/r200_maos.c
  10. 46
    0
      src/mesa/drivers/dri/r200/r200_maos.h
  11. 481
    0
      src/mesa/drivers/dri/r200/r200_maos_arrays.c
  12. 378
    0
      src/mesa/drivers/dri/r200/r200_maos_vbtmp.h
  13. 338
    0
      src/mesa/drivers/dri/r200/r200_maos_verts.c
  14. 494
    0
      src/mesa/drivers/dri/r200/r200_pixel.c
  15. 43
    0
      src/mesa/drivers/dri/r200/r200_pixel.h
  16. 1438
    0
      src/mesa/drivers/dri/r200/r200_reg.h
  17. 1436
    0
      src/mesa/drivers/dri/r200/r200_sanity.c
  18. 11
    0
      src/mesa/drivers/dri/r200/r200_sanity.h
  19. 434
    0
      src/mesa/drivers/dri/r200/r200_screen.c
  20. 96
    0
      src/mesa/drivers/dri/r200/r200_screen.h
  21. 430
    0
      src/mesa/drivers/dri/r200/r200_span.c
  22. 43
    0
      src/mesa/drivers/dri/r200/r200_span.h
  23. 2155
    0
      src/mesa/drivers/dri/r200/r200_state.c
  24. 68
    0
      src/mesa/drivers/dri/r200/r200_state.h
  25. 692
    0
      src/mesa/drivers/dri/r200/r200_state_init.c
  26. 1286
    0
      src/mesa/drivers/dri/r200/r200_swtcl.c
  27. 80
    0
      src/mesa/drivers/dri/r200/r200_swtcl.h
  28. 555
    0
      src/mesa/drivers/dri/r200/r200_tcl.c
  29. 66
    0
      src/mesa/drivers/dri/r200/r200_tcl.h
  30. 988
    0
      src/mesa/drivers/dri/r200/r200_tex.c
  31. 55
    0
      src/mesa/drivers/dri/r200/r200_tex.h
  32. 811
    0
      src/mesa/drivers/dri/r200/r200_texmem.c
  33. 1799
    0
      src/mesa/drivers/dri/r200/r200_texstate.c
  34. 1152
    0
      src/mesa/drivers/dri/r200/r200_vtxfmt.c
  35. 128
    0
      src/mesa/drivers/dri/r200/r200_vtxfmt.h
  36. 797
    0
      src/mesa/drivers/dri/r200/r200_vtxfmt_c.c
  37. 95
    0
      src/mesa/drivers/dri/r200/r200_vtxfmt_sse.c
  38. 462
    0
      src/mesa/drivers/dri/r200/r200_vtxfmt_x86.c
  39. 410
    0
      src/mesa/drivers/dri/r200/r200_vtxtmp_x86.S

+ 134
- 0
src/mesa/drivers/dri/r200/Makefile View File

@@ -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)

+ 344
- 0
src/mesa/drivers/dri/r200/r200_cmdbuf.c View File

@@ -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;
}
}

+ 673
- 0
src/mesa/drivers/dri/r200/r200_context.c View File

@@ -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;
}







+ 944
- 0
src/mesa/drivers/dri/r200/r200_context.h View File

@@ -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__ */

+ 934
- 0
src/mesa/drivers/dri/r200/r200_ioctl.c View File

@@ -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 = &region_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;
}


+ 188
- 0
src/mesa/drivers/dri/r200/r200_ioctl.h View File

@@ -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__ */

+ 118
- 0
src/mesa/drivers/dri/r200/r200_lock.c View File

@@ -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 );
}
}
}

+ 111
- 0
src/mesa/drivers/dri/r200/r200_lock.h View File

@@ -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__ */

+ 12
- 0
src/mesa/drivers/dri/r200/r200_maos.c View File

@@ -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

+ 46
- 0
src/mesa/drivers/dri/r200/r200_maos.h View File

@@ -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

+ 481
- 0
src/mesa/drivers/dri/r200/r200_maos_arrays.c View File

@@ -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__ );
}

+ 378
- 0
src/mesa/drivers/dri/r200/r200_maos_vbtmp.h View File

@@ -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

+ 338
- 0
src/mesa/drivers/dri/r200/r200_maos_verts.c View File

@@ -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__ );
}

+ 494
- 0
src/mesa/drivers/dri/r200/r200_pixel.c View File

@@ -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;
}
}

+ 43
- 0
src/mesa/drivers/dri/r200/r200_pixel.h View File

@@ -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

+ 1438
- 0
src/mesa/drivers/dri/r200/r200_reg.h
File diff suppressed because it is too large
View File


+ 1436
- 0
src/mesa/drivers/dri/r200/r200_sanity.c
File diff suppressed because it is too large
View File


+ 11
- 0
src/mesa/drivers/dri/r200/r200_sanity.h View File

@@ -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

+ 434
- 0
src/mesa/drivers/dri/r200/r200_screen.c View File

@@ -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);
}
}

+ 96
- 0
src/mesa/drivers/dri/r200/r200_screen.h View File

@@ -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__ */

+ 430
- 0
src/mesa/drivers/dri/r200/r200_span.c View File

@@ -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;
}

+ 43
- 0
src/mesa/drivers/dri/r200/r200_span.h View File

@@ -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

+ 2155
- 0
src/mesa/drivers/dri/r200/r200_state.c
File diff suppressed because it is too large
View File


+ 68
- 0
src/mesa/drivers/dri/r200/r200_state.h View File

@@ -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

+ 692
- 0
src/mesa/drivers/dri/r200/r200_state_init.c View File

@@ -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;
}

+ 1286
- 0
src/mesa/drivers/dri/r200/r200_swtcl.c
File diff suppressed because it is too large
View File


+ 80
- 0
src/mesa/drivers/dri/r200/r200_swtcl.h View File

@@ -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

+ 555
- 0
src/mesa/drivers/dri/r200/r200_tcl.c View File

@@ -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 );
}
}
}

+ 66
- 0
src/mesa/drivers/dri/r200/r200_tcl.h View File

@@ -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

+ 988
- 0
src/mesa/drivers/dri/r200/r200_tex.c View File

@@ -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 );
}

+ 55
- 0
src/mesa/drivers/dri/r200/r200_tex.h View File

@@ -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__ */

+ 811
- 0
src/mesa/drivers/dri/r200/r200_texmem.c View File

@@ -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(&region, 0, sizeof(region));
r200AllocDmaRegion( rmesa, &region, 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( &region ),
dstPitch, t->bufAddr,
0, 0,
0, done,
width, lines );
r200EmitWait( rmesa, RADEON_WAIT_2D );

r200ReleaseDmaRegion( rmesa, &region, __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;
}

+ 1799
- 0
src/mesa/drivers/dri/r200/r200_texstate.c
File diff suppressed because it is too large
View File


+ 1152
- 0
src/mesa/drivers/dri/r200/r200_vtxfmt.c
File diff suppressed because it is too large
View File


+ 128
- 0
src/mesa/drivers/dri/r200/r200_vtxfmt.h View File

@@ -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

+ 797
- 0
src/mesa/drivers/dri/r200/r200_vtxfmt_c.c View File

@@ -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
}
}

+ 95
- 0
src/mesa/drivers/dri/r200/r200_vtxfmt_sse.c View File

@@ -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





+ 462
- 0
src/mesa/drivers/dri/r200/r200_vtxfmt_x86.c View File

@@ -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

+ 410
- 0
src/mesa/drivers/dri/r200/r200_vtxtmp_x86.S View File

@@ -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 )

Loading…
Cancel
Save