diff options
author | gareth <gareth> | 2000-06-12 14:27:13 +0000 |
---|---|---|
committer | gareth <gareth> | 2000-06-12 14:27:13 +0000 |
commit | 6c94c4508e050c830c7480f9a87878f3246a7f52 (patch) | |
tree | e5dfa34b6a8f2ff2a71057554a75f7bc41c7e5e2 | |
parent | 55cab1f336a64750c8f83a8a5cf97bf3dc1029b7 (diff) |
More performance improvements, general cleanups including:ati-4-1-0-20000613ati-4-1-0-branch
* variable-sized vertices
* precalculation of depth scale
* removal of user-space command submission functions
* initial support for PCI inlined vertex buffers
27 files changed, 3163 insertions, 569 deletions
diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_cce.c b/xc/lib/GL/mesa/src/drv/r128/r128_cce.c new file mode 100644 index 000000000..a89d7dc84 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_cce.c @@ -0,0 +1,333 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +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, PRECISION INSIGHT 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: + * Gareth Hughes <gareth@precisioninsight.com> + * + */ + +#include "r128_init.h" +#include "r128_mesa.h" +#include "r128_xmesa.h" +#include "r128_context.h" +#include "r128_lock.h" +#include "r128_state.h" +#include "r128_reg.h" +#include "r128_cce.h" + +#define R128_TIMEOUT 2000000 + +typedef drmBufPtr (*r128_get_buffer_func)( r128ContextPtr r128ctx ); + +static r128_get_buffer_func r128GetBufferLocked; +r128_fire_vertices_func r128FireVerticesLocked; + + +static void r128RingStatus( r128ContextPtr r128ctx ) +{ + r128ScreenPtr r128scrn = r128ctx->r128Screen; + unsigned char *R128MMIO = r128scrn->mmio; + + fprintf( stderr, "GUI_STAT = 0x%08x\n", + (unsigned int) INREG( R128_GUI_STAT ) ); + fprintf( stderr, "PM4_STAT = 0x%08x\n", + (unsigned int) INREG( R128_PM4_STAT ) ); + fprintf( stderr, "PM4_BUFFER_DL_WPTR = 0x%08x\n", + (unsigned int) INREG( R128_PM4_BUFFER_DL_WPTR ) ); + fprintf( stderr, "PM4_BUFFER_DL_RPTR = 0x%08x\n", + (unsigned int) INREG( R128_PM4_BUFFER_DL_RPTR ) ); + fprintf( stderr, "ringWrite = 0x%08x\n", + r128scrn->SAREA->ringWrite ); + fprintf( stderr, "*ringReadPtr = 0x%08x\n", + *r128scrn->ringReadPtr ); +} + + +/* Get a new VB from the pool of vertex buffers in AGP space. + */ +static drmBufPtr r128_get_buffer_locked( r128ContextPtr r128ctx ) +{ + int fd = r128ctx->r128Screen->driScreen->fd; + int num; + int index = 0; + int size = 0; + int to = 0; + drmBufPtr buf = NULL; + + while ( !buf && ( to++ < r128ctx->CCEtimeout ) ) { + num = drmR128GetVertexBuffers( fd, 1, &index, &size ); + + if ( num > 0 ) { + buf = &r128ctx->r128Screen->vbBufs->list[index]; + buf->used = 0; + return buf; + } + } + + if ( !buf ) { + drmR128EngineReset( fd ); + fprintf( stderr, "Error: Could not get new VB... exiting\n" ); + exit( -1 ); + } + + return buf; +} + +static void r128_fire_vertices_locked( r128ContextPtr r128ctx ) +{ + int vertsize = r128ctx->vertsize; + int format = r128ctx->vc_format; + int index = r128ctx->vert_buf->idx; + int offset = r128ctx->r128Screen->vbOffset + + index * r128ctx->r128Screen->vbBufSize; + int size = r128ctx->vert_buf->used / (vertsize * sizeof(GLuint)); + int fd = r128ctx->r128Screen->driScreen->fd; + int to = 0; + int ret; + CARD32 prim; + + prim = R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST; + + /* Send the vertex buffer to the hardware */ + BEGIN_CLIP_LOOP( r128ctx ); + { + R128CCE3( R128_CCE_PACKET3_3D_RNDR_GEN_INDX_PRIM, 3 ); + R128CCE( offset ); + R128CCE( size ); + R128CCE( format ); + R128CCE( prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST | + (size << R128_CCE_VC_CNTL_NUM_SHIFT) ); + + R128CCE_SUBMIT_PACKET(); + } + END_CLIP_LOOP( r128ctx ); + + /* Tell the kernel to release the vertex buffer */ + do { + ret = drmR128FlushVertexBuffers( fd, 1, &index, &size, 0 ); + } while ( ( ret == -EBUSY ) && ( to++ < r128ctx->CCEtimeout ) ); + + if ( ret < 0 ) { + drmR128EngineReset( fd ); + fprintf( stderr, "Error: Could not flush VB... exiting\n" ); + exit( -1 ); + } + + r128ctx->vert_buf = NULL; +} + +static drmBufPtr r128_get_ring_locked( r128ContextPtr r128ctx ) +{ + r128ScreenPtr r128scrn = r128ctx->r128Screen; + drmBufPtr buf = NULL; + + buf = (drmBufPtr) malloc( sizeof(*buf) ); + + buf->idx = -666; + buf->total = r128scrn->vbBufSize; + buf->used = 0; + buf->address = (drmAddress *) malloc( r128scrn->vbBufSize ); + + return buf; +} + +static void r128_fire_ring_locked( r128ContextPtr r128ctx ) +{ + int vertsize = r128ctx->vertsize; + int format = r128ctx->vc_format; + int size = r128ctx->vert_buf->used / (vertsize * sizeof(GLuint)); + drmBufPtr buf = r128ctx->vert_buf; + CARD32 prim; + + prim = R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST; + + /* Send the vertex buffer to the hardware */ + BEGIN_CLIP_LOOP( r128ctx ); + { + R128CCE3( R128_CCE_PACKET3_3D_RNDR_GEN_PRIM, 3 ); + R128CCE( format ); + R128CCE( prim | R128_CCE_VC_CNTL_PRIM_WALK_RING | + (size << R128_CCE_VC_CNTL_NUM_SHIFT) ); + + memcpy( &r128ctx->CCEbuf[r128ctx->CCEcount], buf->address, buf->used ); + r128ctx->CCEcount += (buf->used >> 2); + + R128CCE_SUBMIT_PACKET(); + } + END_CLIP_LOOP( r128ctx ); + + free( buf->address ); + free( buf ); + + r128ctx->vert_buf = NULL; +} + + +void r128FlushVerticesLocked( r128ContextPtr r128ctx ) +{ + if ( r128ctx->vert_buf && r128ctx->vert_buf->used ) { + r128FireVerticesLocked( r128ctx ); + } +} + +CARD32 *r128AllocVertexDwords( r128ContextPtr r128ctx, int dwords ) +{ + int bytes = dwords * 4; + CARD32 *head; + + if ( !r128ctx->vert_buf ) { + LOCK_HARDWARE( r128ctx ); + + if ( r128ctx->first_elt != r128ctx->next_elt ) { + r128FlushEltsLocked( r128ctx ); + } + r128ctx->vert_buf = r128GetBufferLocked( r128ctx ); + + UNLOCK_HARDWARE( r128ctx ); + } else if ( r128ctx->vert_buf->used + bytes > r128ctx->vert_buf->total ) { + LOCK_HARDWARE( r128ctx ); + + r128FlushVerticesLocked( r128ctx ); + r128ctx->vert_buf = r128GetBufferLocked( r128ctx ); + + UNLOCK_HARDWARE( r128ctx ); + } + + head = (CARD32 *)((char *)r128ctx->vert_buf->address + + r128ctx->vert_buf->used); + + r128ctx->vert_buf->used += bytes; + return head; +} + + +/* ================================================================ */ + + +void r128GetEltBufLocked( r128ContextPtr r128ctx ) +{ + r128ctx->elt_buf = r128GetBufferLocked( r128ctx ); +} + +void r128FireEltsLocked( r128ContextPtr r128ctx, + GLuint num_elts, GLuint discard ) +{ + int vertsize = r128ctx->vertsize; + int format = r128ctx->vc_format; + int index = r128ctx->vert_buf->idx; + int offset = r128ctx->r128Screen->vbOffset + + index * r128ctx->r128Screen->vbBufSize; + int size = r128ctx->vert_buf->used / (vertsize * sizeof(GLuint)); + int fd = r128ctx->r128Screen->driScreen->fd; + int to = 0; + int ret; + CARD32 prim; + + fprintf( stderr, "Error: elt buffers not supported at this time...\n" ); + return; + + prim = R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST; + + /* Send the vertex buffer to the hardware */ + BEGIN_CLIP_LOOP( r128ctx ); + { + R128CCE3( R128_CCE_PACKET3_3D_RNDR_GEN_INDX_PRIM, 3 ); + R128CCE( offset ); + R128CCE( size ); + R128CCE( format ); + R128CCE( prim | R128_CCE_VC_CNTL_PRIM_WALK_IND | + (size << R128_CCE_VC_CNTL_NUM_SHIFT) ); + + R128CCE_SUBMIT_PACKET(); + } + END_CLIP_LOOP( r128ctx ); + + if ( discard ) { + /* Tell the kernel to release the vertex buffer */ + do { + ret = drmR128FlushVertexBuffers( fd, 1, &index, &size, 0 ); + } while ( ( ret == -EBUSY ) && ( to++ < r128ctx->CCEtimeout ) ); + + if ( ret < 0 ) { + drmR128EngineReset( fd ); + fprintf( stderr, "Error: Could not flush VB... exiting\n" ); + exit( -1 ); + } + } + + r128ctx->vert_buf = NULL; +} + +void r128FlushEltsLocked( r128ContextPtr r128ctx ) +{ + if ( r128ctx->first_elt != r128ctx->next_elt ) { + r128FireEltsLocked( r128ctx, + (GLuint)r128ctx->next_elt - + (GLuint)r128ctx->first_elt, + 0 ); + r128ctx->first_elt = r128ctx->next_elt; + } +} + +void r128ReleaseBufLocked( r128ContextPtr r128ctx, drmBufPtr buffer ) +{ + int index; + int size; + int fd = r128ctx->r128Screen->driScreen->fd; + int to = 0; + int ret; + + if ( !buffer ) return; + + index = buffer->idx; + size = buffer->used = 0; + + /* Tell the kernel to release the vertex buffer */ + do { + ret = drmR128FlushVertexBuffers( fd, 1, &index, &size, 0 ); + } while ( ( ret == -EBUSY ) && ( to++ < r128ctx->CCEtimeout ) ); + + if ( ret < 0 ) { + drmR128EngineReset( fd ); + fprintf( stderr, "Error: Could not release VB... exiting\n" ); + exit( -1 ); + } +} + + +void r128InitVertexBuffers( r128ScreenPtr r128scrn ) +{ + if ( !r128scrn->IsPCI ) { + r128GetBufferLocked = r128_get_buffer_locked; + r128FireVerticesLocked = r128_fire_vertices_locked; + } else { + r128GetBufferLocked = r128_get_ring_locked; + r128FireVerticesLocked = r128_fire_ring_locked; + } +} diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_cce.h b/xc/lib/GL/mesa/src/drv/r128/r128_cce.h new file mode 100644 index 000000000..768151971 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_cce.h @@ -0,0 +1,160 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +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, PRECISION INSIGHT 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 <kevin@precisioninsight.com> + * Gareth Hughes <gareth@precisioninsight.com> + * + */ + +#ifndef _R128_CCE_H_ +#define _R128_CCE_H_ + +#ifdef GLX_DIRECT_RENDERING + +#include "r128_dri.h" +#include "r128_reg.h" + +#include "xf86drmR128.h" + +#define R128_DEFAULT_TOTAL_CCE_TIMEOUT 1000000 /* usecs */ + +typedef union { + float f; + int i; +} floatTOint; + +/* Insert an integer value into the CCE ring buffer. */ +#define R128CCE(v) \ +do { \ + r128ctx->CCEbuf[r128ctx->CCEcount] = (v); \ + r128ctx->CCEcount++; \ +} while (0) + +/* Insert an floating point value into the CCE ring buffer. */ +#define R128CCEF(v) \ +do { \ + floatTOint fTi; \ + fTi.f = (v); \ + r128ctx->CCEbuf[r128ctx->CCEcount] = fTi.i; \ + r128ctx->CCEcount++; \ +} while (0) + +/* Insert a type-[0123] packet header into the ring buffer */ +#define R128CCE0(p,r,n) R128CCE((p) | ((n) << 16) | ((r) >> 2)) +#define R128CCE1(p,r1,r2) R128CCE((p) | (((r2) >> 2) << 11) | ((r1) >> 2)) +#define R128CCE2(p) R128CCE((p)) +#define R128CCE3(p,n) R128CCE((p) | ((n) << 16)) + +#define R128CCE_SUBMIT_PACKET() \ +do { \ + r128SubmitPacketLocked( r128ctx, r128ctx->CCEbuf, r128ctx->CCEcount ); \ + r128ctx->CCEcount = 0; \ +} while (0) + +static __inline void r128SubmitPacketLocked( r128ContextPtr r128ctx, + CARD32 *buf, GLuint count ) +{ + CARD32 *b; + int c = count; + int fd = r128ctx->r128Screen->driScreen->fd; + int to = 0; + int ret; + + do { + b = buf + (count - c); + ret = drmR128SubmitPacket( fd, b, &c, 0 ); + } while ( ( ret == -EBUSY ) && ( to++ < r128ctx->CCEtimeout ) ); + + if ( ret < 0 ) { + drmR128EngineReset( fd ); + fprintf( stderr, "Error: Could not submit packet... exiting\n" ); + exit( -1 ); + } +} + +static __inline void r128WaitForIdleLocked( r128ContextPtr r128ctx ) +{ + int fd = r128ctx->r128Screen->driScreen->fd; + int to = 0; + int ret; + + drmR128EngineFlush( fd ); + + do { + ret = drmR128WaitForIdle( fd ); + } while ( ( ret == -EBUSY ) && ( to++ < r128ctx->CCEtimeout ) ); + + if ( ret < 0 ) { + drmR128EngineReset( fd ); + fprintf( stderr, "Error: Rage 128 timed out... exiting\n" ); + exit( -1 ); + } +} + +#define r128WaitForIdle( r128ctx ) \ +do { \ + LOCK_HARDWARE( r128ctx ); \ + r128WaitForIdleLocked( r128ctx ); \ + UNLOCK_HARDWARE( r128ctx ); \ +} while (0) + + +extern CARD32 *r128AllocVertexDwords( r128ContextPtr r128ctx, int dwords ); +extern void r128FlushVerticesLocked( r128ContextPtr r128ctx ); + +typedef void (*r128_fire_vertices_func)( r128ContextPtr r128ctx ); +extern r128_fire_vertices_func r128FireVerticesLocked; + +#define r128FlushVertices( r128ctx ) \ +do { \ + LOCK_HARDWARE( r128ctx ); \ + r128FlushVerticesLocked( r128ctx ); \ + UNLOCK_HARDWARE( r128ctx ); \ +} while (0) + + +extern void r128GetEltBufLocked( r128ContextPtr r128ctx ); +extern void r128FlushEltsLocked( r128ContextPtr r128ctx ); +extern void r128FireEltsLocked( r128ContextPtr r128ctx, + GLuint num_elts, GLuint discard ); +extern void r128ReleaseBufLocked( r128ContextPtr r128ctx, drmBufPtr buffer ); + +#define r128FlushElts( r128ctx ) \ +do { \ + LOCK_HARDWARE( r128ctx ); \ + r128FlushEltsLocked( r128ctx ); \ + UNLOCK_HARDWARE( r128ctx ); \ +} while (0) + + +extern void r128InitVertexBuffers( r128ScreenPtr r128scrn ); + +#endif +#endif /* _R128_CCE_H_ */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_ccevb.h b/xc/lib/GL/mesa/src/drv/r128/r128_ccevb.h deleted file mode 100644 index a40d5413a..000000000 --- a/xc/lib/GL/mesa/src/drv/r128/r128_ccevb.h +++ /dev/null @@ -1,224 +0,0 @@ -/* $XFree86$ */ -/************************************************************************** - -Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., - Cedar Park, Texas. -All Rights Reserved. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -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, PRECISION INSIGHT 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 <kevin@precisioninsight.com> - * - */ - -#ifndef _R128_CCEVB_H_ -#define _R128_CCEVB_H_ - -#ifdef GLX_DIRECT_RENDERING - -#include "xf86drmR128.h" - -typedef struct { - CARD32 *buf; /* Pointer to current VB */ - int index; /* Index of current VB */ - int start; /* in bytes from the beginning of the VB map */ - int size; /* in vertices */ - int count; /* in vertices */ - drmR128PrimType prim; /* Primitive type for vertices in VB */ - int done; /* VB has been sent to ring */ -} r128CCEVertBuf, *r128CCEVertBufPtr; - - - -/* Flush the CPU's write-combining cache */ -/* FIXME: This code is both processor and compiler specific */ -#define R128_FLUSH_WC_MEMORY() \ - do { \ - int xchangeDummy; \ - \ - __asm__ volatile("push %%eax ;" \ - "xchg %%eax, %0 ;" \ - "pop %%eax" : : "m" (xchangeDummy)); \ - __asm__ volatile("push %%eax ;" \ - "push %%ebx ;" \ - "push %%ecx ;" \ - "push %%edx ;" \ - "movl $0,%%eax ;" \ - "cpuid ;" \ - "pop %%edx ;" \ - "pop %%ecx ;" \ - "pop %%ebx ;" \ - "pop %%eax" : /* no outputs */ : /* no inputs */); \ - } while (0) - - -/* Get a new VB from the pool of vertex buffers in AGP space */ -/* NOTE: By default the primitive type for a VB is set to individual tris */ -#define R128CCE_GET_NEW_VB(r128ctx) \ - do { \ - r128CCEVertBufPtr vb = &r128ctx->vb; \ - int to = 0; \ - int fd = r128ctx->r128Screen->driScreen->fd; \ - int num; \ - int index; \ - int size; \ - \ - vb->buf = NULL; \ - \ - LOCK_HARDWARE(r128ctx); \ - while (!vb->buf && to++ < r128ctx->CCEtimeout) { \ - /* Ask the kernel a new vertex buffer */ \ - num = drmR128GetVertexBuffers(fd, 1, &index, &size); \ - \ - if (num > 0) { \ - vb->buf = (CARD32 *)(r128ctx->r128Screen-> \ - vbBufs->list[index].address); \ - vb->index = index; \ - vb->start = index*r128ctx->r128Screen->vbBufSize; \ - vb->size = size/sizeof(r128_vertex); \ - vb->count = 0; \ - vb->prim = DRM_R128_PRIM_TRI_LIST; \ - vb->done = GL_FALSE; \ - } \ - } \ - UNLOCK_HARDWARE(r128ctx); \ - \ - if (!vb->buf) { \ - (void)drmR128EngineReset(fd); \ - fprintf(stderr, "Error: Could not get new VB... exiting\n"); \ - exit(-1); \ - } \ - } while (0) - -/* Submit a VB to the hardware for processing */ -/* NOTE: This macro is only called while holding the hardware lock */ -#define R128CCE_SUBMIT_VB(r128ctx) \ - do { \ - int index = r128ctx->vb.index; \ - int size = r128ctx->vb.count; \ - int fd = r128ctx->r128Screen->driScreen->fd; \ - int to = 0; \ - int ret; \ - CARD32 prim; \ - \ - switch (r128ctx->vb.prim) { \ - case DRM_R128_PRIM_NONE: \ - prim = R128_CCE_VC_CNTL_PRIM_TYPE_NONE; \ - break; \ - case DRM_R128_PRIM_POINT: \ - prim = R128_CCE_VC_CNTL_PRIM_TYPE_POINT; \ - break; \ - case DRM_R128_PRIM_LINE: \ - prim = R128_CCE_VC_CNTL_PRIM_TYPE_LINE; \ - break; \ - case DRM_R128_PRIM_POLY_LINE: \ - prim = R128_CCE_VC_CNTL_PRIM_TYPE_POLY_LINE; \ - break; \ - case DRM_R128_PRIM_TRI_LIST: \ - prim = R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST; \ - break; \ - case DRM_R128_PRIM_TRI_FAN: \ - prim = R128_CCE_VC_CNTL_PRIM_TYPE_TRI_FAN; \ - break; \ - case DRM_R128_PRIM_TRI_STRIP: \ - prim = R128_CCE_VC_CNTL_PRIM_TYPE_TRI_STRIP; \ - break; \ - case DRM_R128_PRIM_TRI_TYPE2: \ - prim = R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2; \ - break; \ - default: \ - prim = R128_CCE_VC_CNTL_PRIM_TYPE_NONE; \ - break; \ - } \ - \ - /* Send the vertex buffer to the hardware */ \ - BEGIN_CLIP_LOOP(r128ctx); \ - \ - R128CCE3(R128_CCE_PACKET3_3D_RNDR_GEN_INDX_PRIM, 3); \ - R128CCE(r128ctx->r128Screen->vbOffset + r128ctx->vb.start); \ - R128CCE(r128ctx->vb.count); \ - R128CCE(R128_TEX1_VERTEX_FORMAT); \ - R128CCE(prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST | \ - (r128ctx->vb.count << R128_CCE_VC_CNTL_NUM_SHIFT)); \ - R128CCE_SUBMIT_PACKETS(); \ - \ - END_CLIP_LOOP(r128ctx); \ - \ - /* Tell the kernel to release the vertex buffer */ \ - do { \ - ret = drmR128FlushVertexBuffers(fd, 1, &index, &size, \ - r128ctx->vb.prim); \ - } while (ret < 0 && ret == -EBUSY && to++ < r128ctx->CCEtimeout); \ - if (ret < 0) { \ - (void)drmR128EngineReset(fd); \ - fprintf(stderr, "Error: Could not flush VB... exiting\n"); \ - exit(-1); \ - } \ - \ - r128ctx->vb.done = GL_TRUE; \ - } while (0) - -/* Flush the vertex buffer (assuming we already hold the lock) */ -#define R128CCE_FLUSH_VB(r128ctx) \ - do { \ - if (r128ctx->vb.count && !r128ctx->vb.done) { \ - /* FIXME: Is this _really_ needed? */ \ - if (!R128CCE_USE_RING_BUFFER(r128ctx->r128Screen->CCEMode)) \ - R128CCE_WAIT_FOR_IDLE(r128ctx); \ - \ - R128CCE_SUBMIT_VB(r128ctx); \ - } \ - } while (0) - -/* Flush the vertex buffer */ -#define R128CCE_FLUSH_VB_LOCK(r128ctx) \ - do { \ - LOCK_HARDWARE(r128ctx); \ - R128CCE_FLUSH_VB(r128ctx); \ - UNLOCK_HARDWARE(r128ctx); \ - } while (0) - -/* Reserve space in a VB to store `n' vertices, and set the pointer `p' - to point to the next vertex in the current VB. If adding these - vertices to the VB would exceed the size of the VB, then flush the - current VB, get a new one from the pool of VBs, reserve space in the - new VB for the `n' vertices, and set the pointer `p' to point to the - first vertex in the new VB. */ -#define R128CCE_ALLOC_VB_SPACE(r128ctx, p, n) \ - do { \ - r128CCEVertBufPtr vb = &r128ctx->vb; \ - \ - if (vb->done) R128CCE_GET_NEW_VB(r128ctx); \ - \ - if (vb->count + (n) > vb->size) { \ - R128CCE_FLUSH_VB_LOCK(r128ctx); \ - R128CCE_GET_NEW_VB(r128ctx); \ - } \ - \ - (p) = (r128_vertex *)vb->buf + vb->count; \ - vb->count += (n); \ - } while (0) - -#endif -#endif /* _R128_CCEVB_H_ */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_clear.c b/xc/lib/GL/mesa/src/drv/r128/r128_clear.c index a5846b280..725b0caef 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_clear.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_clear.c @@ -2,7 +2,7 @@ /************************************************************************** Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., - Cedar Park, Texas. + Cedar Park, Texas. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a @@ -77,7 +77,7 @@ void r128ClearDepthBuffer(r128ContextPtr r128ctx, GLboolean all, LOCK_HARDWARE(r128ctx); /* Flush any outstanding vertex buffers */ - R128CCE_FLUSH_VB(r128ctx); + r128FlushVerticesLocked(r128ctx); /* Init the clip rects here in case they changed during the LOCK_HARDWARE macro */ @@ -149,7 +149,7 @@ void r128ClearDepthBuffer(r128ContextPtr r128ctx, GLboolean all, #endif - R128CCE_SUBMIT_PACKETS(); + R128CCE_SUBMIT_PACKET(); UNLOCK_HARDWARE(r128ctx); } @@ -187,7 +187,7 @@ void r128ClearColorBuffer(r128ContextPtr r128ctx, GLboolean all, LOCK_HARDWARE(r128ctx); /* Flush any outstanding vertex buffers */ - R128CCE_FLUSH_VB(r128ctx); + r128FlushVerticesLocked(r128ctx); /* Init the clip rects here in case they changed during the LOCK_HARDWARE macro */ @@ -249,7 +249,7 @@ void r128ClearColorBuffer(r128ContextPtr r128ctx, GLboolean all, R128_CTX_ALPHASTATE); #endif - R128CCE_SUBMIT_PACKETS(); + R128CCE_SUBMIT_PACKET(); UNLOCK_HARDWARE(r128ctx); } diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_context.c b/xc/lib/GL/mesa/src/drv/r128/r128_context.c index 3d9ba4ddd..9bbab1dc5 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_context.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_context.c @@ -84,12 +84,7 @@ GLboolean r128CreateContext(Display *dpy, GLvisual *glVisual, r128ctx->useFastPath = GL_FALSE; - r128ctx->vb.start = 0; - r128ctx->vb.count = 0; - r128ctx->vb.size = 0; - r128ctx->vb.index = 0; - r128ctx->vb.buf = NULL; - r128ctx->vb.done = GL_TRUE; + r128ctx->vert_buf = NULL; r128ctx->CCEbuf = (CARD32 *)malloc(sizeof(*r128ctx->CCEbuf) * r128scrn->ringEntries); @@ -118,7 +113,10 @@ GLboolean r128CreateContext(Display *dpy, GLvisual *glVisual, r128ctx->Fallback |= R128_FALLBACK_SWONLY; /* KW: No vertex buffer code for PCI cards -- for now fallback to - * software always. + * software always. + * GTH: There is support there, but I'm seeing strange behaviour + * with it enabled. I'll leave the software fallbacks in place + * for now. */ if (r128scrn->IsPCI) r128ctx->Fallback |= R128_FALLBACK_SWONLY; @@ -139,17 +137,17 @@ GLboolean r128CreateContext(Display *dpy, GLvisual *glVisual, /* 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. (Kevin or - * Gareth: Please check these numbers are OK) + * Gareth: Please check these numbers are OK) */ if (r128scrn->texSize[0] < 2*1024*1024) { glCtx->Const.MaxTextureLevels = 9; glCtx->Const.MaxTextureSize = 1<<8; } else if (r128scrn->texSize[0] < 8*1024*1024) { glCtx->Const.MaxTextureLevels = 10; - glCtx->Const.MaxTextureSize = 1<<9; + glCtx->Const.MaxTextureSize = 1<<9; } else { glCtx->Const.MaxTextureLevels = 11; - glCtx->Const.MaxTextureSize = 1<<10; + glCtx->Const.MaxTextureSize = 1<<10; } glCtx->Const.MaxTextureUnits = 2; diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_context.h b/xc/lib/GL/mesa/src/drv/r128/r128_context.h index 6e8b7948c..f362338d5 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_context.h +++ b/xc/lib/GL/mesa/src/drv/r128/r128_context.h @@ -37,9 +37,12 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #ifdef GLX_DIRECT_RENDERING +struct r128_context; +typedef struct r128_context r128ContextRec; +typedef struct r128_context *r128ContextPtr; + #include "r128_texobj.h" #include "r128_fastpath.h" -#include "r128_ccevb.h" /* Flags for what needs to be updated before a new primitive is rendered */ #define R128_CLEAN 0x0000 @@ -138,11 +141,16 @@ typedef struct { CARD32 pc_gui_ctlstat; /* 0x1748 */ } r128ContextRegs; -typedef struct { +struct r128_context { GLcontext *glCtx; /* Mesa context */ int dirty; /* Hardware state to be updated */ int dirty_context; /* Context state to be updated */ + int vertsize; /* Size of current vertices */ + CARD32 vc_format; /* Format of current vertices */ + int multitex; + GLfloat depth_scale; + int SWfallbackDisable; /* Disable software fallbacks */ r128TexObjPtr CurrentTexObj[2]; /* Ptr to current texture @@ -168,7 +176,15 @@ typedef struct { int RenderIndex; /* Render state function index */ r128InterpFunc interp; /* Current vert interp function */ - r128CCEVertBuf vb; /* VB currently being filled */ + drmBufPtr vert_buf; /* VB currently being filled */ + + drmBufPtr elt_buf, retained_buf; + GLushort *first_elt, *next_elt, *last_elt; + GLfloat *next_vert, *last_vert; + CARD32 next_vert_index; + CARD32 first_vert_index; + struct r128_elt_tab *elt_tab; + GLfloat device_matrix[16]; points_func PointsFunc; /* Current Points, Line, Triangle */ line_func LineFunc; /* and Quad rendering functions */ @@ -203,7 +219,7 @@ typedef struct { __DRIdrawablePrivate *driDrawable; /* DRI drawable bound to this ctx */ r128ScreenPtr r128Screen; /* Screen private DRI data */ -} r128ContextRec, *r128ContextPtr; +}; #define R128_MESACTX(r128ctx) ((r128ctx)->glCtx) #define R128_DRIDRAWABLE(r128ctx) ((r128ctx)->driDrawable) diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_dd.c b/xc/lib/GL/mesa/src/drv/r128/r128_dd.c index f76b2e3aa..b621954f4 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_dd.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_dd.c @@ -2,7 +2,7 @@ /************************************************************************** Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., - Cedar Park, Texas. + Cedar Park, Texas. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a @@ -110,7 +110,7 @@ static void r128DDFlush(GLcontext *ctx) { r128ContextPtr r128ctx = R128_CONTEXT(ctx); - R128CCE_FLUSH_VB_LOCK(r128ctx); + r128FlushVertices(r128ctx); } /* Make sure all commands have been sent to the hardware and have @@ -120,7 +120,7 @@ static void r128DDFinish(GLcontext *ctx) r128ContextPtr r128ctx = R128_CONTEXT(ctx); r128DDFlush(ctx); - R128CCE_WAIT_FOR_IDLE_LOCK(r128ctx); + r128WaitForIdle(r128ctx); } /* Return various parameters requested by Mesa (this is deprecated) */ @@ -132,7 +132,7 @@ static GLint r128DDGetParameteri(const GLcontext *ctx, GLint param) * It is less confusing to simply have it never work until it * is actually fixed. */ - case DD_HAVE_HARDWARE_FOG: return 1; + case DD_HAVE_HARDWARE_FOG: return 1; default: return 0; } } diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_fastpath.c b/xc/lib/GL/mesa/src/drv/r128/r128_fastpath.c index 26d8c8a96..cb0568321 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_fastpath.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_fastpath.c @@ -2,7 +2,7 @@ /************************************************************************** Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., - Cedar Park, Texas. + Cedar Park, Texas. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a @@ -45,7 +45,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* FIXME: These routines were copied from the i810 driver, and were only slightly modified for the Rage 128. They still need to be optmizied - and cleaned up. Also, support for USE_RHW2 needs to be added. + and cleaned up. Also, support for USE_RHW2 needs to be added. KW: The fastpath never does projective texturing, so RHW2 support isn't necesary here. @@ -56,9 +56,9 @@ typedef struct r128_fast_table { r128InterpFunc interp; } r128FastPathTable; -#define POINT(x) r128DrawPointVB(r128ctx, &vert[x].v, psize) -#define LINE(x,y) r128DrawLineVB(r128ctx, &vert[x].v, &vert[y].v, lwidth) -#define TRI(x,y,z) r128DrawTriangleVB(r128ctx, &vert[x].v, &vert[y].v, &vert[z].v) +#define POINT(x) r128DrawPointVB(r128ctx, &vert[x], psize) +#define LINE(x,y) r128DrawLineVB(r128ctx, &vert[x], &vert[y], lwidth) +#define TRI(x,y,z) r128DrawTriangleVB(r128ctx, &vert[x], &vert[y], &vert[z]) /* Direct, and no clipping required. The clip funcs have not been written yet, so this is only useful for the fast path. */ @@ -231,7 +231,7 @@ static void r128TriClip(GLuint **p_elts, /* Convert the planar polygon to a list of triangles */ out = inlist[in]; - + for (i = 2 ; i < n ; i++) { elts[0] = out[0]; elts[1] = out[i-1]; @@ -361,10 +361,10 @@ do { \ /* Pack rgba and/or texture into the remaining half of a 32 byte vertex. */ #define CLIP_UBYTE_COLOR 4 -#define CLIP_UBYTE_B 0 -#define CLIP_UBYTE_G 1 +#define CLIP_UBYTE_B 0 +#define CLIP_UBYTE_G 1 #define CLIP_UBYTE_R 2 -#define CLIP_UBYTE_A 3 +#define CLIP_UBYTE_A 3 #define CLIP_S0 6 #define CLIP_T0 7 #define CLIP_S1 8 @@ -409,7 +409,7 @@ static void r128RenderElementsDirect(struct vertex_buffer *VB) GLuint nr = VB->EltPtr->count; render_func func = render_tab_r128_smooth_indirect[prim]; GLuint p = 0; - + if (r128ctx->dirty) r128UpdateHWState(r128ctx); do { @@ -431,17 +431,8 @@ static void r128ProjectVertices(struct vertex_buffer *VB) m[MAT_TX] = mat->m[MAT_TX]; m[MAT_SY] = -mat->m[MAT_SY]; m[MAT_TY] = -mat->m[MAT_TY] + r128ctx->driDrawable->h; - m[MAT_SZ] = mat->m[MAT_SZ]; - m[MAT_TZ] = mat->m[MAT_TZ]; - - /* KW: Please precalculate this scale: - */ - switch (ctx->Visual->DepthBits) { - case 16: m[MAT_SZ] /= 65536.0; m[MAT_TZ] /= 65536.0; break; - case 24: m[MAT_SZ] /= 16777216.0; m[MAT_TZ] /= 16777216.0; break; - case 32: m[MAT_SZ] /= 4294967296.0; m[MAT_TZ] /= 4294967296.0; break; - default: m[MAT_SZ] /= 65536.0; m[MAT_TZ] /= 65536.0; break; - } + m[MAT_SZ] = mat->m[MAT_SZ] * r128ctx->depth_scale; + m[MAT_TZ] = mat->m[MAT_TZ] * r128ctx->depth_scale; gl_project_v16(r128VB->verts[VB->CopyStart].f, r128VB->verts[r128VB->last_vert].f, @@ -462,15 +453,8 @@ static void r128ProjectClippedVertices(struct vertex_buffer *VB) m[MAT_TX] = mat->m[MAT_TX]; m[MAT_SY] = -mat->m[MAT_SY]; m[MAT_TY] = -mat->m[MAT_TY] + r128ctx->driDrawable->h; - m[MAT_SZ] = mat->m[MAT_SZ]; - m[MAT_TZ] = mat->m[MAT_TZ]; - - switch (ctx->Visual->DepthBits) { - case 16: m[MAT_SZ] /= 65536.0; m[MAT_TZ] /= 65536.0; break; - case 24: m[MAT_SZ] /= 16777216.0; m[MAT_TZ] /= 16777216.0; break; - case 32: m[MAT_SZ] /= 4294967296.0; m[MAT_TZ] /= 4294967296.0; break; - default: m[MAT_SZ] /= 65536.0; m[MAT_TZ] /= 65536.0; break; - } + m[MAT_SZ] = mat->m[MAT_SZ] * r128ctx->depth_scale; + m[MAT_TZ] = mat->m[MAT_TZ] * r128ctx->depth_scale; gl_project_clipped_v16(r128VB->verts[VB->CopyStart].f, r128VB->verts[r128VB->last_vert].f, diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_init.h b/xc/lib/GL/mesa/src/drv/r128/r128_init.h index a091a437e..2d58242a9 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_init.h +++ b/xc/lib/GL/mesa/src/drv/r128/r128_init.h @@ -63,6 +63,12 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. extern int R128_DEBUG_FLAGS; +#else + +#define R128_DEBUG_FLAGS 0 + +#endif + #define DEBUG_VERBOSE_2D 0x0001 #define DEBUG_VERBOSE_CCE 0x0008 #define DEBUG_VERBOSE_OUTREG 0x0010 @@ -76,11 +82,5 @@ extern int R128_DEBUG_FLAGS; #define DEBUG_VERBOSE_DRI 0x2000 #define DEBUG_VERBOSE_IOCTL 0x4000 -#else - -#define R128_DEBUG_FLAGS 0 - -#endif - #endif #endif /* _R128_INIT_H_ */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_lock.h b/xc/lib/GL/mesa/src/drv/r128/r128_lock.h new file mode 100644 index 000000000..91a65c210 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_lock.h @@ -0,0 +1,134 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., + Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +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, PRECISION INSIGHT 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 <kevin@precisioninsight.com> + * + */ + +#ifndef _R128_LOCK_H_ +#define _R128_LOCK_H_ + +#ifdef GLX_DIRECT_RENDERING + +/* Turn DEBUG_LOCKING on to find locking conflicts (see r128_init.h) */ +#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 using the current context */ +#define LOCK_HARDWARE(CC) \ + do { \ + char __ret = 0; \ + __DRIcontextPrivate *cPriv = CC->driContext; \ + __DRIscreenPrivate *sPriv = CC->r128Screen->driScreen; \ + \ + DEBUG_CHECK_LOCK(); \ + DRM_CAS(&sPriv->pSAREA->lock, cPriv->hHWContext, \ + DRM_LOCK_HELD|cPriv->hHWContext, __ret); \ + if (__ret) { \ + /* We lost the context, so we need to request the lock from \ + the kernel and update our state. */ \ + drmGetLock(sPriv->fd, cPriv->hHWContext, 0); \ + XMesaUpdateState(cPriv); \ + } \ + DEBUG_LOCK(); \ + } while (0) + +/* Unlock the hardware using the current context */ +#define UNLOCK_HARDWARE(CC) \ + do { \ + __DRIcontextPrivate *cPriv = CC->driContext; \ + __DRIscreenPrivate *sPriv = CC->r128Screen->driScreen; \ + \ + DRM_UNLOCK(sPriv->fd, &sPriv->pSAREA->lock, cPriv->hHWContext); \ + DEBUG_RESET(); \ + } while (0) + +/* + * This pair of macros makes a loop over the drawing operations, so it + * is not self contained and does not have the nice single statement + * semantics of most macros. + */ +#define BEGIN_CLIP_LOOP(CC) \ + do { \ + __DRIdrawablePrivate *_dPriv = CC->driDrawable; \ + XF86DRIClipRectPtr _pc = _dPriv->pClipRects; \ + int _nc, _sc; \ + \ + for (_nc = _dPriv->numClipRects; _nc > 0; _nc -= 3, _pc += 3) { \ + _sc = (_nc <= 3) ? _nc : 3; \ + r128SetClipRects(CC, _pc, _sc) + +/* FIXME: This should be a function call to turn off aux clipping */ +#define END_CLIP_LOOP(CC) \ + R128CCE0(R128_CCE_PACKET0, R128_AUX_SC_CNTL, 0); \ + R128CCE(0x00000000); \ + R128CCE_SUBMIT_PACKET(); \ + } \ + } while (0) + +#endif +#endif /* _R128_LOCK_H_ */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_screen.c b/xc/lib/GL/mesa/src/drv/r128/r128_screen.c index b385271f4..3f2f0a17f 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_screen.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_screen.c @@ -2,7 +2,7 @@ /************************************************************************** Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., - Cedar Park, Texas. + Cedar Park, Texas. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a @@ -229,6 +229,8 @@ r128ScreenPtr r128CreateScreen(__DRIscreenPrivate *sPriv) r128Screen->driScreen = sPriv; + r128InitVertexBuffers(r128Screen); + r128FastPathInit(); r128TriangleFuncsInit(); r128SetupInit(); diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_span.c b/xc/lib/GL/mesa/src/drv/r128/r128_span.c index 5aa0ed6d1..97e70b1c3 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_span.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_span.c @@ -2,7 +2,7 @@ /************************************************************************** Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., - Cedar Park, Texas. + Cedar Park, Texas. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a @@ -95,7 +95,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define HW_LOCK() \ r128ContextPtr r128ctx = R128_CONTEXT(ctx); \ LOCK_HARDWARE(r128ctx); \ - R128CCE_WAIT_FOR_IDLE(r128ctx); + r128WaitForIdleLocked(r128ctx); #define HW_CLIPLOOP() \ do { \ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_state.c b/xc/lib/GL/mesa/src/drv/r128/r128_state.c index 66835cbce..981874493 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_state.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_state.c @@ -110,7 +110,7 @@ static void r128DDReducedPrimitiveChange(GLcontext *ctx, GLenum prim) f |= R128_BACKFACE_SOLID | R128_FRONTFACE_SOLID; - /* Should really use an intermediate value to hold this rather + /* Should really use an intermediate value to hold this rather * than recalculating all the time. */ if (prim == GL_POLYGON && ctx->Polygon.CullFlag) { @@ -124,7 +124,7 @@ static void r128DDReducedPrimitiveChange(GLcontext *ctx, GLenum prim) } if (r128ctx->regs.pm4_vc_fpu_setup != f) { - R128CCE_FLUSH_VB_LOCK(r128ctx); + r128FlushVertices(r128ctx); r128ctx->regs.pm4_vc_fpu_setup = f; /* FIXME: Load into hardware now??? */ @@ -133,7 +133,7 @@ static void r128DDReducedPrimitiveChange(GLcontext *ctx, GLenum prim) } } -static void r128DDClearColor(GLcontext *ctx, +static void r128DDClearColor(GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a) { r128ContextPtr r128ctx = R128_CONTEXT(ctx); @@ -179,7 +179,8 @@ static GLboolean r128DDSetDrawBuffer(GLcontext *ctx, GLenum mode) x += r128ctx->drawX; y += r128ctx->drawY; - R128CCE_FLUSH_VB_LOCK(r128ctx); + r128FlushVertices(r128ctx); + r128ctx->regs.window_xy_offset = ((y << R128_WINDOW_Y_SHIFT) | (x << R128_WINDOW_X_SHIFT)); @@ -234,7 +235,7 @@ static GLboolean r128DDColorMask(GLcontext *ctx, ctx->Color.ColorMask[ACOMP]); if (r128ctx->regs.plane_3d_mask_c != mask) { - R128CCE_FLUSH_VB_LOCK(r128ctx); + r128FlushVertices(r128ctx); r128ctx->regs.plane_3d_mask_c = mask; /* FIXME: Load into hardware now??? */ @@ -274,7 +275,7 @@ static void r128DDAlphaFunc(GLcontext *ctx, GLenum func, GLclampf ref) } if (r128ctx->regs.misc_3d_state_cntl_reg != a) { - R128CCE_FLUSH_VB_LOCK(r128ctx); + r128FlushVertices(r128ctx); r128ctx->regs.misc_3d_state_cntl_reg = a; /* FIXME: Load into hardware now??? */ @@ -363,7 +364,7 @@ static void r128DDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor) } if (r128ctx->regs.misc_3d_state_cntl_reg != b) { - R128CCE_FLUSH_VB_LOCK(r128ctx); + r128FlushVertices(r128ctx); r128ctx->regs.misc_3d_state_cntl_reg = b; /* FIXME: Load into hardware now??? */ @@ -413,7 +414,7 @@ static void r128DDCullFace(GLcontext *ctx, GLenum mode) } if (r128ctx->regs.pm4_vc_fpu_setup != f) { - R128CCE_FLUSH_VB_LOCK(r128ctx); + r128FlushVertices(r128ctx); r128ctx->regs.pm4_vc_fpu_setup = f; /* FIXME: Load into hardware now??? */ @@ -436,7 +437,7 @@ static void r128DDFrontFace(GLcontext *ctx, GLenum mode) } if (r128ctx->regs.pm4_vc_fpu_setup != f) { - R128CCE_FLUSH_VB_LOCK(r128ctx); + r128FlushVertices(r128ctx); r128ctx->regs.pm4_vc_fpu_setup = f; /* FIXME: Load into hardware now??? */ @@ -465,7 +466,7 @@ static void r128DDDepthFunc(GLcontext *ctx, GLenum func) } if (r128ctx->regs.z_sten_cntl_c != z) { - R128CCE_FLUSH_VB_LOCK(r128ctx); + r128FlushVertices(r128ctx); r128ctx->regs.z_sten_cntl_c = z; /* FIXME: Load into hardware now??? */ @@ -483,7 +484,7 @@ static void r128DDDepthMask(GLcontext *ctx, GLboolean flag) else t &= ~R128_Z_WRITE_ENABLE; if (r128ctx->regs.tex_cntl_c != t) { - R128CCE_FLUSH_VB_LOCK(r128ctx); + r128FlushVertices(r128ctx); r128ctx->regs.tex_cntl_c = t; /* FIXME: Load into hardware now??? */ @@ -492,21 +493,21 @@ static void r128DDDepthMask(GLcontext *ctx, GLboolean flag) } } -static void r128DDLightModelfv(GLcontext *ctx, GLenum pname, +static void r128DDLightModelfv(GLcontext *ctx, GLenum pname, const GLfloat *param) { - if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) - { + if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) + { r128ContextPtr r128ctx = R128_CONTEXT( ctx ); CARD32 t = r128ctx->regs.tex_cntl_c; if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) t |= R128_SPEC_LIGHT_ENABLE; - else + else t &= ~R128_SPEC_LIGHT_ENABLE; - + if (r128ctx->regs.tex_cntl_c != t) { - R128CCE_FLUSH_VB_LOCK(r128ctx); + r128FlushVertices(r128ctx); r128ctx->regs.tex_cntl_c = t; /* FIXME: Load into hardware now??? */ @@ -654,7 +655,7 @@ static void r128DDEnable(GLcontext *ctx, GLenum cap, GLboolean state) } if (r128ctx->regs.tex_cntl_c != t) { - R128CCE_FLUSH_VB_LOCK(r128ctx); + r128FlushVertices(r128ctx); r128ctx->regs.tex_cntl_c = t; /* FIXME: Load into hardware now??? */ @@ -662,7 +663,7 @@ static void r128DDEnable(GLcontext *ctx, GLenum cap, GLboolean state) r128ctx->dirty_context |= R128_CTX_ENGINESTATE; } if (r128ctx->regs.pm4_vc_fpu_setup != f) { - R128CCE_FLUSH_VB_LOCK(r128ctx); + r128FlushVertices(r128ctx); r128ctx->regs.pm4_vc_fpu_setup = f; /* FIXME: Load into hardware now??? */ @@ -688,7 +689,7 @@ static void r128DDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param) case GL_FOG_MODE: mode = (GLenum)(GLint)*param; if (r128ctx->FogMode != mode) { - R128CCE_FLUSH_VB_LOCK(r128ctx); + r128FlushVertices(r128ctx); r128ctx->FogMode = mode; /* FIXME: Load into hardware now??? */ @@ -700,7 +701,7 @@ static void r128DDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param) case GL_FOG_DENSITY: fog.f = *param; if (r128ctx->regs.fog_3d_table_density != fog.i) { - R128CCE_FLUSH_VB_LOCK(r128ctx); + r128FlushVertices(r128ctx); r128ctx->regs.fog_3d_table_density = fog.i; /* FIXME: Load into hardware now??? */ @@ -712,7 +713,7 @@ static void r128DDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param) case GL_FOG_START: fog.f = *param; if (r128ctx->regs.fog_3d_table_start != fog.i) { - R128CCE_FLUSH_VB_LOCK(r128ctx); + r128FlushVertices(r128ctx); r128ctx->regs.fog_3d_table_start = fog.i; /* FIXME: Load into hardware now??? */ @@ -724,7 +725,7 @@ static void r128DDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param) case GL_FOG_END: fog.f = *param; if (r128ctx->regs.fog_3d_table_end != fog.i) { - R128CCE_FLUSH_VB_LOCK(r128ctx); + r128FlushVertices(r128ctx); r128ctx->regs.fog_3d_table_end = fog.i; /* FIXME: Load into hardware now??? */ @@ -737,7 +738,7 @@ static void r128DDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param) FLOAT_RGBA_TO_UBYTE_RGBA(c, ctx->Fog.Color); col = r128PackColor(32, c[0], c[1], c[2], c[3]); if (r128ctx->regs.fog_color_c != col) { - R128CCE_FLUSH_VB_LOCK(r128ctx); + r128FlushVertices(r128ctx); r128ctx->regs.fog_color_c = col; /* FIXME: Load into hardware now??? */ @@ -849,6 +850,14 @@ void r128DDInitState(r128ContextPtr r128ctx) break; } + /* Precalculate the depth scale while we're here */ + switch (r128ctx->glCtx->Visual->DepthBits) { + case 16: r128ctx->depth_scale = 1.0 / 65536.0; break; + case 24: r128ctx->depth_scale = 1.0 / 16777216.0; break; + case 32: r128ctx->depth_scale = 1.0 / 4294967296.0; break; + default: r128ctx->depth_scale = 1.0 / 65536.0; break; + } + r128ctx->dirty = R128_ALL_DIRTY; r128ctx->dirty_context = R128_CTX_ALL_DIRTY; @@ -1069,15 +1078,15 @@ static void r128UploadFogTable(r128ContextPtr r128ctx) R128CCE0(R128_CCE_PACKET0_ONE_REG_WR, R128_FOG_TABLE_DATA, 255); - if (0) - fprintf(stderr, "uploading fog table for %s\n", + if (0) + fprintf(stderr, "uploading fog table for %s\n", gl_lookup_enum_by_nr(r128ctx->FogMode)); /* KW: I'm not sure we're doing enough here - shouldn't density * play a role in calculating the exp and exp2 tables -- is the * card really doing exponent calculations of its own? Need to - * see the spec... + * see the spec... */ switch (r128ctx->FogMode) { case GL_LINEAR: @@ -1132,7 +1141,7 @@ static void r128LoadContext(r128ContextPtr r128ctx) /* FIXME: Is this _really_ needed? */ if (r128ctx->dirty_context) if (!R128CCE_USE_RING_BUFFER(r128ctx->r128Screen->CCEMode)) - R128CCE_WAIT_FOR_IDLE(r128ctx); + r128WaitForIdleLocked(r128ctx); #endif if (r128ctx->dirty_context & R128_CTX_MISC) { @@ -1247,7 +1256,7 @@ static void r128LoadContext(r128ContextPtr r128ctx) } #endif - R128CCE_SUBMIT_PACKETS(); + R128CCE_SUBMIT_PACKET(); /* Turn off the texture cache flushing */ r128ctx->regs.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH; @@ -1304,7 +1313,7 @@ void r128SetClipRects(r128ContextPtr r128ctx, R128CCE0(R128_CCE_PACKET0, R128_AUX_SC_CNTL, 0); R128CCE(r128ctx->regs.aux_sc_cntl); - R128CCE_SUBMIT_PACKETS(); + R128CCE_SUBMIT_PACKET(); } /* Update the driver's notion of the window position */ @@ -1340,7 +1349,7 @@ static void r128UpdateWindowPosition(r128ContextPtr r128ctx) static void r128UpdateHWStateLocked(r128ContextPtr r128ctx) { if (r128ctx->dirty & R128_REQUIRE_QUIESCENCE) - R128CCE_WAIT_FOR_IDLE(r128ctx); + r128WaitForIdleLocked(r128ctx); /* Update any state that might have changed recently */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_swap.c b/xc/lib/GL/mesa/src/drv/r128/r128_swap.c index 4effcf9fa..d6467970e 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_swap.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_swap.c @@ -2,7 +2,7 @@ /************************************************************************** Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., - Cedar Park, Texas. + Cedar Park, Texas. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a @@ -43,6 +43,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r128_vb.h" #include "r128_swap.h" +static void delay(void) { + /* stop the compiler from optimizing our spin loop away */ +} + /* Copy the back color buffer to the front color buffer */ void r128SwapBuffers(r128ContextPtr r128ctx) { @@ -52,6 +56,7 @@ void r128SwapBuffers(r128ContextPtr r128ctx) XF86DRIClipRectPtr c; int dst_bpp; CARD32 swapAge; + int i, to = 0; switch (r128ctx->r128Screen->bpp) { case 8: @@ -73,11 +78,15 @@ void r128SwapBuffers(r128ContextPtr r128ctx) LOCK_HARDWARE(r128ctx); /* Flush any outstanding vertex buffers */ - R128CCE_FLUSH_VB(r128ctx); + r128FlushVerticesLocked(r128ctx); /* Throttle the frame rate -- only allow one pending swap buffers request at a time */ - while (r128ctx->lastSwapAge > (swapAge = INREG(R128_SWAP_AGE_REG))); + while ((r128ctx->lastSwapAge > (swapAge = INREG(R128_SWAP_AGE_REG))) && + (to++ < r128ctx->CCEtimeout)) { + /* Don't just sit here hammering the register */ + for (i = 0; i < 1000; i++) delay(); + } /* Init the clip rects here in case they changed during the LOCK_HARDWARE macro */ @@ -118,7 +127,7 @@ void r128SwapBuffers(r128ContextPtr r128ctx) R128_CTX_ENGINESTATE | R128_CTX_ALPHASTATE); - R128CCE_SUBMIT_PACKETS(); + R128CCE_SUBMIT_PACKET(); UNLOCK_HARDWARE(r128ctx); } diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_tex.c b/xc/lib/GL/mesa/src/drv/r128/r128_tex.c index 47c1c30f2..51f282462 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_tex.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_tex.c @@ -318,7 +318,7 @@ static void r128TexturesGone(r128ContextPtr r128ctx, int heap, int offset, int size, int in_use) { r128TexObjPtr t, tmp; - + foreach_s (t, tmp, &r128ctx->TexObjList[heap]) { if (t->memBlock->ofs >= offset + size || t->memBlock->ofs + t->memBlock->size <= offset) @@ -714,7 +714,7 @@ static void r128UploadSubImage(r128ContextPtr r128ctx, R128CCE(r128ctx->regs.pc_gui_ctlstat | R128_PC_RI_GUI | R128_PC_FLUSH_GUI); - R128CCE_SUBMIT_PACKETS(); + R128CCE_SUBMIT_PACKET(); /* Build the CCE host data blit header */ R128CCE3(R128_CCE_PACKET3_CNTL_HOSTDATA_BLT, 0); @@ -776,10 +776,10 @@ static void r128UploadSubImage(r128ContextPtr r128ctx, R128CCE(r128ctx->regs.pc_gui_ctlstat | R128_PC_FLUSH_GUI); /* Save the partial blit header */ - R128CCE_SUBMIT_PACKETS(); + R128CCE_SUBMIT_PACKET(); r128ctx->CCEcount = 5; } - + /* Clean up CCE ring buffer */ r128ctx->CCEcount = 0; } @@ -887,7 +887,7 @@ int r128UploadTexImages(r128ContextPtr r128ctx, r128TexObjPtr t) r128ctx->regs.sec_tex_offset[i] = (CARD32)t->bufAddr; } else { for (i = maxLevel; i >= minLevel; i--) - r128ctx->regs.sec_tex_offset[i] = + r128ctx->regs.sec_tex_offset[i] = t->image[maxLevel-i].offset + (CARD32)t->bufAddr; } /* Fix AGP texture offsets */ @@ -959,6 +959,8 @@ static void r128UpdateTex0State(r128ContextPtr r128ctx) return; } + r128ctx->regs.scale_3d_cntl &= ~R128_TEX_CACHE_SPLIT; + /* If this is the first time the texture has been used, then create a new texture object for it. */ t = tObj->DriverData; @@ -1244,7 +1246,7 @@ static void r128UpdateTex0State(r128ContextPtr r128ctx) int minLevel = ((t->regs.size_pitch & R128_TEX_MIN_SIZE_MASK) >> R128_TEX_MIN_SIZE_SHIFT); for (i = maxLevel; i >= minLevel; i--) - r128ctx->regs.prim_tex_offset[i] = + r128ctx->regs.prim_tex_offset[i] = t->image[maxLevel-i].offset + (CARD32)t->bufAddr; } /* Fix AGP texture offsets */ @@ -1281,6 +1283,9 @@ static void r128UpdateTex1State(r128ContextPtr r128ctx) return; } + /* If te1 is enabled, split the texel cache */ + r128ctx->regs.scale_3d_cntl |= R128_TEX_CACHE_SPLIT; + /* If this is the first time the texture has been used, then create a new texture object for it. */ t = tObj->DriverData; @@ -1558,7 +1563,7 @@ static void r128UpdateTex1State(r128ContextPtr r128ctx) int minLevel = ((t->regs.size_pitch & R128_TEX_MIN_SIZE_MASK) >> R128_TEX_MIN_SIZE_SHIFT); for (i = maxLevel; i >= minLevel; i--) - r128ctx->regs.sec_tex_offset[i] = + r128ctx->regs.sec_tex_offset[i] = t->image[maxLevel-i].offset + (CARD32)t->bufAddr; } /* Fix AGP texture offsets */ @@ -1585,7 +1590,7 @@ void r128UpdateTextureState(r128ContextPtr r128ctx) r128ctx->CurrentTexObj[0] = NULL; r128ctx->CurrentTexObj[1] = NULL; - if (r128ctx->glCtx->Enabled & (TEXTURE0_3D|TEXTURE1_3D)) + if (r128ctx->glCtx->Enabled & (TEXTURE0_3D|TEXTURE1_3D)) r128ctx->Fallback |= R128_FALLBACK_TEXTURE; /* Update the texture unit 0/1 state */ @@ -1662,13 +1667,13 @@ static void r128DDTexEnv(GLcontext *ctx, GLenum target, GLenum pname, struct gl_texture_unit *texUnit; GLubyte c[4]; CARD32 col; - + /* FIXME: Add texture LOD bias extension */ switch (pname) { case GL_TEXTURE_ENV_MODE: /* TexEnv modes are handled in UpdateTextureState */ - R128CCE_FLUSH_VB_LOCK(r128ctx); + r128FlushVertices(r128ctx); r128ctx->dirty |= R128_UPDATE_TEXSTATE; break; case GL_TEXTURE_ENV_COLOR: @@ -1676,7 +1681,7 @@ static void r128DDTexEnv(GLcontext *ctx, GLenum target, GLenum pname, FLOAT_RGBA_TO_UBYTE_RGBA(texUnit->EnvColor, c); col = r128PackColor(32, c[0], c[1], c[2], c[3]); if (r128ctx->regs.constant_color_c != col) { - R128CCE_FLUSH_VB_LOCK(r128ctx); + r128FlushVertices(r128ctx); r128ctx->regs.constant_color_c = col; /* FIXME: Load into hardware now??? */ @@ -1706,7 +1711,7 @@ static void r128DDTexImage(GLcontext *ctx, GLenum target, t = (r128TexObjPtr)tObj->DriverData; if (t) { - if (t->bound) R128CCE_FLUSH_VB_LOCK(r128ctx); + if (t->bound) r128FlushVertices(r128ctx); /* Destroy the old texture, and upload a new one. The actual uploading of the texture image occurs in the UploadSubImage @@ -1737,7 +1742,7 @@ static void r128DDTexSubImage(GLcontext *ctx, GLenum target, t = (r128TexObjPtr)tObj->DriverData; if (t) { - if (t->bound) R128CCE_FLUSH_VB_LOCK(r128ctx); + if (t->bound) r128FlushVertices(r128ctx); LOCK_HARDWARE(r128ctx); r128UploadSubImage(r128ctx, t, level, @@ -1769,18 +1774,18 @@ static void r128DDTexParameter(GLcontext *ctx, GLenum target, switch (pname) { case GL_TEXTURE_MIN_FILTER: case GL_TEXTURE_MAG_FILTER: - if (t->bound) R128CCE_FLUSH_VB_LOCK(r128ctx); + if (t->bound) r128FlushVertices(r128ctx); r128SetTexFilter(t, tObj->MinFilter, tObj->MagFilter); break; case GL_TEXTURE_WRAP_S: case GL_TEXTURE_WRAP_T: - if (t->bound) R128CCE_FLUSH_VB_LOCK(r128ctx); + if (t->bound) r128FlushVertices(r128ctx); r128SetTexWrap(t, tObj->WrapS, tObj->WrapT); break; - + case GL_TEXTURE_BORDER_COLOR: - if (t->bound) R128CCE_FLUSH_VB_LOCK(r128ctx); + if (t->bound) r128FlushVertices(r128ctx); r128SetTexBorderColor(t, tObj->BorderColor); break; @@ -1797,7 +1802,7 @@ static void r128DDBindTexture(GLcontext *ctx, GLenum target, { r128ContextPtr r128ctx = R128_CONTEXT(ctx); - R128CCE_FLUSH_VB_LOCK(r128ctx); + r128FlushVertices(r128ctx); /* Unbind the old texture */ if (r128ctx->CurrentTexObj[ctx->Texture.CurrentUnit]) { @@ -1818,7 +1823,7 @@ static void r128DDDeleteTexture(GLcontext *ctx, if (t) { if (t->bound) { - R128CCE_FLUSH_VB_LOCK(r128ctx); + r128FlushVertices(r128ctx); r128ctx->CurrentTexObj[t->bound-1] = 0; r128ctx->dirty |= R128_UPDATE_TEXSTATE; @@ -1831,7 +1836,7 @@ static void r128DDDeleteTexture(GLcontext *ctx, /* Determine if a texture is currently residing in either AGP/local texture memory */ -static GLboolean r128DDIsTextureResident(GLcontext *ctx, +static GLboolean r128DDIsTextureResident(GLcontext *ctx, struct gl_texture_object *tObj) { r128TexObjPtr t = (r128TexObjPtr)tObj->DriverData; diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_tris.c b/xc/lib/GL/mesa/src/drv/r128/r128_tris.c index e30b2d304..00bbe948e 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_tris.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_tris.c @@ -1,4 +1,4 @@ -/* $XFree86$ */ +/* $XFree86$ */ /* -*- c-basic-offset: 4 -*- */ /************************************************************************** Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., @@ -43,74 +43,137 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r128_tris.h" #include "r128_state.h" -static triangle_func tri_tab[0x10]; -static quad_func quad_tab[0x10]; -static line_func line_tab[0x10]; +static triangle_func tri_tab[0x10]; +static quad_func quad_tab[0x10]; +static line_func line_tab[0x10]; static points_func points_tab[0x10]; /* Draw a triangle from the vertices in the vertex buffer */ -void r128DrawTriangleVB(r128ContextPtr r128ctx, - r128_vertex *v0, - r128_vertex *v1, - r128_vertex *v2) +__inline void r128DrawTriangleVB(r128ContextPtr r128ctx, + r128Vertex *v0, + r128Vertex *v1, + r128Vertex *v2) { - r128_vertex *vbptr; + int vertsize = r128ctx->vertsize; + CARD32 *vb = r128AllocVertexDwords( r128ctx, 3 * vertsize ); + int j; - R128CCE_ALLOC_VB_SPACE(r128ctx, vbptr, 3); + for (j = 0 ; j < vertsize ; j++) + vb[j] = v0->ui[j]; - *vbptr++ = *v0; - *vbptr++ = *v1; - *vbptr++ = *v2; + vb += vertsize; + for (j = 0 ; j < vertsize ; j++) + vb[j] = v1->ui[j]; + + vb += vertsize; + for (j = 0 ; j < vertsize ; j++) + vb[j] = v2->ui[j]; } /* Draw a line from the vertices in the vertex buffer */ -void r128DrawLineVB(r128ContextPtr r128ctx, - r128_vertex *v0, r128_vertex *v1, - float width) +__inline void r128DrawLineVB( r128ContextPtr r128ctx, + r128Vertex *tmp0, + r128Vertex *tmp1, + float width ) { - float dx, dy, ix, iy; - r128_vertex *vbptr; + int vertsize = r128ctx->vertsize; + CARD32 *vb = r128AllocVertexDwords( r128ctx, 6 * vertsize ); + float dx, dy, ix, iy; + int j; - /* FIXME: Use r128's line primitive for width 1 lines */ + dx = tmp0->vert1.x - tmp1->vert1.x; + dy = tmp0->vert1.y - tmp1->vert1.y; - R128CCE_ALLOC_VB_SPACE(r128ctx, vbptr, 6); + ix = width * .5; iy = 0; - dx = v0->x - v1->x; - dy = v0->y - v1->y; + if ((ix<.5) && (ix>0.1)) ix = .5; /* I want to see lines with width + 0.5 also */ - ix = width * 0.5; iy = 0; - if (dx*dx > dy*dy) { - iy = ix; ix = 0; + if (dx * dx > dy * dy) { + iy = ix; ix = 0; } - *vbptr = *v0; vbptr->x = v0->x - ix; vbptr->y = v0->y - iy; - *++vbptr = *v1; vbptr->x = v1->x + ix; vbptr->y = v1->y + iy; - *++vbptr = *v0; vbptr->x = v0->x + ix; vbptr->y = v0->y + iy; - *++vbptr = *v0; vbptr->x = v0->x - ix; vbptr->y = v0->y - iy; - *++vbptr = *v1; vbptr->x = v1->x - ix; vbptr->y = v1->y - iy; - *++vbptr = *v1; vbptr->x = v1->x + ix; vbptr->y = v1->y + iy; + *(float *)&vb[0] = tmp0->vert1.x - ix; + *(float *)&vb[1] = tmp0->vert1.y - iy; + for (j = 2 ; j < vertsize ; j++) + vb[j] = tmp0->ui[j]; + vb += vertsize; + + *(float *)&vb[0] = tmp1->vert1.x + ix; + *(float *)&vb[1] = tmp1->vert1.y + iy; + for (j = 2 ; j < vertsize ; j++) + vb[j] = tmp1->ui[j]; + vb += vertsize; + + *(float *)&vb[0] = tmp0->vert1.x + ix; + *(float *)&vb[1] = tmp0->vert1.y + iy; + for (j = 2 ; j < vertsize ; j++) + vb[j] = tmp0->ui[j]; + vb += vertsize; + + *(float *)&vb[0] = tmp0->vert1.x - ix; + *(float *)&vb[1] = tmp0->vert1.y - iy; + for (j = 2 ; j < vertsize ; j++) + vb[j] = tmp0->ui[j]; + vb += vertsize; + + *(float *)&vb[0] = tmp1->vert1.x - ix; + *(float *)&vb[1] = tmp1->vert1.y - iy; + for (j = 2 ; j < vertsize ; j++) + vb[j] = tmp1->ui[j]; + vb += vertsize; + + *(float *)&vb[0] = tmp1->vert1.x + ix; + *(float *)&vb[1] = tmp1->vert1.y + iy; + for (j = 2 ; j < vertsize ; j++) + vb[j] = tmp1->ui[j]; } /* Draw a point from the vertices in the vertex buffer */ -void r128DrawPointVB(r128ContextPtr r128ctx, - r128_vertex *v0, float size) +__inline void r128DrawPointVB( r128ContextPtr r128ctx, + r128Vertex *tmp, float sz ) { - r128_vertex *vbptr; - - /* FIXME: Use r128's point primitive for diameter 1 points */ - - R128CCE_ALLOC_VB_SPACE(r128ctx, vbptr, 6); - - *vbptr = *v0; vbptr->x = v0->x - size; vbptr->y = v0->y - size; - *++vbptr = *v0; vbptr->x = v0->x + size; vbptr->y = v0->y - size; - *++vbptr = *v0; vbptr->x = v0->x + size; vbptr->y = v0->y + size; - *++vbptr = *v0; vbptr->x = v0->x + size; vbptr->y = v0->y + size; - *++vbptr = *v0; vbptr->x = v0->x - size; vbptr->y = v0->y + size; - *++vbptr = *v0; vbptr->x = v0->x - size; vbptr->y = v0->y - size; + int vertsize = r128ctx->vertsize; + CARD32 *vb = r128AllocVertexDwords( r128ctx, 6 * vertsize ); + int j; + + *(float *)&vb[0] = tmp->vert1.x - sz; + *(float *)&vb[1] = tmp->vert1.y - sz; + for (j = 2 ; j < vertsize ; j++) + vb[j] = tmp->ui[j]; + vb += vertsize; + + *(float *)&vb[0] = tmp->vert1.x + sz; + *(float *)&vb[1] = tmp->vert1.y - sz; + for (j = 2 ; j < vertsize ; j++) + vb[j] = tmp->ui[j]; + vb += vertsize; + + *(float *)&vb[0] = tmp->vert1.x + sz; + *(float *)&vb[1] = tmp->vert1.y + sz; + for (j = 2 ; j < vertsize ; j++) + vb[j] = tmp->ui[j]; + vb += vertsize; + + *(float *)&vb[0] = tmp->vert1.x + sz; + *(float *)&vb[1] = tmp->vert1.y + sz; + for (j = 2 ; j < vertsize ; j++) + vb[j] = tmp->ui[j]; + vb += vertsize; + + *(float *)&vb[0] = tmp->vert1.x - sz; + *(float *)&vb[1] = tmp->vert1.y + sz; + for (j = 2 ; j < vertsize ; j++) + vb[j] = tmp->ui[j]; + vb += vertsize; + + *(float *)&vb[0] = tmp->vert1.x - sz; + *(float *)&vb[1] = tmp->vert1.y - sz; + for (j = 2 ; j < vertsize ; j++) + vb[j] = tmp->ui[j]; } - #define R128_COLOR(to, from) \ do { \ (to)[0] = (from)[2]; \ @@ -172,9 +235,9 @@ void r128ChooseRenderState(GLcontext *ctx) r128ContextPtr r128ctx = R128_CONTEXT(ctx); GLuint flags = ctx->TriangleCaps; - /* KW: Includes handling of SWonly rendering: + /* KW: Includes handling of SWonly rendering: */ - if (r128ctx->Fallback) + if (r128ctx->Fallback) return; r128ctx->IndirectTriangles = 0; @@ -183,20 +246,20 @@ void r128ChooseRenderState(GLcontext *ctx) CARD32 index = 0; CARD32 shared = 0; CARD32 fallback = R128_FALLBACK_BIT; - + /* KW: I'd prefer to remove SWfallbackDisable & just use * R128_FALLBACK_BIT throughout this routine. */ - if (r128ctx->SWfallbackDisable) fallback = 0; + if (r128ctx->SWfallbackDisable) fallback = 0; if (flags & DD_FLATSHADE) shared |= R128_FLAT_BIT; if (flags & DD_TRI_LIGHT_TWOSIDE) shared |= R128_TWOSIDE_BIT; /* TODO: Fix mesa so that these can be handled in - * r128ctx->Fallback. + * r128ctx->Fallback. */ if (flags & (DD_MULTIDRAW | - DD_SELECT | + DD_SELECT | DD_FEEDBACK)) shared |= R128_FALLBACK_BIT; /* Setup PointFunc */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_tris.h b/xc/lib/GL/mesa/src/drv/r128/r128_tris.h index 2640d0c8f..4a7a0736e 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_tris.h +++ b/xc/lib/GL/mesa/src/drv/r128/r128_tris.h @@ -2,7 +2,7 @@ /************************************************************************** Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., - Cedar Park, Texas. + Cedar Park, Texas. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a @@ -44,15 +44,15 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define R128_TWOSIDE_BIT 0x04 #define R128_FALLBACK_BIT 0x08 -extern void r128DrawTriangleVB(r128ContextPtr r128ctx, - r128_vertex *v0, - r128_vertex *v1, - r128_vertex *v2); -extern void r128DrawLineVB(r128ContextPtr r128ctx, - r128_vertex *tmp0, r128_vertex *tmp1, - float width); -extern void r128DrawPointVB(r128ContextPtr r128ctx, - r128_vertex *tmp, float size); +extern __inline void r128DrawTriangleVB(r128ContextPtr r128ctx, + r128Vertex *v0, + r128Vertex *v1, + r128Vertex *v2); +extern __inline void r128DrawLineVB(r128ContextPtr r128ctx, + r128Vertex *tmp0, r128Vertex *tmp1, + float width); +extern __inline void r128DrawPointVB(r128ContextPtr r128ctx, + r128Vertex *tmp, float size); extern void r128ChooseRenderState(GLcontext *ctx); extern void r128TriangleFuncsInit(void); diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_tritmp.h b/xc/lib/GL/mesa/src/drv/r128/r128_tritmp.h index aa0d16b39..51fc9acfb 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_tritmp.h +++ b/xc/lib/GL/mesa/src/drv/r128/r128_tritmp.h @@ -2,7 +2,7 @@ /************************************************************************** Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., - Cedar Park, Texas. + Cedar Park, Texas. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a @@ -43,63 +43,60 @@ static void TAG(triangle)(GLcontext *ctx, GLuint pv) { r128ContextPtr r128ctx = R128_CONTEXT(ctx); + int vertsize = r128ctx->vertsize; + CARD32 *vb = r128AllocVertexDwords(r128ctx, + 3 * vertsize); struct vertex_buffer *VB = ctx->VB; r128VertexPtr r128verts = R128_DRIVER_DATA(VB)->verts; - const r128_vertex *v0 = &r128verts[e0].v; - const r128_vertex *v1 = &r128verts[e1].v; - const r128_vertex *v2 = &r128verts[e2].v; + const r128Vertex *v[3]; + int i, j; #if (IND & R128_OFFSET_BIT) - GLfloat offset; + GLfloat offset = ctx->Polygon.OffsetUnits * r128ctx->depth_scale; #endif #if (IND & (R128_FLAT_BIT | R128_TWOSIDE_BIT)) - int c0 = *(int *)&r128verts[pv].v.dif_argb; - int c1 = c0; - int c2 = c0; -#endif + int c[3]; -#if (IND & R128_OFFSET_BIT) - switch (ctx->Visual->DepthBits) { - case 16: offset = ctx->Polygon.OffsetUnits / 65536.0; break; - case 24: offset = ctx->Polygon.OffsetUnits / 16777216.0; break; - case 32: offset = ctx->Polygon.OffsetUnits / 4294967296.0; break; - default: offset = ctx->Polygon.OffsetUnits / 65536.0; break; - } + c[0] = c[1] = c[2] = *(int *)&r128verts[pv].vert1.dif_argb; #endif -#if (IND & (R128_TWOSIDE_BIT | R128_OFFSET_BIT)) + v[0] = &r128verts[e0]; + v[1] = &r128verts[e1]; + v[2] = &r128verts[e2]; + +#if (IND & (R128_TWOSIDE_BIT | R128_OFFSET_BIT)) { - GLfloat ex = v0->x - v2->x; - GLfloat ey = v0->y - v2->y; - GLfloat fx = v1->x - v2->x; - GLfloat fy = v1->y - v2->y; - GLfloat c = ex*fy - ey*fx; - -#if (IND & R128_TWOSIDE_BIT) + GLfloat ex = v[0]->vert1.x - v[2]->vert1.x; + GLfloat ey = v[0]->vert1.y - v[2]->vert1.y; + GLfloat fx = v[1]->vert1.x - v[2]->vert1.x; + GLfloat fy = v[1]->vert1.y - v[2]->vert1.y; + GLfloat cc = ex*fy - ey*fx; + +#if (IND & R128_TWOSIDE_BIT) { - GLuint facing = (c > 0.0) ^ ctx->Polygon.FrontBit; + GLuint facing = (cc > 0.0) ^ ctx->Polygon.FrontBit; GLubyte (*vbcolor)[4] = VB->Color[facing]->data; if (IND & R128_FLAT_BIT) { - R128_COLOR((char *)&c0, vbcolor[pv]); - c2 = c1 = c0; + R128_COLOR((char *)&c[0], vbcolor[pv]); + c[2] = c[1] = c[0]; } else { - R128_COLOR((char *)&c0, vbcolor[e0]); - R128_COLOR((char *)&c1, vbcolor[e1]); - R128_COLOR((char *)&c2, vbcolor[e2]); + R128_COLOR((char *)&c[0], vbcolor[e0]); + R128_COLOR((char *)&c[1], vbcolor[e1]); + R128_COLOR((char *)&c[2], vbcolor[e2]); } } #endif - -#if (IND & R128_OFFSET_BIT) + +#if (IND & R128_OFFSET_BIT) { - if (c * c > 1e-16) { + if (cc * cc > 1e-16) { GLfloat factor = ctx->Polygon.OffsetFactor; - GLfloat ez = v0->z - v2->z; - GLfloat fz = v1->z - v2->z; + GLfloat ez = v[0]->vert1.z - v[2]->vert1.z; + GLfloat fz = v[1]->vert1.z - v[2]->vert1.z; GLfloat a = ey*fz - ez*fy; GLfloat b = ez*fx - ex*fz; - GLfloat ic = 1.0 / c; + GLfloat ic = 1.0 / cc; GLfloat ac = a * ic; GLfloat bc = b * ic; if (ac < 0.0f) ac = -ac; @@ -109,34 +106,18 @@ static void TAG(triangle)(GLcontext *ctx, } #endif } -#endif - - { - r128_vertex *vbptr; - R128CCE_ALLOC_VB_SPACE(r128ctx, vbptr, 3); - - vbptr[0] = *v0; -#if (IND & (R128_FLAT_BIT|R128_TWOSIDE_BIT)) - *((int *)(&vbptr[0].dif_argb)) = c0; -#endif -#if (IND & R128_OFFSET_BIT) - vbptr[0].z = v0->z + offset; #endif - vbptr[1] = *v1; -#if (IND & (R128_FLAT_BIT|R128_TWOSIDE_BIT)) - *((int *)(&vbptr[1].dif_argb)) = c1; -#endif -#if (IND & R128_OFFSET_BIT) - vbptr[1].z = v1->z + offset; -#endif + for (j = 0 ; j < 3 ; j++, vb += vertsize) { + + for (i = 0 ; i < vertsize ; i++) + vb[i] = v[j]->ui[i]; - vbptr[2] = *v2; #if (IND & (R128_FLAT_BIT|R128_TWOSIDE_BIT)) - *((int *)(&vbptr[2].dif_argb)) = c2; + vb[4] = c[j]; /* color is the fifth element... */ #endif #if (IND & R128_OFFSET_BIT) - vbptr[2].z = v2->z + offset; + *(float *)&vb[2] = v[j]->vert1.z + offset; #endif } } @@ -169,21 +150,21 @@ static void TAG(line)(GLcontext *ctx, GLubyte (*vbcolor)[4] = ctx->VB->ColorPtr->data; if (IND & R128_FLAT_BIT) { - R128_COLOR((char *)&tmp0.v.dif_argb, vbcolor[pv]); - *(int *)&tmp1.v.dif_argb = *(int *)&tmp0.v.dif_argb; + R128_COLOR((char *)&tmp0.vert1.dif_argb, vbcolor[pv]); + *(int *)&tmp1.vert1.dif_argb = *(int *)&tmp0.vert1.dif_argb; } else { - R128_COLOR((char *)&tmp0.v.dif_argb, vbcolor[v0]); - R128_COLOR((char *)&tmp1.v.dif_argb, vbcolor[v1]); + R128_COLOR((char *)&tmp0.vert1.dif_argb, vbcolor[v0]); + R128_COLOR((char *)&tmp1.vert1.dif_argb, vbcolor[v1]); } } else { - *(int *)&tmp0.v.dif_argb = *(int *)&r128verts[pv].v.dif_argb; - *(int *)&tmp1.v.dif_argb = *(int *)&r128verts[pv].v.dif_argb; + *(int *)&tmp0.vert1.dif_argb = *(int *)&r128verts[pv].vert1.dif_argb; + *(int *)&tmp1.vert1.dif_argb = *(int *)&r128verts[pv].vert1.dif_argb; } - r128DrawLineVB( r128ctx, &tmp0.v, &tmp1.v, width ); + r128DrawLineVB( r128ctx, &tmp0, &tmp1, width ); } else - r128DrawLineVB( r128ctx, &r128verts[v0].v, &r128verts[v1].v, width ); + r128DrawLineVB( r128ctx, &r128verts[v0], &r128verts[v1], width ); } /* Draw a set of points. Note that the device-dependent vertex data @@ -199,13 +180,13 @@ static void TAG(points)(GLcontext *ctx, for(i = first; i <= last; i++) { if(VB->ClipMask[i] == 0) { - if (IND & R128_TWOSIDE_BIT) { + if (IND & R128_TWOSIDE_BIT) { GLubyte (*vbcolor)[4] = VB->ColorPtr->data; r128Vertex tmp0 = r128verts[i]; - R128_COLOR((char *)&tmp0.v.dif_argb, vbcolor[i]); - r128DrawPointVB( r128ctx, &tmp0.v, size ); + R128_COLOR((char *)&tmp0.vert1.dif_argb, vbcolor[i]); + r128DrawPointVB( r128ctx, &tmp0, size ); } else - r128DrawPointVB( r128ctx, &r128verts[i].v, size ); + r128DrawPointVB( r128ctx, &r128verts[i], size ); } } } diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_vb.c b/xc/lib/GL/mesa/src/drv/r128/r128_vb.c index cf89f6b39..eb04e4473 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_vb.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_vb.c @@ -2,7 +2,7 @@ /************************************************************************** Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., - Cedar Park, Texas. + Cedar Park, Texas. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a @@ -46,32 +46,32 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define TEX0 \ do { \ - v->v.tu0 = tc0[i][0]; \ - v->v.tv0 = tc0[i][1]; \ + v->vert1.tu0 = tc0[i][0]; \ + v->vert1.tv0 = tc0[i][1]; \ } while (0) #define TEX1 \ do { \ - v->v.tu1 = tc1[i][0]; \ - v->v.tv1 = tc1[i][1]; \ + v->vert2.tu1 = tc1[i][0]; \ + v->vert2.tv1 = tc1[i][1]; \ } while (0) #define SPC \ do { \ GLubyte *spec = &(VB->Spec[0][i][0]); \ - v->v.spec_frgb.r = spec[0]; \ - v->v.spec_frgb.g = spec[1]; \ - v->v.spec_frgb.b = spec[2]; \ + v->vert1.spec_frgb.r = spec[0]; \ + v->vert1.spec_frgb.g = spec[1]; \ + v->vert1.spec_frgb.b = spec[2]; \ } while (0) #define COL \ do { \ GLubyte *col = &(VB->Color[0]->data[i][0]); \ - v->v.dif_argb.a = col[3]; \ - v->v.dif_argb.r = col[0]; \ - v->v.dif_argb.g = col[1]; \ - v->v.dif_argb.b = col[2]; \ + v->vert1.dif_argb.a = col[3]; \ + v->vert1.dif_argb.r = col[0]; \ + v->vert1.dif_argb.g = col[1]; \ + v->vert1.dif_argb.b = col[2]; \ } while (0) #if 1 @@ -86,9 +86,9 @@ do { \ v = &(R128_DRIVER_DATA(VB)->verts[start]); \ for (i = start; i < end; i++, v++) { \ float oow = 1.0 / tc[i][3]; \ - v->v.rhw *= tc[i][3]; \ - v->v.tu0 *= oow; \ - v->v.tv0 *= oow; \ + v->vert1.rhw *= tc[i][3]; \ + v->vert1.tu0 *= oow; \ + v->vert1.tv0 *= oow; \ } \ } \ } while (0) @@ -101,9 +101,9 @@ do { \ v = &(R128_DRIVER_DATA(VB)->verts[start]); \ for (i = start; i < end; i++, v++) { \ float oow = 1.0 / tc[i][3]; \ - v->v.rhw2 *= tc[i][3]; \ - v->v.tu1 *= oow; \ - v->v.tv1 *= oow; \ + v->vert3.rhw2 *= tc[i][3]; \ + v->vert3.tu1 *= oow; \ + v->vert3.tv1 *= oow; \ } \ } \ } while (0) @@ -116,19 +116,19 @@ do { \ #define COORD \ do { \ GLfloat *win = VB->Win.data[i]; \ - v->v.x = win[0]; \ - v->v.y = r128height - win[1]; \ - v->v.z = scale * win[2]; \ - v->v.rhw = v->v.rhw2 = win[3]; \ + v->vert3.x = win[0]; \ + v->vert3.y = r128height - win[1]; \ + v->vert3.z = scale * win[2]; \ + v->vert3.rhw = v->vert3.rhw2 = win[3]; \ } while (0) #else #define COORD \ do { \ GLfloat *win = VB->Win.data[i]; \ - v->v.x = win[0]; \ - v->v.y = r128height - win[1]; \ - v->v.z = scale * win[2]; \ - v->v.rhw = win[3]; \ + v->vert1.x = win[0]; \ + v->vert1.y = r128height - win[1]; \ + v->vert1.z = scale * win[2]; \ + v->vert1.rhw = win[3]; \ } while (0) #endif @@ -144,23 +144,16 @@ static void name(struct vertex_buffer *VB, GLuint start, GLuint end) \ GLfloat (*tc0)[4]; \ GLfloat (*tc1)[4]; \ GLfloat r128height = dPriv->h; \ - GLfloat scale; \ + GLfloat scale = r128ctx->depth_scale; \ int i; \ \ - (void) r128height; (void) r128ctx; \ + (void) r128height; (void) r128ctx; (void) scale; \ \ gl_import_client_data(VB, VB->ctx->RenderFlags, \ (VB->ClipOrMask \ ? VEC_WRITABLE | VEC_GOOD_STRIDE \ : VEC_GOOD_STRIDE)); \ \ - switch (VB->ctx->Visual->DepthBits) { \ - case 16: scale = 1.0 / 65536.0; break; \ - case 24: scale = 1.0 / 16777216.0; break; \ - case 32: scale = 1.0 / 4294967296.0; break; \ - default: scale = 1.0 / 65536.0; break; \ - } \ - \ tc0 = VB->TexCoordPtr[0]->data; \ tc1 = VB->TexCoordPtr[1]->data; \ \ @@ -264,14 +257,28 @@ void r128ChooseRasterSetupFunc(GLcontext *ctx) r128ContextPtr r128ctx = R128_CONTEXT(ctx); int funcIndex = R128_WIN_BIT | R128_RGBA_BIT; - if (ctx->Texture.Enabled & 0xf) { + r128ctx->vertsize = 8; + r128ctx->vc_format = R128_TEX0_VERTEX_FORMAT; + r128ctx->multitex = 0; + + if (ctx->Texture.Enabled & ENABLE_TEX0) { if (ctx->Texture.Unit[0].EnvMode == GL_REPLACE) funcIndex &= ~R128_RGBA_BIT; funcIndex |= R128_TEX0_BIT; } - if (ctx->Texture.Enabled & 0xf0) + if (ctx->Texture.Enabled & ENABLE_TEX1) { + /* GTH: we should really only enable the second texture unit + * when we're doing true multitexturing. I guess there aren't + * that many cases where apps will only bind a texture to the + * second texture unit, but it would definitely be a performance + * win in those cases. + */ + r128ctx->vertsize = 10; + r128ctx->vc_format = R128_TEX1_VERTEX_FORMAT; + r128ctx->multitex = 1; funcIndex |= R128_TEX1_BIT; + } /* FIXME: Verify this works properly */ if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_vb.h b/xc/lib/GL/mesa/src/drv/r128/r128_vb.h index 4417dcbae..f2244b687 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_vb.h +++ b/xc/lib/GL/mesa/src/drv/r128/r128_vb.h @@ -2,7 +2,7 @@ /************************************************************************** Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc., - Cedar Park, Texas. + Cedar Park, Texas. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a @@ -45,6 +45,18 @@ typedef struct { GLubyte a; } r128Color; +/* Single texture vertex, single x86 cache line. + * + * GTH: This is in use now. + */ +typedef struct { + GLfloat x, y, z; /* Coordinates in screen space */ + GLfloat rhw; /* Reciprocal homogeneous w */ + r128Color dif_argb; /* Diffuse color */ + r128Color spec_frgb; /* Specular color (alpha is fog) */ + GLfloat tu0, tv0; /* Texture 0 coordinates */ +} r128_vertex1; + /* The only vertex format in current use, but unsatisfactory for two * reasons: * - Not possible to implement fully conformant rendering @@ -52,7 +64,7 @@ typedef struct { * - Performance is lower with this vertex for single-texture * geometry, as the vertex is unnecessarily larger than * a cacheline. - * + * * Switching to single-texture vertices can be accomplished in state * management, and is relatively trivial. Switching to the rhw2 * format is data-dependent (are there any glTexCoord4f's in the @@ -60,7 +72,9 @@ typedef struct { * and rhw2 vertex formats only on the standard path. * * The fastpath never requires the rhw2 format, as it already makes - * the data-dependent checks. + * the data-dependent checks. + * + * GTH: This is fixed. */ typedef struct { GLfloat x, y, z; /* Coordinates in screen space */ @@ -69,12 +83,12 @@ typedef struct { r128Color spec_frgb; /* Specular color (alpha is fog) */ GLfloat tu0, tv0; /* Texture 0 coordinates */ GLfloat tu1, tv1; /* Texture 1 coordinates */ -} r128_vertex; +} r128_vertex2; /* Need to be slightly clever about flushing vertex buffers in order * to use rhw2 only on demand. * - * Not in use. + * GTH: This can be used now. */ typedef struct { GLfloat x, y, z; /* Coordinates in screen space */ @@ -83,29 +97,15 @@ typedef struct { r128Color spec_frgb; /* Specular color (alpha is fog) */ GLfloat tu0, tv0; /* Texture 0 coordinates */ GLfloat tu1, tv1; /* Texture 1 coordinates */ - GLfloat rhw2; /* Reciprocal homogeneous w */ -} r128_rhw2_vertex; - -/* Single texture vertex, single cache line. - * - * Not in use. - */ -typedef struct { - GLfloat x, y, z; /* Coordinates in screen space */ - GLfloat rhw; /* Reciprocal homogeneous w */ - r128Color dif_argb; /* Diffuse color */ - r128Color spec_frgb; /* Specular color (alpha is fog) */ - GLfloat tu0, tv0; /* Texture 0 coordinates */ -} r128_st_vertex; + GLfloat rhw2; /* Reciprocal homogeneous w2 */ +} r128_vertex2_rhw2; /* Format of vertices in r128_vertex struct */ -#define R128_PROJ_TEX1_VERTEX_FORMAT \ +#define R128_TEX0_VERTEX_FORMAT \ R128_CCE_VC_FRMT_RHW | \ R128_CCE_VC_FRMT_DIFFUSE_ARGB | \ R128_CCE_VC_FRMT_SPEC_FRGB | \ - R128_CCE_VC_FRMT_S_T | \ - R128_CCE_VC_FRMT_S2_T2 | \ - R128_CCE_VC_FRMT_RHW2 + R128_CCE_VC_FRMT_S_T #define R128_TEX1_VERTEX_FORMAT \ R128_CCE_VC_FRMT_RHW | \ @@ -114,18 +114,26 @@ typedef struct { R128_CCE_VC_FRMT_S_T | \ R128_CCE_VC_FRMT_S2_T2 -#define R128_TEX0_VERTEX_FORMAT \ +#define R128_PROJ_TEX1_VERTEX_FORMAT \ R128_CCE_VC_FRMT_RHW | \ R128_CCE_VC_FRMT_DIFFUSE_ARGB | \ R128_CCE_VC_FRMT_SPEC_FRGB | \ - R128_CCE_VC_FRMT_S_T + R128_CCE_VC_FRMT_S_T | \ + R128_CCE_VC_FRMT_S2_T2 | \ + R128_CCE_VC_FRMT_RHW2 /* FIXME: We currently only have assembly for 16-stride vertices */ -typedef union { - r128_vertex v; - float f[16]; -} r128Vertex, *r128VertexPtr; +union r128_vertex_t { + r128_vertex1 vert1; + r128_vertex2 vert2; + r128_vertex2_rhw2 vert3; + float f[16]; + CARD32 ui[16]; +}; + +typedef union r128_vertex_t r128Vertex; +typedef union r128_vertex_t *r128VertexPtr; /* Vertex buffer for use when on the fast path */ typedef struct { @@ -140,7 +148,7 @@ typedef struct { #define R128_SPEC_BIT 0x01 #define R128_TEX1_BIT 0x02 -#define R128_TEX0_BIT 0x04 +#define R128_TEX0_BIT 0x04 #define R128_RGBA_BIT 0x08 #define R128_WIN_BIT 0x10 diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_xmesa.c b/xc/lib/GL/mesa/src/drv/r128/r128_xmesa.c index 60d528813..aae13df65 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_xmesa.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_xmesa.c @@ -49,19 +49,17 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #ifndef R128_DEBUG_FLAGS int R128_DEBUG_FLAGS = (0 -#if 0 - | DEBUG_ALWAYS_SYNC - | DEBUG_VERBOSE_CCE - | DEBUG_VERBOSE_OUTREG - | DEBUG_VERBOSE_MSG - | DEBUG_NO_OUTRING - | DEBUG_NO_OUTREG - | DEBUG_VERBOSE_API - | DEBUG_VERBOSE_2D - | DEBUG_VERBOSE_DRI - | DEBUG_VALIDATE_RING - | DEBUG_VERBOSE_IOCTL -#endif +/* | DEBUG_ALWAYS_SYNC */ +/* | DEBUG_VERBOSE_CCE */ +/* | DEBUG_VERBOSE_OUTREG */ +/* | DEBUG_VERBOSE_MSG */ +/* | DEBUG_NO_OUTRING */ +/* | DEBUG_NO_OUTREG */ +/* | DEBUG_VERBOSE_API */ +/* | DEBUG_VERBOSE_2D */ +/* | DEBUG_VERBOSE_DRI */ +/* | DEBUG_VALIDATE_RING */ +/* | DEBUG_VERBOSE_IOCTL */ ); #endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h index 7b8e88265..c71af2cc6 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h @@ -1,8 +1,8 @@ /* drm.h -- Header for Direct Rendering Manager -*- linux-c -*- * Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com - * Revised: Mon Feb 14 00:15:23 2000 by kevin@precisioninsight.com * * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -11,11 +11,11 @@ * 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 @@ -23,8 +23,9 @@ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. - * - * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h,v 1.5 2000/02/23 04:47:26 martin Exp $ + * + * Authors: + * Rickard E. (Rik) Faith <faith@valinux.com> * * Acknowledgements: * Dec 1999, Richard Henderson <rth@twiddle.net>, move to generic cmpxchg. @@ -61,6 +62,20 @@ typedef unsigned int drm_context_t; typedef unsigned int drm_drawable_t; typedef unsigned int drm_magic_t; +/* Warning: If you change this structure, make sure you change + * XF86DRIClipRectRec in the server as well */ + +typedef struct drm_clip_rect { + unsigned short x1; + unsigned short y1; + unsigned short x2; + unsigned short y2; +} drm_clip_rect_t; + +/* Seperate include files for the i810/mga/r128 specific structures */ +#include "mga_drm.h" +#include "i810_drm.h" +#include "r128_drm.h" typedef struct drm_version { int version_major; /* Major version */ @@ -101,7 +116,8 @@ typedef struct drm_control { typedef enum drm_map_type { _DRM_FRAME_BUFFER = 0, /* WC (no caching), no core dump */ _DRM_REGISTERS = 1, /* no caching, no core dump */ - _DRM_SHM = 2 /* shared, cached */ + _DRM_SHM = 2, /* shared, cached */ + _DRM_AGP = 3 /* AGP/GART */ } drm_map_type_t; typedef enum drm_map_flags { @@ -165,8 +181,11 @@ typedef struct drm_buf_desc { int low_mark; /* Low water mark */ int high_mark; /* High water mark */ enum { - DRM_PAGE_ALIGN = 0x01 /* Align on page boundaries for DMA */ + _DRM_PAGE_ALIGN = 0x01, /* Align on page boundaries for DMA */ + _DRM_AGP_BUFFER = 0x02 /* Buffer is in agp space */ } flags; + unsigned long agp_start; /* Start address of where the agp buffers + * are in the agp aperture */ } drm_buf_desc_t; typedef struct drm_buf_info { @@ -237,6 +256,38 @@ typedef struct drm_irq_busid { int funcnum; } drm_irq_busid_t; +typedef struct drm_agp_mode { + unsigned long mode; +} drm_agp_mode_t; + + /* For drm_agp_alloc -- allocated a buffer */ +typedef struct drm_agp_buffer { + unsigned long size; /* In bytes -- will round to page boundary */ + unsigned long handle; /* Used for BIND/UNBIND ioctls */ + unsigned long type; /* Type of memory to allocate */ + unsigned long physical; /* Physical used by i810 */ +} drm_agp_buffer_t; + + /* For drm_agp_bind */ +typedef struct drm_agp_binding { + unsigned long handle; /* From drm_agp_buffer */ + unsigned long offset; /* In bytes -- will round to page boundary */ +} drm_agp_binding_t; + +typedef struct drm_agp_info { + int agp_version_major; + int agp_version_minor; + unsigned long mode; + unsigned long aperture_base; /* physical address */ + unsigned long aperture_size; /* bytes */ + unsigned long memory_allowed; /* bytes */ + unsigned long memory_used; + + /* PCI information */ + unsigned short id_vendor; + unsigned short id_device; +} drm_agp_info_t; + #define DRM_IOCTL_BASE 'd' #define DRM_IOCTL_NR(n) _IOC_NR(n) #define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr) @@ -247,7 +298,7 @@ typedef struct drm_irq_busid { #define DRM_IOCTL_VERSION DRM_IOWR(0x00, drm_version_t) #define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm_unique_t) -#define DRM_IOCTL_GET_MAGIC DRM_IOW( 0x02, drm_auth_t) +#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, drm_auth_t) #define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, drm_irq_busid_t) #define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm_unique_t) @@ -276,4 +327,39 @@ typedef struct drm_irq_busid { #define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, drm_lock_t) #define DRM_IOCTL_FINISH DRM_IOW( 0x2c, drm_lock_t) +#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30) +#define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31) +#define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, drm_agp_mode_t) +#define DRM_IOCTL_AGP_INFO DRM_IOR( 0x33, drm_agp_info_t) +#define DRM_IOCTL_AGP_ALLOC DRM_IOWR(0x34, drm_agp_buffer_t) +#define DRM_IOCTL_AGP_FREE DRM_IOW( 0x35, drm_agp_buffer_t) +#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, drm_agp_binding_t) +#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_t) + +/* Mga specific ioctls */ +#define DRM_IOCTL_MGA_INIT DRM_IOW( 0x40, drm_mga_init_t) +#define DRM_IOCTL_MGA_SWAP DRM_IOW( 0x41, drm_mga_swap_t) +#define DRM_IOCTL_MGA_CLEAR DRM_IOW( 0x42, drm_mga_clear_t) +#define DRM_IOCTL_MGA_ILOAD DRM_IOW( 0x43, drm_mga_iload_t) +#define DRM_IOCTL_MGA_VERTEX DRM_IOW( 0x44, drm_mga_vertex_t) +#define DRM_IOCTL_MGA_FLUSH DRM_IOW( 0x45, drm_lock_t ) +#define DRM_IOCTL_MGA_INDICES DRM_IOW( 0x46, drm_mga_indices_t) + +/* I810 specific ioctls */ +#define DRM_IOCTL_I810_INIT DRM_IOW( 0x40, drm_i810_init_t) +#define DRM_IOCTL_I810_VERTEX DRM_IOW( 0x41, drm_i810_vertex_t) +#define DRM_IOCTL_I810_CLEAR DRM_IOW( 0x42, drm_i810_clear_t) +#define DRM_IOCTL_I810_FLUSH DRM_IO ( 0x43) +#define DRM_IOCTL_I810_GETAGE DRM_IO ( 0x44) +#define DRM_IOCTL_I810_GETBUF DRM_IOW( 0x45, drm_i810_dma_t) +#define DRM_IOCTL_I810_SWAP DRM_IO ( 0x46) + +/* Rage 128 specific ioctls */ +#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) +#define DRM_IOCTL_R128_RESET DRM_IO( 0x41) +#define DRM_IOCTL_R128_FLUSH DRM_IO( 0x42) +#define DRM_IOCTL_R128_IDLE DRM_IO( 0x43) +#define DRM_IOCTL_R128_PACKET DRM_IOW( 0x44, drm_r128_packet_t) +#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x45, drm_r128_vertex_t) + #endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_dma.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_dma.c new file mode 100644 index 000000000..dd416db17 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_dma.c @@ -0,0 +1,923 @@ +/* r128_drv.c -- ATI Rage 128 driver -*- linux-c -*- + * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com + * + * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Kevin E. Martin <kevin@precisioninsight.com> + * + * $XFree86$ + * + */ + +#define __NO_VERSION__ +#include "drmP.h" +#include "r128_drv.h" + +#include <linux/interrupt.h> /* For task queue support */ +#include <linux/delay.h> + + + +#define DO_REMAP(_m) (_m)->handle = drm_ioremap((_m)->offset, (_m)->size) + +#define DO_REMAPFREE(_m) \ + do { \ + if ((_m)->handle && (_m)->size) \ + drm_ioremapfree((_m)->handle, (_m)->size); \ + } while (0) + +#define DO_FIND_MAP(_m, _o) \ + do { \ + int _i; \ + for (_i = 0; _i < dev->map_count; _i++) { \ + if (dev->maplist[_i]->offset == _o) { \ + _m = dev->maplist[_i]; \ + break; \ + } \ + } \ + } while (0) + + +#define R128_MAX_VBUF_AGE 0x10000000 +#define R128_VB_AGE_REG R128_GUI_SCRATCH_REG0 + +int R128_READ_PLL(drm_device_t *dev, int addr) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + + R128_WRITE8(R128_CLOCK_CNTL_INDEX, addr & 0x1f); + return R128_READ(R128_CLOCK_CNTL_DATA); +} + +static void r128_flush_write_combine(void) +{ + int xchangeDummy; + + __asm__ volatile("push %%eax ;" + "xchg %%eax, %0 ;" + "pop %%eax" : : "m" (xchangeDummy)); + __asm__ volatile("push %%eax ;" + "push %%ebx ;" + "push %%ecx ;" + "push %%edx ;" + "movl $0,%%eax ;" + "cpuid ;" + "pop %%edx ;" + "pop %%ecx ;" + "pop %%ebx ;" + "pop %%eax" : /* no outputs */ : /* no inputs */ ); +} + +static void r128_status(drm_device_t *dev) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + + printk("GUI_STAT = 0x%08x\n", + (unsigned int)R128_READ(R128_GUI_STAT)); + printk("PM4_STAT = 0x%08x\n", + (unsigned int)R128_READ(R128_PM4_STAT)); + printk("PM4_BUFFER_DL_WPTR = 0x%08x\n", + (unsigned int)R128_READ(R128_PM4_BUFFER_DL_WPTR)); + printk("PM4_BUFFER_DL_RPTR = 0x%08x\n", + (unsigned int)R128_READ(R128_PM4_BUFFER_DL_RPTR)); +} + +static int r128_do_cleanup_cce(drm_device_t *dev) +{ + if (dev->dev_private) { + drm_r128_private_t *dev_priv = dev->dev_private; + + if (!dev_priv->is_pci) { + DO_REMAPFREE(dev_priv->agp_ring); + DO_REMAPFREE(dev_priv->agp_read_ptr); + DO_REMAPFREE(dev_priv->agp_vertbufs); + DO_REMAPFREE(dev_priv->agp_indbufs); + DO_REMAPFREE(dev_priv->agp_textures); + } + + drm_free(dev->dev_private, sizeof(drm_r128_private_t), + DRM_MEM_DRIVER); + dev->dev_private = NULL; + } + + return 0; +} + +static int r128_do_init_cce(drm_device_t *dev, drm_r128_init_t *init) +{ + drm_r128_private_t *dev_priv; + int i; + + dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER); + if (dev_priv == NULL) return -ENOMEM; + dev->dev_private = (void *)dev_priv; + + memset(dev_priv, 0, sizeof(drm_r128_private_t)); + + dev_priv->is_pci = init->is_pci; + + dev_priv->usec_timeout = init->usec_timeout; + if (dev_priv->usec_timeout < 1 || + dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT) { + drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); + dev->dev_private = NULL; + return -EINVAL; + } + + dev_priv->cce_mode = init->cce_mode; + dev_priv->cce_fifo_size = init->cce_fifo_size; + dev_priv->cce_is_bm_mode = + ((init->cce_mode == R128_PM4_192BM) || + (init->cce_mode == R128_PM4_128BM_64INDBM) || + (init->cce_mode == R128_PM4_64BM_128INDBM) || + (init->cce_mode == R128_PM4_64BM_64VCBM_64INDBM)); + dev_priv->cce_secure = init->cce_secure; + + if (dev_priv->cce_is_bm_mode && dev_priv->is_pci) { + drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); + dev->dev_private = NULL; + return -EINVAL; + } + + for (i = 0; i < dev->map_count; i++) { + if (dev->maplist[i]->type == _DRM_SHM) { + dev_priv->sarea = dev->maplist[i]; + break; + } + } + + DO_FIND_MAP(dev_priv->fb, init->fb_offset); + if (!dev_priv->is_pci) { + DO_FIND_MAP(dev_priv->agp_ring, init->agp_ring_offset); + DO_FIND_MAP(dev_priv->agp_read_ptr, init->agp_read_ptr_offset); + DO_FIND_MAP(dev_priv->agp_vertbufs, init->agp_vertbufs_offset); + DO_FIND_MAP(dev_priv->agp_indbufs, init->agp_indbufs_offset); + DO_FIND_MAP(dev_priv->agp_textures, init->agp_textures_offset); + } + DO_FIND_MAP(dev_priv->mmio, init->mmio_offset); + + dev_priv->sarea_priv = + (drm_r128_sarea_t *)((u8 *)dev_priv->sarea->handle + + init->sarea_priv_offset); + + if (!dev_priv->is_pci) { + DO_REMAP(dev_priv->agp_ring); + DO_REMAP(dev_priv->agp_read_ptr); + DO_REMAP(dev_priv->agp_vertbufs); +#if 0 + DO_REMAP(dev_priv->agp_indirectbufs); + DO_REMAP(dev_priv->agp_textures); +#endif + + dev_priv->ring_size = init->ring_size; + dev_priv->ring_sizel2qw = drm_order(init->ring_size/8); + dev_priv->ring_entries = init->ring_size/sizeof(u32); + dev_priv->ring_read_ptr = ((__volatile__ u32 *) + dev_priv->agp_read_ptr->handle); + dev_priv->ring_start = (u32 *)dev_priv->agp_ring->handle; + dev_priv->ring_end = ((u32 *)dev_priv->agp_ring->handle + + dev_priv->ring_entries); + } + + dev_priv->submit_age = 0; + R128_WRITE(R128_VB_AGE_REG, dev_priv->submit_age); + + return 0; +} + +int r128_init_cce(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_r128_init_t init; + + copy_from_user_ret(&init, (drm_r128_init_t *)arg, sizeof(init), + -EFAULT); + + switch (init.func) { + case R128_INIT_CCE: + return r128_do_init_cce(dev, &init); + case R128_CLEANUP_CCE: + return r128_do_cleanup_cce(dev); + } + + return -EINVAL; +} + +static void r128_mark_vertbufs_done(drm_device_t *dev) +{ + drm_device_dma_t *dma = dev->dma; + int i; + + for (i = 0; i < dma->buf_count; i++) { + drm_buf_t *buf = dma->buflist[i]; + drm_r128_buf_priv_t *buf_priv = buf->dev_private; + buf_priv->age = 0; + } +} + +static int r128_do_pixcache_flush(drm_device_t *dev) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + u32 tmp; + int i; + + tmp = R128_READ(R128_PC_NGUI_CTLSTAT) | R128_PC_FLUSH_ALL; + R128_WRITE(R128_PC_NGUI_CTLSTAT, tmp); + + for (i = 0; i < dev_priv->usec_timeout; i++) { + if (!(R128_READ(R128_PC_NGUI_CTLSTAT) & R128_PC_BUSY)) + return 0; + udelay(1); + } + + return -EBUSY; +} + +static int r128_do_wait_for_fifo(drm_device_t *dev, int entries) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int i; + + for (i = 0; i < dev_priv->usec_timeout; i++) { + int slots = R128_READ(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK; + if (slots >= entries) return 0; + udelay(1); + } + return -EBUSY; +} + +static int r128_do_wait_for_idle(drm_device_t *dev) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int i, ret; + + if (!(ret = r128_do_wait_for_fifo(dev, 64))) return ret; + + for (i = 0; i < dev_priv->usec_timeout; i++) { + if (!(R128_READ(R128_GUI_STAT) & R128_GUI_ACTIVE)) { + (void)r128_do_pixcache_flush(dev); + return 0; + } + udelay(1); + } + return -EBUSY; +} + +int r128_do_engine_reset(drm_device_t *dev) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + u32 clock_cntl_index, mclk_cntl, gen_reset_cntl; + + (void)r128_do_pixcache_flush(dev); + + clock_cntl_index = R128_READ(R128_CLOCK_CNTL_INDEX); + mclk_cntl = R128_READ_PLL(dev, R128_MCLK_CNTL); + + R128_WRITE_PLL(R128_MCLK_CNTL, + mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CPP); + + gen_reset_cntl = R128_READ(R128_GEN_RESET_CNTL); + + R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl | R128_SOFT_RESET_GUI); + (void)R128_READ(R128_GEN_RESET_CNTL); + R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl & ~R128_SOFT_RESET_GUI); + (void)R128_READ(R128_GEN_RESET_CNTL); + + R128_WRITE_PLL(R128_MCLK_CNTL, mclk_cntl); + R128_WRITE(R128_CLOCK_CNTL_INDEX, clock_cntl_index); + R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl); + + /* For CCE ring buffer only */ + if (dev_priv->cce_is_bm_mode) { + R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0); + R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0); + *dev_priv->ring_read_ptr = 0; + dev_priv->sarea_priv->ring_write = 0; + } + + /* Reset the CCE mode */ + (void)r128_do_wait_for_idle(dev); + R128_WRITE(R128_PM4_BUFFER_CNTL, + dev_priv->cce_mode | dev_priv->ring_sizel2qw); + (void)R128_READ(R128_PM4_BUFFER_ADDR); /* as per the sample code */ + R128_WRITE(R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN); + + r128_mark_vertbufs_done(dev); + return 0; +} + +int r128_eng_reset(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) || + dev->lock.pid != current->pid) { + DRM_ERROR("r128_eng_reset called without holding the lock\n"); + return -EINVAL; + } + + return r128_do_engine_reset(dev); +} + +static int r128_do_engine_flush(drm_device_t *dev) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + u32 tmp; + + tmp = R128_READ(R128_PM4_BUFFER_DL_WPTR); + R128_WRITE(R128_PM4_BUFFER_DL_WPTR, tmp | R128_PM4_BUFFER_DL_DONE); + + return 0; +} + +int r128_eng_flush(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) || + dev->lock.pid != current->pid) { + DRM_ERROR("r128_eng_flush called without holding the lock\n"); + return -EINVAL; + } + + return r128_do_engine_flush(dev); +} + +static int r128_do_cce_wait_for_fifo(drm_device_t *dev, int entries) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int i; + + for (i = 0; i < dev_priv->usec_timeout; i++) { + int slots = R128_READ(R128_PM4_STAT) & R128_PM4_FIFOCNT_MASK; + if (slots >= entries) return 0; + udelay(1); + } + return -EBUSY; +} + +int r128_do_cce_wait_for_idle(drm_device_t *dev) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int i; + + if (dev_priv->cce_is_bm_mode) { + for (i = 0; i < dev_priv->usec_timeout; i++) { + if (*dev_priv->ring_read_ptr == dev_priv->sarea_priv->ring_write) { + int pm4stat = R128_READ(R128_PM4_STAT); + if ((pm4stat & R128_PM4_FIFOCNT_MASK) >= dev_priv->cce_fifo_size && + !(pm4stat & (R128_PM4_BUSY | R128_PM4_GUI_ACTIVE))) { + return r128_do_pixcache_flush(dev); + } + } + udelay(1); + } + return -EBUSY; + } else { + int ret = r128_do_cce_wait_for_fifo(dev, dev_priv->cce_fifo_size); + if (ret < 0) return ret; + + for (i = 0; i < dev_priv->usec_timeout; i++) { + int pm4stat = R128_READ(R128_PM4_STAT); + if (!(pm4stat & (R128_PM4_BUSY | R128_PM4_GUI_ACTIVE))) { + return r128_do_pixcache_flush(dev); + } + udelay(1); + } + return -EBUSY; + } +} + +int r128_cce_idle(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) || + dev->lock.pid != current->pid) { + DRM_ERROR("r128_wait_idle called without holding the lock\n"); + return -EINVAL; + } + + return r128_do_cce_wait_for_idle(dev); +} + +static int r128_submit_packets_ring_secure(drm_device_t *dev, + u32 *commands, int *count) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int write = dev_priv->sarea_priv->ring_write; + int *write_ptr = dev_priv->ring_start + write; + int c = *count; + u32 tmp = 0; + int psize = 0; + int writing = 1; + int timeout; + + while (c > 0) { + tmp = *commands++; + if (!psize) { + writing = 1; + + if ((tmp & R128_CCE_PACKET_MASK) == R128_CCE_PACKET0) { + if ((tmp & R128_CCE_PACKET0_REG_MASK) <= (0x1004 >> 2)) { + if ((tmp & R128_CCE_PACKET0_REG_MASK) != + (R128_PM4_VC_FPU_SETUP >> 2)) { + writing = 0; + } + } + psize = ((tmp & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2; + } else if ((tmp & R128_CCE_PACKET_MASK) == R128_CCE_PACKET1) { + if ((tmp & R128_CCE_PACKET1_REG0_MASK) <= (0x1004 >> 2)) { + if ((tmp & R128_CCE_PACKET1_REG0_MASK) != + (R128_PM4_VC_FPU_SETUP >> 2)) { + writing = 0; + } + } else if ((tmp & R128_CCE_PACKET1_REG1_MASK) <= + (0x1004 << 9)) { + if ((tmp & R128_CCE_PACKET1_REG1_MASK) != + (R128_PM4_VC_FPU_SETUP << 9)) { + writing = 0; + } + } + psize = 3; + } else { + psize = ((tmp & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2; + } + } + psize--; + + if (writing) { + write++; + *write_ptr++ = tmp; + } + if (write >= dev_priv->ring_entries) { + write = 0; + write_ptr = dev_priv->ring_start; + } + timeout = 0; + while (write == *dev_priv->ring_read_ptr) { + (void)R128_READ(R128_PM4_BUFFER_DL_RPTR); + if (timeout++ >= dev_priv->usec_timeout) + return -EBUSY; + udelay(1); + } + c--; + } + + if (write < 32) + memcpy(dev_priv->ring_end, + dev_priv->ring_start, + write * sizeof(u32)); + + /* Make sure WC cache has been flushed */ + r128_flush_write_combine(); + + dev_priv->sarea_priv->ring_write = write; + R128_WRITE(R128_PM4_BUFFER_DL_WPTR, write); + + *count = 0; + + return 0; +} + +static int r128_submit_packets_pio_secure(drm_device_t *dev, + u32 *commands, int *count) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + u32 tmp = 0; + int psize = 0; + int writing = 1; + int addr = R128_PM4_FIFO_DATA_EVEN; + int ret; + + while (*count > 0) { + tmp = *commands++; + if (!psize) { + writing = 1; + + if ((tmp & R128_CCE_PACKET_MASK) == R128_CCE_PACKET0) { + if ((tmp & R128_CCE_PACKET0_REG_MASK) <= (0x1004 >> 2)) { + if ((tmp & R128_CCE_PACKET0_REG_MASK) != + (R128_PM4_VC_FPU_SETUP >> 2)) { + writing = 0; + } + } + psize = ((tmp & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2; + } else if ((tmp & R128_CCE_PACKET_MASK) == R128_CCE_PACKET1) { + if ((tmp & R128_CCE_PACKET1_REG0_MASK) <= (0x1004 >> 2)) { + if ((tmp & R128_CCE_PACKET1_REG0_MASK) != + (R128_PM4_VC_FPU_SETUP >> 2)) { + writing = 0; + } + } else if ((tmp & R128_CCE_PACKET1_REG1_MASK) <= + (0x1004 << 9)) { + if ((tmp & R128_CCE_PACKET1_REG1_MASK) != + (R128_PM4_VC_FPU_SETUP << 9)) { + writing = 0; + } + } + psize = 3; + } else { + psize = ((tmp & R128_CCE_PACKET_COUNT_MASK) >> 16) + 2; + } + } + psize--; + + if (writing) { + if ((ret = r128_do_cce_wait_for_fifo(dev, 1)) < 0) + return ret; + R128_WRITE(addr, tmp); + addr ^= 0x0004; + } + + *count -= 1; + } + + if (addr == R128_PM4_FIFO_DATA_ODD) { + if ((ret = r128_do_cce_wait_for_fifo(dev, 1)) < 0) return ret; + R128_WRITE(addr, R128_CCE_PACKET2); + } + + return 0; +} + +static int r128_submit_packets_ring(drm_device_t *dev, + u32 *commands, int *count) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int write = dev_priv->sarea_priv->ring_write; + int *write_ptr = dev_priv->ring_start + write; + int c = *count; + int timeout; + + while (c > 0) { + write++; + *write_ptr++ = *commands++; + if (write >= dev_priv->ring_entries) { + write = 0; + write_ptr = dev_priv->ring_start; + } + timeout = 0; + while (write == *dev_priv->ring_read_ptr) { + (void)R128_READ(R128_PM4_BUFFER_DL_RPTR); + if (timeout++ >= dev_priv->usec_timeout) + return -EBUSY; + udelay(1); + } + c--; + } + + if (write < 32) + memcpy(dev_priv->ring_end, + dev_priv->ring_start, + write * sizeof(u32)); + + /* Make sure WC cache has been flushed */ + r128_flush_write_combine(); + + dev_priv->sarea_priv->ring_write = write; + R128_WRITE(R128_PM4_BUFFER_DL_WPTR, write); + + *count = 0; + + return 0; +} + +static int r128_submit_packets_pio(drm_device_t *dev, + u32 *commands, int *count) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int ret; + + while (*count > 1) { + if ((ret = r128_do_cce_wait_for_fifo(dev, 2)) < 0) return ret; + R128_WRITE(R128_PM4_FIFO_DATA_EVEN, *commands++); + R128_WRITE(R128_PM4_FIFO_DATA_ODD, *commands++); + *count -= 2; + } + + if (*count) { + if ((ret = r128_do_cce_wait_for_fifo(dev, 2)) < 0) return ret; + R128_WRITE(R128_PM4_FIFO_DATA_EVEN, *commands++); + R128_WRITE(R128_PM4_FIFO_DATA_ODD, R128_CCE_PACKET2); + *count = 0; + } + + return 0; +} + +static int r128_do_submit_packets(drm_device_t *dev, u32 *buffer, int count) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int c = count; + int ret; + + if (dev_priv->cce_is_bm_mode) { + int left = 0; + + if (c >= dev_priv->ring_entries) { + c = dev_priv->ring_entries-1; + left = count - c; + } + + /* Since this is only used by the kernel we can use the + insecure ring buffer submit packet routine */ + ret = r128_submit_packets_ring(dev, buffer, &c); + + c += left; + } else { + /* Since this is only used by the kernel we can use the + insecure PIO submit packet routine */ + ret = r128_submit_packets_pio(dev, buffer, &c); + } + + if (ret < 0) return ret; + else return c; +} + +int r128_submit_pkt(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_r128_private_t *dev_priv = dev->dev_private; + drm_r128_packet_t packet; + u32 *buffer; + int c; + int size; + int ret = 0; + + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) || + dev->lock.pid != current->pid) { + DRM_ERROR("r128_submit_pkt called without holding the lock\n"); + return -EINVAL; + } + + copy_from_user_ret(&packet, (drm_r128_packet_t *)arg, sizeof(packet), + -EFAULT); + + c = packet.count; + size = c * sizeof(*buffer); + + if (dev_priv->cce_is_bm_mode) { + int left = 0; + + if (c >= dev_priv->ring_entries) { + c = dev_priv->ring_entries-1; + size = c * sizeof(*buffer); + left = packet.count - c; + } + + if ((buffer = kmalloc(size, 0)) == NULL) return -ENOMEM; + copy_from_user_ret(buffer, packet.buffer, size, -EFAULT); + + if (dev_priv->cce_secure) + ret = r128_submit_packets_ring_secure(dev, buffer, &c); + else + ret = r128_submit_packets_ring(dev, buffer, &c); + + c += left; + } else { + if ((buffer = kmalloc(size, 0)) == NULL) return -ENOMEM; + copy_from_user_ret(buffer, packet.buffer, size, -EFAULT); + + if (dev_priv->cce_secure) + ret = r128_submit_packets_pio_secure(dev, buffer, &c); + else + ret = r128_submit_packets_pio(dev, buffer, &c); + } + + kfree(buffer); + + packet.count = c; + copy_to_user_ret((drm_r128_packet_t *)arg, &packet, sizeof(packet), + -EFAULT); + + if (ret) return ret; + else if (c > 0) return -EAGAIN; + + return 0; +} + +static int r128_send_vertbufs(drm_device_t *dev, drm_r128_vertex_t *v) +{ + drm_device_dma_t *dma = dev->dma; + drm_r128_private_t *dev_priv = dev->dev_private; + drm_r128_buf_priv_t *buf_priv; + drm_buf_t *buf; + int i, ret; + u32 cce[2]; + + /* Make sure we have valid data */ + for (i = 0; i < v->send_count; i++) { + int idx = v->send_indices[i]; + + if (idx < 0 || idx >= dma->buf_count) { + DRM_ERROR("Index %d (of %d max)\n", + idx, dma->buf_count - 1); + return -EINVAL; + } + buf = dma->buflist[idx]; + if (buf->pid != current->pid) { + DRM_ERROR("Process %d using buffer owned by %d\n", + current->pid, buf->pid); + return -EINVAL; + } + if (buf->pending) { + DRM_ERROR("Sending pending buffer:" + " buffer %d, offset %d\n", + v->send_indices[i], i); + return -EINVAL; + } + } + + /* Wait for idle, if we've wrapped to make sure that all pending + buffers have been processed */ + if (dev_priv->submit_age == R128_MAX_VBUF_AGE) { + if ((ret = r128_do_cce_wait_for_idle(dev)) < 0) return ret; + dev_priv->submit_age = 0; + r128_mark_vertbufs_done(dev); + } + + /* Make sure WC cache has been flushed (if in PIO mode) */ + if (!dev_priv->cce_is_bm_mode) r128_flush_write_combine(); + + /* FIXME: Add support for sending vertex buffer to the CCE here + instead of in client code. The v->prim holds the primitive + type that should be drawn. Loop over the list buffers in + send_indices[] and submit a packet for each VB. + + This will require us to loop over the clip rects here as + well, which implies that we extend the kernel driver to allow + cliprects to be stored here. Note that the cliprects could + possibly come from the X server instead of the client, but + this will require additional changes to the DRI to allow for + this optimization. */ + + /* Submit a CCE packet that writes submit_age to R128_VB_AGE_REG */ + cce[0] = R128CCE0(R128_CCE_PACKET0, R128_VB_AGE_REG, 0); + cce[1] = dev_priv->submit_age; + if ((ret = r128_do_submit_packets(dev, cce, 2)) < 0) { + /* Until we add support for sending VBs to the CCE in + this routine, we can recover from this error. After + we add that support, we won't be able to easily + recover, so we will probably have to implement + another mechanism for handling timeouts from packets + submitted directly by the kernel. */ + return ret; + } + + /* Now that the submit packet request has succeeded, we can mark + the buffers as pending */ + for (i = 0; i < v->send_count; i++) { + buf = dma->buflist[v->send_indices[i]]; + buf->pending = 1; + + buf_priv = buf->dev_private; + buf_priv->age = dev_priv->submit_age; + } + + dev_priv->submit_age++; + + return 0; +} + +static drm_buf_t *r128_freelist_get(drm_device_t *dev) +{ + drm_device_dma_t *dma = dev->dma; + drm_r128_private_t *dev_priv = dev->dev_private; + drm_r128_buf_priv_t *buf_priv; + drm_buf_t *buf; + int i, t; + + /* FIXME: Optimize -- use freelist code */ + + for (i = 0; i < dma->buf_count; i++) { + buf = dma->buflist[i]; + buf_priv = buf->dev_private; + if (buf->pid == 0) return buf; + } + + for (t = 0; t < dev_priv->usec_timeout; t++) { + u32 done_age = R128_READ(R128_VB_AGE_REG); + + for (i = 0; i < dma->buf_count; i++) { + buf = dma->buflist[i]; + buf_priv = buf->dev_private; + if (buf->pending && buf_priv->age <= done_age) { + /* The buffer has been processed, so it + can now be used */ + buf->pending = 0; + return buf; + } + } + udelay(1); + } + + r128_status(dev); + return NULL; +} + + +static int r128_get_vertbufs(drm_device_t *dev, drm_r128_vertex_t *v) +{ + drm_buf_t *buf; + int i; + + for (i = v->granted_count; i < v->request_count; i++) { + buf = r128_freelist_get(dev); + if (!buf) break; + buf->pid = current->pid; + copy_to_user_ret(&v->request_indices[i], + &buf->idx, + sizeof(buf->idx), + -EFAULT); + copy_to_user_ret(&v->request_sizes[i], + &buf->total, + sizeof(buf->total), + -EFAULT); + ++v->granted_count; + } + return 0; +} + +int r128_vertex_buf(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_r128_private_t *dev_priv = dev->dev_private; + drm_device_dma_t *dma = dev->dma; + int retcode = 0; + drm_r128_vertex_t v; + + if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) || + dev->lock.pid != current->pid) { + DRM_ERROR("r128_vertex_buf called without holding the lock\n"); + return -EINVAL; + } + + if (!dev_priv || dev_priv->is_pci) { + DRM_ERROR("r128_vertex_buf called with a PCI card\n"); + return -EINVAL; + } + + copy_from_user_ret(&v, (drm_r128_vertex_t *)arg, sizeof(v), -EFAULT); + DRM_DEBUG("%d: %d send, %d req\n", + current->pid, v.send_count, v.request_count); + + if (v.send_count < 0 || v.send_count > dma->buf_count) { + DRM_ERROR("Process %d trying to send %d buffers (of %d max)\n", + current->pid, v.send_count, dma->buf_count); + return -EINVAL; + } + if (v.request_count < 0 || v.request_count > dma->buf_count) { + DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", + current->pid, v.request_count, dma->buf_count); + return -EINVAL; + } + + if (v.send_count) { + retcode = r128_send_vertbufs(dev, &v); + } + + v.granted_count = 0; + + if (!retcode && v.request_count) { + retcode = r128_get_vertbufs(dev, &v); + } + + DRM_DEBUG("%d returning, granted = %d\n", + current->pid, v.granted_count); + copy_to_user_ret((drm_r128_vertex_t *)arg, &v, sizeof(v), -EFAULT); + + return retcode; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_drv.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_drv.c new file mode 100644 index 000000000..e5a85af90 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/r128_drv.c @@ -0,0 +1,737 @@ +/* r128_drv.c -- ATI Rage 128 driver -*- linux-c -*- + * Created: Mon Dec 13 09:47:27 1999 by faith@precisioninsight.com + * + * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Rickard E. (Rik) Faith <faith@precisioninsight.com> + * Kevin E. Martin <kevin@precisioninsight.com> + * + * $XFree86$ + * + */ + +#define EXPORT_SYMTAB +#include "drmP.h" +#include "r128_drv.h" +EXPORT_SYMBOL(r128_init); +EXPORT_SYMBOL(r128_cleanup); + +#define R128_NAME "r128" +#define R128_DESC "r128" +#define R128_DATE "20000607" +#define R128_MAJOR 1 +#define R128_MINOR 0 +#define R128_PATCHLEVEL 0 + +static drm_device_t r128_device; +drm_ctx_t r128_res_ctx; + +static struct file_operations r128_fops = { + open: r128_open, + flush: drm_flush, + release: r128_release, + ioctl: r128_ioctl, + mmap: drm_mmap, + read: drm_read, + fasync: drm_fasync, + poll: drm_poll, +}; + +static struct miscdevice r128_misc = { + minor: MISC_DYNAMIC_MINOR, + name: R128_NAME, + fops: &r128_fops, +}; + +static drm_ioctl_desc_t r128_ioctls[] = { + [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { r128_version, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = { drm_irq_busid, 0, 1 }, + + [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { drm_setunique, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { drm_block, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = { drm_unblock, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = { drm_authmagic, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = { drm_addmap, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { r128_addbufs, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { drm_markbufs, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { drm_infobufs, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { r128_mapbufs, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { drm_freebufs, 1, 0 }, + + [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { r128_addctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = { r128_rmctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = { r128_modctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = { r128_getctx, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = { r128_switchctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = { r128_newctx, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = { r128_resctx, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { r128_lock, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { r128_unlock, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 }, + +#ifdef DRM_AGP + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = { drm_agp_acquire, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = { drm_agp_release, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = { drm_agp_enable, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = { drm_agp_info, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = { drm_agp_alloc, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 }, +#endif + + [DRM_IOCTL_NR(DRM_IOCTL_R128_INIT)] = { r128_init_cce, 1, 1 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_RESET)] = { r128_eng_reset, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_FLUSH)] = { r128_eng_flush, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_PACKET)] = { r128_submit_pkt, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_IDLE)] = { r128_cce_idle, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_vertex_buf, 1, 0 }, +}; +#define R128_IOCTL_COUNT DRM_ARRAY_SIZE(r128_ioctls) + +#ifdef MODULE +int init_module(void); +void cleanup_module(void); +static char *r128 = NULL; + +MODULE_AUTHOR("Precision Insight, Inc., Cedar Park, Texas."); +MODULE_DESCRIPTION("r128"); +MODULE_PARM(r128, "s"); + +/* init_module is called when insmod is used to load the module */ + +int init_module(void) +{ + return r128_init(); +} + +/* cleanup_module is called when rmmod is used to unload the module */ + +void cleanup_module(void) +{ + r128_cleanup(); +} +#endif + +#ifndef MODULE +/* r128_setup is called by the kernel to parse command-line options passed + * via the boot-loader (e.g., LILO). It calls the insmod option routine, + * drm_parse_drm. + * + * This is not currently supported, since it requires changes to + * linux/init/main.c. */ + + +void __init r128_setup(char *str, int *ints) +{ + if (ints[0] != 0) { + DRM_ERROR("Illegal command line format, ignored\n"); + return; + } + drm_parse_options(str); +} +#endif + +static int r128_setup(drm_device_t *dev) +{ + int i; + + atomic_set(&dev->ioctl_count, 0); + atomic_set(&dev->vma_count, 0); + dev->buf_use = 0; + atomic_set(&dev->buf_alloc, 0); + + drm_dma_setup(dev); + + atomic_set(&dev->total_open, 0); + atomic_set(&dev->total_close, 0); + atomic_set(&dev->total_ioctl, 0); + atomic_set(&dev->total_irq, 0); + atomic_set(&dev->total_ctx, 0); + atomic_set(&dev->total_locks, 0); + atomic_set(&dev->total_unlocks, 0); + atomic_set(&dev->total_contends, 0); + atomic_set(&dev->total_sleeps, 0); + + for (i = 0; i < DRM_HASH_SIZE; i++) { + dev->magiclist[i].head = NULL; + dev->magiclist[i].tail = NULL; + } + dev->maplist = NULL; + dev->map_count = 0; + dev->vmalist = NULL; + dev->lock.hw_lock = NULL; + init_waitqueue_head(&dev->lock.lock_queue); + dev->queue_count = 0; + dev->queue_reserved = 0; + dev->queue_slots = 0; + dev->queuelist = NULL; + dev->irq = 0; + dev->context_flag = 0; + dev->interrupt_flag = 0; + dev->dma_flag = 0; + dev->last_context = 0; + dev->last_switch = 0; + dev->last_checked = 0; + init_timer(&dev->timer); + init_waitqueue_head(&dev->context_wait); + + dev->ctx_start = 0; + dev->lck_start = 0; + + dev->buf_rp = dev->buf; + dev->buf_wp = dev->buf; + dev->buf_end = dev->buf + DRM_BSZ; + dev->buf_async = NULL; + init_waitqueue_head(&dev->buf_readers); + init_waitqueue_head(&dev->buf_writers); + + r128_res_ctx.handle=-1; + + DRM_DEBUG("\n"); + + /* The kernel's context could be created here, but is now created + in drm_dma_enqueue. This is more resource-efficient for + hardware that does not do DMA, but may mean that + drm_select_queue fails between the time the interrupt is + initialized and the time the queues are initialized. */ + + return 0; +} + + +static int r128_takedown(drm_device_t *dev) +{ + int i; + drm_magic_entry_t *pt, *next; + drm_map_t *map; + drm_vma_entry_t *vma, *vma_next; + + DRM_DEBUG("\n"); + + down(&dev->struct_sem); + del_timer(&dev->timer); + + if (dev->devname) { + drm_free(dev->devname, strlen(dev->devname)+1, DRM_MEM_DRIVER); + dev->devname = NULL; + } + + if (dev->unique) { + drm_free(dev->unique, strlen(dev->unique)+1, DRM_MEM_DRIVER); + dev->unique = NULL; + dev->unique_len = 0; + } + /* Clear pid list */ + for (i = 0; i < DRM_HASH_SIZE; i++) { + for (pt = dev->magiclist[i].head; pt; pt = next) { + next = pt->next; + drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); + } + dev->magiclist[i].head = dev->magiclist[i].tail = NULL; + } + +#ifdef DRM_AGP + /* Clear AGP information */ + if (dev->agp) { + drm_agp_mem_t *entry; + drm_agp_mem_t *nexte; + + /* Remove AGP resources, but leave dev->agp + intact until r128_cleanup is called. */ + for (entry = dev->agp->memory; entry; entry = nexte) { + nexte = entry->next; + if (entry->bound) drm_unbind_agp(entry->memory); + drm_free_agp(entry->memory, entry->pages); + drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS); + } + dev->agp->memory = NULL; + + if (dev->agp->acquired && drm_agp.release) + (*drm_agp.release)(); + + dev->agp->acquired = 0; + dev->agp->enabled = 0; + } +#endif + + /* Clear vma list (only built for debugging) */ + if (dev->vmalist) { + for (vma = dev->vmalist; vma; vma = vma_next) { + vma_next = vma->next; + drm_free(vma, sizeof(*vma), DRM_MEM_VMAS); + } + dev->vmalist = NULL; + } + + /* Clear map area and mtrr information */ + if (dev->maplist) { + for (i = 0; i < dev->map_count; i++) { + map = dev->maplist[i]; + switch (map->type) { + case _DRM_REGISTERS: + case _DRM_FRAME_BUFFER: +#ifdef CONFIG_MTRR + if (map->mtrr >= 0) { + int retcode; + retcode = mtrr_del(map->mtrr, + map->offset, + map->size); + DRM_DEBUG("mtrr_del = %d\n", retcode); + } +#endif + drm_ioremapfree(map->handle, map->size); + break; + case _DRM_SHM: + drm_free_pages((unsigned long)map->handle, + drm_order(map->size) + - PAGE_SHIFT, + DRM_MEM_SAREA); + break; + case _DRM_AGP: + /* Do nothing here, because this is all + handled in the AGP/GART driver. */ + break; + } + drm_free(map, sizeof(*map), DRM_MEM_MAPS); + } + drm_free(dev->maplist, + dev->map_count * sizeof(*dev->maplist), + DRM_MEM_MAPS); + dev->maplist = NULL; + dev->map_count = 0; + } + + drm_dma_takedown(dev); + + dev->queue_count = 0; + if (dev->lock.hw_lock) { + dev->lock.hw_lock = NULL; /* SHM removed */ + dev->lock.pid = 0; + wake_up_interruptible(&dev->lock.lock_queue); + } + up(&dev->struct_sem); + + return 0; +} + +/* r128_init is called via init_module at module load time, or via + * linux/init/main.c (this is not currently supported). */ + +int r128_init(void) +{ + int retcode; + drm_device_t *dev = &r128_device; + + DRM_DEBUG("\n"); + + memset((void *)dev, 0, sizeof(*dev)); + dev->count_lock = SPIN_LOCK_UNLOCKED; + sema_init(&dev->struct_sem, 1); + +#ifdef MODULE + drm_parse_options(r128); +#endif + + if ((retcode = misc_register(&r128_misc))) { + DRM_ERROR("Cannot register \"%s\"\n", R128_NAME); + return retcode; + } + dev->device = MKDEV(MISC_MAJOR, r128_misc.minor); + dev->name = R128_NAME; + + drm_mem_init(); + drm_proc_init(dev); + +#ifdef DRM_AGP + dev->agp = drm_agp_init(); + +#ifdef CONFIG_MTRR + dev->agp->agp_mtrr = mtrr_add(dev->agp->agp_info.aper_base, + dev->agp->agp_info.aper_size*1024*1024, + MTRR_TYPE_WRCOMB, + 1); +#endif +#endif + + if((retcode = drm_ctxbitmap_init(dev))) { + DRM_ERROR("Cannot allocate memory for context bitmap.\n"); + drm_proc_cleanup(); + misc_deregister(&r128_misc); + r128_takedown(dev); + return retcode; + } + + DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", + R128_NAME, + R128_MAJOR, + R128_MINOR, + R128_PATCHLEVEL, + R128_DATE, + r128_misc.minor); + + return 0; +} + +/* r128_cleanup is called via cleanup_module at module unload time. */ + +void r128_cleanup(void) +{ + drm_device_t *dev = &r128_device; + + DRM_DEBUG("\n"); + + drm_proc_cleanup(); + if (misc_deregister(&r128_misc)) { + DRM_ERROR("Cannot unload module\n"); + } else { + DRM_INFO("Module unloaded\n"); + } + drm_ctxbitmap_cleanup(dev); + r128_takedown(dev); +#ifdef DRM_AGP + if (dev->agp) { + /* FIXME -- free other information, too */ + drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS); + dev->agp = NULL; + } +#endif +} + +int r128_version(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_version_t version; + int len; + + copy_from_user_ret(&version, + (drm_version_t *)arg, + sizeof(version), + -EFAULT); + +#define DRM_COPY(name,value) \ + len = strlen(value); \ + if (len > name##_len) len = name##_len; \ + name##_len = strlen(value); \ + if (len && name) { \ + copy_to_user_ret(name, value, len, -EFAULT); \ + } + + version.version_major = R128_MAJOR; + version.version_minor = R128_MINOR; + version.version_patchlevel = R128_PATCHLEVEL; + + DRM_COPY(version.name, R128_NAME); + DRM_COPY(version.date, R128_DATE); + DRM_COPY(version.desc, R128_DESC); + + copy_to_user_ret((drm_version_t *)arg, + &version, + sizeof(version), + -EFAULT); + return 0; +} + +int r128_open(struct inode *inode, struct file *filp) +{ + drm_device_t *dev = &r128_device; + int retcode = 0; + + DRM_DEBUG("open_count = %d\n", dev->open_count); + if (!(retcode = drm_open_helper(inode, filp, dev))) { + MOD_INC_USE_COUNT; + atomic_inc(&dev->total_open); + spin_lock(&dev->count_lock); + if (!dev->open_count++) { + spin_unlock(&dev->count_lock); + return r128_setup(dev); + } + spin_unlock(&dev->count_lock); + } + return retcode; +} + +int r128_release(struct inode *inode, struct file *filp) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + int retcode = 0; + + DRM_DEBUG("open_count = %d\n", dev->open_count); + if (!(retcode = drm_release(inode, filp))) { + MOD_DEC_USE_COUNT; + atomic_inc(&dev->total_close); + spin_lock(&dev->count_lock); + if (!--dev->open_count) { + if (atomic_read(&dev->ioctl_count) || dev->blocked) { + DRM_ERROR("Device busy: %d %d\n", + atomic_read(&dev->ioctl_count), + dev->blocked); + spin_unlock(&dev->count_lock); + return -EBUSY; + } + spin_unlock(&dev->count_lock); + return r128_takedown(dev); + } + spin_unlock(&dev->count_lock); + } + return retcode; +} + +/* r128_ioctl is called whenever a process performs an ioctl on /dev/drm. */ + +int r128_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + int nr = DRM_IOCTL_NR(cmd); + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + int retcode = 0; + drm_ioctl_desc_t *ioctl; + drm_ioctl_t *func; + + atomic_inc(&dev->ioctl_count); + atomic_inc(&dev->total_ioctl); + ++priv->ioctl_count; + + DRM_DEBUG("pid = %d, cmd = 0x%02x, nr = 0x%02x, dev 0x%x, auth = %d\n", + current->pid, cmd, nr, dev->device, priv->authenticated); + + if (nr >= R128_IOCTL_COUNT) { + retcode = -EINVAL; + } else { + ioctl = &r128_ioctls[nr]; + func = ioctl->func; + + if (!func) { + DRM_DEBUG("no function\n"); + retcode = -EINVAL; + } else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN)) + || (ioctl->auth_needed && !priv->authenticated)) { + retcode = -EACCES; + } else { + retcode = (func)(inode, filp, cmd, arg); + } + } + + atomic_dec(&dev->ioctl_count); + return retcode; +} + +int r128_lock(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + DECLARE_WAITQUEUE(entry, current); + int ret = 0; + drm_lock_t lock; +#if DRM_DMA_HISTOGRAM + cycles_t start; + + dev->lck_start = start = get_cycles(); +#endif + + copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT); + + if (lock.context == DRM_KERNEL_CONTEXT) { + DRM_ERROR("Process %d using kernel context %d\n", + current->pid, lock.context); + return -EINVAL; + } + + DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n", + lock.context, current->pid, dev->lock.hw_lock->lock, + lock.flags); + +#if 0 + /* dev->queue_count == 0 right now for + r128. FIXME? */ + if (lock.context < 0 || lock.context >= dev->queue_count) + return -EINVAL; +#endif + + if (!ret) { +#if 0 + if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) + != lock.context) { + long j = jiffies - dev->lock.lock_time; + + if (lock.context == r128_res_ctx.handle && + j >= 0 && j < DRM_LOCK_SLICE) { + /* Can't take lock if we just had it and + there is contention. */ + DRM_DEBUG("%d (pid %d) delayed j=%d dev=%d jiffies=%d\n", + lock.context, current->pid, j, + dev->lock.lock_time, jiffies); + current->state = TASK_INTERRUPTIBLE; + current->policy |= SCHED_YIELD; + schedule_timeout(DRM_LOCK_SLICE-j); + DRM_DEBUG("jiffies=%d\n", jiffies); + } + } +#endif + add_wait_queue(&dev->lock.lock_queue, &entry); + for (;;) { + if (!dev->lock.hw_lock) { + /* Device has been unregistered */ + ret = -EINTR; + break; + } + if (drm_lock_take(&dev->lock.hw_lock->lock, + lock.context)) { + dev->lock.pid = current->pid; + dev->lock.lock_time = jiffies; + atomic_inc(&dev->total_locks); + break; /* Got lock */ + } + + /* Contention */ + atomic_inc(&dev->total_sleeps); + current->state = TASK_INTERRUPTIBLE; +#if 1 + current->policy |= SCHED_YIELD; +#endif + schedule(); + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + } + current->state = TASK_RUNNING; + remove_wait_queue(&dev->lock.lock_queue, &entry); + } + +#if 0 + if (!ret && dev->last_context != lock.context && + lock.context != r128_res_ctx.handle && + dev->last_context != r128_res_ctx.handle) { + add_wait_queue(&dev->context_wait, &entry); + current->state = TASK_INTERRUPTIBLE; + /* PRE: dev->last_context != lock.context */ + r128_context_switch(dev, dev->last_context, lock.context); + /* POST: we will wait for the context + switch and will dispatch on a later call + when dev->last_context == lock.context + NOTE WE HOLD THE LOCK THROUGHOUT THIS + TIME! */ + current->policy |= SCHED_YIELD; + schedule(); + current->state = TASK_RUNNING; + remove_wait_queue(&dev->context_wait, &entry); + if (signal_pending(current)) { + ret = -EINTR; + } else if (dev->last_context != lock.context) { + DRM_ERROR("Context mismatch: %d %d\n", + dev->last_context, lock.context); + } + } +#endif + + if (!ret) { + if (lock.flags & _DRM_LOCK_READY) { + /* Wait for space in DMA/FIFO */ + } + if (lock.flags & _DRM_LOCK_QUIESCENT) { + /* Make hardware quiescent */ +#if 0 + r128_quiescent(dev); +#endif + } + } + +#if 0 + DRM_ERROR("pid = %5d, old counter = %5ld\n", + current->pid, current->counter); +#endif + if (lock.context != r128_res_ctx.handle) { + current->counter = 5; + current->priority = DEF_PRIORITY/4; + } +#if 0 + while (current->counter > 25) + current->counter >>= 1; /* decrease time slice */ + DRM_ERROR("pid = %5d, new counter = %5ld\n", + current->pid, current->counter); +#endif + DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock"); + +#if DRM_DMA_HISTOGRAM + atomic_inc(&dev->histo.lacq[drm_histogram_slot(get_cycles() - start)]); +#endif + + return ret; +} + + +int r128_unlock(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_lock_t lock; + + copy_from_user_ret(&lock, (drm_lock_t *)arg, sizeof(lock), -EFAULT); + + if (lock.context == DRM_KERNEL_CONTEXT) { + DRM_ERROR("Process %d using kernel context %d\n", + current->pid, lock.context); + return -EINVAL; + } + + DRM_DEBUG("%d frees lock (%d holds)\n", + lock.context, + _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); + atomic_inc(&dev->total_unlocks); + if (_DRM_LOCK_IS_CONT(dev->lock.hw_lock->lock)) + atomic_inc(&dev->total_contends); + drm_lock_transfer(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT); + /* FIXME: Try to send data to card here */ + if (!dev->context_flag) { + if (drm_lock_free(dev, &dev->lock.hw_lock->lock, + DRM_KERNEL_CONTEXT)) { + DRM_ERROR("\n"); + } + } + +#if 0 + current->policy |= SCHED_YIELD; + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1000); +#endif + + if (lock.context != r128_res_ctx.handle) { + current->counter = 5; + current->priority = DEF_PRIORITY; + } +#if 0 + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(10); +#endif + + return 0; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmR128.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmR128.c new file mode 100644 index 000000000..e08a3185d --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmR128.c @@ -0,0 +1,199 @@ +/* xf86drmR128.c -- User-level interface to Rage 128 DRM device + * Created: Sun Apr 9 18:13:54 2000 by kevin@precisioninsight.com + * + * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Kevin E. Martin <kevin@precisioninsight.com> + * + * $XFree86$ + * + */ + +#ifdef XFree86Server +# include "xf86.h" +# include "xf86_OSproc.h" +# include "xf86_ansic.h" +# include "xf86Priv.h" +# define _DRM_MALLOC xalloc +# define _DRM_FREE xfree +# ifndef XFree86LOADER +# include <sys/stat.h> +# include <sys/mman.h> +# endif +#else +# include <stdio.h> +# include <stdlib.h> +# include <unistd.h> +# include <string.h> +# include <ctype.h> +# include <fcntl.h> +# include <errno.h> +# include <signal.h> +# include <sys/types.h> +# include <sys/stat.h> +# include <sys/ioctl.h> +# include <sys/mman.h> +# include <sys/time.h> +# ifdef DRM_USE_MALLOC +# define _DRM_MALLOC malloc +# define _DRM_FREE free +extern int xf86InstallSIGIOHandler(int fd, void (*f)(int, void *), void *); +extern int xf86RemoveSIGIOHandler(int fd); +# else +# include <Xlibint.h> +# define _DRM_MALLOC Xmalloc +# define _DRM_FREE Xfree +# endif +#endif + +/* Not all systems have MAP_FAILED defined */ +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +#include <sys/sysmacros.h> /* for makedev() */ +#include "xf86drm.h" +#include "xf86drmR128.h" +#include "drm.h" + +int drmR128InitCCE(int fd, drmR128Init *info) +{ + drm_r128_init_t init; + + memset(&init, 0, sizeof(drm_r128_init_t)); + + init.func = R128_INIT_CCE; + init.sarea_priv_offset = info->sarea_priv_offset; + init.is_pci = info->is_pci; + init.cce_mode = info->cce_mode; + init.cce_fifo_size = info->cce_fifo_size; + init.cce_secure = info->cce_secure; + init.ring_size = info->ring_size; + init.usec_timeout = info->usec_timeout; + + init.fb_offset = info->fb_offset; + init.agp_ring_offset = info->agp_ring_offset; + init.agp_read_ptr_offset = info->agp_read_ptr_offset; + init.agp_vertbufs_offset = info->agp_vertbufs_offset; + init.agp_indbufs_offset = info->agp_indbufs_offset; + init.agp_textures_offset = info->agp_textures_offset; + init.mmio_offset = info->mmio_offset; + + if (ioctl(fd, DRM_IOCTL_R128_INIT, &init)) return -errno; + + return 0; +} + +int drmR128CleanupCCE(int fd) +{ + drm_r128_init_t init; + + memset(&init, 0, sizeof(drm_r128_init_t)); + + init.func = R128_CLEANUP_CCE; + + if (ioctl(fd, DRM_IOCTL_R128_INIT, &init)) return -errno; + + return 0; +} + +int drmR128EngineReset(int fd) +{ + if (ioctl(fd, DRM_IOCTL_R128_RESET, NULL)) return -errno; + + return 0; +} + +int drmR128EngineFlush(int fd) +{ + if (ioctl(fd, DRM_IOCTL_R128_FLUSH, NULL)) return -errno; + + return 0; +} + +int drmR128WaitForIdle(int fd) +{ + if (ioctl(fd, DRM_IOCTL_R128_IDLE, NULL)) return -errno; + + return 0; +} + +int drmR128SubmitPacket(int fd, CARD32 *buffer, int *count, int flags) +{ + drm_r128_packet_t packet; + int ret; + + memset(&packet, 0, sizeof(drm_r128_packet_t)); + + packet.count = *count; + packet.flags = flags; + + while (packet.count > 0) { + packet.buffer = buffer + (*count - packet.count); + ret = ioctl(fd, DRM_IOCTL_R128_PACKET, &packet); + if (ret < 0 && ret != -EAGAIN) { + *count = packet.count; + return -errno; + } + } + + *count = 0; + return 0; +} + +int drmR128GetVertexBuffers(int fd, int count, int *indices, int *sizes) +{ + drm_r128_vertex_t v; + + v.send_count = 0; + v.send_indices = NULL; + v.send_sizes = NULL; + v.prim = DRM_R128_PRIM_NONE; + v.request_count = count; + v.request_indices = indices; + v.request_sizes = sizes; + v.granted_count = 0; + + if (ioctl(fd, DRM_IOCTL_R128_VERTEX, &v)) return -errno; + + return v.granted_count; +} + +int drmR128FlushVertexBuffers(int fd, int count, int *indices, + int *sizes, drmR128PrimType prim) +{ + drm_r128_vertex_t v; + + v.send_count = count; + v.send_indices = indices; + v.send_sizes = sizes; + v.prim = prim; + v.request_count = 0; + v.request_indices = NULL; + v.request_sizes = NULL; + v.granted_count = 0; + + if (ioctl(fd, DRM_IOCTL_R128_VERTEX, &v) < 0) return -errno; + + return 0; +} diff --git a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/drm.h b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/drm.h index 7b8e88265..c71af2cc6 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/drm.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/drm.h @@ -1,8 +1,8 @@ /* drm.h -- Header for Direct Rendering Manager -*- linux-c -*- * Created: Mon Jan 4 10:05:05 1999 by faith@precisioninsight.com - * Revised: Mon Feb 14 00:15:23 2000 by kevin@precisioninsight.com * * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -11,11 +11,11 @@ * 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 @@ -23,8 +23,9 @@ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. - * - * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h,v 1.5 2000/02/23 04:47:26 martin Exp $ + * + * Authors: + * Rickard E. (Rik) Faith <faith@valinux.com> * * Acknowledgements: * Dec 1999, Richard Henderson <rth@twiddle.net>, move to generic cmpxchg. @@ -61,6 +62,20 @@ typedef unsigned int drm_context_t; typedef unsigned int drm_drawable_t; typedef unsigned int drm_magic_t; +/* Warning: If you change this structure, make sure you change + * XF86DRIClipRectRec in the server as well */ + +typedef struct drm_clip_rect { + unsigned short x1; + unsigned short y1; + unsigned short x2; + unsigned short y2; +} drm_clip_rect_t; + +/* Seperate include files for the i810/mga/r128 specific structures */ +#include "mga_drm.h" +#include "i810_drm.h" +#include "r128_drm.h" typedef struct drm_version { int version_major; /* Major version */ @@ -101,7 +116,8 @@ typedef struct drm_control { typedef enum drm_map_type { _DRM_FRAME_BUFFER = 0, /* WC (no caching), no core dump */ _DRM_REGISTERS = 1, /* no caching, no core dump */ - _DRM_SHM = 2 /* shared, cached */ + _DRM_SHM = 2, /* shared, cached */ + _DRM_AGP = 3 /* AGP/GART */ } drm_map_type_t; typedef enum drm_map_flags { @@ -165,8 +181,11 @@ typedef struct drm_buf_desc { int low_mark; /* Low water mark */ int high_mark; /* High water mark */ enum { - DRM_PAGE_ALIGN = 0x01 /* Align on page boundaries for DMA */ + _DRM_PAGE_ALIGN = 0x01, /* Align on page boundaries for DMA */ + _DRM_AGP_BUFFER = 0x02 /* Buffer is in agp space */ } flags; + unsigned long agp_start; /* Start address of where the agp buffers + * are in the agp aperture */ } drm_buf_desc_t; typedef struct drm_buf_info { @@ -237,6 +256,38 @@ typedef struct drm_irq_busid { int funcnum; } drm_irq_busid_t; +typedef struct drm_agp_mode { + unsigned long mode; +} drm_agp_mode_t; + + /* For drm_agp_alloc -- allocated a buffer */ +typedef struct drm_agp_buffer { + unsigned long size; /* In bytes -- will round to page boundary */ + unsigned long handle; /* Used for BIND/UNBIND ioctls */ + unsigned long type; /* Type of memory to allocate */ + unsigned long physical; /* Physical used by i810 */ +} drm_agp_buffer_t; + + /* For drm_agp_bind */ +typedef struct drm_agp_binding { + unsigned long handle; /* From drm_agp_buffer */ + unsigned long offset; /* In bytes -- will round to page boundary */ +} drm_agp_binding_t; + +typedef struct drm_agp_info { + int agp_version_major; + int agp_version_minor; + unsigned long mode; + unsigned long aperture_base; /* physical address */ + unsigned long aperture_size; /* bytes */ + unsigned long memory_allowed; /* bytes */ + unsigned long memory_used; + + /* PCI information */ + unsigned short id_vendor; + unsigned short id_device; +} drm_agp_info_t; + #define DRM_IOCTL_BASE 'd' #define DRM_IOCTL_NR(n) _IOC_NR(n) #define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr) @@ -247,7 +298,7 @@ typedef struct drm_irq_busid { #define DRM_IOCTL_VERSION DRM_IOWR(0x00, drm_version_t) #define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm_unique_t) -#define DRM_IOCTL_GET_MAGIC DRM_IOW( 0x02, drm_auth_t) +#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, drm_auth_t) #define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, drm_irq_busid_t) #define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm_unique_t) @@ -276,4 +327,39 @@ typedef struct drm_irq_busid { #define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, drm_lock_t) #define DRM_IOCTL_FINISH DRM_IOW( 0x2c, drm_lock_t) +#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30) +#define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31) +#define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, drm_agp_mode_t) +#define DRM_IOCTL_AGP_INFO DRM_IOR( 0x33, drm_agp_info_t) +#define DRM_IOCTL_AGP_ALLOC DRM_IOWR(0x34, drm_agp_buffer_t) +#define DRM_IOCTL_AGP_FREE DRM_IOW( 0x35, drm_agp_buffer_t) +#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, drm_agp_binding_t) +#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_t) + +/* Mga specific ioctls */ +#define DRM_IOCTL_MGA_INIT DRM_IOW( 0x40, drm_mga_init_t) +#define DRM_IOCTL_MGA_SWAP DRM_IOW( 0x41, drm_mga_swap_t) +#define DRM_IOCTL_MGA_CLEAR DRM_IOW( 0x42, drm_mga_clear_t) +#define DRM_IOCTL_MGA_ILOAD DRM_IOW( 0x43, drm_mga_iload_t) +#define DRM_IOCTL_MGA_VERTEX DRM_IOW( 0x44, drm_mga_vertex_t) +#define DRM_IOCTL_MGA_FLUSH DRM_IOW( 0x45, drm_lock_t ) +#define DRM_IOCTL_MGA_INDICES DRM_IOW( 0x46, drm_mga_indices_t) + +/* I810 specific ioctls */ +#define DRM_IOCTL_I810_INIT DRM_IOW( 0x40, drm_i810_init_t) +#define DRM_IOCTL_I810_VERTEX DRM_IOW( 0x41, drm_i810_vertex_t) +#define DRM_IOCTL_I810_CLEAR DRM_IOW( 0x42, drm_i810_clear_t) +#define DRM_IOCTL_I810_FLUSH DRM_IO ( 0x43) +#define DRM_IOCTL_I810_GETAGE DRM_IO ( 0x44) +#define DRM_IOCTL_I810_GETBUF DRM_IOW( 0x45, drm_i810_dma_t) +#define DRM_IOCTL_I810_SWAP DRM_IO ( 0x46) + +/* Rage 128 specific ioctls */ +#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t) +#define DRM_IOCTL_R128_RESET DRM_IO( 0x41) +#define DRM_IOCTL_R128_FLUSH DRM_IO( 0x42) +#define DRM_IOCTL_R128_IDLE DRM_IO( 0x43) +#define DRM_IOCTL_R128_PACKET DRM_IOW( 0x44, drm_r128_packet_t) +#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x45, drm_r128_vertex_t) + #endif diff --git a/xc/programs/Xserver/hw/xfree86/os-support/xf86drmR128.h b/xc/programs/Xserver/hw/xfree86/os-support/xf86drmR128.h new file mode 100644 index 000000000..dd430ed87 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/os-support/xf86drmR128.h @@ -0,0 +1,80 @@ +/* xf86drm.h -- OS-independent header for DRM user-level library interface + * Created: Sun Apr 9 18:16:28 2000 by kevin@precisioninsight.com + * + * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, 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 + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Kevin E. Martin <kevin@precisioninsight.com> + * + * $XFree86$ + * + */ + +#ifndef _XF86DRI_R128_H_ +#define _XF86DRI_R128_H_ + +/* WARNING: If you change any of these defines, make sure to change + * the kernel include file as well (r128_drm.h) + */ + +typedef struct _drmR128Init { + int sarea_priv_offset; + int is_pci; + int cce_mode; + int cce_fifo_size; + int cce_secure; + int ring_size; + int usec_timeout; + + int fb_offset; + int agp_ring_offset; + int agp_read_ptr_offset; + int agp_vertbufs_offset; + int agp_indbufs_offset; + int agp_textures_offset; + int mmio_offset; +} drmR128Init; + +typedef enum { + DRM_R128_PRIM_NONE = 0x0001, + DRM_R128_PRIM_POINT = 0x0002, + DRM_R128_PRIM_LINE = 0x0004, + DRM_R128_PRIM_POLY_LINE = 0x0008, + DRM_R128_PRIM_TRI_LIST = 0x0010, + DRM_R128_PRIM_TRI_FAN = 0x0020, + DRM_R128_PRIM_TRI_STRIP = 0x0040, + DRM_R128_PRIM_TRI_TYPE2 = 0x0080 +} drmR128PrimType; + + +extern int drmR128InitCCE(int fd, drmR128Init *info); +extern int drmR128CleanupCCE(int fd); +extern int drmR128EngineReset(int fd); +extern int drmR128EngineFlush(int fd); +extern int drmR128WaitForIdle(int fd); +extern int drmR128SubmitPacket(int fd, CARD32 *buffer, int *count, int flags); +extern int drmR128GetVertexBuffers(int fd, int count, int *indices, + int *sizes); +extern int drmR128FlushVertexBuffers(int fd, int count, int *indices, + int *sizes, drmR128PrimType prim); + +#endif |