diff options
41 files changed, 5225 insertions, 1092 deletions
diff --git a/xc/lib/GL/mesa/src/drv/r128/Imakefile b/xc/lib/GL/mesa/src/drv/r128/Imakefile index 6ca57a376..dd01c3ce2 100644 --- a/xc/lib/GL/mesa/src/drv/r128/Imakefile +++ b/xc/lib/GL/mesa/src/drv/r128/Imakefile @@ -25,10 +25,14 @@ MESA_INCLUDES = -I. -I.. -I../../include INCLUDES = -I$(XLIBSRC) -I$(EXTINCSRC) $(MESA_INCLUDES) $(DRI_INCLUDES) DRISRCS = r128_xmesa.c r128_cce.c r128_dd.c r128_state.c \ r128_span.c r128_depth.c r128_tex.c r128_clear.c \ - r128_swap.c r128_tris.c r128_vb.c + r128_swap.c r128_tris.c r128_vb.c r128_context.c \ + r128_screen.c r128_pipeline.c r128_fastpath.c \ + mm.c DRIOBJS = r128_xmesa.o r128_cce.o r128_dd.o r128_state.o \ r128_span.o r128_depth.o r128_tex.o r128_clear.o \ - r128_swap.o r128_tris.o r128_vb.o + r128_swap.o r128_tris.o r128_vb.o r128_context.o \ + r128_screen.o r128_pipeline.o r128_fastpath.o \ + mm.o SRCS = $(DRISRCS) OBJS = $(DRIOBJS) diff --git a/xc/lib/GL/mesa/src/drv/r128/mm.c b/xc/lib/GL/mesa/src/drv/r128/mm.c new file mode 100644 index 000000000..00ad43a8c --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/mm.c @@ -0,0 +1,262 @@ +/* + * GLX Hardware Device Driver common code + * Copyright (C) 1999 Keith Whitwell + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * + */ + +#include <stdlib.h> +#include <stdio.h> + +#include "mm.h" +/* #include "hwlog.h" */ + +#define ISFREE(bptr) ((bptr)->free) +/* #define PRINTF(f,a...) hwMsg(1,f, ## a) */ +#define PRINTF(f,a...) fprintf(stderr, f, ## a) + +void mmDumpMemInfo( memHeap_t *heap ) +{ + TMemBlock *p; + + PRINTF("Memory heap %p:\n", heap); + if (heap == 0) { + PRINTF(" heap == 0\n"); + } else { + p = (TMemBlock *)heap; + while (p) { + PRINTF(" Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size, + p->free ? '.':'U', + p->reserved ? 'R':'.'); + p = p->next; + } + } + PRINTF("End of memory blocks\n"); +} + +memHeap_t *mmInit(int ofs, + int size) +{ + PMemBlock blocks; + + if (size <= 0) { + return 0; + } + blocks = (TMemBlock *) calloc(1,sizeof(TMemBlock)); + if (blocks) { + blocks->ofs = ofs; + blocks->size = size; + blocks->free = 1; + return (memHeap_t *)blocks; + } else + return 0; +} + +/* Kludgey workaround for existing i810 server. Remove soon. + */ +memHeap_t *mmAddRange( memHeap_t *heap, + int ofs, + int size ) +{ + PMemBlock blocks; + blocks = (TMemBlock *) calloc(2,sizeof(TMemBlock)); + if (blocks) { + blocks[0].size = size; + blocks[0].free = 1; + blocks[0].ofs = ofs; + blocks[0].next = &blocks[1]; + + /* Discontinuity - stops JoinBlock from trying to join non-adjacent + * ranges. + */ + blocks[1].size = 0; + blocks[1].free = 0; + blocks[1].ofs = ofs+size; + blocks[1].next = (PMemBlock) heap; + return (memHeap_t *)blocks; + } + else + return heap; +} + +static TMemBlock* SliceBlock(TMemBlock *p, + int startofs, int size, + int reserved, int alignment) +{ + TMemBlock *newblock; + + /* break left */ + if (startofs > p->ofs) { + newblock = (TMemBlock*) calloc(1,sizeof(TMemBlock)); + newblock->ofs = startofs; + newblock->size = p->size - (startofs - p->ofs); + newblock->free = 1; + newblock->next = p->next; + p->size -= newblock->size; + p->next = newblock; + p = newblock; + } + + /* break right */ + if (size < p->size) { + newblock = (TMemBlock*) calloc(1,sizeof(TMemBlock)); + newblock->ofs = startofs + size; + newblock->size = p->size - size; + newblock->free = 1; + newblock->next = p->next; + p->size = size; + p->next = newblock; + } + + /* p = middle block */ + p->align = alignment; + p->free = 0; + p->reserved = reserved; + return p; +} + +PMemBlock mmAllocMem( memHeap_t *heap, int size, int align2, int startSearch) +{ + int mask,startofs,endofs; + TMemBlock *p; + + if (!heap || align2 < 0 || size <= 0) + return NULL; + mask = (1 << align2)-1; + startofs = 0; + p = (TMemBlock *)heap; + while (p) { + if (ISFREE(p)) { + startofs = (p->ofs + mask) & ~mask; + if ( startofs < startSearch ) { + startofs = startSearch; + } + endofs = startofs+size; + if (endofs <= (p->ofs+p->size)) + break; + } + p = p->next; + } + if (!p) + return NULL; + p = SliceBlock(p,startofs,size,0,mask+1); + p->heap = heap; + return p; +} + +static __inline__ int Join2Blocks(TMemBlock *p) +{ + if (p->free && p->next && p->next->free) { + TMemBlock *q = p->next; + p->size += q->size; + p->next = q->next; + free(q); + return 1; + } + return 0; +} + +int mmFreeMem(PMemBlock b) +{ + TMemBlock *p,*prev; + + if (!b) + return 0; + if (!b->heap) { + fprintf(stderr, "no heap\n"); + return -1; + } + p = b->heap; + prev = NULL; + while (p && p != b) { + prev = p; + p = p->next; + } + if (!p || p->free || p->reserved) { + if (!p) + fprintf(stderr, "block not found in heap\n"); + else if (p->free) + fprintf(stderr, "block already free\n"); + else + fprintf(stderr, "block is reserved\n"); + return -1; + } + p->free = 1; + Join2Blocks(p); + if (prev) + Join2Blocks(prev); + return 0; +} + +int mmReserveMem(memHeap_t *heap, int offset,int size) +{ + int endofs; + TMemBlock *p; + + if (!heap || size <= 0) + return -1; + endofs = offset+size; + p = (TMemBlock *)heap; + while (p && p->ofs <= offset) { + if (ISFREE(p) && endofs <= (p->ofs+p->size)) { + SliceBlock(p,offset,size,1,1); + return 0; + } + p = p->next; + } + return -1; +} + +int mmFreeReserved(memHeap_t *heap, int offset) +{ + TMemBlock *p,*prev; + + if (!heap) + return -1; + p = (TMemBlock *)heap; + prev = NULL; + while (p && p->ofs != offset) { + prev = p; + p = p->next; + } + if (!p || !p->reserved) + return -1; + p->free = 1; + p->reserved = 0; + Join2Blocks(p); + if (prev) + Join2Blocks(prev); + return 0; +} + +void mmDestroy(memHeap_t *heap) +{ + TMemBlock *p,*q; + + if (!heap) + return; + p = (TMemBlock *)heap; + while (p) { + q = p->next; + free(p); + p = q; + } +} diff --git a/xc/lib/GL/mesa/src/drv/r128/mm.h b/xc/lib/GL/mesa/src/drv/r128/mm.h new file mode 100644 index 000000000..6fa6e8b69 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/mm.h @@ -0,0 +1,101 @@ +/* + * GLX Hardware Device Driver common code + * Copyright (C) 1999 Keith Whitwell + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef MM_INC +#define MM_INC + +struct mem_block_t { + struct mem_block_t *next; + struct mem_block_t *heap; + int ofs,size; + int align; + int free:1; + int reserved:1; +}; +typedef struct mem_block_t TMemBlock; +typedef struct mem_block_t *PMemBlock; + +/* a heap is just the first block in a chain */ +typedef struct mem_block_t memHeap_t; + +static __inline__ int mmBlockSize(PMemBlock b) +{ return b->size; } + +static __inline__ int mmOffset(PMemBlock b) +{ return b->ofs; } + +static __inline__ void mmMarkReserved(PMemBlock b) +{ b->reserved = 1; } + +/* + * input: total size in bytes + * return: a heap pointer if OK, NULL if error + */ +memHeap_t *mmInit( int ofs, int size ); + + + +memHeap_t *mmAddRange( memHeap_t *heap, + int ofs, + int size ); + + +/* + * Allocate 'size' bytes with 2^align2 bytes alignment, + * restrict the search to free memory after 'startSearch' + * depth and back buffers should be in different 4mb banks + * to get better page hits if possible + * input: size = size of block + * align2 = 2^align2 bytes alignment + * startSearch = linear offset from start of heap to begin search + * return: pointer to the allocated block, 0 if error + */ +PMemBlock mmAllocMem( memHeap_t *heap, int size, int align2, int startSearch ); + +/* + * Free block starts at offset + * input: pointer to a block + * return: 0 if OK, -1 if error + */ +int mmFreeMem( PMemBlock b ); + +/* + * Reserve 'size' bytes block start at offset + * This is used to prevent allocation of memory already used + * by the X server for the front buffer, pixmaps, and cursor + * input: size, offset + * output: 0 if OK, -1 if error + */ +int mmReserveMem( memHeap_t *heap, int offset,int size ); +int mmFreeReserved( memHeap_t *heap, int offset ); + +/* + * destroy MM + */ +void mmDestroy( memHeap_t *mmInit ); + +/* For debuging purpose. */ +void mmDumpMemInfo( memHeap_t *mmInit ); + +#endif diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_cce.c b/xc/lib/GL/mesa/src/drv/r128/r128_cce.c index 9f9fec81c..63742fe78 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_cce.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_cce.c @@ -38,6 +38,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r128_reg.h" #include "r128_cce.h" +/* FIXME: Requires access to secure registers */ static int INPLL(r128ScreenPtr pScrn, int addr) { unsigned char *R128MMIO = pScrn->mmio; @@ -46,6 +47,7 @@ static int INPLL(r128ScreenPtr pScrn, int addr) return INREG(R128_CLOCK_CNTL_DATA); } +/* FIXME: Requires access to secure registers */ void R128EngineFlush(r128ScreenPtr pScrn) { unsigned char *R128MMIO = pScrn->mmio; @@ -57,6 +59,7 @@ void R128EngineFlush(r128ScreenPtr pScrn) } } +/* FIXME: Requires access to secure registers */ void R128EngineReset(r128ScreenPtr pScrn) { unsigned char *R128MMIO = pScrn->mmio; @@ -83,6 +86,8 @@ void R128EngineReset(r128ScreenPtr pScrn) OUTREG(R128_GEN_RESET_CNTL, gen_reset_cntl); } +/* The FIFO has 64 slots. This routines waits until at least `entries' + of these slots are empty. */ void R128WaitForFifoFunction(r128ScreenPtr pScrn, int entries) { unsigned char *R128MMIO = pScrn->mmio; @@ -100,6 +105,9 @@ void R128WaitForFifoFunction(r128ScreenPtr pScrn, int entries) } } +/* Wait for the graphics engine to be completely idle: the FIFO has + drained, the Pixel Cache is flushed, and the engine is idle. This is + a standard "sync" function that will make the hardware quiescent. */ void R128WaitForIdle(r128ScreenPtr pScrn) { unsigned char *R128MMIO = pScrn->mmio; @@ -120,6 +128,8 @@ void R128WaitForIdle(r128ScreenPtr pScrn) } } +/* Wait for at least `entries' slots are free. The actual number of + slots available is stored in info->CCEFifoSize. */ void R128CCEWaitForFifoFunction(r128ScreenPtr pScrn, int entries) { unsigned char *R128MMIO = pScrn->mmio; @@ -136,6 +146,8 @@ void R128CCEWaitForFifoFunction(r128ScreenPtr pScrn, int entries) } } +/* Wait until the CCE is completely idle: the FIFO has drained and the + CCE is idle. */ void R128CCEWaitForIdle(r128ScreenPtr pScrn) { unsigned char *R128MMIO = pScrn->mmio; @@ -157,28 +169,23 @@ void R128CCEWaitForIdle(r128ScreenPtr pScrn) } } -/* NOTE: This function must be called before using the CCE */ -void R128CCEStart(r128ScreenPtr pScrn) +/* Flush the CPU's write-combining cache */ +void R128FlushWCMemory(void) { - unsigned char *R128MMIO = pScrn->mmio; - - R128WaitForIdle(pScrn); - OUTREG(R128_PM4_BUFFER_CNTL, pScrn->CCEMode); - (void)INREG(R128_PM4_BUFFER_ADDR); /* as per the sample code */ - OUTREG(R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN); -} - -/* NOTE: This function must be called before using the standard MMIO - mode for the X server. Also, this function is not (currently) called - by the client-side DRI driver; rather, it is only called in the X - server when the X server's context is swapped in. */ -void R128CCEEnd(r128ScreenPtr pScrn) -{ - unsigned char *R128MMIO = pScrn->mmio; - - R128CCEWaitForIdle(pScrn); - OUTREGP(R128_PM4_BUFFER_DL_WPTR, - R128_PM4_BUFFER_DL_DONE, ~R128_PM4_BUFFER_DL_DONE); - OUTREG(R128_PM4_MICRO_CNTL, 0); - OUTREG(R128_PM4_BUFFER_CNTL, R128_PM4_NONPM4); + int xchangeDummy; + + /* FIXME: This should be in standard XFree86 assembly format */ + __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 */); } diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_cce.h b/xc/lib/GL/mesa/src/drv/r128/r128_cce.h index a1d426eb8..5da4fd348 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_cce.h +++ b/xc/lib/GL/mesa/src/drv/r128/r128_cce.h @@ -37,24 +37,48 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #ifdef GLX_DIRECT_RENDERING +#include "r128_dri.h" +#include "r128_reg.h" + typedef union { float f; int i; } floatTOint; -#define R128_USE_CCE_PIO_MODE -#ifdef R128_USE_CCE_PIO_MODE +#if (R128_CCE_MODE == R128_PM4_192PIO) || \ + (R128_CCE_MODE == R128_PM4_128PIO_64INDBM) || \ + (R128_CCE_MODE == R128_PM4_64PIO_128INDBM) || \ + (R128_CCE_MODE == R128_PM4_64PIO_64VCBM_64INDBM) || \ + (R128_CCE_MODE == R128_PM4_64PIO_64VCPIO_64INDPIO) + +/* The ring buffer is in PIO mode */ +/* Start a sequence of CCE commands. This grabs the lock, and wait for + `n' entries to be free in the ring buffer. */ #define R128CCE_BEGIN(n) \ do { \ LOCK_HARDWARE(r128ctx); \ R128WaitForFifo(r128ctx->r128Screen, (n)); \ } while (0) + +/* End a sequence of CCE commands. This also releases the lock. */ +#define R128CCE_END() \ + do { \ + if (r128ctx->r128Screen->CCEFifoAddr != R128_PM4_FIFO_DATA_EVEN) { \ + OUTREG(r128ctx->r128Screen->CCEFifoAddr, R128_CCE_PACKET2); \ + r128ctx->r128Screen->CCEFifoAddr ^= 0x0004; \ + } \ + UNLOCK_HARDWARE(r128ctx); \ + } while (0) + +/* Insert an integer value into the CCE ring buffer. */ #define R128CCE(v) \ do { \ OUTREG(r128ctx->r128Screen->CCEFifoAddr, (v)); \ r128ctx->r128Screen->CCEFifoAddr ^= 0x0004; \ } while (0) + +/* Insert an floating point value into the CCE ring buffer. */ #define R128CCEF(v) \ do { \ floatTOint fTi; \ @@ -62,23 +86,14 @@ typedef union { OUTREG(r128ctx->r128Screen->CCEFifoAddr, fTi.i); \ r128ctx->r128Screen->CCEFifoAddr ^= 0x0004; \ } while (0) -#define R128CCE_END() \ - do { \ - if (r128ctx->r128Screen->CCEFifoAddr != R128_PM4_FIFO_DATA_EVEN) { \ - OUTREG(r128ctx->r128Screen->CCEFifoAddr, R128_CCE_PACKET2); \ - r128ctx->r128Screen->CCEFifoAddr ^= 0x0004; \ - } \ - UNLOCK_HARDWARE(r128ctx); \ - } while (0) -#define R128CCE_BEGIN_LOCKED(n) \ - do { \ - R128WaitForFifo(r128ctx->r128Screen, (n)); \ - } while (0) +/* Wait for `n' entries to be free in the ring buffer, while locked. */ #define R128CCE_WAIT_LOCKED(n) \ do { \ R128WaitForFifo(r128ctx->r128Screen, (n)); \ } while (0) + +/* End a sequence of CCE commands, but do not releases the lock. */ #define R128CCE_END_LOCKED() \ do { \ if (r128ctx->r128Screen->CCEFifoAddr != R128_PM4_FIFO_DATA_EVEN) { \ @@ -89,12 +104,31 @@ typedef union { #else +/* The ring buffer is in BM mode */ +/* FIXME: Implement support for the ring buffer */ + +/* Start a sequence of CCE commands. This grabs the lock, and wait for + `n' entries to be free in the ring buffer. */ #define R128CCE_BEGIN(n) -#define R128CCE(v) + +/* End a sequence of CCE commands. This also releases the lock. */ #define R128CCE_END() +/* Insert an integer value into the CCE ring buffer. */ +#define R128CCE(v) + +/* Insert an floating point value into the CCE ring buffer. */ +#define R128CCEF(v) + +/* Wait for `n' entries to be free in the ring buffer, while locked. */ +#define R128CCE_WAIT_LOCKED(n) + +/* End a sequence of CCE commands, but do not releases the lock. */ +#define R128CCE_END_LOCKED() + #endif +/* 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)) @@ -125,8 +159,7 @@ extern void R128WaitForIdle(r128ScreenPtr pScrn); extern void R128CCEWaitForFifoFunction(r128ScreenPtr pScrn, int entries); extern void R128CCEWaitForIdle(r128ScreenPtr pScrn); -extern void R128CCEStart(r128ScreenPtr pScrn); -extern void R128CCEEnd(r128ScreenPtr pScrn); +extern void R128FlushWCMemory(void); #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 new file mode 100644 index 000000000..2a1d4e590 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_ccevb.h @@ -0,0 +1,48 @@ +/* $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 + +typedef struct { + int start; /* in bytes from the beginning of AGP memory */ + int count; /* in vertices */ + int size; /* in vertices */ + int done; /* VB has been sent to ring (FIXME) */ +} r128CCEVertBuf, *r128CCEVertBufPtr; + +#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 19aaaebfe..b10bb4629 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_clear.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_clear.c @@ -39,106 +39,125 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r128_lock.h" #include "r128_reg.h" #include "r128_cce.h" +#include "r128_vb.h" #include "r128_clear.h" +/* Clear the depth buffer */ void r128ClearDepthBuffer(r128ContextPtr r128ctx, GLboolean all, - GLint x, GLint y, GLint width, GLint height) + GLint cx, GLint cy, GLint cw, GLint ch) { - unsigned char *R128MMIO = r128ctx->r128Screen->mmio; - int dst_bpp; - CARD32 write_mask; + unsigned char *R128MMIO = r128ctx->r128Screen->mmio; + __DRIdrawablePrivate *dPriv = r128ctx->driDrawable; + int nc = dPriv->numClipRects; + XF86DRIClipRectPtr c = dPriv->pClipRects; + int dst_bpp; + CARD32 write_mask; if (!(r128ctx->regs.tex_cntl_c & R128_Z_WRITE_ENABLE)) return; switch (r128ctx->regs.z_sten_cntl_c & R128_Z_PIX_WIDTH_MASK) { case R128_Z_PIX_WIDTH_16: - dst_bpp = R128_GMC_DST_16BPP; write_mask = 0x0000ffff; + dst_bpp = R128_GMC_DST_16BPP; break; case R128_Z_PIX_WIDTH_24: - dst_bpp = R128_GMC_DST_24BPP; write_mask = 0x00ffffff; + dst_bpp = R128_GMC_DST_24BPP; break; case R128_Z_PIX_WIDTH_32: - dst_bpp = R128_GMC_DST_32BPP; write_mask = 0xffffffff; + dst_bpp = R128_GMC_DST_32BPP; break; default: return; } - /* FIXME: save DP_WRITE_MASK or add to context???? */ - /* FIXME: use x, y, width, height */ + cx += dPriv->x; + cy = dPriv->y + dPriv->h - cy - ch; - R128CCE_BEGIN(11); + /* Flush any outstanding vertex buffers */ + R128_FLUSH_VB(r128ctx); + + LOCK_HARDWARE(r128ctx); /* Set the write mask so that we _only_ clear the Z buffer */ + R128CCE_WAIT_LOCKED(2); R128CCE0(R128_CCE_PACKET0, R128_DP_WRITE_MASK, 0); R128CCE(write_mask); /* Temporarily disable Z and stencil buffer and texture mapping modes */ + R128CCE_WAIT_LOCKED(2); R128CCE0(R128_CCE_PACKET0, R128_TEX_CNTL_C, 0); R128CCE(r128ctx->regs.tex_cntl_c & ~(R128_Z_ENABLE | R128_STENCIL_ENABLE | R128_TEXMAP_ENABLE)); - R128CCE3(R128_CCE_PACKET3_CNTL_PAINT_MULTI, 3); -#if 0 - /* FIXME: do we want to set R128_GMC_DST_PITCH_OFFSET_CNTL? - This requires us to include the offset and pitch - registers below, but this could be very useful since it - means we don't have to add the depthX and depthY values - to the drawable's x and y values. */ - R128CCE(R128_GMC_DST_PITCH_OFFSET_CNTL - | R128_GMC_BRUSH_SOLID_COLOR - | dst_bpp - | R128_GMC_SRC_DATATYPE_COLOR - | R128_ROP3_P - | R128_GMC_3D_FCN_EN /* FIXME?? */ - | R128_GMC_CLR_CMP_CNTL_DIS /* FIXME?? */ - | R128_AUX_CLIP_DIS /* FIXME?? */ - | R128_GMC_WR_MSK_DIS); /* FIXME?? */ -#else - R128CCE(R128_GMC_BRUSH_SOLID_COLOR - | dst_bpp - | R128_GMC_SRC_DATATYPE_COLOR - | R128_ROP3_P - | R128_GMC_3D_FCN_EN /* FIXME?? */ - | R128_GMC_CLR_CMP_CNTL_DIS /* FIXME?? */ - | R128_AUX_CLIP_DIS /* FIXME?? */ - | R128_GMC_WR_MSK_DIS); /* FIXME?? */ -#endif - R128CCE(r128ctx->ClearDepth); - R128CCE(((r128ctx->driDrawable->x + r128ctx->r128Screen->depthX)<< 16) - | (r128ctx->driDrawable->y + r128ctx->r128Screen->depthY)); - R128CCE((r128ctx->driDrawable->w << 16) | r128ctx->driDrawable->h); + /* Cycle through the clip rects */ + while (nc--) { + int x = c[nc].x1; + int y = c[nc].y1; + int w = c[nc].x2 - x; + int h = c[nc].y2 - y; + + if (!all) { + if (x < cx) w -= cx - x, x = cx; + if (y < cy) h -= cy - y, y = cy; + + if (x + w > cx + cw) w = cx + cw - x; + if (y + h > cy + ch) h = cy + ch - y; + + if (w <= 0 || h <= 0) continue; + } + + x += r128ctx->r128Screen->depthX; + y += r128ctx->r128Screen->depthY; + + R128CCE_WAIT_LOCKED(5); + R128CCE3(R128_CCE_PACKET3_CNTL_PAINT_MULTI, 3); + R128CCE(R128_GMC_BRUSH_SOLID_COLOR + | dst_bpp + | R128_GMC_SRC_DATATYPE_COLOR + | R128_ROP3_P + | R128_GMC_3D_FCN_EN /* FIXME?? */ + | R128_GMC_CLR_CMP_CNTL_DIS /* FIXME?? */ + | R128_AUX_CLIP_DIS /* FIXME?? */ + | R128_GMC_WR_MSK_DIS); /* FIXME?? */ + R128CCE(r128ctx->ClearDepth); + R128CCE((x << 16) | y); + R128CCE((w << 16) | h); + } #if 0 - /* FIXME: if we include this, change CCE_BEGIN() above */ - /* Set the write mask so that we _only_ clear the Z buffer */ - /* FIXME: should this be in the context? */ + R128CCE_WAIT_LOCKED(2); R128CCE0(R128_CCE_PACKET0, R128_DP_WRITE_MASK, 0); R128CCE(0xffffffff); /* Restore Z and stencil buffer and texture mapping modes */ + R128CCE_WAIT_LOCKED(2); R128CCE0(R128_CCE_PACKET0, R128_TEX_CNTL_C, 0); R128CCE(r128ctx->regs.tex_cntl_c); #else - /* FIXME: this should not be needed! */ + /* FIXME: We should be able to optimize this by restoring only the + registers that change (above) */ /* NOTE: The restore of TEX_CNTL_C and R128_DP_WRITE_MASK is handled by vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */ r128ctx->dirty = R128_UPDATE_CONTEXT; - /* r128UpdateState(r128ctx); */ #endif - R128CCE_END(); + R128CCE_END_LOCKED(); + + UNLOCK_HARDWARE(r128ctx); } +/* Clear a color buffer */ void r128ClearColorBuffer(r128ContextPtr r128ctx, GLboolean all, - GLint x, GLint y, GLint width, GLint height) + GLint cx, GLint cy, GLint cw, GLint ch) { - unsigned char *R128MMIO = r128ctx->r128Screen->mmio; - int dst_bpp; + unsigned char *R128MMIO = r128ctx->r128Screen->mmio; + __DRIdrawablePrivate *dPriv = r128ctx->driDrawable; + int nc = dPriv->numClipRects; + XF86DRIClipRectPtr c = dPriv->pClipRects; + int dst_bpp; switch (r128ctx->r128Screen->bpp) { case 8: @@ -157,44 +176,73 @@ void r128ClearColorBuffer(r128ContextPtr r128ctx, GLboolean all, break; } - /* FIXME: use x, y, width, height */ + cx += dPriv->x; + cy = dPriv->y + dPriv->h - cy - ch; + /* FIXME: use R128_GMC_DST_PITCH_OFFSET_CNTL to set to the back buffer when we should be draing to the back buffer? */ - R128CCE_BEGIN(7); + /* Flush any outstanding vertex buffers */ + R128_FLUSH_VB(r128ctx); + + LOCK_HARDWARE(r128ctx); /* Temporarily disable Z and stencil buffer and texture mapping modes */ + R128CCE_WAIT_LOCKED(2); R128CCE0(R128_CCE_PACKET0, R128_TEX_CNTL_C, 0); R128CCE(r128ctx->regs.tex_cntl_c & ~(R128_Z_ENABLE | R128_STENCIL_ENABLE | R128_TEXMAP_ENABLE)); - R128CCE3(R128_CCE_PACKET3_CNTL_PAINT_MULTI, 3); - R128CCE(R128_GMC_BRUSH_SOLID_COLOR - | dst_bpp - | R128_GMC_SRC_DATATYPE_COLOR - | R128_ROP3_P - | R128_GMC_3D_FCN_EN /* FIXME?? */ - | R128_GMC_CLR_CMP_CNTL_DIS /* FIXME?? */ - | R128_AUX_CLIP_DIS); /* FIXME?? */ - R128CCE(r128ctx->ClearColor); - /* FIXME: when not using the back buf, make sure clears go to front buf */ - R128CCE(((r128ctx->driDrawable->x + r128ctx->bufX)<< 16) - | (r128ctx->driDrawable->y + r128ctx->bufY)); - R128CCE((r128ctx->driDrawable->w << 16) | r128ctx->driDrawable->h); + /* Cycle through the clip rects */ + while (nc--) { + int x = c[nc].x1; + int y = c[nc].y1; + int w = c[nc].x2 - x; + int h = c[nc].y2 - y; + + if (!all) { + if (x < cx) w -= cx - x, x = cx; + if (y < cy) h -= cy - y, y = cy; + + if (x + w > cx + cw) w = cx + cw - x; + if (y + h > cy + ch) h = cy + ch - h; + + if (w <= 0 || h <= 0) continue; + } + + x += r128ctx->bufX; + y += r128ctx->bufY; + + R128CCE_WAIT_LOCKED(5); + R128CCE3(R128_CCE_PACKET3_CNTL_PAINT_MULTI, 3); + R128CCE(R128_GMC_BRUSH_SOLID_COLOR + | dst_bpp + | R128_GMC_SRC_DATATYPE_COLOR + | R128_ROP3_P + | R128_GMC_3D_FCN_EN /* FIXME?? */ + | R128_GMC_CLR_CMP_CNTL_DIS /* FIXME?? */ + | R128_AUX_CLIP_DIS); /* FIXME?? */ + R128CCE(r128ctx->ClearColor); + R128CCE((x << 16) | y); + R128CCE((w << 16) | h); + } #if 0 - /* FIXME: if we include this, change CCE_BEGIN() above */ /* Restore Z and stencil buffer and texture mapping modes */ + R128CCE_WAIT_LOCKED(2); R128CCE0(R128_CCE_PACKET0, R128_TEX_CNTL_C, 0); R128CCE(r128ctx->regs.tex_cntl_c); #else - /* FIXME: this should not be needed! */ + /* FIXME: We should be able to optimize this by restoring only the + registers that change (above) */ /* NOTE: The restore of TEX_CNTL_C is handled by vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */ - r128ctx->dirty = R128_UPDATE_CONTEXT; - /* r128UpdateState(r128ctx); */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_ALL_DIRTY; #endif - R128CCE_END(); + R128CCE_END_LOCKED(); + + 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 new file mode 100644 index 000000000..e3983d214 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_context.c @@ -0,0 +1,183 @@ +/* $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> + * + */ + +#include "r128_init.h" +#include "r128_mesa.h" +#include "r128_xmesa.h" +#include "r128_context.h" +#include "r128_dd.h" +#include "r128_state.h" +#include "r128_span.h" +#include "r128_depth.h" +#include "r128_tex.h" +#include "r128_vb.h" +#include "r128_pipeline.h" + +#include "context.h" +#include "simple_list.h" + +/* Create the device specific context */ +r128ContextPtr r128CreateContext(GLvisual *glVisual, + XMesaContext c, + XMesaContext share_list) +{ + r128ContextPtr r128ctx; + GLcontext *shareCtx, *glCtx; + + r128ctx = (r128ContextPtr)Xmalloc(sizeof(*r128ctx)); + if (!r128ctx) return NULL; + + if (share_list) + shareCtx = ((r128ContextPtr)(share_list->private))->glCtx; + else + shareCtx = NULL; + + /* Initialize r128Context */ + r128ctx->xmCtx = c; + r128ctx->glCtx = gl_create_context(glVisual, + shareCtx, + (void *)r128ctx, + GL_TRUE); + r128ctx->display = c->display; + r128ctx->driContext = c->driContextPriv; + r128ctx->driDrawable = NULL; /* Set by XMesaMakeCurrent */ + r128ctx->dirty = R128_ALL_DIRTY; + r128ctx->dirty_context = R128_CTX_ALL_DIRTY; + r128ctx->needClip = GL_TRUE; + if (getenv("LIBGL_SOFTWARE_RENDERING")) + r128ctx->SWonly = GL_TRUE; + else + r128ctx->SWonly = GL_FALSE; + if (getenv("LIBGL_NO_SOFTWARE_FALLBACKS")) + r128ctx->SWfallbackDisable = GL_TRUE; + else + r128ctx->SWfallbackDisable = GL_FALSE; + r128ctx->r128Screen = + (r128ScreenPtr)(c->driContextPriv->driScreenPriv->private); + r128ctx->SAREA = + (R128SAREAPrivPtr)((char *)c->driContextPriv->driScreenPriv->pSAREA + + sizeof(XF86DRISAREARec)); + + r128ctx->CurrentTexObj[0] = NULL; + r128ctx->CurrentTexObj[1] = NULL; + make_empty_list(&r128ctx->TexObjList); + make_empty_list(&r128ctx->SwappedOut); +#if USE_AGP_TEXTURES + r128ctx->texHeap = mmInit(0, r128ctx->r128Screen->agpTexSize); +#else + r128ctx->texHeap = mmInit(0, r128ctx->r128Screen->textureSize); +#endif + r128ctx->lastTexAge = -1; + + r128ctx->RenderIndex = -1; + r128ctx->useFastPath = GL_FALSE; + + r128ctx->vb = NULL; + + /* Initialize GLcontext */ + glCtx = r128ctx->glCtx; + + r128DDInitExtensions(glCtx); + + r128DDInitDriverFuncs(glCtx); + r128DDInitStateFuncs(glCtx); + r128DDInitSpanFuncs(glCtx); + r128DDInitDepthFuncs(glCtx); + r128DDInitTextureFuncs(glCtx); + + glCtx->Driver.TriangleCaps = (DD_TRI_CULL + | DD_TRI_LIGHT_TWOSIDE + | DD_TRI_OFFSET); + glCtx->TriangleCaps |= DD_CLIP_FOG_COORD; + + /* Reset Mesa's current 2D texture pointers to the driver's textures */ + glCtx->Shared->DefaultD[2][0].DriverData = NULL; + glCtx->Shared->DefaultD[2][1].DriverData = NULL; + + /* If Mesa has current a vertex buffer, make sure the driver's VB + data is up to date */ + if (glCtx->VB) r128DDRegisterVB(glCtx->VB); + + /* Register the fast path */ + if (glCtx->NrPipelineStages) + glCtx->NrPipelineStages = + r128RegisterPipelineStages(glCtx->PipelineStage, + glCtx->PipelineStage, + glCtx->NrPipelineStages); + + r128DDInitState(r128ctx); + + return r128ctx; +} + +/* Destroy the device specific context */ +void r128DestroyContext(r128ContextPtr r128ctx) +{ + if (r128ctx) { + r128TexObjPtr t, next_t; + + foreach_s (t, next_t, &r128ctx->TexObjList) + r128DestroyTexObj(r128ctx, t); + + foreach_s (t, next_t, &r128ctx->SwappedOut) + r128DestroyTexObj(r128ctx, t); + + gl_destroy_context(r128ctx->glCtx); + Xfree(r128ctx); + } +} + +/* Load the device specific context into the hardware. The actual + setting of the hardware state is done in the r128UpdateHWState(). */ +r128ContextPtr r128MakeCurrent(r128ContextPtr oldCtx, + r128ContextPtr newCtx, + __DRIdrawablePrivate *dPriv) +{ + if (oldCtx) { + newCtx->dirty = R128_REQUIRE_QUIESCENCE; + if (oldCtx != newCtx) { + newCtx->dirty |= R128_UPDATE_CONTEXT; + newCtx->dirty_context = R128_CTX_ALL_DIRTY; + } + if (oldCtx->driDrawable != dPriv) + newCtx->dirty |= R128_UPDATE_WINPOS; + } else { + newCtx->dirty = R128_ALL_DIRTY; + newCtx->dirty_context = R128_CTX_ALL_DIRTY; + } + + newCtx->driDrawable = dPriv; + + return newCtx; +} 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 3127223ef..1be2070b5 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_context.h +++ b/xc/lib/GL/mesa/src/drv/r128/r128_context.h @@ -37,17 +37,50 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #ifdef GLX_DIRECT_RENDERING +#include "r128_sarea.h" +#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 #define R128_REQUIRE_QUIESCENCE 0x0001 -#define R128_START_CCE 0x0002 -#define R128_UPDATE_CONTEXT 0x0004 -#define R128_UPDATE_CLIPRECTS 0x0008 +#define R128_UPDATE_CONTEXT 0x0002 +#define R128_UPDATE_WINPOS 0x0004 +#define R128_UPDATE_TEX0IMAGES 0x0008 +#define R128_UPDATE_TEX1IMAGES 0x0010 +#define R128_UPDATE_TEXSTATE 0x0020 #define R128_ALL_DIRTY 0xffff +/* Flags for what context state needs to be updated */ +#define R128_CTX_CLEAN 0x0000 +#define R128_CTX_MISC 0x0001 +#define R128_CTX_ENGINESTATE 0x0002 +#define R128_CTX_TEX0STATE 0x0004 +#define R128_CTX_TEX1STATE 0x0008 +#define R128_CTX_TEXENVSTATE 0x0010 +#define R128_CTX_FOGSTATE 0x0020 +#define R128_CTX_ZSTENSTATE 0x0040 +#define R128_CTX_SCISSORS 0x0080 +#define R128_CTX_ALPHASTATE 0x0100 +#define R128_CTX_SETUPSTATE 0x0200 +#define R128_CTX_WIN_Z_POS 0x0400 +#define R128_CTX_FLUSH_PIX_CACHE 0x0800 +#define R128_CTX_ALL_DIRTY 0xffff + +/* Flags for software fallback cases */ +#define R128_FALLBACK_TEXTURE 0x0001 +#define R128_FALLBACK_DRAW_BUFFER 0x0002 +#define R128_FALLBACK_READ_BUFFER 0x0004 +#define R128_FALLBACK_COLORMASK 0x0008 +#define R128_FALLBACK_STIPPLE 0x0010 + +/* NOTE: The groups below need to be kept together so that a single + memcpy can be used to transfer data to the ring buffer */ typedef struct { - CARD32 scale_3d_cntl; /* 0x1a00 */ + CARD32 scale_3d_cntl; /* 0x1a00 */ - CARD32 dst_pitch_offset_c; /* 0x1c80 */ + CARD32 dst_pitch_offset_c; /* 0x1c80 */ CARD32 dp_gui_master_cntl; CARD32 sc_top_left_c; CARD32 sc_bottom_right_c; @@ -62,80 +95,100 @@ typedef struct { CARD32 prim_tex_cntl_c; CARD32 prim_texture_combine_cntl_c; CARD32 tex_size_pitch_c; - CARD32 prim_tex_0_offset_c; - CARD32 prim_tex_1_offset_c; - CARD32 prim_tex_2_offset_c; - CARD32 prim_tex_3_offset_c; - CARD32 prim_tex_4_offset_c; - CARD32 prim_tex_5_offset_c; - CARD32 prim_tex_6_offset_c; - CARD32 prim_tex_7_offset_c; - CARD32 prim_tex_8_offset_c; - CARD32 prim_tex_9_offset_c; - CARD32 prim_tex_10_offset_c; /* 0x1ce4 */ - - CARD32 sec_tex_cntl_c; /* 0x1d00 */ + CARD32 prim_tex_offset[R128_TEX_MAXLEVELS]; /* 0x1ce4 */ + + CARD32 sec_tex_cntl_c; /* 0x1d00 */ CARD32 sec_tex_combine_cntl_c; - CARD32 sec_tex_0_offset_c; - CARD32 sec_tex_1_offset_c; - CARD32 sec_tex_2_offset_c; - CARD32 sec_tex_3_offset_c; - CARD32 sec_tex_4_offset_c; - CARD32 sec_tex_5_offset_c; - CARD32 sec_tex_6_offset_c; - CARD32 sec_tex_7_offset_c; - CARD32 sec_tex_8_offset_c; - CARD32 sec_tex_9_offset_c; - CARD32 sec_tex_10_offset_c; + CARD32 sec_tex_offset[R128_TEX_MAXLEVELS]; CARD32 constant_color_c; CARD32 prim_texture_border_color_c; CARD32 sec_texture_border_color_c; CARD32 sten_ref_mask_c; - CARD32 plane_3d_mask_c; /* 0x1d44 */ + CARD32 plane_3d_mask_c; /* 0x1d44 */ + + CARD32 setup_cntl; /* 0x1bc4 */ - CARD32 setup_cntl; /* 0x1bc4 */ - CARD32 pm4_vc_fpu_setup; /* 0x071c */ + CARD32 pm4_vc_fpu_setup; /* 0x071c */ - CARD32 fog_3d_table_start; /* 0x1810 */ + CARD32 fog_3d_table_start; /* 0x1810 */ CARD32 fog_3d_table_end; - CARD32 fog_3d_table_density; /* 0x181c */ + CARD32 fog_3d_table_density; /* 0x181c */ - CARD32 window_xy_offset; /* 0x1bcc */ + CARD32 window_xy_offset; /* 0x1bcc */ - CARD32 dp_write_mask; /* 0x16cc */ + CARD32 dp_write_mask; /* 0x16cc */ + + CARD32 pc_gui_ctlstat; /* 0x1748 */ } r128ContextRegs; typedef struct { - XMesaContext xmCtx; - GLcontext *glCtx; - int dirty; - int needClip; - - int RenderIndex; - points_func PointsFunc; - line_func LineFunc; + XMesaContext xmCtx; /* XMesa context */ + GLcontext *glCtx; /* Mesa context */ + int dirty; /* Hardware state to be updated */ + int dirty_context; /* Context state to be updated */ + + int needClip; /* Primitives need to be clipped + to the window */ + + int SWonly; /* Force software-only rendering */ + int SWfallbackDisable; /* Disable software fallbacks */ + + + r128TexObjPtr CurrentTexObj[2]; /* Ptr to current texture + object associated with + each texture unit */ + r128TexObj TexObjList; /* List of textures swapped in */ + r128TexObj SwappedOut; /* List of textures swapped out */ + memHeap_t *texHeap; /* Global heap of textures */ + int lastTexAge; /* Last known global texture age */ + + int useFastPath; /* Currently using Fast Path code */ + int SetupIndex; /* Raster setup function index */ + int SetupDone; /* Partial raster setup done? */ + int RenderIndex; /* Render state function index */ + r128InterpFunc interp; /* Current vert interp function */ + + r128CCEVertBufPtr vb; /* VB currently being filled */ + + points_func PointsFunc; /* Current Points, Line, Triangle */ + line_func LineFunc; /* and Quad rendering functions */ triangle_func TriangleFunc; quad_func QuadFunc; - CARD32 IndirectTriangles; - CARD32 Fallback; + CARD32 IndirectTriangles; /* Flags for point, line, + tri and quad software + fallbacks */ + CARD32 Fallback; /* Need software fallback */ + + r128ContextRegs regs; /* Hardware state */ + CARD32 Color; /* Current draw color */ + CARD32 ClearColor; /* Color used to clear color buffer */ + CARD32 ClearDepth; /* Value used to clear depth buffer */ - r128ContextRegs regs; - CARD32 ClearColor; - CARD32 ClearDepth; + int bufX; /* x-offset to current draw buffer */ + int bufY; /* y-offset to current draw buffer */ - int bufX; - int bufY; + R128SAREAPrivPtr SAREA; /* Pointer to SAREA private data */ - Display *display; + Display *display; /* X server display */ - __DRIcontextPrivate *driContext; - __DRIdrawablePrivate *driDrawable; + __DRIcontextPrivate *driContext; /* DRI context */ + __DRIdrawablePrivate *driDrawable; /* DRI drawable bound to this ctx */ - r128ScreenPtr r128Screen; + r128ScreenPtr r128Screen; /* Screen private DRI data */ } r128ContextRec, *r128ContextPtr; -extern r128ContextPtr r128Context; +#define R128_MESACTX(r128ctx) ((r128ctx)->glCtx) +#define R128_DRIDRAWABLE(r128ctx) ((r128ctx)->driDrawable) +#define R128_DRISCREEN(r128ctx) ((r128ctx)->r128Screen->driScreen) + +extern r128ContextPtr r128CreateContext(GLvisual *glVisual, + XMesaContext c, + XMesaContext share_list); +extern void r128DestroyContext(r128ContextPtr r128ctx); +extern r128ContextPtr r128MakeCurrent(r128ContextPtr oldCtx, + r128ContextPtr newCtx, + __DRIdrawablePrivate *dPriv); #endif #endif /* _R128_CONTEXT_H_ */ 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 04745d240..230205783 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_dd.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_dd.c @@ -37,8 +37,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r128_cce.h" #include "r128_clear.h" #include "r128_vb.h" +#include "r128_pipeline.h" #include "r128_dd.h" +/* Driver entry point for clearing color and ancillary buffers */ static GLbitfield r128DDClear(GLcontext *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height) { @@ -55,6 +57,7 @@ static GLbitfield r128DDClear(GLcontext *ctx, GLbitfield mask, GLboolean all, } #if 0 + /* FIXME: Add stencil support */ if (mask & GL_STENCIL_BUFFER_BIT) { r128ClearStencilBuffer(r128ctx, all, x, y, width, height); mask &= ~GL_STENCIL_BUFFER_BIT; @@ -64,6 +67,7 @@ static GLbitfield r128DDClear(GLcontext *ctx, GLbitfield mask, GLboolean all, return mask; } +/* Return the current color buffer size */ static void r128DDGetBufferSize(GLcontext *ctx, GLuint *width, GLuint *height) { r128ContextPtr r128ctx = R128_CONTEXT(ctx); @@ -72,6 +76,7 @@ static void r128DDGetBufferSize(GLcontext *ctx, GLuint *width, GLuint *height) *height = r128ctx->driDrawable->h; } +/* Return various strings for glGetString() */ static const GLubyte *r128DDGetString(GLcontext *ctx, GLenum name) { switch (name) { @@ -84,53 +89,75 @@ static const GLubyte *r128DDGetString(GLcontext *ctx, GLenum name) } } +/* Send all commands to the hardware. If vertex buffers or indirect + buffers are in use, then we need to make sure they are sent to the + hardware. All commands that are normally sent to the ring are + already considered `flushed'. */ +static void r128DDFlush(GLcontext *ctx) +{ + R128_FLUSH_VB(R128_CONTEXT(ctx)); +} + +/* Make sure all commands have been sent to the hardware and have + completed processing. */ static void r128DDFinish(GLcontext *ctx) { r128ContextPtr r128ctx = R128_CONTEXT(ctx); + r128DDFlush(ctx); R128CCEWaitForIdle(r128ctx->r128Screen); } -static void r128DDFlush(GLcontext *ctx) -{ - /* Nothing to do here since all commands are automatically flushed */ -} - +/* Return various parameters requested by Mesa */ static GLint r128DDGetParameteri(const GLcontext *ctx, GLint param) { switch (param) { #if 0 - case DD_MAX_TEXTURE_SIZE: - return 2048; /* FIXME ?? */ - case DD_MAX_TEXTURES: - return 2; /* FIXME ?? */ - case DD_HAVE_HARDWARE_FOG: - return 1; /* FIXME ?? */ + /* FIXME: Support for these needs to be added to Mesa */ + case DD_MAX_TEXTURE_SIZE: return 1024; + case DD_MAX_TEXTURES: return 2; #endif - default: - return 0; +#if 0 + case DD_HAVE_HARDWARE_FOG: return 1; /* FIXME: Add HW fog support */ +#endif + default: return 0; } } +/* Initialize the extensions supported by this driver */ void r128DDInitExtensions(GLcontext *ctx) { + /* FIXME: Are there other extensions to enable/disable??? */ + gl_extensions_disable(ctx, "GL_EXT_shared_texture_palette"); + gl_extensions_disable(ctx, "GL_EXT_paletted_texture"); + gl_extensions_disable(ctx, "GL_EXT_point_parameters"); + gl_extensions_disable(ctx, "ARB_imaging"); + gl_extensions_disable(ctx, "GL_EXT_blend_minmax"); + gl_extensions_disable(ctx, "GL_EXT_blend_logic_op"); + gl_extensions_disable(ctx, "GL_EXT_blend_subtract"); + gl_extensions_disable(ctx, "GL_INGR_blend_func_separate"); + + if (getenv("LIBGL_NO_MULTITEXTURE")) + gl_extensions_disable(ctx, "GL_ARB_multitexture"); } +/* Initialize the driver's misc functions */ void r128DDInitDriverFuncs(GLcontext *ctx) { - ctx->Driver.Clear = r128DDClear; + ctx->Driver.Clear = r128DDClear; - ctx->Driver.GetBufferSize = r128DDGetBufferSize; - ctx->Driver.GetString = r128DDGetString; - ctx->Driver.Finish = r128DDFinish; - ctx->Driver.Flush = r128DDFlush; + ctx->Driver.GetBufferSize = r128DDGetBufferSize; + ctx->Driver.GetString = r128DDGetString; + ctx->Driver.Finish = r128DDFinish; + ctx->Driver.Flush = r128DDFlush; - ctx->Driver.Error = NULL; - ctx->Driver.GetParameteri = r128DDGetParameteri; + ctx->Driver.Error = NULL; + ctx->Driver.GetParameteri = r128DDGetParameteri; - ctx->Driver.DrawPixels = NULL; - ctx->Driver.Bitmap = NULL; + ctx->Driver.DrawPixels = NULL; + ctx->Driver.Bitmap = NULL; - ctx->Driver.RegisterVB = r128DDRegisterVB; - ctx->Driver.UnregisterVB = r128DDUnregisterVB; + ctx->Driver.RegisterVB = r128DDRegisterVB; + ctx->Driver.UnregisterVB = r128DDUnregisterVB; + ctx->Driver.BuildPrecalcPipeline = r128DDBuildPrecalcPipeline; } diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_depth.c b/xc/lib/GL/mesa/src/drv/r128/r128_depth.c index 0c4076058..589556b15 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_depth.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_depth.c @@ -58,10 +58,13 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. volatile GLdepth *zptr; \ int i +/* Return a pointer to the offset in the depth buffer at (x,y) */ #define DEPTH_ADDR(base, _x, _y) \ (GLdepth*)(zbase + _x * (r128scrn->bpp/8) + \ (height - _y) * r128scrn->fbStride) +/* Test a span for a particular `_op_' comparison, and update the depth + buffer (if needed). */ #define DEPTH_TEST_SPAN(_op_) \ if (ctx->Depth.Mask) { /* Update Z buffer */ \ for (i = 0; i < n; i++, zptr++, m++) { \ @@ -86,6 +89,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. } \ } +/* Test a list of pixels for a particular `_op_' comparison, and update + the depth buffer (if needed). */ #define DEPTH_TEST_PIXELS(_op_) \ if (ctx->Depth.Mask) { /* Update Z buffer */ \ for (i = 0; i < n; i++) { \ @@ -105,10 +110,13 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. } \ } +/* Allocate a depth buffer */ static void r128DDAllocDepthBuffer(GLcontext *ctx) { } +/* Update the depth buffer for a given span. This is only used for + software fallbacks. */ static GLuint r128DDDepthTestSpan(GLcontext *ctx, GLuint n, GLint x, GLint y, const GLdepth z[], @@ -154,6 +162,8 @@ static GLuint r128DDDepthTestSpan(GLcontext *ctx, return passed; } +/* Update the depth buffer for a given array of pixels. This is only + used for software fallbacks. */ static void r128DDDepthTestPixels(GLcontext *ctx, GLuint n, const GLint x[], @@ -195,6 +205,8 @@ static void r128DDDepthTestPixels(GLcontext *ctx, UNLOCK_HARDWARE(r128ctx); } +/* Return a span in the depth buffer as floats. This is only used for + software fallbacks. */ static void r128DDReadDepthSpanFloat(GLcontext *ctx, GLuint n, GLint x, GLint y, GLfloat depth[]) @@ -216,6 +228,8 @@ static void r128DDReadDepthSpanFloat(GLcontext *ctx, UNLOCK_HARDWARE(r128ctx); } +/* Return a span in the depth buffer as ints. This is only used for + software fallbacks. */ static void r128DDReadDepthSpanInt(GLcontext *ctx, GLuint n, GLint x, GLint y, GLdepth depth[]) @@ -237,6 +251,7 @@ static void r128DDReadDepthSpanInt(GLcontext *ctx, } +/* Initialize the driver's depth functions */ void r128DDInitDepthFuncs(GLcontext *ctx) { ctx->Driver.AllocDepthBuffer = r128DDAllocDepthBuffer; diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_fastpath.c b/xc/lib/GL/mesa/src/drv/r128/r128_fastpath.c new file mode 100644 index 000000000..953f9d9a6 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_fastpath.c @@ -0,0 +1,537 @@ +/* $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> + * + */ + +#include "r128_init.h" +#include "r128_mesa.h" +#include "r128_state.h" +#include "r128_vb.h" +#include "r128_tris.h" +#include "r128_fastpath.h" + +#include "mmath.h" +#include "cva.h" +#include "vertices.h" + +/* 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. */ + +typedef struct r128_fast_table { + r128BuildVerticesFunc build_vertices; + r128InterpFunc interp; +} r128FastPathTable; + +#define POINT(x) r128DrawPoint(r128ctx, &vert[x].v, psize) +#define LINE(x,y) r128DrawLine(r128ctx, &vert[x].v, &vert[y].v, lwidth) +#define TRI(x,y,z) r128DrawTriangle(r128ctx, &vert[x].v, &vert[y].v, &vert[z].v) + +/* Direct, and no clipping required. The clip funcs have not been + written yet, so this is only useful for the fast path. */ +#define RENDER_POINTS(start, count) \ +do { \ + GLuint e; \ + for (e = start; e <= count; e++) \ + POINT(elt[e]); \ +} while (0) + +#define RENDER_LINE(i1, i) \ +do { \ + GLuint e1 = elt[i1], e = elt[i]; \ + LINE(e1, e); \ +} while (0) + +#define RENDER_TRI(i2, i1, i, pv, parity) \ +do { \ + GLuint e2 = elt[i2], e1 = elt[i1], e = elt[i]; \ + if (parity) { \ + GLuint tmp = e2; \ + e2 = e1; \ + e1 = tmp; \ + } \ + TRI(e2, e1, e); \ +} while (0) + +#define RENDER_QUAD(i3, i2, i1, i, pv) \ +do { \ + GLuint e3 = elt[i3], e2 = elt[i2], e1 = elt[i1], e = elt[i]; \ + TRI(e3, e2, e); \ + TRI(e2, e1, e); \ +} while (0) + +#define LOCAL_VARS \ + r128VertexPtr vert = R128_DRIVER_DATA(VB)->verts; \ + const GLuint *elt = VB->EltPtr->data; \ + GLcontext *ctx = VB->ctx; \ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); \ + const GLfloat lwidth = ctx->Line.Width; \ + const GLfloat psize = ctx->Point.Size; \ + (void) lwidth; (void)psize; (void) vert; + +#define TAG(x) x##_r128_smooth_indirect +#include "render_tmp.h" + + + +#define NEGATIVE(f) (f < 0) +#define DIFFERENT_SIGNS(a,b) ((a*b) < 0) +#define LINTERP(T, A, B) ((A) + (T) * ((B) - (A))) + + +#define INTERP_RGBA(t, out, a, b) \ +do { \ + int i; \ + for (i = 0; i < 4; i++) { \ + GLfloat fa = UBYTE_COLOR_TO_FLOAT_COLOR(a[i]); \ + GLfloat fb = UBYTE_COLOR_TO_FLOAT_COLOR(b[i]); \ + GLfloat fo = LINTERP(t, fa, fb); \ + FLOAT_COLOR_TO_UBYTE_COLOR(out[i], fo); \ + } \ +} while (0) + + +#define CLIP(SGN, V, PLANE) \ +do { \ + if (mask & PLANE) { \ + GLuint *indata = inlist[in]; \ + GLuint *outdata = inlist[in ^= 1]; \ + GLuint nr = n; \ + GLfloat *J = verts[indata[nr-1]].f; \ + GLfloat dpJ = (SGN J[V]) + J[3]; \ + \ + inlist[0] = vlist1; \ + for (i = n = 0 ; i < nr ; i++) { \ + GLuint elt_i = indata[i]; \ + GLfloat *I = verts[elt_i].f; \ + GLfloat dpI = (SGN I[V]) + I[3]; \ + \ + if (DIFFERENT_SIGNS(dpI, dpJ)) { \ + GLfloat *O = verts[next_vert].f; \ + GLfloat t, *in, *out; \ + \ + if (NEGATIVE(dpI)) { \ + t = dpI / (dpI - dpJ); \ + in = I; \ + out = J; \ + } else { \ + t = dpJ / (dpJ - dpI); \ + in = J; \ + out = I; \ + } \ + \ + interp(t, O, in, out); \ + \ + clipmask[next_vert] = 0; \ + outdata[n++] = next_vert++; \ + } \ + \ + clipmask[elt_i] |= PLANE; /* don't set up */ \ + \ + if (!NEGATIVE(dpI)) { \ + outdata[n++] = elt_i; \ + clipmask[elt_i] &= ~PLANE; /* set up after all */ \ + } \ + \ + J = I; \ + dpJ = dpI; \ + } \ + \ + if (n < 3) return; \ + } \ +} while (0) + +#define LINE_CLIP(x,y,z,w,PLANE) \ +do { \ + if (mask & PLANE) { \ + GLfloat dpI = DOT4V(I,x,y,z,w); \ + GLfloat dpJ = DOT4V(J,x,y,z,w); \ + \ + if (DIFFERENT_SIGNS(dpI, dpJ)) { \ + GLfloat *O = verts[next_vert].f; \ + GLfloat t = dpI / (dpI - dpJ); \ + \ + interp(t, O, I, J); \ + \ + clipmask[next_vert] = 0; \ + \ + if (NEGATIVE(dpI)) { \ + clipmask[elts[0]] |= PLANE; \ + I = O; \ + elts[0] = next_vert++; \ + } else { \ + clipmask[elts[1]] |= PLANE; \ + J = O; \ + elts[1] = next_vert++; \ + } \ + } else if (NEGATIVE(dpI)) return; \ + } \ +} while (0) + + +static void r128TriClip(GLuint **p_elts, + r128Vertex *verts, + GLubyte *clipmask, + GLuint *p_next_vert, + GLubyte mask, + r128InterpFunc interp) +{ + GLuint *elts = *p_elts; + GLuint next_vert = *p_next_vert; + GLuint in = 0; + GLuint n = 3; + GLuint vlist1[VB_MAX_CLIPPED_VERTS]; + GLuint vlist2[VB_MAX_CLIPPED_VERTS]; + GLuint *inlist[2]; + GLuint *out; + GLuint i; + + inlist[0] = elts; + inlist[1] = vlist2; + + CLIP(-,0,CLIP_RIGHT_BIT); + CLIP(+,0,CLIP_LEFT_BIT); + CLIP(-,1,CLIP_TOP_BIT); + CLIP(+,1,CLIP_BOTTOM_BIT); + CLIP(-,2,CLIP_FAR_BIT); + CLIP(+,2,CLIP_NEAR_BIT); + + /* 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]; + elts[2] = out[i]; + elts += 3; + } + + *p_next_vert = next_vert; + *p_elts = elts; +} + + +static void r128LineClip(GLuint **p_elts, + r128Vertex *verts, + GLubyte *clipmask, + GLuint *p_next_vert, + GLubyte mask, + r128InterpFunc interp) +{ + GLuint *elts = *p_elts; + GLfloat *I = verts[elts[0]].f; + GLfloat *J = verts[elts[1]].f; + GLuint next_vert = *p_next_vert; + + LINE_CLIP(1,0,0,-1,CLIP_LEFT_BIT); + LINE_CLIP(-1,0,0,1,CLIP_RIGHT_BIT); + LINE_CLIP(0,1,0,-1,CLIP_TOP_BIT); + LINE_CLIP(0,-1,0,1,CLIP_BOTTOM_BIT); + LINE_CLIP(0,0,1,-1,CLIP_FAR_BIT); + LINE_CLIP(0,0,-1,1,CLIP_NEAR_BIT); + + *p_next_vert = next_vert; + *p_elts += 2; +} + + + +#define CLIP_POINT(e) \ +do { \ + if (mask[e]) *out++ = e; \ +} while (0) + +#define CLIP_LINE(e1, e0) \ +do { \ + GLubyte ormask = mask[e0] | mask[e1]; \ + out[0] = e1; \ + out[1] = e0; \ + out += 2; \ + if (ormask) { \ + out-=2; \ + if (!(mask[e0] & mask[e1])) { \ + r128LineClip(&out, verts, mask, &next_vert, ormask, interp); \ + } \ + } \ +} while (0) + +#define CLIP_TRIANGLE(e2, e1, e0) \ +do { \ + GLubyte ormask; \ + out[0] = e2; \ + out[1] = e1; \ + out[2] = e0; \ + out += 3; \ + ormask = mask[e2] | mask[e1] | mask[e0]; \ + if (ormask) { \ + out -= 3; \ + if (!(mask[e2] & mask[e1] & mask[e0])) { \ + r128TriClip(&out, verts, mask, &next_vert, ormask, interp); \ + } \ + } \ +} while (0) + + + +/* Build a table of functions to clip each primitive type. These + * produce a list of elements in the appropriate 'reduced' primitive, + * ie (points, lines, triangles) containing all the clipped and + * unclipped primitives from the original list. + */ +#define LOCAL_VARS \ + r128ContextPtr r128ctx = R128_CONTEXT(VB->ctx); \ + r128VertexBufferPtr r128VB = R128_DRIVER_DATA(VB); \ + GLuint *elt = VB->EltPtr->data; \ + r128Vertex *verts = r128VB->verts; \ + GLuint next_vert = r128VB->last_vert; \ + GLuint *out = r128VB->clipped_elements.data; \ + GLubyte *mask = VB->ClipMask; \ + r128InterpFunc interp = r128ctx->interp; \ + (void) interp; (void) verts; + +#define POSTFIX \ + r128VB->clipped_elements.count = out - r128VB->clipped_elements.data; \ + r128VB->last_vert = next_vert; + + +#define INIT(x) + +#define RENDER_POINTS(start, count) \ +do { \ + GLuint i; \ + for (i = start; i < count; i++) \ + CLIP_POINT(elt[i]); \ +} while (0) + +#define RENDER_LINE(i1, i0) \ +do { \ + CLIP_LINE(elt[i1], elt[i0]); \ +} while (0) + +#define RENDER_TRI(i2, i1, i0, pv, parity) \ +do { \ + GLuint e2 = elt[i2], e1 = elt[i1], e0 = elt[i0]; \ + if (parity) e2 = elt[i1], e1 = elt[i2]; \ + CLIP_TRIANGLE(e2, e1, e0); \ +} while (0) + +#define RENDER_QUAD(i3, i2, i1, i0, pv) \ +do { \ + CLIP_TRIANGLE(elt[i3], elt[i2], elt[i0]); \ + CLIP_TRIANGLE(elt[i2], elt[i1], elt[i0]); \ +} while (0) + +#define TAG(x) r128_clip_##x##_elt +#include "render_tmp.h" + + +/* 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_R 2 +#define CLIP_UBYTE_A 3 +#define CLIP_S0 6 +#define CLIP_T0 7 +#define CLIP_S1 8 +#define CLIP_T1 9 + +#define TYPE (0) +#define TAG(x) x +#include "r128_fasttmp.h" + +#define TYPE (R128_RGBA_BIT) +#define TAG(x) x##_RGBA +#include "r128_fasttmp.h" + +#define TYPE (R128_TEX0_BIT) +#define TAG(x) x##_TEX0 +#include "r128_fasttmp.h" + +#define TYPE (R128_RGBA_BIT | R128_TEX0_BIT) +#define TAG(x) x##_RGBA_TEX0 +#include "r128_fasttmp.h" + +#define TYPE (R128_RGBA_BIT | R128_TEX0_BIT | R128_TEX1_BIT) +#define TAG(x) x##_RGBA_TEX0_TEX1 +#include "r128_fasttmp.h" + +/* This one *could* get away with sneaking TEX1 into the color and + * specular slots, thus fitting inside a cache line. Would be even + * better to switch to a smaller vertex. + */ +#define TYPE (R128_TEX0_BIT | R128_TEX1_BIT) +#define TAG(x) x##_TEX0_TEX1 +#include "r128_fasttmp.h" + + + +/* Render elements directly from original list of vertices. */ +static void r128RenderElementsDirect(struct vertex_buffer *VB) +{ + GLcontext *ctx = VB->ctx; + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + GLenum prim = ctx->CVA.elt_mode; + GLuint nr = VB->EltPtr->count; + render_func func = render_tab_r128_smooth_indirect[prim]; + GLuint p = 0; + + if (r128ctx->dirty) r128UpdateHWState(r128ctx); + + do { + func(VB, 0, nr, 0); + } while (ctx->Driver.MultipassFunc && + ctx->Driver.MultipassFunc(VB, ++p)); +} + +/* Project vertices from clip to device space */ +static void r128ProjectVertices(struct vertex_buffer *VB) +{ + GLcontext *ctx = VB->ctx; + GLmatrix *mat = &ctx->Viewport.WindowMap; + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + r128VertexBufferPtr r128VB = R128_DRIVER_DATA(VB); + GLfloat m[16]; + + m[MAT_SX] = mat->m[MAT_SX]; + 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] * (1.0 / 0x10000); + m[MAT_TZ] = mat->m[MAT_TZ] * (1.0 / 0x10000); + +#if USE_RHW2 + /* FIXME: Handle RHW2?? */ + gl_project_v16(r128VB->verts[VB->CopyStart].f, + r128VB->verts[r128VB->last_vert].f, + m, + 16 * 4); +#else + gl_project_v16(r128VB->verts[VB->CopyStart].f, + r128VB->verts[r128VB->last_vert].f, + m, + 16 * 4); +#endif +} + +/* Project clipped vertices from clip to device space */ +static void r128ProjectClippedVertices(struct vertex_buffer *VB) +{ + GLcontext *ctx = VB->ctx; + GLmatrix *mat = &ctx->Viewport.WindowMap; + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + r128VertexBufferPtr r128VB = R128_DRIVER_DATA(VB); + GLfloat m[16]; + + m[MAT_SX] = mat->m[MAT_SX]; + 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] * (1.0 / 0x10000); + m[MAT_TZ] = mat->m[MAT_TZ] * (1.0 / 0x10000); + +#if USE_RHW2 + /* FIXME: Handle RHW2?? */ + gl_project_clipped_v16(r128VB->verts[VB->CopyStart].f, + r128VB->verts[r128VB->last_vert].f, + m, + 16 * 4, + VB->ClipMask + VB->CopyStart); +#else + gl_project_clipped_v16(r128VB->verts[VB->CopyStart].f, + r128VB->verts[r128VB->last_vert].f, + m, + 16 * 4, + VB->ClipMask + VB->CopyStart); +#endif +} + +static r128FastPathTable r128FastTab[0x80]; + +/* Initialize the table of fast path support functions */ +void r128FastPathInit(void) +{ + r128_clip_render_init_elt(); + render_init_r128_smooth_indirect(); + + r128_init_fastpath(&r128FastTab[0]); + r128_init_fastpath_RGBA(&r128FastTab[R128_RGBA_BIT]); + r128_init_fastpath_TEX0(&r128FastTab[R128_TEX0_BIT]); + r128_init_fastpath_RGBA_TEX0(&r128FastTab[R128_RGBA_BIT|R128_TEX0_BIT]); + r128_init_fastpath_TEX0_TEX1(&r128FastTab[R128_TEX0_BIT|R128_TEX1_BIT]); + r128_init_fastpath_RGBA_TEX0_TEX1(&r128FastTab[R128_RGBA_BIT|R128_TEX0_BIT| + R128_TEX1_BIT]); +} + +#define VALID_SETUP (R128_RGBA_BIT | R128_TEX0_BIT | R128_TEX1_BIT) + +void r128FastPath(struct vertex_buffer *VB) +{ + GLcontext *ctx = VB->ctx; + GLenum prim = ctx->CVA.elt_mode; + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + r128FastPathTable *tab = &r128FastTab[r128ctx->SetupIndex & VALID_SETUP]; + GLuint do_cliptest = 1; + + gl_prepare_arrays_cva(VB); /* still need this */ + + /* Reserve enough space for the pathological case */ + if (VB->EltPtr->count * 12 > R128_DRIVER_DATA(VB)->size) { + r128ResizeVB(VB, VB->EltPtr->count * 12); + do_cliptest = 1; + } + + tab->build_vertices(VB, do_cliptest); /* object->clip space */ + + if (r128ctx->dirty) r128UpdateHWState(r128ctx); + + if (VB->ClipOrMask) { + if (!VB->ClipAndMask) { + render_func *clip = r128_clip_render_tab_elt; + + r128ctx->interp = tab->interp; + clip[prim](VB, 0, VB->EltPtr->count, 0); /* build new elts */ + ctx->CVA.elt_mode = gl_reduce_prim[prim]; + VB->EltPtr = &(R128_DRIVER_DATA(VB)->clipped_elements); + r128ProjectClippedVertices(VB); /* clip->device space */ + r128RenderElementsDirect(VB); /* render using new list */ + } + } else { + r128ProjectVertices(VB); /* clip->device space */ + r128RenderElementsDirect(VB); /* render using orig list */ + } + + /* This indicates that there is no cached data to reuse */ + VB->pipeline->data_valid = 0; + VB->pipeline->new_state = 0; +} diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_fastpath.h b/xc/lib/GL/mesa/src/drv/r128/r128_fastpath.h new file mode 100644 index 000000000..47bb92049 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_fastpath.h @@ -0,0 +1,48 @@ +/* $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_FASTPATH_H_ +#define _R128_FASTPATH_H_ + +typedef void (*r128BuildVerticesFunc)(struct vertex_buffer *VB, + GLuint do_cliptest); +typedef void (*r128InterpFunc)(GLfloat t, + GLfloat *result, + const GLfloat *in, + const GLfloat *out); + +extern void r128FastPathInit(void); +extern void r128FastPath(struct vertex_buffer *VB); + +#endif /* _R128_FASTPATH_H_ */ diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_fasttmp.h b/xc/lib/GL/mesa/src/drv/r128/r128_fasttmp.h new file mode 100644 index 000000000..e76dd52b4 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_fasttmp.h @@ -0,0 +1,155 @@ +/* $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> + * + */ + +/* 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. */ + +/* The first part of setup is applied to all vertices, clipped or + * unclipped. This data w!ill be used for clipping, and then all + * vertices with a zero clipmask will be projected to device space. + * + * This could be split into several loops, but - it seems that the + * large stride of the fxVertices makes cache issues the big + * performance factor, and that multiple loops mean multiple cache + * misses.... + */ +static void TAG(r128_setup_full)(struct vertex_buffer *VB, GLuint do_cliptest) +{ + GLcontext *ctx = VB->ctx; + r128VertexBufferPtr r128VB = R128_DRIVER_DATA(VB); + const GLfloat *m = ctx->ModelProjectMatrix.m; + GLuint start = VB->CopyStart; + GLuint count = VB->Count; + GLuint i; + + gl_xform_points3_v16_general(r128VB->verts[start].f, + m, + VB->ObjPtr->start, + VB->ObjPtr->stride, + count - start); + + if (do_cliptest) { + VB->ClipAndMask = ~0; + VB->ClipOrMask = 0; + gl_cliptest_points4_v16(r128VB->verts[start].f, + r128VB->verts[count].f, + &(VB->ClipOrMask), + &(VB->ClipAndMask), + VB->ClipMask + start); + } + + /* These branches are all resolved at compile time. Hopefully all + * the pointers are valid addresses even when not enabled. + */ + if (TYPE) { + GLubyte *color = VB->ColorPtr->start; + GLfloat *tex0_data = VB->TexCoordPtr[0]->start; + GLfloat *tex1_data = VB->TexCoordPtr[1]->start; + + GLuint color_stride = VB->ColorPtr->stride; + GLuint tex0_stride = VB->TexCoordPtr[0]->stride; + GLuint tex1_stride = VB->TexCoordPtr[1]->stride; + + GLfloat *f = r128VB->verts[start].f; + + for (i = start ; i < count ; i++, f += 16) { + if (TYPE & R128_RGBA_BIT) { + GLubyte *b = (GLubyte *)&f[CLIP_UBYTE_COLOR]; + GLubyte *col = color; color += color_stride; + b[CLIP_UBYTE_R] = col[0]; + b[CLIP_UBYTE_G] = col[1]; + b[CLIP_UBYTE_B] = col[2]; + b[CLIP_UBYTE_A] = col[3]; + } + if (TYPE & R128_TEX0_BIT) { + f[CLIP_S0] = tex0_data[0]; + f[CLIP_T0] = tex0_data[1]; + STRIDE_F(tex0_data, tex0_stride); + } + if (TYPE & R128_TEX1_BIT) { + f[CLIP_S1] = tex1_data[0]; + f[CLIP_T1] = tex1_data[1]; + STRIDE_F(tex1_data, tex1_stride); + } + } + } + + r128VB->clipped_elements.count = start; + r128VB->last_vert = count; +} + + +/* Changed to just put the interp func instead of the whole clip + * routine into the header. Less code and better chance of doing some + * of this stuff in assembly. + */ +static void TAG(r128_interp_vert)(GLfloat t, + GLfloat *O, + const GLfloat *I, + const GLfloat *J) +{ + O[0] = LINTERP(t, I[0], J[0]); + O[1] = LINTERP(t, I[1], J[1]); + O[2] = LINTERP(t, I[2], J[2]); + O[3] = LINTERP(t, I[3], J[3]); + + if (TYPE & R128_RGBA_BIT) { + INTERP_RGBA(t, + ((GLubyte *)&(O[4])), + ((GLubyte *)&(I[4])), + ((GLubyte *)&(J[4]))); + } + + if (TYPE & R128_TEX0_BIT) { + O[6] = LINTERP(t, I[6], J[6]); + O[7] = LINTERP(t, I[7], J[7]); + } + + if (TYPE & R128_TEX1_BIT) { + O[8] = LINTERP(t, I[8], J[8]); + O[9] = LINTERP(t, I[9], J[9]); + } +} + + +static void TAG(r128_init_fastpath)(r128FastPathTable *tab) +{ + tab->build_vertices = TAG(r128_setup_full); + tab->interp = TAG(r128_interp_vert); +} + +#undef TYPE +#undef TAG +#undef SIZE 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 6cb43ae90..2140a7525 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_init.h +++ b/xc/lib/GL/mesa/src/drv/r128/r128_init.h @@ -48,8 +48,20 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r128_screen.h" #include "r128_context.h" -#define DEBUG -#ifdef DEBUG +/* NOTE: The vertex buffer code is currently unstable because of the + switches between CCE and MMIO mode in the X server. Fixing the X + server to use the CCE should fix this problem. So, for now, it is + recommended that you do not use it. */ + +#define DEBUG 1 +#define USE_FAST_PATH 1 +#define USE_VERTEX_BUFFERS 0 +#define USE_AGP_TEXTURES 0 +#define USE_RGB8_TEXTURES 0 +#define FLUSH_VB_ON_STATE_CHANGE 1 + + +#if DEBUG #include <stdio.h> #define R128_DEBUG(p) printf p #endif diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_lock.h b/xc/lib/GL/mesa/src/drv/r128/r128_lock.h index 2d80b0bbe..58bb33f47 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_lock.h +++ b/xc/lib/GL/mesa/src/drv/r128/r128_lock.h @@ -92,6 +92,8 @@ extern int prevLockLine; 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(CC->xmCtx); \ } \ @@ -116,16 +118,26 @@ extern int prevLockLine; /* FIXME: The Rage128 has multiple clip rects -- optimize! */ #define BEGIN_CLIP_LOOP(CC) \ do { \ - __DRIdrawablePrivate *dPriv = CC->driDrawable; \ - int _nc = dPriv->numClipRects; \ + __DRIdrawablePrivate *_dPriv = CC->driDrawable; \ + int _nc = _dPriv->numClipRects; \ \ LOCK_HARDWARE(CC); \ while (_nc--) { \ if (CC->needClip) { \ - r128SetClipRect(CC, &dPriv->pClipRects[_nc]); \ + r128SetClipRect(CC, &_dPriv->pClipRects[_nc]); \ } +/* FIXME: Have the X server save/restore its own clip rect */ #define END_CLIP_LOOP(CC) \ + if (CC->needClip) { \ + /* FIXME: Move this to r128_state.c ?? */ \ + unsigned char *R128MMIO = CC->r128Screen->mmio; \ + R128CCE_WAIT_LOCKED(3); \ + R128CCE0(R128_CCE_PACKET0, R128_SC_TOP_LEFT_C, 1); \ + R128CCE(0x00000000); \ + R128CCE(0x1fff1fff); \ + R128CCE_END_LOCKED(); \ + } \ } \ UNLOCK_HARDWARE(CC); \ } while (0) diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_pipeline.c b/xc/lib/GL/mesa/src/drv/r128/r128_pipeline.c new file mode 100644 index 000000000..55487ffcd --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_pipeline.c @@ -0,0 +1,126 @@ +/* $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> + * + */ + +#include "r128_init.h" +#include "r128_mesa.h" +#include "r128_vb.h" +#include "r128_fastpath.h" +#include "r128_pipeline.h" + +#include "types.h" + +static struct gl_pipeline_stage r128FastStage = { + "R128 Fast Path", + (PIPE_OP_VERT_XFORM | + PIPE_OP_RAST_SETUP_0 | + PIPE_OP_RAST_SETUP_1 | + PIPE_OP_RENDER), + PIPE_PRECALC, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + r128FastPath +}; + +/* Build the PRECALC pipeline with our stage, if possible. Otherwise, + return GL_FALSE */ +GLboolean r128DDBuildPrecalcPipeline(GLcontext *ctx) +{ +#if USE_FAST_PATH + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + struct gl_pipeline *pipe = &ctx->CVA.pre; + + if (r128ctx->RenderIndex == 0 && + !(ctx->Enabled & (TEXTURE0_3D | + TEXTURE1_3D | + ENABLE_TEXMAT0 | + ENABLE_TEXMAT1 | + ENABLE_TEXGEN0 | + ENABLE_TEXGEN1 | + ENABLE_USERCLIP | + ENABLE_LIGHT | + ENABLE_FOG)) && + (ctx->Array.Flags & (VERT_OBJ_234 | + VERT_TEX0_4 | + VERT_TEX1_4 | + VERT_ELT)) == (VERT_OBJ_23 | + VERT_ELT)) { + pipe->stages[0] = &r128FastStage; + pipe->stages[1] = 0; + pipe->new_inputs = ctx->RenderFlags & VERT_DATA; + pipe->ops = pipe->stages[0]->ops; + + r128ctx->useFastPath = GL_TRUE; + return GL_TRUE; + } + + if (r128ctx->useFastPath) { + r128ctx->useFastPath = GL_FALSE; + + ctx->CVA.VB->ClipOrMask = 0; + ctx->CVA.VB->ClipAndMask = CLIP_ALL_BITS; + ctx->Array.NewArrayState |= ctx->Array.Summary; + } +#endif + + return GL_FALSE; +} + +/* Register the pipeline with our stages included */ +GLuint r128RegisterPipelineStages(struct gl_pipeline_stage *out, + const struct gl_pipeline_stage *in, + GLuint nr) +{ +#if USE_FAST_PATH + int i; + + for (i = 0; i < nr; i++) { + out[i] = in[i]; + switch (in[i].ops) { + case PIPE_OP_RAST_SETUP_0: + out[i].cva_state_change = (NEW_LIGHTING | + NEW_TEXTURING | + NEW_RASTER_OPS); + out[i].state_change = ~0; + out[i].check = r128CheckPartialRasterSetup; + out[i].run = r128PartialRasterSetup; + break; + + case PIPE_OP_RAST_SETUP_0|PIPE_OP_RAST_SETUP_1: + out[i].run = r128DoRasterSetup; + break; + } + } +#endif + + return nr; +} diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_pipeline.h b/xc/lib/GL/mesa/src/drv/r128/r128_pipeline.h new file mode 100644 index 000000000..280e6b943 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_pipeline.h @@ -0,0 +1,43 @@ +/* $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_PIPELINE_H_ +#define _R128_PIPELINE_H_ + +extern GLboolean r128DDBuildPrecalcPipeline(GLcontext *ctx); +extern GLuint r128RegisterPipelineStages(struct gl_pipeline_stage *out, + const struct gl_pipeline_stage *in, + GLuint nr); + +#endif /* _R128_PIPELINE_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 new file mode 100644 index 000000000..32e72e97d --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_screen.c @@ -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> + * + */ + +#include "r128_dri.h" +#include "r128_reg.h" + +#include "r128_init.h" +#include "r128_context.h" +#include "r128_xmesa.h" +#include "r128_tris.h" +#include "r128_vb.h" +#include "r128_fastpath.h" + +/* Create the device specific screen private data struct */ +r128ScreenPtr r128CreateScreen(__DRIscreenPrivate *sPriv) +{ + r128ScreenPtr r128Screen; + R128DRIPtr r128DRIPriv = (R128DRIPtr)sPriv->pDevPriv; + + /* Allocate the private area */ + r128Screen = (r128ScreenPtr)Xmalloc(sizeof(*r128Screen)); + if (!r128Screen) return NULL; + + r128Screen->mmioRgn.handle = r128DRIPriv->registerHandle; + r128Screen->mmioRgn.size = r128DRIPriv->registerSize; + if (drmMap(sPriv->fd, + r128Screen->mmioRgn.handle, + r128Screen->mmioRgn.size, + (drmAddressPtr)&r128Screen->mmio)) { + Xfree(r128Screen); + return NULL; + } + + r128Screen->agpRgn.handle = r128DRIPriv->agpHandle; + r128Screen->agpRgn.size = r128DRIPriv->agpSize; + if (drmMap(sPriv->fd, + r128Screen->agpRgn.handle, + r128Screen->agpRgn.size, + (drmAddressPtr)&r128Screen->agp)) { + drmUnmap((drmAddress)r128Screen->mmio, r128Screen->mmioRgn.size); + Xfree(r128Screen); + return NULL; + } + + r128Screen->deviceID = r128DRIPriv->deviceID; + + r128Screen->width = r128DRIPriv->width; + r128Screen->height = r128DRIPriv->height; + r128Screen->depth = r128DRIPriv->depth; + r128Screen->bpp = r128DRIPriv->bpp; + + r128Screen->fb = sPriv->pFB; + r128Screen->fbOffset = sPriv->fbOrigin; + r128Screen->fbStride = sPriv->fbStride; + r128Screen->fbSize = sPriv->fbSize; + + r128Screen->fbX = r128DRIPriv->fbX; + r128Screen->fbY = r128DRIPriv->fbY; + r128Screen->backX = r128DRIPriv->backX; + r128Screen->backY = r128DRIPriv->backY; + r128Screen->depthX = r128DRIPriv->depthX; + r128Screen->depthY = r128DRIPriv->depthY; + r128Screen->textureX = r128DRIPriv->textureX; + r128Screen->textureY = r128DRIPriv->textureY; + r128Screen->textureSize = r128DRIPriv->textureSize; + r128Screen->log2TexGran = r128DRIPriv->log2TexGran; + +#if 0 + /* FIXME: For testing only */ + r128Screen->textureX = 0; + r128Screen->textureY = 8192; + r128Screen->textureSize = 4*1024*1024; + r128Screen->log2TexGran = 15; +#endif + +#if 1 + /* FIXME: For testing only */ + if (getenv("LIBGL_SHOW_BUFFERS")) { + r128Screen->backX = 0; + r128Screen->backY = r128DRIPriv->height/2; + r128Screen->depthX = r128DRIPriv->width/2; + r128Screen->depthY = r128DRIPriv->height/2; + } +#endif + + r128Screen->CCEMode = r128DRIPriv->CCEMode; + r128Screen->CCEFifoSize = r128DRIPriv->CCEFifoSize; + + r128Screen->ringStart = r128DRIPriv->ringStart; + r128Screen->ringSize = r128DRIPriv->ringSize; + r128Screen->ringWritePtr = &r128DRIPriv->ringWrite; + r128Screen->ringReadPtr = (int *)(r128Screen->agp + + r128DRIPriv->ringReadOffset); + + r128Screen->vbStart = r128DRIPriv->vbStart; + r128Screen->vbSize = r128DRIPriv->vbSize; + + r128Screen->indStart = r128DRIPriv->indStart; + r128Screen->indSize = r128DRIPriv->indSize; + + r128Screen->agpTexStart = r128DRIPriv->agpTexStart; + r128Screen->agpTexSize = r128DRIPriv->agpTexSize; + r128Screen->log2AGPTexGran = r128DRIPriv->log2AGPTexGran; + + r128Screen->MMIOFifoSlots = 0; + r128Screen->CCEFifoSlots = 0; + + r128Screen->CCEFifoAddr = R128_PM4_FIFO_DATA_EVEN; + + r128Screen->driScreen = sPriv; + + r128FastPathInit(); + r128TriangleFuncsInit(); + r128SetupInit(); + + return r128Screen; +} + +/* Destroy the device specific screen private data struct */ +void r128DestroyScreen(__DRIscreenPrivate *sPriv) +{ + r128ScreenPtr r128Screen = (r128ScreenPtr)sPriv->private; + + drmUnmap((drmAddress)r128Screen->mmio, r128Screen->mmioRgn.size); + drmUnmap((drmAddress)r128Screen->agp, r128Screen->agpRgn.size); + + Xfree(r128Screen); + sPriv->private = NULL; +} diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_screen.h b/xc/lib/GL/mesa/src/drv/r128/r128_screen.h index bfbf4bc5f..07670331e 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_screen.h +++ b/xc/lib/GL/mesa/src/drv/r128/r128_screen.h @@ -38,54 +38,85 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #ifdef GLX_DIRECT_RENDERING typedef struct { - drmHandle handle; - drmSize size; + drmHandle handle; /* Handle to the DRM region */ + drmSize size; /* Size of the DRM region */ } r128RegionRec, *r128RegionPtr; typedef struct { + /* FIXME: There needs to be two register regions. One to allow + read-only access to the block of non-FIFO'd GUI registers + (0x0000-0x0FFC), and one to allow read/write acces to the block + of FIFO'd GUI registers (0x1000-0x1FFC) */ + + /* MMIO register data */ r128RegionRec mmioRgn; unsigned char *mmio; + /* AGP data */ r128RegionRec agpRgn; unsigned char *agp; - int deviceID; - - int width; - int height; - int depth; - int bpp; - + /* Frame buffer data */ unsigned char *fb; unsigned long fbOffset; int fbStride; int fbSize; - int fbX; + int CCEMode; /* CCE mode that server/clients use */ + int CCEFifoSize; /* Size of the CCE command FIFO */ + + /* CCE ring buffer data */ + unsigned long ringStart; + int ringSize; + /* FIXME: These should be in the + SAREA so that they can be + shared with other clients. */ + int *ringWritePtr; /* Pointer to current write addr */ + int *ringReadPtr; /* Pointer to current read addr */ + + /* CCE vertex buffer data */ + unsigned long vbStart; + int vbSize; + + /* CCE indirect buffer data */ + unsigned long indStart; + int indSize; + + /* CCE AGP Texture data */ + unsigned long agpTexStart; + int agpTexSize; + int log2AGPTexGran; + + /* DRI screen private data */ + int deviceID; /* PCI device ID */ + int width; /* Width in pixels of display */ + int height; /* Height in scanlines of display */ + int depth; /* Depth of display (8, 15, 16, 24) */ + int bpp; /* Bit depth of disp (8, 16, 24, 32) */ + + int fbX; /* Start of frame buffer */ int fbY; - int backX; + int backX; /* Start of shared back buffer */ int backY; - int depthX; + int depthX; /* Start of shared depth buffer */ int depthY; - int textureX; + int textureX; /* Start of textures in frame buffer */ int textureY; int textureSize; + int log2TexGran; - int CCEMode; - int CCEFifoSize; + int MMIOFifoSlots; /* Free slots in the FIFO (64 max) */ + int CCEFifoSlots; /* Free slots in the CCE FIFO */ - unsigned long ringStart; - int ringSize; - int *ringWritePtr; - int *ringReadPtr; - - int MMIOFifoSlots; - int CCEFifoSlots; - - int CCEFifoAddr; + int CCEFifoAddr; /* MMIO offset to write next CCE + value (only used when CCE is + in PIO mode). */ __DRIscreenPrivate *driScreen; } r128ScreenRec, *r128ScreenPtr; +r128ScreenPtr r128CreateScreen(__DRIscreenPrivate *sPriv); +void r128DestroyScreen(__DRIscreenPrivate *sPriv); + #endif #endif /* _R128_SCREEN_H_ */ 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 f6452b1b5..6338d0e54 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_span.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_span.c @@ -42,60 +42,42 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r128_cce.h" #include "r128_span.h" +/* Null functions for span functions not yet implemented */ + static void r128DDWriteRGBASpan(const GLcontext *ctx, GLuint n, GLint x, GLint y, const GLubyte rgba[][4], - const GLubyte mask[]) -{ -} - + const GLubyte mask[]) {} static void r128DDWriteRGBSpan(const GLcontext *ctx, GLuint n, GLint x, GLint y, const GLubyte rgb[][3], - const GLubyte mask[]) -{ -} - + const GLubyte mask[]) {} static void r128DDWriteMonoRGBASpan(const GLcontext *ctx, GLuint n, GLint x, GLint y, - const GLubyte mask[]) -{ -} - + const GLubyte mask[]) {} static void r128DDWriteRGBAPixels(const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte rgba[][4], - const GLubyte mask[]) -{ -} - + const GLubyte mask[]) {} static void r128DDWriteMonoRGBAPixels(const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], - const GLubyte mask[]) -{ -} - + const GLubyte mask[]) {} static void r128DDReadRGBASpan(const GLcontext *ctx, GLuint n, GLint x, GLint y, - GLubyte rgba[][4]) -{ -} - + GLubyte rgba[][4]) {} static void r128DDReadRGBAPixels(const GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], GLubyte rgba[][4], - const GLubyte mask[]) -{ -} + const GLubyte mask[]) {} -/* 16bpp span routines */ +/* 16bpp-specific span functions */ #define DBG 0 @@ -114,7 +96,7 @@ static void r128DDReadRGBAPixels(const GLcontext *ctx, (r128ctx->bufY + dPriv->y) * pitch) #define INIT_MONO_PIXEL(p) \ - GLushort p = R128_CONTEXT(ctx)->regs.constant_color_c; + GLushort p = R128_CONTEXT(ctx)->Color; #define CLIPPIXEL(_x,_y) (_x >= minx && _x <= maxx && \ _y >= miny && _y <= maxy) @@ -146,7 +128,6 @@ static void r128DDReadRGBAPixels(const GLcontext *ctx, UNLOCK_HARDWARE(r128ctx); -/* For 16 bit depth visuals */ #define Y_FLIP(_y) (height - _y) #define WRITE_RGBA(_x, _y, r, g, b, a) \ *(GLushort *)(buf + (_x)*2 + (_y)*pitch) = ((((int)r & 0xf8) << 8) | \ @@ -168,6 +149,7 @@ static void r128DDReadRGBAPixels(const GLcontext *ctx, #include "spantmp.h" +/* Initialize the driver's span functions */ void r128DDInitSpanFuncs(GLcontext *ctx) { r128ContextPtr r128ctx = R128_CONTEXT(ctx); 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 8517960f9..55ab014a7 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_state.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_state.c @@ -42,69 +42,41 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r128_cce.h" #include "r128_tris.h" #include "r128_vb.h" +#include "r128_tex.h" -#if 0 -/* FIXME: FOR TESTING A SIMPLE DRAWING FUNCTION */ -static void pfunc(GLcontext *ctx, GLuint first, GLuint last) {} -static void lfunc(GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv) {} -static void tfunc(GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint pv) -{ - r128ContextPtr r128ctx = R128_CONTEXT(ctx); - unsigned char *R128MMIO = r128ctx->r128Screen->mmio; - float h = r128ctx->driDrawable->h; - - if (r128ctx->dirty) { - R128_DEBUG(("Rendering with a dirty context: %08x\n", r128ctx->dirty)); - /* r128UpdateState(r128ctx); */ - } - - R128CCE_BEGIN(15); - R128CCE3(R128_CCE_PACKET3_3D_RNDR_GEN_PRIM, 13); - R128CCE(R128_CCE_VC_FRMT_DIFFUSE_ARGB); - R128CCE(R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST | - R128_CCE_VC_CNTL_PRIM_WALK_RING | - (3 << R128_CCE_VC_CNTL_NUM_SHIFT)); - - R128CCEF(ctx->VB->Win.data[v1][0]); - R128CCEF(h-ctx->VB->Win.data[v1][1]); - R128CCEF(ctx->VB->Win.data[v1][2]); - R128CCE((ctx->VB->Color[0]->data[v1][2] << 0) | - (ctx->VB->Color[0]->data[v1][1] << 8) | - (ctx->VB->Color[0]->data[v1][0] << 16) | - (ctx->VB->Color[0]->data[v1][3] << 24)); - - R128CCEF(ctx->VB->Win.data[v2][0]); - R128CCEF(h-ctx->VB->Win.data[v2][1]); - R128CCEF(ctx->VB->Win.data[v2][2]); - R128CCE((ctx->VB->Color[0]->data[v2][2] << 0) | - (ctx->VB->Color[0]->data[v2][1] << 8) | - (ctx->VB->Color[0]->data[v2][0] << 16) | - (ctx->VB->Color[0]->data[v2][3] << 24)); - - R128CCEF(ctx->VB->Win.data[v3][0]); - R128CCEF(h-ctx->VB->Win.data[v3][1]); - R128CCEF(ctx->VB->Win.data[v3][2]); - R128CCE((ctx->VB->Color[0]->data[v3][2] << 0) | - (ctx->VB->Color[0]->data[v3][1] << 8) | - (ctx->VB->Color[0]->data[v3][0] << 16) | - (ctx->VB->Color[0]->data[v3][3] << 24)); - - R128CCE_END(); -} -static void qfunc(GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint v4, GLuint pv) +CARD32 r128PackColor(GLuint d, + GLubyte r, GLubyte g, GLubyte b, GLubyte a) { - tfunc(ctx, v1, v2, v4, pv); - tfunc(ctx, v2, v3, v4, pv); -} + switch (d) { + case 8: + return (((r & 0xe0) >> 0) | + ((g & 0xe0) >> 3) | + ((b & 0xc0) >> 6) | + ((a & 0x00) >> 0)); + case 15: + return (((r & 0xf8) << 7) | + ((g & 0xf8) << 2) | + ((b & 0xf8) >> 3) | + ((a & 0x80) << 8)); + case 16: + return (((r & 0xf8) << 8) | + ((g & 0xfc) << 3) | + ((b & 0xf8) >> 3) | + ((a & 0x00) << 0)); + case 24: + return (((r & 0xff) << 16) | + ((g & 0xff) << 8) | + ((b & 0xff) >> 0) | + ((a & 0x00) << 0)); + case 32: + return (((r & 0xff) << 16) | + ((g & 0xff) << 8) | + ((b & 0xff) >> 0) | + ((a & 0xff) << 24)); + } -static void r128DDUpdateState(GLcontext *ctx) -{ - ctx->Driver.PointsFunc = pfunc; - ctx->Driver.LineFunc = lfunc; - ctx->Driver.TriangleFunc = tfunc; - ctx->Driver.QuadFunc = qfunc; + return 0; } -#else #define INTERESTED (~(NEW_MODELVIEW | \ NEW_PROJECTION | \ @@ -133,7 +105,6 @@ static void r128DDUpdateState(GLcontext *ctx) ctx->Driver.RectFunc = NULL; } } -#endif static void r128DDUpdateHWState(GLcontext *ctx) { @@ -141,7 +112,16 @@ static void r128DDUpdateHWState(GLcontext *ctx) /* FIXME: state is being updated too often */ if (r128ctx->dirty) - r128UpdateState(r128ctx); + r128UpdateHWState(r128ctx); +} + +static void r128DDReducedPrimitiveChange(GLcontext *ctx, GLenum prim) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + + /* FIXME: Also need to flush between tris and tristrips/fans when we + support them directly */ + R128_FLUSH_VB(r128ctx); } static void r128DDClearColor(GLcontext *ctx, @@ -149,10 +129,7 @@ static void r128DDClearColor(GLcontext *ctx, { r128ContextPtr r128ctx = R128_CONTEXT(ctx); - r128ctx->ClearColor = (((r >> 0) << 16) | - ((g >> 0) << 8) | - ((b >> 0) << 0) | - ((a >> 0) << 24)); + r128ctx->ClearColor = r128PackColor(32, r, g, b, a); } static void r128DDColor(GLcontext *ctx, @@ -160,25 +137,19 @@ static void r128DDColor(GLcontext *ctx, { r128ContextPtr r128ctx = R128_CONTEXT(ctx); -#if 1 - r128ctx->regs.constant_color_c = (((r >> 3) << 11) | - ((g >> 2) << 5) | - ((b >> 3) << 0) | - ((a >> 8) << 16)); -#else - r128ctx->regs.constant_color_c = (((r >> 0) << 16) | - ((g >> 0) << 8) | - ((b >> 0) << 0) | - ((a >> 0) << 24)); -#endif + r128ctx->Color = r128PackColor(r128ctx->r128Screen->depth, r, g, b, a); } -static GLboolean r128DDSetBuffer(GLcontext *ctx, GLenum mode ) +/* FIXME: After moving to Mesa 3.3, change this to SetReadBuffer and + SetDrawBuffer */ +static GLboolean r128DDSetBuffer(GLcontext *ctx, GLenum mode) { r128ContextPtr r128ctx = R128_CONTEXT(ctx); - int found = GL_FALSE; int x = r128ctx->driDrawable->x; int y = r128ctx->driDrawable->y; + int found; + + r128ctx->Fallback &= ~R128_FALLBACK_DRAW_BUFFER; switch (mode) { case GL_FRONT_LEFT: @@ -191,11 +162,18 @@ static GLboolean r128DDSetBuffer(GLcontext *ctx, GLenum mode ) r128ctx->bufY = r128ctx->r128Screen->backY; found = GL_TRUE; break; + default: + r128ctx->Fallback |= R128_FALLBACK_DRAW_BUFFER; + found = GL_FALSE; + break; } x += r128ctx->bufX; y += r128ctx->bufY; +#if FLUSH_VB_ON_STATE_CHANGE + R128_FLUSH_VB(r128ctx); +#endif r128ctx->regs.window_xy_offset = ((y << R128_WINDOW_Y_SHIFT) | (x << R128_WINDOW_X_SHIFT)); @@ -208,6 +186,9 @@ static GLboolean r128DDSetBuffer(GLcontext *ctx, GLenum mode ) (r128ctx->r128Screen->depthY - r128ctx->bufY) * r128ctx->r128Screen->fbStride); + + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_WIN_Z_POS; return found; } @@ -215,7 +196,9 @@ static GLboolean r128DDColorMask(GLcontext *ctx, GLboolean r, GLboolean g, GLboolean b, GLboolean a) { - /* FIXME??? */ + /* FIXME: Implement this function. Make sure the fallbacks are + covered if they do not properly handle individual color channel + masking. */ return GL_TRUE; } @@ -242,10 +225,16 @@ static void r128DDAlphaFunc(GLcontext *ctx, GLenum func, GLclampf ref) return; } - r128ctx->regs.misc_3d_state_cntl_reg = a; + if (r128ctx->regs.misc_3d_state_cntl_reg != a) { +#if FLUSH_VB_ON_STATE_CHANGE + R128_FLUSH_VB(r128ctx); +#endif + r128ctx->regs.misc_3d_state_cntl_reg = a; - /* FIXME: Load into hardware now??? */ - r128ctx->dirty |= R128_UPDATE_CONTEXT; + /* FIXME: Load into hardware now??? */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_ALPHASTATE; + } } static void r128DDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor) @@ -275,7 +264,9 @@ static void r128DDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor) case GL_SRC_ALPHA_SATURATE: b |= R128_ALPHA_BLEND_SRC_SRCALPHASAT; break; #if 0 - /* FIXME */ + /* FIXME: These are not supported directly by the Rage 128. + They could be emulated using something like the TexEnv + modes. */ case GL_CONSTANT_COLOR: b |= 0; break; case GL_ONE_MINUS_CONSTANT_COLOR: b |= 0; @@ -308,7 +299,9 @@ static void r128DDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor) case GL_ONE_MINUS_DST_ALPHA: b |= R128_ALPHA_BLEND_DST_INVDESTALPHA; break; #if 0 - /* FIXME */ + /* FIXME: These are not supported directly by the Rage 128. + They could be emulated using something like the TexEnv + modes. */ case GL_CONSTANT_COLOR: b |= 0; break; case GL_ONE_MINUS_CONSTANT_COLOR: b |= 0; @@ -323,10 +316,16 @@ static void r128DDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor) return; } - r128ctx->regs.misc_3d_state_cntl_reg = b; + if (r128ctx->regs.misc_3d_state_cntl_reg != b) { +#if FLUSH_VB_ON_STATE_CHANGE + R128_FLUSH_VB(r128ctx); +#endif + r128ctx->regs.misc_3d_state_cntl_reg = b; - /* FIXME: Load into hardware now??? */ - r128ctx->dirty |= R128_UPDATE_CONTEXT; + /* FIXME: Load into hardware now??? */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_ALPHASTATE; + } } static void r128DDBlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, @@ -346,16 +345,10 @@ static void r128DDClearDepth(GLcontext *ctx, GLclampd d) r128ContextPtr r128ctx = R128_CONTEXT(ctx); switch (r128ctx->regs.z_sten_cntl_c & R128_Z_PIX_WIDTH_MASK) { - case R128_Z_PIX_WIDTH_16: - r128ctx->ClearDepth = d * 0x0000ffff; - break; - case R128_Z_PIX_WIDTH_24: - r128ctx->ClearDepth = d * 0x00ffffff; - break; - case R128_Z_PIX_WIDTH_32: - default: - r128ctx->ClearDepth = d * 0xffffffff; - break; + case R128_Z_PIX_WIDTH_16: r128ctx->ClearDepth = d * 0x0000ffff; break; + case R128_Z_PIX_WIDTH_24: r128ctx->ClearDepth = d * 0x00ffffff; break; + case R128_Z_PIX_WIDTH_32: r128ctx->ClearDepth = d * 0xffffffff; break; + default: return; } } @@ -375,10 +368,16 @@ static void r128DDCullFace(GLcontext *ctx, GLenum mode) default: return; } - r128ctx->regs.pm4_vc_fpu_setup = f; + if (r128ctx->regs.pm4_vc_fpu_setup != f) { +#if FLUSH_VB_ON_STATE_CHANGE + R128_FLUSH_VB(r128ctx); +#endif + r128ctx->regs.pm4_vc_fpu_setup = f; - /* FIXME: Load into hardware now??? */ - r128ctx->dirty |= R128_UPDATE_CONTEXT; + /* FIXME: Load into hardware now??? */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_SETUPSTATE; + } } static void r128DDFrontFace(GLcontext *ctx, GLenum mode) @@ -394,10 +393,16 @@ static void r128DDFrontFace(GLcontext *ctx, GLenum mode) default: return; } - r128ctx->regs.pm4_vc_fpu_setup = f; + if (r128ctx->regs.pm4_vc_fpu_setup != f) { +#if FLUSH_VB_ON_STATE_CHANGE + R128_FLUSH_VB(r128ctx); +#endif + r128ctx->regs.pm4_vc_fpu_setup = f; - /* FIXME: Load into hardware now??? */ - r128ctx->dirty |= R128_UPDATE_CONTEXT; + /* FIXME: Load into hardware now??? */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_SETUPSTATE; + } } static void r128DDDepthFunc(GLcontext *ctx, GLenum func) @@ -419,20 +424,36 @@ static void r128DDDepthFunc(GLcontext *ctx, GLenum func) default: return; } - r128ctx->regs.z_sten_cntl_c = z; + if (r128ctx->regs.z_sten_cntl_c != z) { +#if FLUSH_VB_ON_STATE_CHANGE + R128_FLUSH_VB(r128ctx); +#endif + r128ctx->regs.z_sten_cntl_c = z; - /* FIXME: Load into hardware now??? */ - r128ctx->dirty |= R128_UPDATE_CONTEXT; + /* FIXME: Load into hardware now??? */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_ZSTENSTATE; + } } static void r128DDDepthMask(GLcontext *ctx, GLboolean flag) { r128ContextPtr r128ctx = R128_CONTEXT(ctx); - if (flag) r128ctx->regs.tex_cntl_c |= R128_Z_WRITE_ENABLE; - else r128ctx->regs.tex_cntl_c &= ~R128_Z_WRITE_ENABLE; + CARD32 t = r128ctx->regs.tex_cntl_c; - /* FIXME: Load into hardware now??? */ - r128ctx->dirty |= R128_UPDATE_CONTEXT; + if (flag) t |= R128_Z_WRITE_ENABLE; + else t &= ~R128_Z_WRITE_ENABLE; + + if (r128ctx->regs.tex_cntl_c != t) { +#if FLUSH_VB_ON_STATE_CHANGE + R128_FLUSH_VB(r128ctx); +#endif + r128ctx->regs.tex_cntl_c = t; + + /* FIXME: Load into hardware now??? */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_ENGINESTATE; + } } static void r128DDEnable(GLcontext *ctx, GLenum cap, GLboolean state) @@ -442,7 +463,6 @@ static void r128DDEnable(GLcontext *ctx, GLenum cap, GLboolean state) CARD32 f = r128ctx->regs.pm4_vc_fpu_setup; switch (cap) { -#if 0 case GL_ALPHA_TEST: if (state) t |= R128_ALPHA_TEST_ENABLE; else t &= ~R128_ALPHA_TEST_ENABLE; @@ -462,7 +482,6 @@ static void r128DDEnable(GLcontext *ctx, GLenum cap, GLboolean state) case GL_CLIP_PLANE4: case GL_CLIP_PLANE5: case GL_COLOR_MATERIAL: return; -#endif case GL_CULL_FACE: f &= ~(R128_BACKFACE_MASK | R128_FRONTFACE_MASK); @@ -478,20 +497,21 @@ static void r128DDEnable(GLcontext *ctx, GLenum cap, GLboolean state) } break; -#if 1 case GL_DEPTH_TEST: if (state) t |= R128_Z_ENABLE; else t &= ~R128_Z_ENABLE; break; -#endif #if 0 + /* FIXME */ case GL_DITHER: return; + /* FIXME */ case GL_FOG: if (state) t |= R128_FOG_ENABLE; else t &= ~R128_FOG_ENABLE; break; +#endif case GL_LIGHT0: case GL_LIGHT1: @@ -531,15 +551,32 @@ static void r128DDEnable(GLcontext *ctx, GLenum cap, GLboolean state) case GL_POLYGON_OFFSET_POINT: case GL_POLYGON_OFFSET_LINE: case GL_POLYGON_OFFSET_FILL: +#if 0 + /* FIXME: Are there others in Mesa 3.3 that we need to add? */ case GL_RESCALE_NORMAL_EXT: +#endif case GL_SCISSOR_TEST: +#if 0 + /* FIXME: Are there others in Mesa 3.3 that we need to add? */ case GL_SHARED_TEXTURE_PALETTE_EXT: +#endif case GL_STENCIL_TEST: case GL_TEXTURE_1D: return; case GL_TEXTURE_2D: - if (state) t |= R128_TEXMAP_ENABLE; - else t &= ~R128_TEXMAP_ENABLE; + switch (ctx->Texture.CurrentUnit) { + case 0: + if (state) t |= R128_TEXMAP_ENABLE; + else t &= ~R128_TEXMAP_ENABLE; + break; + case 1: + if (state) t |= R128_SEC_TEXMAP_ENABLE; + else t &= ~R128_SEC_TEXMAP_ENABLE; + break; + default: + return; + } + r128ctx->dirty |= R128_UPDATE_TEXSTATE; break; case GL_TEXTURE_3D: @@ -555,22 +592,29 @@ static void r128DDEnable(GLcontext *ctx, GLenum cap, GLboolean state) case GL_INDEX_ARRAY: case GL_TEXTURE_COORD_ARRAY: case GL_EDGE_FLAG_ARRAY: return; -#endif default: return; } - if (t != r128ctx->regs.tex_cntl_c) { + if (r128ctx->regs.tex_cntl_c != t) { +#if FLUSH_VB_ON_STATE_CHANGE + R128_FLUSH_VB(r128ctx); +#endif r128ctx->regs.tex_cntl_c = t; /* FIXME: Load into hardware now??? */ - r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_ENGINESTATE; } - if (f != r128ctx->regs.pm4_vc_fpu_setup) { + if (r128ctx->regs.pm4_vc_fpu_setup != f) { +#if FLUSH_VB_ON_STATE_CHANGE + R128_FLUSH_VB(r128ctx); +#endif r128ctx->regs.pm4_vc_fpu_setup = f; /* FIXME: Load into hardware now??? */ - r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_SETUPSTATE; } } @@ -581,6 +625,7 @@ static void r128DDScissor(GLcontext *ctx, /* FIXME */ } +/* Initialize the driver's state functions */ void r128DDInitStateFuncs(GLcontext *ctx) { ctx->Driver.UpdateState = r128DDUpdateState; @@ -606,7 +651,7 @@ void r128DDInitStateFuncs(GLcontext *ctx) ctx->Driver.RenderVBCulledTab = NULL; ctx->Driver.RenderVBRawTab = NULL; - ctx->Driver.ReducedPrimitiveChange = NULL; + ctx->Driver.ReducedPrimitiveChange = r128DDReducedPrimitiveChange; ctx->Driver.MultipassFunc = NULL; ctx->Driver.AlphaFunc = r128DDAlphaFunc; @@ -635,9 +680,11 @@ void r128DDInitStateFuncs(GLcontext *ctx) ctx->Driver.Viewport = NULL; } +/* Initialize the context's hardware state */ void r128DDInitState(r128ContextPtr r128ctx) { - int dst_bpp, pitch; + int dst_bpp, depth_bpp, pitch, i; + CARD32 depthClear; pitch = r128ctx->r128Screen->fbStride / r128ctx->r128Screen->bpp; @@ -658,6 +705,33 @@ void r128DDInitState(r128ContextPtr r128ctx) break; } + switch ( +#if 0 + /* FIXME: Figure out how to use 16bpp depth buffer in 32bpp mode */ + r128ctx->glCtx->Visual->DepthBits +#else + r128ctx->r128Screen->bpp +#endif + ) { + case 16: + depthClear = 0x0000ffff; + depth_bpp = R128_Z_PIX_WIDTH_16; + break; + case 24: + depthClear = 0x00ffffff; + depth_bpp = R128_Z_PIX_WIDTH_24; + break; + case 32: + depthClear = 0xffffffff; + depth_bpp = R128_Z_PIX_WIDTH_32; + break; + default: + /* FIXME: This is an error */ + depthClear = 0x00000000; + depth_bpp = R128_Z_PIX_WIDTH_16; + break; + } + r128ctx->dirty = R128_CLEAN; r128ctx->needClip = GL_FALSE; @@ -679,37 +753,38 @@ void r128DDInitState(r128ContextPtr r128ctx) } r128ctx->ClearColor = 0x00000000; - r128ctx->ClearDepth = 0x0000ffff; /* FIXME: init to requested depth */ + r128ctx->ClearDepth = depthClear; r128ctx->regs.scale_3d_cntl = - R128_SCALE_DITHER_ERR_DIFF | - R128_TEX_CACHE_SIZE_FULL | - R128_DITHER_INIT_RESET | - R128_SCALE_3D_TEXMAP_SHADE | - R128_SCALE_PIX_REPLICATE | - R128_ALPHA_COMB_ADD_CLAMP | - R128_FOG_TABLE | - R128_ALPHA_BLEND_SRC_ONE | - R128_ALPHA_BLEND_DST_ZERO | - R128_ALPHA_TEST_ALWAYS | + R128_SCALE_DITHER_ERR_DIFF | + R128_TEX_CACHE_SIZE_FULL | + R128_DITHER_INIT_RESET | + R128_SCALE_3D_TEXMAP_SHADE | + R128_SCALE_PIX_REPLICATE | + R128_ALPHA_COMB_ADD_CLAMP | + R128_FOG_TABLE | + R128_ALPHA_BLEND_SRC_ONE | + R128_ALPHA_BLEND_DST_ZERO | + R128_ALPHA_TEST_ALWAYS | R128_COMPOSITE_SHADOW_CMP_EQUAL | - R128_TEX_MAP_ALPHA_IN_TEXTURE | + R128_TEX_MAP_ALPHA_IN_TEXTURE | R128_TEX_CACHE_LINE_SIZE_8QW; r128ctx->regs.dst_pitch_offset_c = pitch << R128_PITCH_SHIFT; r128ctx->regs.dp_gui_master_cntl = R128_GMC_DST_PITCH_OFFSET_CNTL | - R128_GMC_BRUSH_SOLID_COLOR | - dst_bpp | - R128_GMC_SRC_DATATYPE_COLOR | - R128_GMC_BYTE_MSB_TO_LSB | - R128_GMC_CONVERSION_TEMP_6500 | - R128_ROP3_S | - R128_DP_SRC_SOURCE_MEMORY | - R128_GMC_3D_FCN_EN | - R128_GMC_CLR_CMP_CNTL_DIS | - R128_AUX_CLIP_DIS | + R128_GMC_DST_CLIPPING | + R128_GMC_BRUSH_SOLID_COLOR | + dst_bpp | + R128_GMC_SRC_DATATYPE_COLOR | + R128_GMC_BYTE_MSB_TO_LSB | + R128_GMC_CONVERSION_TEMP_6500 | + R128_ROP3_S | + R128_DP_SRC_SOURCE_MEMORY | + R128_GMC_3D_FCN_EN | + R128_GMC_CLR_CMP_CNTL_DIS | + R128_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS; r128ctx->regs.sc_top_left_c = 0x00000000; @@ -721,28 +796,29 @@ void r128DDInitState(r128ContextPtr r128ctx) r128ctx->regs.z_pitch_c = pitch; r128ctx->regs.z_sten_cntl_c = - R128_Z_PIX_WIDTH_16 | - R128_Z_TEST_LESS | + depth_bpp | + R128_Z_TEST_LESS | R128_STENCIL_TEST_ALWAYS | R128_STENCIL_S_FAIL_KEEP | - R128_STENCIL_ZPASS_KEEP | + R128_STENCIL_ZPASS_KEEP | R128_STENCIL_ZFAIL_KEEP; r128ctx->regs.tex_cntl_c = - R128_Z_WRITE_ENABLE | - R128_SHADE_ENABLE | + R128_Z_WRITE_ENABLE | + R128_SHADE_ENABLE | R128_ALPHA_IN_TEX_COMPLETE_A | - R128_LIGHT_DIS | - R128_ALPHA_LIGHT_DIS | + R128_LIGHT_DIS | + R128_ALPHA_LIGHT_DIS | + R128_TEX_CACHE_FLUSH | (0x0f << R128_LOD_BIAS_SHIFT); r128ctx->regs.misc_3d_state_cntl_reg = R128_MISC_SCALE_3D_TEXMAP_SHADE | - R128_MISC_SCALE_PIX_REPLICATE | - R128_ALPHA_COMB_ADD_CLAMP | - R128_FOG_TABLE | - R128_ALPHA_BLEND_SRC_ONE | - R128_ALPHA_BLEND_DST_ZERO | + R128_MISC_SCALE_PIX_REPLICATE | + R128_ALPHA_COMB_ADD_CLAMP | + R128_FOG_TABLE | + R128_ALPHA_BLEND_SRC_ONE | + R128_ALPHA_BLEND_DST_ZERO | R128_ALPHA_TEST_ALWAYS; r128ctx->regs.texture_clr_cmp_clr_c = 0x00000000; @@ -752,62 +828,44 @@ void r128DDInitState(r128ContextPtr r128ctx) r128ctx->regs.prim_tex_cntl_c = R128_MIN_BLEND_NEAREST | R128_MAG_BLEND_NEAREST | - R128_MIP_MAP_DISABLE | - R128_TEX_CLAMP_S_WRAP | + R128_MIP_MAP_DISABLE | + R128_TEX_CLAMP_S_WRAP | R128_TEX_CLAMP_T_WRAP; r128ctx->regs.prim_texture_combine_cntl_c = - R128_COMB_MODULATE | - R128_COLOR_FACTOR_TEX | + R128_COMB_MODULATE | + R128_COLOR_FACTOR_TEX | R128_INPUT_FACTOR_INT_COLOR | - R128_COMB_ALPHA_COPY | + R128_COMB_ALPHA_COPY | R128_ALPHA_FACTOR_TEX_ALPHA | R128_INP_FACTOR_A_INT_ALPHA; r128ctx->regs.tex_size_pitch_c = - (0 << R128_TEX_PITCH_SHIFT) | - (0 << R128_TEX_SIZE_SHIFT) | - (0 << R128_TEX_HEIGHT_SHIFT) | - (0 << R128_TEX_MIN_SIZE_SHIFT) | - (0 << R128_SEC_TEX_PITCH_SHIFT) | - (0 << R128_SEC_TEX_SIZE_SHIFT) | + (0 << R128_TEX_PITCH_SHIFT) | + (0 << R128_TEX_SIZE_SHIFT) | + (0 << R128_TEX_HEIGHT_SHIFT) | + (0 << R128_TEX_MIN_SIZE_SHIFT) | + (0 << R128_SEC_TEX_PITCH_SHIFT) | + (0 << R128_SEC_TEX_SIZE_SHIFT) | (0 << R128_SEC_TEX_HEIGHT_SHIFT) | (0 << R128_SEC_TEX_MIN_SIZE_SHIFT); - r128ctx->regs.prim_tex_0_offset_c = 0x00000000; - r128ctx->regs.prim_tex_1_offset_c = 0x00000000; - r128ctx->regs.prim_tex_2_offset_c = 0x00000000; - r128ctx->regs.prim_tex_3_offset_c = 0x00000000; - r128ctx->regs.prim_tex_4_offset_c = 0x00000000; - r128ctx->regs.prim_tex_5_offset_c = 0x00000000; - r128ctx->regs.prim_tex_6_offset_c = 0x00000000; - r128ctx->regs.prim_tex_7_offset_c = 0x00000000; - r128ctx->regs.prim_tex_8_offset_c = 0x00000000; - r128ctx->regs.prim_tex_9_offset_c = 0x00000000; - r128ctx->regs.prim_tex_10_offset_c = 0x00000000; + for (i = 0; i < R128_TEX_MAXLEVELS; i++) + r128ctx->regs.prim_tex_offset[i] = 0x00000000; r128ctx->regs.sec_tex_cntl_c = R128_SEC_SELECT_PRIM_ST; r128ctx->regs.sec_tex_combine_cntl_c = - R128_COMB_DIS | - R128_COLOR_FACTOR_TEX | + R128_COMB_DIS | + R128_COLOR_FACTOR_TEX | R128_INPUT_FACTOR_PREV_COLOR | - R128_COMB_ALPHA_DIS | - R128_ALPHA_FACTOR_TEX_ALPHA | + R128_COMB_ALPHA_DIS | + R128_ALPHA_FACTOR_TEX_ALPHA | R128_INP_FACTOR_A_PREV_ALPHA; - r128ctx->regs.sec_tex_0_offset_c = 0x00000000; - r128ctx->regs.sec_tex_1_offset_c = 0x00000000; - r128ctx->regs.sec_tex_2_offset_c = 0x00000000; - r128ctx->regs.sec_tex_3_offset_c = 0x00000000; - r128ctx->regs.sec_tex_4_offset_c = 0x00000000; - r128ctx->regs.sec_tex_5_offset_c = 0x00000000; - r128ctx->regs.sec_tex_6_offset_c = 0x00000000; - r128ctx->regs.sec_tex_7_offset_c = 0x00000000; - r128ctx->regs.sec_tex_8_offset_c = 0x00000000; - r128ctx->regs.sec_tex_9_offset_c = 0x00000000; - r128ctx->regs.sec_tex_10_offset_c = 0x00000000; + for (i = 0; i < R128_TEX_MAXLEVELS; i++) + r128ctx->regs.sec_tex_offset[i] = 0x00000000; r128ctx->regs.constant_color_c = 0x00ffffff; r128ctx->regs.prim_texture_border_color_c = 0x00ffffff; @@ -816,26 +874,32 @@ void r128DDInitState(r128ContextPtr r128ctx) r128ctx->regs.plane_3d_mask_c = 0xffffffff; r128ctx->regs.setup_cntl = - R128_COLOR_GOURAUD | - R128_PRIM_TYPE_TRI | - R128_TEXTURE_ST_MULT_W | - R128_STARTING_VERTEX_1 | - R128_ENDING_VERTEX_3 | + R128_COLOR_GOURAUD | + R128_PRIM_TYPE_TRI | +#if 1 + /* FIXME: Let r128 multiply? */ + R128_TEXTURE_ST_MULT_W | +#else + /* FIXME: Or, pre multiply? */ + R128_TEXTURE_ST_DIRECT | +#endif + R128_STARTING_VERTEX_1 | + R128_ENDING_VERTEX_3 | R128_SU_POLY_LINE_NOT_LAST | R128_SUB_PIX_4BITS; r128ctx->regs.pm4_vc_fpu_setup = - R128_FRONT_DIR_CCW | - R128_BACKFACE_SOLID | - R128_FRONTFACE_SOLID | - R128_FPU_COLOR_GOURAUD | - R128_FPU_SUB_PIX_4BITS | - R128_FPU_MODE_3D | - R128_TRAP_BITS_DISABLE | - R128_XFACTOR_2 | - R128_YFACTOR_2 | + R128_FRONT_DIR_CCW | + R128_BACKFACE_SOLID | + R128_FRONTFACE_SOLID | + R128_FPU_COLOR_GOURAUD | + R128_FPU_SUB_PIX_4BITS | + R128_FPU_MODE_3D | + R128_TRAP_BITS_DISABLE | + R128_XFACTOR_2 | + R128_YFACTOR_2 | R128_FLAT_SHADE_VERTEX_OGL | - R128_FPU_ROUND_TRUNCATE | + R128_FPU_ROUND_TRUNCATE | R128_WM_SEL_8DW; r128ctx->regs.fog_3d_table_start = 0x00000000; @@ -845,105 +909,209 @@ void r128DDInitState(r128ContextPtr r128ctx) r128ctx->regs.window_xy_offset = 0x00000000; r128ctx->regs.dp_write_mask = 0xffffffff; + + r128ctx->regs.pc_gui_ctlstat = R128_PC_FLUSH_GUI; + + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_ALL_DIRTY; } -/* This is only called when we have the lock */ +/* Load the current context's state into the hardware */ +/* NOTE: This function is only called while holding the hardware lock */ static void r128LoadContext(r128ContextPtr r128ctx) { unsigned char *R128MMIO = r128ctx->r128Screen->mmio; + int i; + int tex_size_pitch_done = GL_FALSE; - R128CCE_BEGIN_LOCKED(2); - R128CCE0(R128_CCE_PACKET0, R128_SCALE_3D_CNTL, 0); - R128CCE(r128ctx->regs.scale_3d_cntl); - - R128CCE_WAIT_LOCKED(27); - R128CCE0(R128_CCE_PACKET0, R128_DST_PITCH_OFFSET_C, 25); - R128CCE(r128ctx->regs.dst_pitch_offset_c); - R128CCE(r128ctx->regs.dp_gui_master_cntl); - R128CCE(r128ctx->regs.sc_top_left_c); - R128CCE(r128ctx->regs.sc_bottom_right_c); - R128CCE(r128ctx->regs.z_offset_c); - R128CCE(r128ctx->regs.z_pitch_c); - R128CCE(r128ctx->regs.z_sten_cntl_c); - R128CCE(r128ctx->regs.tex_cntl_c); - R128CCE(r128ctx->regs.misc_3d_state_cntl_reg); - R128CCE(r128ctx->regs.texture_clr_cmp_clr_c); - R128CCE(r128ctx->regs.texture_clr_cmp_msk_c); - R128CCE(r128ctx->regs.fog_color_c); - R128CCE(r128ctx->regs.prim_tex_cntl_c); - R128CCE(r128ctx->regs.prim_texture_combine_cntl_c); - R128CCE(r128ctx->regs.tex_size_pitch_c); - R128CCE(r128ctx->regs.prim_tex_0_offset_c); - R128CCE(r128ctx->regs.prim_tex_1_offset_c); - R128CCE(r128ctx->regs.prim_tex_2_offset_c); - R128CCE(r128ctx->regs.prim_tex_3_offset_c); - R128CCE(r128ctx->regs.prim_tex_4_offset_c); - R128CCE(r128ctx->regs.prim_tex_5_offset_c); - R128CCE(r128ctx->regs.prim_tex_6_offset_c); - R128CCE(r128ctx->regs.prim_tex_7_offset_c); - R128CCE(r128ctx->regs.prim_tex_8_offset_c); - R128CCE(r128ctx->regs.prim_tex_9_offset_c); - R128CCE(r128ctx->regs.prim_tex_10_offset_c); - - R128CCE_WAIT_LOCKED(19); - R128CCE0(R128_CCE_PACKET0, R128_SEC_TEX_CNTL_C, 17); - R128CCE(r128ctx->regs.sec_tex_cntl_c); - R128CCE(r128ctx->regs.sec_tex_combine_cntl_c); - R128CCE(r128ctx->regs.sec_tex_0_offset_c); - R128CCE(r128ctx->regs.sec_tex_1_offset_c); - R128CCE(r128ctx->regs.sec_tex_2_offset_c); - R128CCE(r128ctx->regs.sec_tex_3_offset_c); - R128CCE(r128ctx->regs.sec_tex_4_offset_c); - R128CCE(r128ctx->regs.sec_tex_5_offset_c); - R128CCE(r128ctx->regs.sec_tex_6_offset_c); - R128CCE(r128ctx->regs.sec_tex_7_offset_c); - R128CCE(r128ctx->regs.sec_tex_8_offset_c); - R128CCE(r128ctx->regs.sec_tex_9_offset_c); - R128CCE(r128ctx->regs.sec_tex_10_offset_c); - R128CCE(r128ctx->regs.constant_color_c); - R128CCE(r128ctx->regs.prim_texture_border_color_c); - R128CCE(r128ctx->regs.sec_texture_border_color_c); - R128CCE(r128ctx->regs.sten_ref_mask_c); - R128CCE(r128ctx->regs.plane_3d_mask_c); - - R128CCE_WAIT_LOCKED(2); - R128CCE0(R128_CCE_PACKET0, R128_SETUP_CNTL, 0); - R128CCE(r128ctx->regs.setup_cntl); - - R128CCE_WAIT_LOCKED(2); - R128CCE0(R128_CCE_PACKET0, R128_PM4_VC_FPU_SETUP, 0); - R128CCE(r128ctx->regs.pm4_vc_fpu_setup); +#if 0 + r128ctx->dirty_context = R128_ALL_DIRTY; +#endif - R128CCE_WAIT_LOCKED(3); - R128CCE0(R128_CCE_PACKET0, R128_FOG_3D_TABLE_START, 1); - R128CCE(r128ctx->regs.fog_3d_table_start); - R128CCE(r128ctx->regs.fog_3d_table_end); +#if 1 + /* FIXME: Why do these need to be updated even when they don't change? */ + r128ctx->dirty_context |= (R128_CTX_MISC | + R128_CTX_ENGINESTATE | + R128_CTX_ALPHASTATE); +#endif + +#if 1 + /* FIXME: Is this _really_ needed? */ + if (r128ctx->dirty_context) R128CCEWaitForIdle(r128ctx->r128Screen); +#endif + +#if !FLUSH_VB_ON_STATE_CHANGE + /* FIXME: It might make sense to do this here instead of flushing + immediately in each state setting routine. */ + /* FIXME: Is this _really_ necessary? It slows down rendering, and + it seems like state changes shouldn't take effect until after the + VB has completed rendering. */ + if (r128ctx->dirty_context) R128_FLUSH_VB(r128ctx); +#endif + + if (r128ctx->dirty_context & R128_CTX_MISC) { + R128CCE_WAIT_LOCKED(3); + R128CCE1(R128_CCE_PACKET1, R128_SCALE_3D_CNTL, R128_DP_WRITE_MASK); + R128CCE(r128ctx->regs.scale_3d_cntl); + R128CCE(r128ctx->regs.dp_write_mask); + + R128CCE_WAIT_LOCKED(3); + R128CCE0(R128_CCE_PACKET0, R128_DST_PITCH_OFFSET_C, 1); + R128CCE(r128ctx->regs.dst_pitch_offset_c); + R128CCE(r128ctx->regs.dp_gui_master_cntl); + + R128CCE_WAIT_LOCKED(3); + R128CCE0(R128_CCE_PACKET0, R128_TEXTURE_CLR_CMP_CLR_C, 1); + R128CCE(r128ctx->regs.texture_clr_cmp_clr_c); + R128CCE(r128ctx->regs.texture_clr_cmp_msk_c); + + R128CCE_WAIT_LOCKED(3); + R128CCE0(R128_CCE_PACKET0, R128_STEN_REF_MASK_C, 1); + R128CCE(r128ctx->regs.sten_ref_mask_c); + R128CCE(r128ctx->regs.plane_3d_mask_c); + } + + if (r128ctx->dirty_context & R128_CTX_ENGINESTATE) { + R128CCE_WAIT_LOCKED(2); + R128CCE0(R128_CCE_PACKET0, R128_TEX_CNTL_C, 0); + R128CCE(r128ctx->regs.tex_cntl_c); + } - R128CCE_WAIT_LOCKED(2); - R128CCE0(R128_CCE_PACKET0, R128_FOG_3D_TABLE_DENSITY, 0); - R128CCE(r128ctx->regs.fog_3d_table_density); + if (r128ctx->dirty_context & R128_CTX_TEX0STATE) { + R128CCE_WAIT_LOCKED(4+R128_TEX_MAXLEVELS); + R128CCE0(R128_CCE_PACKET0, R128_PRIM_TEX_CNTL_C, 2+R128_TEX_MAXLEVELS); + R128CCE(r128ctx->regs.prim_tex_cntl_c); + R128CCE(r128ctx->regs.prim_texture_combine_cntl_c); + R128CCE(r128ctx->regs.tex_size_pitch_c); + for (i = 0; i < R128_TEX_MAXLEVELS; i++) + R128CCE(r128ctx->regs.prim_tex_offset[i]); - R128CCE_WAIT_LOCKED(2); - R128CCE0(R128_CCE_PACKET0, R128_WINDOW_XY_OFFSET, 0); - R128CCE(r128ctx->regs.window_xy_offset); + R128CCE_WAIT_LOCKED(2); + R128CCE0(R128_CCE_PACKET0, R128_PRIM_TEXTURE_BORDER_COLOR_C, 0); + R128CCE(r128ctx->regs.prim_texture_border_color_c); - R128CCE_WAIT_LOCKED(2); - R128CCE0(R128_CCE_PACKET0, R128_DP_WRITE_MASK, 0); - R128CCE(r128ctx->regs.dp_write_mask); + tex_size_pitch_done = GL_TRUE; + } + + if (r128ctx->dirty_context & R128_CTX_TEX1STATE) { + if (!tex_size_pitch_done) { + R128CCE_WAIT_LOCKED(2); + R128CCE0(R128_CCE_PACKET0, R128_TEX_SIZE_PITCH_C, 0); + R128CCE(r128ctx->regs.tex_size_pitch_c); + } + + R128CCE_WAIT_LOCKED(3+R128_TEX_MAXLEVELS); + R128CCE0(R128_CCE_PACKET0, R128_SEC_TEX_CNTL_C, 1+R128_TEX_MAXLEVELS); + R128CCE(r128ctx->regs.sec_tex_cntl_c); + R128CCE(r128ctx->regs.sec_tex_combine_cntl_c); + for (i = 0; i < R128_TEX_MAXLEVELS; i++) + R128CCE(r128ctx->regs.sec_tex_offset[i]); + + R128CCE_WAIT_LOCKED(2); + R128CCE0(R128_CCE_PACKET0, R128_SEC_TEXTURE_BORDER_COLOR_C, 0); + R128CCE(r128ctx->regs.sec_texture_border_color_c); + + } + + if (r128ctx->dirty_context & R128_CTX_TEXENVSTATE) { + R128CCE_WAIT_LOCKED(2); + R128CCE0(R128_CCE_PACKET0, R128_CONSTANT_COLOR_C, 0); + R128CCE(r128ctx->regs.constant_color_c); + } + + if (r128ctx->dirty_context & R128_CTX_FOGSTATE) { + R128CCE_WAIT_LOCKED(3); + R128CCE0(R128_CCE_PACKET0, R128_FOG_3D_TABLE_START, 1); + R128CCE(r128ctx->regs.fog_3d_table_start); + R128CCE(r128ctx->regs.fog_3d_table_end); + + R128CCE_WAIT_LOCKED(3); + R128CCE1(R128_CCE_PACKET1, + R128_FOG_COLOR_C, R128_FOG_3D_TABLE_DENSITY); + R128CCE(r128ctx->regs.fog_color_c); + R128CCE(r128ctx->regs.fog_3d_table_density); + } + + if (r128ctx->dirty_context & R128_CTX_ZSTENSTATE) { + R128CCE_WAIT_LOCKED(2); + R128CCE0(R128_CCE_PACKET0, R128_Z_STEN_CNTL_C, 0); + R128CCE(r128ctx->regs.z_sten_cntl_c); + } + + if (r128ctx->dirty_context & R128_CTX_SCISSORS) { + R128CCE_WAIT_LOCKED(3); + R128CCE0(R128_CCE_PACKET0, R128_SC_TOP_LEFT_C, 1); + R128CCE(r128ctx->regs.sc_top_left_c); + R128CCE(r128ctx->regs.sc_bottom_right_c); + } + + if (r128ctx->dirty_context & (R128_CTX_ALPHASTATE | + R128_CTX_FOGSTATE)) { + R128CCE_WAIT_LOCKED(2); + R128CCE0(R128_CCE_PACKET0, R128_MISC_3D_STATE_CNTL_REG, 0); + R128CCE(r128ctx->regs.misc_3d_state_cntl_reg); + } + + if (r128ctx->dirty_context & R128_CTX_SETUPSTATE) { + R128CCE_WAIT_LOCKED(3); + R128CCE1(R128_CCE_PACKET1, R128_SETUP_CNTL, R128_PM4_VC_FPU_SETUP); + R128CCE(r128ctx->regs.setup_cntl); + R128CCE(r128ctx->regs.pm4_vc_fpu_setup); + } + + if (r128ctx->dirty_context & R128_CTX_WIN_Z_POS) { + R128CCE_WAIT_LOCKED(2); + R128CCE0(R128_CCE_PACKET0, R128_WINDOW_XY_OFFSET, 0); + R128CCE(r128ctx->regs.window_xy_offset); + + R128CCE_WAIT_LOCKED(3); + R128CCE0(R128_CCE_PACKET0, R128_Z_OFFSET_C, 1); + R128CCE(r128ctx->regs.z_offset_c); + R128CCE(r128ctx->regs.z_pitch_c); + } + + if (r128ctx->dirty_context & R128_CTX_FLUSH_PIX_CACHE) { + R128CCE_WAIT_LOCKED(2); + R128CCE0(R128_CCE_PACKET0, R128_PC_GUI_CTLSTAT, 0); + R128CCE(r128ctx->regs.pc_gui_ctlstat); + } R128CCE_END_LOCKED(); + + /* Turn off the texture cache flushing */ + r128ctx->regs.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH; + + /* Turn off the pixel cache flushing */ + r128ctx->regs.pc_gui_ctlstat &= ~R128_PC_FLUSH_ALL; + + r128ctx->dirty_context = R128_CTX_CLEAN; } -/* This is only called when we have the lock */ +/* Set a hardware clip rect for drawing to the current color buffer */ +/* NOTE: This function is only called while holding the hardware lock */ void r128SetClipRect(r128ContextPtr r128ctx, XF86DRIClipRectPtr pc) { + unsigned char *R128MMIO = r128ctx->r128Screen->mmio; + + /* FIXME: Use the Rage 128's multiple clip rects */ + R128CCE_WAIT_LOCKED(3); + R128CCE0(R128_CCE_PACKET0, R128_SC_TOP_LEFT_C, 1); + R128CCE(((pc->y1 + r128ctx->bufY) << 16)|(pc->x1 + r128ctx->bufX)); + R128CCE(((pc->y2 + r128ctx->bufY - 1) << 16)|(pc->x2 + r128ctx->bufX - 1)); + R128CCE_END_LOCKED(); } -static void r128LoadCliprects(r128ContextPtr r128ctx) +/* Update the driver's notion of the window position */ +/* NOTE: This function is only called while holding the hardware lock */ +static void r128UpdateWindowPosition(r128ContextPtr r128ctx) { int x = r128ctx->driDrawable->x + r128ctx->bufX; int y = r128ctx->driDrawable->y + r128ctx->bufY; +#if 0 + /* FIXME: This happens during a lock, but is it _really_ needed? */ + R128_FLUSH_VB(r128ctx); +#endif r128ctx->regs.window_xy_offset = ((y << R128_WINDOW_Y_SHIFT) | (x << R128_WINDOW_X_SHIFT)); @@ -956,24 +1124,109 @@ static void r128LoadCliprects(r128ContextPtr r128ctx) (r128ctx->r128Screen->depthY - r128ctx->bufY) * r128ctx->r128Screen->fbStride); + + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_WIN_Z_POS; + + r128ctx->needClip = (r128ctx->driDrawable->numClipRects > 1); } -void r128UpdateState(r128ContextPtr r128ctx) +/* Update the hardware state */ +/* NOTE: This function is only called while holding the hardware lock */ +static void r128UpdateHWStateLocked(r128ContextPtr r128ctx) +{ + r128ScreenPtr r128Screen = r128ctx->r128Screen; + + if (r128ctx->dirty & R128_REQUIRE_QUIESCENCE) + R128WaitForIdle(r128Screen); + + /* Update any state that might have changed recently */ + + /* Update the clip rects */ + if (r128ctx->dirty & R128_UPDATE_WINPOS) + r128UpdateWindowPosition(r128ctx); + + /* Update texture state and then upload the images */ + /* Note: Texture images can only be updated after the state has been set */ + if (r128ctx->dirty & R128_UPDATE_TEXSTATE) + r128UpdateTextureState(r128ctx); + if (r128ctx->dirty & R128_UPDATE_TEX0IMAGES) + r128UploadTexImages(r128ctx, r128ctx->CurrentTexObj[0]); + if (r128ctx->dirty & R128_UPDATE_TEX1IMAGES) + r128UploadTexImages(r128ctx, r128ctx->CurrentTexObj[1]); + + /* Load the state into the hardware */ + /* Note: This must be done after all other state has been set */ + if (r128ctx->dirty & R128_UPDATE_CONTEXT) + r128LoadContext(r128ctx); + + r128ctx->dirty = R128_CLEAN; +} + +/* Update the hardware state */ +void r128UpdateHWState(r128ContextPtr r128ctx) { LOCK_HARDWARE(r128ctx); - r128UpdateStateLocked(r128ctx); + r128UpdateHWStateLocked(r128ctx); UNLOCK_HARDWARE(r128ctx); } -/* This is only called when we have the lock */ -void r128UpdateStateLocked(r128ContextPtr r128ctx) +/* Update the driver's state */ +/* NOTE: This function is only called while holding the hardware lock */ +void r128UpdateState(r128ContextPtr r128ctx, int winMoved) { - r128ScreenPtr r128Screen = r128ctx->r128Screen; + if (r128ctx->SAREA->ctxOwner != r128ctx->driContext->hHWContext) { + r128ctx->SAREA->ctxOwner = r128ctx->driContext->hHWContext; + r128ctx->dirty |= R128_ALL_DIRTY; + } - if (r128ctx->dirty & R128_REQUIRE_QUIESCENCE) R128WaitForIdle(r128Screen); - if (r128ctx->dirty & R128_START_CCE) R128CCEStart(r128Screen); - if (r128ctx->dirty & R128_UPDATE_CLIPRECTS) r128LoadCliprects(r128ctx); - if (r128ctx->dirty & R128_UPDATE_CONTEXT) r128LoadContext(r128ctx); + if (r128ctx->SAREA->texAge != r128ctx->lastTexAge) { +#if USE_AGP_TEXTURES + int sz = 1 << r128ctx->r128Screen->log2AGPTexGran; +#else + int sz = 1 << r128ctx->r128Screen->log2TexGran; +#endif + int nr = 0; + int idx; + + for (idx = r128ctx->SAREA->texList[R128_NR_TEX_REGIONS].prev; + idx != R128_NR_TEX_REGIONS && nr < R128_NR_TEX_REGIONS; + idx = r128ctx->SAREA->texList[idx].prev, nr++) { + + /* If switching texturing schemes, then the SAREA might not + have been properly cleared, so we need to reset the + global texture LRU. */ +#if USE_AGP_TEXTURES + if (idx * sz > r128ctx->r128Screen->agpTexSize) { +#else + if (idx * sz > r128ctx->r128Screen->textureSize) { +#endif + nr = R128_NR_TEX_REGIONS; + break; + } - r128ctx->dirty = R128_CLEAN; + if (r128ctx->SAREA->texList[idx].age > r128ctx->lastTexAge) + r128TexturesGone(r128ctx, idx * sz, sz, + r128ctx->SAREA->texList[idx].in_use); + } + + if (nr == R128_NR_TEX_REGIONS) { +#if USE_AGP_TEXTURES + r128TexturesGone(r128ctx, 0, r128ctx->r128Screen->agpTexSize, 0); +#else + r128TexturesGone(r128ctx, 0, r128ctx->r128Screen->textureSize, 0); +#endif + r128ResetGlobalLRU(r128ctx); + } + + r128ctx->dirty |= R128_UPDATE_TEX0IMAGES; + r128ctx->dirty |= R128_UPDATE_TEX1IMAGES; + r128ctx->lastTexAge = r128ctx->SAREA->texAge; + } + + if (winMoved) { /* FIXME??: handle window moves */ + r128ctx->dirty |= R128_UPDATE_WINPOS; + } + + if (r128ctx->dirty) r128UpdateHWStateLocked(r128ctx); } diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_state.h b/xc/lib/GL/mesa/src/drv/r128/r128_state.h index f604f6ca8..570d38f8e 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_state.h +++ b/xc/lib/GL/mesa/src/drv/r128/r128_state.h @@ -37,13 +37,15 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #ifdef GLX_DIRECT_RENDERING -extern void r128DDInitState(r128ContextPtr r128ctx); -extern void r128DDInitStateFuncs(GLcontext *ctx); +extern void r128DDInitState(r128ContextPtr r128ctx); +extern void r128DDInitStateFuncs(GLcontext *ctx); -extern void r128UpdateState(r128ContextPtr r128ctx); -extern void r128UpdateStateLocked(r128ContextPtr r128ctx); +extern void r128UpdateState(r128ContextPtr r128ctx, int winMoved); +extern void r128UpdateHWState(r128ContextPtr r128ctx); -extern void r128SetClipRect(r128ContextPtr r128ctx, XF86DRIClipRectPtr pc); +extern void r128SetClipRect(r128ContextPtr r128ctx, XF86DRIClipRectPtr pc); +extern CARD32 r128PackColor(GLuint d, + GLubyte r, GLubyte g, GLubyte b, GLubyte a); #endif #endif /* _R128_STATE_H_ */ 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 2f561a74d..27150d510 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_swap.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_swap.c @@ -39,12 +39,17 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r128_lock.h" #include "r128_reg.h" #include "r128_cce.h" +#include "r128_vb.h" #include "r128_swap.h" +/* Copy the back color buffer to the front color buffer */ void r128SwapBuffers(r128ContextPtr r128ctx) { - unsigned char *R128MMIO = r128ctx->r128Screen->mmio; - int dst_bpp; + unsigned char *R128MMIO = r128ctx->r128Screen->mmio; + __DRIdrawablePrivate *dPriv = r128ctx->driDrawable; + int nc = dPriv->numClipRects; + XF86DRIClipRectPtr c = dPriv->pClipRects; + int dst_bpp; switch (r128ctx->r128Screen->bpp) { case 8: @@ -63,21 +68,39 @@ void r128SwapBuffers(r128ContextPtr r128ctx) break; } - R128CCE_BEGIN(5); + /* Flush any outstanding vertex buffers */ + R128_FLUSH_VB(r128ctx); - R128CCE3(R128_CCE_PACKET3_CNTL_BITBLT_MULTI, 3); - R128CCE(R128_GMC_BRUSH_NONE - | R128_GMC_SRC_DATATYPE_COLOR - | R128_DP_SRC_SOURCE_MEMORY - | dst_bpp - | R128_ROP3_S); - R128CCE(((r128ctx->driDrawable->x + r128ctx->r128Screen->backX)<< 16) - | (r128ctx->driDrawable->y + r128ctx->r128Screen->backY)); - R128CCE((r128ctx->driDrawable->x << 16) | r128ctx->driDrawable->y); - R128CCE((r128ctx->driDrawable->w << 16) | r128ctx->driDrawable->h); + LOCK_HARDWARE(r128ctx); - r128ctx->dirty = R128_UPDATE_CONTEXT; - /* r128UpdateState(r128ctx); */ + /* Cycle through the clip rects */ + while (nc--) { + int fx = c[nc].x1; + int fy = c[nc].y1; + int fw = c[nc].x2 - fx; + int fh = c[nc].y2 - fy; + int bx = fx + r128ctx->r128Screen->backX; + int by = fy + r128ctx->r128Screen->backY; - R128CCE_END(); + fx += r128ctx->r128Screen->fbX; + fy += r128ctx->r128Screen->fbY; + + R128CCE_WAIT_LOCKED(5); + R128CCE3(R128_CCE_PACKET3_CNTL_BITBLT_MULTI, 3); + R128CCE(R128_GMC_BRUSH_NONE + | R128_GMC_SRC_DATATYPE_COLOR + | R128_DP_SRC_SOURCE_MEMORY + | dst_bpp + | R128_ROP3_S); + R128CCE((bx << 16) | by); + R128CCE((fx << 16) | fy); + R128CCE((fw << 16) | fh); + } + + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_ALL_DIRTY; + + R128CCE_END_LOCKED(); + + 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 75b08e527..b61f9cdc1 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_tex.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_tex.c @@ -34,19 +34,1028 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #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" +#include "r128_vb.h" #include "r128_tex.h" +#include "mmath.h" +#include "simple_list.h" + +static void r128SetTexWrap(r128TexObjPtr t, GLenum srwap, GLenum twrap); +static void r128SetTexFilter(r128TexObjPtr t, GLenum minf, GLenum magf); +static void r128SetTexBorderColor(r128TexObjPtr t, GLubyte c[4]); + +/* Allocate and initialize hardware state associated with texture `t' */ +/* NOTE: This function is only called while holding the hardware lock */ +static r128TexObjPtr r128CreateTexObj(r128ContextPtr r128ctx, + struct gl_texture_object *tObj) +{ + r128TexObjPtr t; + struct gl_texture_image *image; + CARD32 texFormat; + int log2Pitch, log2Height, log2Size, log2MinSize; + int pitch, totalSize, width; + int i; + + image = tObj->Image[0]; + if (!image) return NULL; /* ERROR!!! */ + + t = (r128TexObjPtr)calloc(1,sizeof(*t)); + if (!t) return NULL; /* ERROR!!! */ + + for (i = 1, log2Height = 0; i < image->Height; i *= 2) log2Height++; + for (i = 1, log2Pitch = 0; i < image->Width; i *= 2) log2Pitch++; + if (image->Width > image->Height) log2Size = log2Pitch; + else log2Size = log2Height; + + pitch = image->Width; + t->internFormat = image->IntFormat; + + switch (image->Format) { + case GL_LUMINANCE: + case GL_ALPHA: + case GL_RGB: + if (r128ctx->r128Screen->bpp == 16 && + (t->internFormat == GL_RGB || t->internFormat == 3)) + t->internFormat = GL_RGB5; + + switch (t->internFormat) { + case GL_RGB5: pitch *= 2; texFormat = R128_DATATYPE_RGB565; break; + case 3: + case GL_RGB: +#if USE_RGB8_TEXTURES + case GL_RGB8: pitch *= 3; texFormat = R128_DATATYPE_RGB888; break; +#else + case GL_RGB8: pitch *= 4; texFormat = R128_DATATYPE_ARGB8888; break; +#endif + default: + /* Format not supported */ + free(t); + return NULL; + } + break; + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + case GL_RGBA: + if (r128ctx->r128Screen->bpp == 16 && + (t->internFormat == GL_RGBA || t->internFormat == 4)) + t->internFormat = GL_RGBA4; + + switch (t->internFormat) { + case GL_RGB5_A1: pitch *= 2; texFormat = R128_DATATYPE_ARGB1555; break; + case GL_RGBA4: pitch *= 2; texFormat = R128_DATATYPE_ARGB4444; break; + case 4: + case GL_RGBA: + case GL_RGBA8: pitch *= 4; texFormat = R128_DATATYPE_ARGB8888; break; + default: + /* Format not supported */ + free(t); + return NULL; + } + break; + case GL_COLOR_INDEX: + switch (t->internFormat) { + case 1: + case GL_COLOR_INDEX: + case GL_COLOR_INDEX8_EXT: texFormat = R128_DATATYPE_CI8; break; + default: + /* Format not supported */ + free(t); + return NULL; + } + break; + default: + /* ERROR!!! */ + free(t); + return NULL; + } + + t->dirty_images = 0; + t->bound = 0; + t->tObj = tObj; + + t->memBlock = NULL; + t->bufAddr = NULL; + + totalSize = 0; + width = image->Width; + for (i = 0; i <= log2Size && tObj->Image[i]; i++) { + t->image[i].offset = totalSize; + t->image[i].width = width; + t->dirty_images |= 1 << i; + totalSize += tObj->Image[i]->Height * pitch; + pitch /= 2; + width /= 2; + } + log2MinSize = log2Size - i + 1; + + t->totalSize = totalSize; + + t->regs.tex_cntl = texFormat; + t->regs.size_pitch = ((log2Pitch << R128_TEX_PITCH_SHIFT) | + (log2Size << R128_TEX_SIZE_SHIFT) | + (log2Height << R128_TEX_HEIGHT_SHIFT) | + (log2MinSize << R128_TEX_MIN_SIZE_SHIFT)); + t->regs.border_color = 0x00000000; + + if (log2MinSize == log2Size || + log2MinSize != 0) + t->regs.tex_cntl |= R128_MIP_MAP_DISABLE; + + r128SetTexWrap(t, tObj->WrapS, tObj->WrapT); + r128SetTexFilter(t, tObj->MinFilter, tObj->MagFilter); + r128SetTexBorderColor(t, tObj->BorderColor); + + tObj->DriverData = t; + /* r128ctx->dirty |= R128_UPDATE_CONTEXT; */ + + make_empty_list(t); + + return t; +} + +/* Destroy hardware state associated with texture `t' */ +/* NOTE: This function can be called while holding the hardware lock and + while not holding the lock*/ +void r128DestroyTexObj(r128ContextPtr r128ctx, r128TexObjPtr t) +{ + if (!t) return; + + if (t->memBlock) { + mmFreeMem(t->memBlock); + t->memBlock = NULL; + } + + if (t->tObj) t->tObj->DriverData = NULL; + if (t->bound) r128ctx->CurrentTexObj[t->bound-1] = NULL; + + remove_from_list(t); + free(t); +} + +/* Keep track of swapped out texture objects */ +/* NOTE: This function is only called while holding the hardware lock */ +static void r128SwapOutTexObj(r128ContextPtr r128ctx, r128TexObjPtr t) +{ + if (t->memBlock) { + mmFreeMem(t->memBlock); + t->memBlock = NULL; + } + + t->dirty_images = ~0; + move_to_tail(&r128ctx->SwappedOut, t); +} + +/* Upload the texture image associated with texture `t' at level `level' + at the address relative to `start'. */ +/* NOTE: This function is only called while holding the hardware lock */ +static void r128UploadTexLevel(r128TexObjPtr t, int level, int start) +{ + struct gl_texture_image *image; + int i, j, width; + + if (level < 0 || level > R128_TEX_MAXLEVELS) return; + if (!(image = t->tObj->Image[level])) return; + + width = t->image[level].width; + + /* FIXME: Use HOSTDATA_BLT (type 3 packet) for texture uploads */ + /* FIXME: Add the other texture formats that we support here */ + switch (t->internFormat) { + case GL_RGB5: + { + CARD16 *dst = (CARD16 *)(t->image[level].offset + t->bufAddr + start); + CARD8 *src = (CARD8 *)image->Data; + + for (j = 0; j < image->Height; j++) { + for (i = 0; i < width; i++) { + dst[i] = (((src[0] & 0xf8) << 8) | + ((src[1] & 0xfc) << 3) | + ((src[2] & 0xf8) >> 3)); + src += 3; + } + dst += width; + } + break; + } + case 3: + case GL_RGB: + case GL_RGB8: + { +#if USE_RGB8_TEXTURES + CARD8 *dst = (CARD8 *)(t->image[level].offset + t->bufAddr + start); + CARD8 *src = (CARD8 *)image->Data; + + for (j = 0; j < image->Height; j++) { + for (i = 0; i < width; i++) { + *dst++ = src[0]; + *dst++ = src[1]; + *dst++ = src[2]; + src += 3; + } + } +#else + CARD32 *dst = (CARD32 *)(t->image[level].offset + t->bufAddr + start); + CARD8 *src = (CARD8 *)image->Data; + + for (j = 0; j < image->Height; j++) { + for (i = 0; i < width; i++) { + dst[i] = ((src[0] << 16) | + (src[1] << 8) | + (src[2] << 0) | + (0xff << 24)); + src += 3; + } + dst += width; + } +#endif + break; + } + case GL_RGB5_A1: + { + CARD16 *dst = (CARD16 *)(t->image[level].offset + t->bufAddr + start); + CARD8 *src = (CARD8 *)image->Data; + + for (j = 0; j < image->Height; j++) { + for (i = 0; i < width; i++) { + dst[i] = (((src[0] & 0xf8) << 7) | + ((src[1] & 0xf8) << 2) | + ((src[2] & 0xf8) >> 3) | + ((src[3] & 0x80) << 8)); + src += 4; + } + dst += width; + } + break; + } + case GL_RGBA4: + { + CARD16 *dst = (CARD16 *)(t->image[level].offset + t->bufAddr + start); + CARD8 *src = (CARD8 *)image->Data; + + for (j = 0; j < image->Height; j++) { + for (i = 0; i < width; i++) { + dst[i] = (((src[0] & 0xf0) << 4) | + ((src[1] & 0xf0) << 0) | + ((src[2] & 0xf0) >> 4) | + ((src[3] & 0xf0) << 8)); + src += 4; + } + dst += width; + } + break; + } + case 4: + case GL_RGBA: + case GL_RGBA8: + { + CARD32 *dst = (CARD32 *)(t->image[level].offset + t->bufAddr + start); + CARD8 *src = (CARD8 *)image->Data; + + for (j = 0; j < image->Height; j++) { + for (i = 0; i < width; i++) { + dst[i] = ((src[0] << 16) | + (src[1] << 8) | + (src[2] << 0) | + (src[3] << 24)); + src += 4; + } + dst += width; + } + break; + } + default: + return; + } +} + +/* Reset the global texture LRU */ +/* NOTE: This function is only called while holding the hardware lock */ +void r128ResetGlobalLRU(r128ContextPtr r128ctx) +{ + R128TexRegion *list = r128ctx->SAREA->texList; +#if USE_AGP_TEXTURES + int sz = 1 << r128ctx->r128Screen->log2AGPTexGran; +#else + int sz = 1 << r128ctx->r128Screen->log2TexGran; +#endif + int i; + + /* + * (Re)initialize the global circular LRU list. The last element in + * the array (R128_NR_TEX_REGIONS) is the sentinal. Keeping it at + * the end of the array allows it to be addressed rationally when + * looking up objects at a particular location in texture memory. + */ + +#if USE_AGP_TEXTURES + for (i = 0; (i+1) * sz <= r128ctx->r128Screen->agpTexSize; i++) { +#else + for (i = 0; (i+1) * sz <= r128ctx->r128Screen->textureSize; i++) { +#endif + list[i].prev = i-1; + list[i].next = i+1; + list[i].age = 0; + } + + i--; + list[0].prev = R128_NR_TEX_REGIONS; + list[i].prev = i-1; + list[i].next = R128_NR_TEX_REGIONS; + list[R128_NR_TEX_REGIONS].prev = i; + list[R128_NR_TEX_REGIONS].next = 0; + r128ctx->SAREA->texAge = 0; +} + +/* Update the local and glock texture LRUs */ +/* NOTE: This function is only called while holding the hardware lock */ +static void r128UpdateTexLRU(r128ContextPtr r128ctx, r128TexObjPtr t) +{ + R128TexRegion *list = r128ctx->SAREA->texList; +#if USE_AGP_TEXTURES + int log2sz = r128ctx->r128Screen->log2AGPTexGran; +#else + int log2sz = r128ctx->r128Screen->log2TexGran; +#endif + + int start = t->memBlock->ofs >> log2sz; + int end = (t->memBlock->ofs + t->memBlock->size - 1) >> log2sz; + int i; + + r128ctx->lastTexAge = ++r128ctx->SAREA->texAge; + + /* Update our local LRU */ + move_to_head(&r128ctx->TexObjList, t); + + /* Update the global LRU */ + for (i = start ; i <= end ; i++) { + list[i].in_use = 1; + list[i].age = r128ctx->lastTexAge; + + /* remove_from_list(i) */ + list[(CARD32)list[i].next].prev = list[i].prev; + list[(CARD32)list[i].prev].next = list[i].next; + + /* insert_at_head(list, i) */ + list[i].prev = R128_NR_TEX_REGIONS; + list[i].next = list[R128_NR_TEX_REGIONS].next; + list[(CARD32)list[R128_NR_TEX_REGIONS].next].prev = i; + list[R128_NR_TEX_REGIONS].next = i; + } +} + +/* Update our notion of what textures have been changed since we last + held the lock. This pertains to both our local textures and the + textures belonging to other clients. Keep track of other client's + textures by pushing a placeholder texture onto the LRU list -- these + are denoted by (tObj == NULL). */ +/* NOTE: This function is only called while holding the hardware lock */ +void r128TexturesGone(r128ContextPtr r128ctx, + int offset, int size, int in_use) +{ + r128TexObjPtr t, tmp; + + foreach_s (t, tmp, &r128ctx->TexObjList) { + if (t->memBlock->ofs >= offset + size || + t->memBlock->ofs + t->memBlock->size <= offset) + continue; + + /* It overlaps - kick it out. Need to hold onto the currently + bound objects, however. */ + if (t->bound) r128SwapOutTexObj(r128ctx, t); + else r128DestroyTexObj(r128ctx, t); + } + + if (in_use) { + t = (r128TexObjPtr) calloc(1,sizeof(*t)); + if (!t) return; + + t->memBlock = mmAllocMem(r128ctx->texHeap, size, 0, offset); + insert_at_head(&r128ctx->TexObjList, t); + } +} + +/* Upload the texture images associated with texture `t'. This might + require removing our own and/or other client's texture objects to + make room for these images. */ +/* NOTE: This function is only called while holding the hardware lock */ +int r128UploadTexImages(r128ContextPtr r128ctx, r128TexObjPtr t) +{ + int i; + int minLevel; + int maxLevel; + + if (!t) return 0; + + /* Do we need to eject LRU texture objects? */ + if (!t->memBlock) { + while (1) { + /* Allocate a memory block on a 4k boundary (1<<12 == 4096) */ + t->memBlock = mmAllocMem(r128ctx->texHeap, t->totalSize, 12, 0); + if (t->memBlock) break; + + if (r128ctx->TexObjList.prev->bound) { + fprintf(stderr, + "r128UploadTexImages: ran into bound texture\n"); + return -1; + } + if (r128ctx->TexObjList.prev == &(r128ctx->TexObjList)) { + fprintf(stderr, + "r128UploadTexImages: upload texture failure, sz=%d\n", + t->totalSize); + return -1; + } + + r128DestroyTexObj(r128ctx, r128ctx->TexObjList.prev); + } + + /* FIXME: Allow both local and AGP textures to co-exist. */ +#if USE_AGP_TEXTURES + t->bufAddr = (unsigned char *)r128ctx->r128Screen->agpTexStart; +#else + t->bufAddr = (unsigned char *)(r128ctx->r128Screen->textureY * + r128ctx->r128Screen->fbStride + + r128ctx->r128Screen->textureX * + (r128ctx->r128Screen->bpp/8)); +#endif + t->bufAddr += t->memBlock->ofs; + + maxLevel = ((t->regs.size_pitch & R128_TEX_SIZE_MASK) >> + R128_TEX_SIZE_SHIFT); + minLevel = ((t->regs.size_pitch & R128_TEX_MIN_SIZE_MASK) >> + R128_TEX_MIN_SIZE_SHIFT); + + /* Update the hardware's texture image addresses */ + switch (t->bound) { + case 1: + if (t->regs.tex_cntl & R128_MIP_MAP_DISABLE) { + for (i = 0; i < R128_TEX_MAXLEVELS; i++) + r128ctx->regs.prim_tex_offset[i] = (CARD32)t->bufAddr; + } else { + for (i = maxLevel; i >= minLevel; i--) + r128ctx->regs.prim_tex_offset[i] = + t->image[maxLevel-i].offset + (CARD32)t->bufAddr; + } +#if USE_AGP_TEXTURES + for (i = 0; i < R128_TEX_MAXLEVELS; i++) + r128ctx->regs.prim_tex_offset[i] |= 0x02000000; +#endif + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_TEX0STATE; + break; + case 2: + if (t->regs.tex_cntl & R128_MIP_MAP_DISABLE) { + for (i = 0; i < R128_TEX_MAXLEVELS; i++) + r128ctx->regs.sec_tex_offset[i] = (CARD32)t->bufAddr; + } else { + for (i = maxLevel; i >= minLevel; i--) + r128ctx->regs.sec_tex_offset[i] = + t->image[maxLevel-i].offset + (CARD32)t->bufAddr; + } +#if USE_AGP_TEXTURES + for (i = 0; i < R128_TEX_MAXLEVELS; i++) + r128ctx->regs.sec_tex_offset[i] |= 0x02000000; +#endif + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_TEX1STATE; + break; + default: + return -1; + } + } + + /* Let the world know we've used this memory recently */ + r128UpdateTexLRU(r128ctx, t); + + /* Wait for texturing to complete */ + R128CCEWaitForIdle(r128ctx->r128Screen); + + /* Upload any images that are new */ + if (t->dirty_images) { + int num_levels = (((t->regs.size_pitch & R128_TEX_SIZE_MASK) >> + R128_TEX_SIZE_SHIFT) - + ((t->regs.size_pitch & R128_TEX_MIN_SIZE_MASK) >> + R128_TEX_MIN_SIZE_SHIFT)); + + for (i = 0; i <= num_levels; i++) + if (t->dirty_images & (1<<i)) { +#if USE_AGP_TEXTURES + r128UploadTexLevel(t, i, (int)r128ctx->r128Screen->agp); +#else + r128UploadTexLevel(t, i, (int)r128ctx->r128Screen->fb); +#endif + } + + r128ctx->regs.tex_cntl_c |= R128_TEX_CACHE_FLUSH; + + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_ENGINESTATE; + + /* FIXME: r128ctx->regs.pc_gui_ctlstat = R128_PC_FLUSH_GUI; */ + /* FIXME: r128ctx->dirty_context |= R128_CTX_FLUSH_PIX_CACHE; */ + } + + t->dirty_images = 0; + return 0; +} + +/* Update the hardware state for texture unit 0 */ +/* NOTE: This function is only called while holding the hardware lock */ +static void r128UpdateTex0State(r128ContextPtr r128ctx) +{ + GLcontext *ctx = r128ctx->glCtx; + r128TexObjPtr t; + struct gl_texture_object *tObj; + int i; + CARD32 tex_size_pitch, tex_combine_cntl; + + /* Only update the hardware texture state if the texture is current, + complete and enabled. */ + if (!(tObj = ctx->Texture.Unit[0].Current)) return; + if (tObj != ctx->Texture.Unit[0].CurrentD[2]) return; + if (!tObj->Complete) return; + if (!(ctx->Texture.Enabled & 0x0f)) return; + + /* If this is the first time the texture has been used, then create + a new texture object for it. */ + t = tObj->DriverData; + if (!t) t = r128CreateTexObj(r128ctx, tObj); + if (!t) return; + + /* Force any texture images to be loaded into the hardware */ + if (t->dirty_images) r128ctx->dirty |= R128_UPDATE_TEX0IMAGES; + + /* Bind texture to texture 0 unit */ + r128ctx->CurrentTexObj[0] = t; + t->bound = 1; + + if (t->memBlock) r128UpdateTexLRU(r128ctx, t); + + /* Set the texture environment state */ + /* FIXME: This only works for GL_RGB and GL_RGBA right now */ + /* FIXME: Handle GL_ALPHA, GL_LIMINANCE{_ALPHA} and GL_INTENSITY */ + switch (ctx->Texture.Unit[0].EnvMode) { + case GL_REPLACE: + switch (tObj->Image[0]->Format) { + case GL_RGB: + tex_combine_cntl = (R128_COMB_DIS | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + break; + case GL_RGBA: + tex_combine_cntl = (R128_COMB_DIS | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_DIS | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + break; + case GL_LUMINANCE: + case GL_ALPHA: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + case GL_COLOR_INDEX: + default: + return; + } + break; + case GL_MODULATE: + switch (tObj->Image[0]->Format) { + case GL_RGB: + tex_combine_cntl = (R128_COMB_MODULATE | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + break; + case GL_RGBA: + tex_combine_cntl = (R128_COMB_MODULATE | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + break; + case GL_LUMINANCE: + case GL_ALPHA: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + case GL_COLOR_INDEX: + default: + return; + } + break; + case GL_DECAL: + switch (tObj->Image[0]->Format) { + case GL_RGB: + tex_combine_cntl = (R128_COMB_DIS | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + break; + case GL_RGBA: + tex_combine_cntl = (R128_COMB_BLEND_TEXTURE | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + break; + case GL_LUMINANCE: + case GL_ALPHA: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + case GL_COLOR_INDEX: + default: + return; + } + break; + case GL_BLEND: + switch (tObj->Image[0]->Format) { + case GL_RGB: + tex_combine_cntl = (R128_COMB_BLEND_PREV | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + break; + case GL_RGBA: + tex_combine_cntl = (R128_COMB_BLEND_PREV | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_INT_COLOR | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_INT_ALPHA); + break; + case GL_LUMINANCE: + case GL_ALPHA: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + case GL_COLOR_INDEX: + default: + return; + } + break; + default: + return; + } + + tex_size_pitch = r128ctx->regs.tex_size_pitch_c; + tex_size_pitch &= ~R128_TEX_SIZE_PITCH_MASK; + tex_size_pitch |= t->regs.size_pitch << R128_TEX_SIZE_PITCH_SHIFT; + + /* Set the primary texture state in r128ctx->regs */ + r128ctx->regs.prim_tex_cntl_c = t->regs.tex_cntl; + r128ctx->regs.prim_texture_combine_cntl_c = tex_combine_cntl; + r128ctx->regs.tex_size_pitch_c = tex_size_pitch; + r128ctx->regs.prim_texture_border_color_c = t->regs.border_color; + if (t->regs.tex_cntl & R128_MIP_MAP_DISABLE) { + for (i = 0; i < R128_TEX_MAXLEVELS; i++) + r128ctx->regs.prim_tex_offset[i] = (CARD32)t->bufAddr; + } else { + int maxLevel = ((t->regs.size_pitch & R128_TEX_SIZE_MASK) >> + R128_TEX_SIZE_SHIFT); + 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] = + t->image[maxLevel-i].offset + (CARD32)t->bufAddr; + } +#if USE_AGP_TEXTURES + for (i = 0; i < R128_TEX_MAXLEVELS; i++) + r128ctx->regs.prim_tex_offset[i] |= 0x02000000; +#endif + + /* Force loading the new state into the hardware */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_TEX0STATE; +} + +/* Update the hardware state for texture unit 1 */ +/* NOTE: This function is only called while holding the hardware lock */ +static void r128UpdateTex1State(r128ContextPtr r128ctx) +{ + GLcontext *ctx = r128ctx->glCtx; + r128TexObjPtr t; + struct gl_texture_object *tObj; + int i; + CARD32 tex_size_pitch, tex_combine_cntl, tex_cntl; + + /* Only update the hardware texture state if the texture is current, + complete and enabled. */ + if (!(tObj = ctx->Texture.Unit[1].Current)) return; + if (tObj != ctx->Texture.Unit[1].CurrentD[2]) return; + if (!tObj->Complete) return; + if (!(ctx->Texture.Enabled & 0xf0)) return; + + /* If this is the first time the texture has been used, then create + a new texture object for it. */ + t = tObj->DriverData; + if (!t) t = r128CreateTexObj(r128ctx, tObj); + if (!t) return; + + /* Force any texture images to be loaded into the hardware */ + if (t->dirty_images) r128ctx->dirty |= R128_UPDATE_TEX1IMAGES; + + /* Bind texture to texture 1 unit */ + r128ctx->CurrentTexObj[1] = t; + t->bound = 2; + + if (t->memBlock) r128UpdateTexLRU(r128ctx, t); + + /* Set the texture environment state */ + /* FIXME: This only works for GL_RBG and GL_RGBA right now */ + /* FIXME: Handle GL_ALPHA, GL_LIMINANCE{_ALPHA} and GL_INTENSITY */ + /* FIXME: Handle when no Tex0: i.e., !(ctx->Texture.Enabled & 0x0f) */ + switch (ctx->Texture.Unit[1].EnvMode) { + case GL_REPLACE: + switch (tObj->Image[0]->Format) { + case GL_RGB: + tex_combine_cntl = (R128_COMB_DIS | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + break; + case GL_RGBA: + tex_combine_cntl = (R128_COMB_DIS | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_DIS | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + break; + case GL_LUMINANCE: + case GL_ALPHA: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + case GL_COLOR_INDEX: + default: + return; + } + break; + case GL_MODULATE: + switch (tObj->Image[0]->Format) { + case GL_RGB: + tex_combine_cntl = (R128_COMB_MODULATE | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + break; + case GL_RGBA: + tex_combine_cntl = (R128_COMB_MODULATE | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + break; + case GL_LUMINANCE: + case GL_ALPHA: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + case GL_COLOR_INDEX: + default: + return; + } + break; + case GL_DECAL: + switch (tObj->Image[0]->Format) { + case GL_RGB: + tex_combine_cntl = (R128_COMB_DIS | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + break; + case GL_RGBA: + tex_combine_cntl = (R128_COMB_BLEND_TEXTURE | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + break; + case GL_LUMINANCE: + case GL_ALPHA: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + case GL_COLOR_INDEX: + default: + return; + } + break; + case GL_BLEND: + switch (tObj->Image[0]->Format) { + case GL_RGB: + tex_combine_cntl = (R128_COMB_BLEND_PREV | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_COPY_INP | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + break; + case GL_RGBA: + tex_combine_cntl = (R128_COMB_BLEND_PREV | + R128_COLOR_FACTOR_TEX | + R128_INPUT_FACTOR_PREV_COLOR | + R128_COMB_ALPHA_MODULATE | + R128_ALPHA_FACTOR_TEX_ALPHA | + R128_INP_FACTOR_A_PREV_ALPHA); + break; + case GL_LUMINANCE: + case GL_ALPHA: + case GL_LUMINANCE_ALPHA: + case GL_INTENSITY: + case GL_COLOR_INDEX: + default: + return; + } + break; + default: + return; + } + + tex_size_pitch = r128ctx->regs.tex_size_pitch_c; + tex_size_pitch &= ~R128_SEC_TEX_SIZE_PITCH_MASK; + tex_size_pitch |= t->regs.size_pitch << R128_SEC_TEX_SIZE_PITCH_SHIFT; + + tex_cntl = t->regs.tex_cntl | R128_SEC_SELECT_SEC_ST; + + /* Set the secondary texture state in r128ctx->regs */ + r128ctx->regs.sec_tex_cntl_c = tex_cntl; + r128ctx->regs.sec_tex_combine_cntl_c = tex_combine_cntl; + r128ctx->regs.tex_size_pitch_c = tex_size_pitch; + r128ctx->regs.sec_texture_border_color_c = t->regs.border_color; + if (t->regs.tex_cntl & R128_MIP_MAP_DISABLE) { + for (i = 0; i < R128_TEX_MAXLEVELS; i++) + r128ctx->regs.sec_tex_offset[i] = (CARD32)t->bufAddr; + } else { + int maxLevel = ((t->regs.size_pitch & R128_TEX_SIZE_MASK) >> + R128_TEX_SIZE_SHIFT); + 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] = + t->image[maxLevel-i].offset + (CARD32)t->bufAddr; + } +#if USE_AGP_TEXTURES + for (i = 0; i < R128_TEX_MAXLEVELS; i++) + r128ctx->regs.sec_tex_offset[i] |= 0x02000000; +#endif + + /* Force loading the new state into the hardware */ + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_TEX1STATE; +} + +/* Update the hardware texture state */ +/* NOTE: This function is only called while holding the hardware lock */ +void r128UpdateTextureState(r128ContextPtr r128ctx) +{ + /* Unbind any currently bound textures */ + if (r128ctx->CurrentTexObj[0]) r128ctx->CurrentTexObj[0]->bound = 0; + if (r128ctx->CurrentTexObj[1]) r128ctx->CurrentTexObj[1]->bound = 0; + r128ctx->CurrentTexObj[0] = NULL; + r128ctx->CurrentTexObj[1] = NULL; + + /* Update the texture unit 0/1 state */ + r128UpdateTex0State(r128ctx); + r128UpdateTex1State(r128ctx); +} + +/* Set the texture wrap mode */ +static void r128SetTexWrap(r128TexObjPtr t, GLenum swrap, GLenum twrap) +{ + t->regs.tex_cntl &= ~(R128_TEX_CLAMP_S_MASK | R128_TEX_CLAMP_T_MASK); + + switch (swrap) { + case GL_CLAMP: t->regs.tex_cntl |= R128_TEX_CLAMP_S_CLAMP; break; + case GL_REPEAT: t->regs.tex_cntl |= R128_TEX_CLAMP_S_WRAP; break; + default: /* ERROR!! */ return; + } + + switch (twrap) { + case GL_CLAMP: t->regs.tex_cntl |= R128_TEX_CLAMP_T_CLAMP; break; + case GL_REPEAT: t->regs.tex_cntl |= R128_TEX_CLAMP_T_WRAP; break; + default: /* ERROR!! */ return; + } +} + +/* Set the texture filter mode */ +static void r128SetTexFilter(r128TexObjPtr t, GLenum minf, GLenum magf) +{ + t->regs.tex_cntl &= ~(R128_MIN_BLEND_MASK | R128_MAG_BLEND_MASK); + + switch (minf) { + case GL_NEAREST: + t->regs.tex_cntl |= R128_MIN_BLEND_NEAREST; + break; + case GL_LINEAR: + t->regs.tex_cntl |= R128_MIN_BLEND_LINEAR; + break; + case GL_NEAREST_MIPMAP_NEAREST: + t->regs.tex_cntl |= R128_MIN_BLEND_MIPNEAREST; + break; + case GL_LINEAR_MIPMAP_NEAREST: + t->regs.tex_cntl |= R128_MIN_BLEND_LINEARMIPNEAREST; + break; + case GL_NEAREST_MIPMAP_LINEAR: + t->regs.tex_cntl |= R128_MIN_BLEND_MIPLINEAR; + break; + case GL_LINEAR_MIPMAP_LINEAR: + t->regs.tex_cntl |= R128_MIN_BLEND_LINEARMIPLINEAR; + break; + default: /* ERROR!! */ return; + } + + switch (magf) { + case GL_NEAREST: + t->regs.tex_cntl |= R128_MAG_BLEND_NEAREST; + break; + case GL_LINEAR: + t->regs.tex_cntl |= R128_MAG_BLEND_LINEAR; + break; + } +} + +/* Set the texture border color */ +static void r128SetTexBorderColor(r128TexObjPtr t, GLubyte c[4]) +{ + t->regs.border_color = r128PackColor(32, c[0], c[1], c[2], c[3]); +} + +/* Set the texture environment state */ static void r128DDTexEnv(GLcontext *ctx, GLenum pname, const GLfloat *param) { + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + struct gl_texture_unit *texUnit; + GLubyte c[4]; + CARD32 col; + + switch (pname) { + case GL_TEXTURE_ENV_MODE: + /* TexEnv modes are handled in UpdateTextureState */ + R128_FLUSH_VB(r128ctx); + r128ctx->dirty |= R128_UPDATE_TEXSTATE; + break; + case GL_TEXTURE_ENV_COLOR: + texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + 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) { + R128_FLUSH_VB(r128ctx); + r128ctx->regs.constant_color_c = col; + r128ctx->dirty |= R128_UPDATE_CONTEXT; + r128ctx->dirty_context |= R128_CTX_TEXENVSTATE; + } + break; + default: + return; + } } +/* Upload a new texture image */ static void r128DDTexImage(GLcontext *ctx, GLenum target, struct gl_texture_object *tObj, GLint level, GLint internalFormat, const struct gl_texture_image *image) { + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + r128TexObjPtr t; + + if (target != GL_TEXTURE_2D) return; + if (level >= R128_TEX_MAXLEVELS) return; + + t = (r128TexObjPtr)tObj->DriverData; + if (t) { + if (t->bound) R128_FLUSH_VB(r128ctx); + + /* Destroy the old texture, and upload a new one. The actual + uploading of the texture image occurs in the UploadTexLevel + function. */ + r128DestroyTexObj(r128ctx, t); + r128ctx->dirty |= R128_UPDATE_TEXSTATE; + } } +/* Upload a new texture sub-image */ static void r128DDTexSubImage(GLcontext *ctx, GLenum target, struct gl_texture_object *tObj, GLint level, GLint xoffset, GLint yoffset, @@ -54,30 +1063,113 @@ static void r128DDTexSubImage(GLcontext *ctx, GLenum target, GLint internalFormat, const struct gl_texture_image *image) { + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + r128TexObjPtr t; + + if (target != GL_TEXTURE_2D) return; + if (level >= R128_TEX_MAXLEVELS) return; + + t = (r128TexObjPtr)tObj->DriverData; + if (t) { + if (t->bound) R128_FLUSH_VB(r128ctx); + + /* Destroy the old texture, and upload a new one. The actual + uploading of the texture image occurs in the UploadTexLevel + function. */ + r128DestroyTexObj(r128ctx, t); + tObj->DriverData = NULL; + r128ctx->dirty |= R128_UPDATE_TEXSTATE; + } } +/* Set the texture parameter state */ static void r128DDTexParameter(GLcontext *ctx, GLenum target, struct gl_texture_object *tObj, GLenum pname, const GLfloat *params) { + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + r128TexObjPtr t = (r128TexObjPtr)tObj->DriverData; + + if (!t) return; + if (target != GL_TEXTURE_2D) return; + + switch (pname) { + case GL_TEXTURE_MIN_FILTER: + case GL_TEXTURE_MAG_FILTER: + if (t->bound) R128_FLUSH_VB(r128ctx); + + r128SetTexFilter(t, tObj->MinFilter, tObj->MagFilter); + break; + + case GL_TEXTURE_WRAP_S: + case GL_TEXTURE_WRAP_T: + if (t->bound) R128_FLUSH_VB(r128ctx); + + r128SetTexWrap(t, tObj->WrapS, tObj->WrapT); + break; + + case GL_TEXTURE_BORDER_COLOR: + if (t->bound) R128_FLUSH_VB(r128ctx); + + r128SetTexBorderColor(t, tObj->BorderColor); + break; + + default: + return; + } + + r128ctx->dirty |= R128_UPDATE_TEXSTATE; } +/* Bind a texture to the currently active texture unit */ static void r128DDBindTexture(GLcontext *ctx, GLenum target, struct gl_texture_object *tObj) { + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + + R128_FLUSH_VB(r128ctx); + + /* Unbind the old texture */ + if (r128ctx->CurrentTexObj[ctx->Texture.CurrentUnit]) { + r128ctx->CurrentTexObj[ctx->Texture.CurrentUnit]->bound = 0; + r128ctx->CurrentTexObj[ctx->Texture.CurrentUnit] = NULL; + } + + /* The actualy binding occurs in the Tex[01]UpdateState function */ + r128ctx->dirty |= R128_UPDATE_TEXSTATE; } +/* Remove texture from AGP/local texture memory */ static void r128DDDeleteTexture(GLcontext *ctx, struct gl_texture_object *tObj) { + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + r128TexObjPtr t = (r128TexObjPtr)tObj->DriverData; + + if (t) { + if (t->bound) { + R128_FLUSH_VB(r128ctx); + + r128ctx->CurrentTexObj[t->bound-1] = 0; + r128ctx->dirty |= R128_UPDATE_TEXSTATE; + } + + r128DestroyTexObj(r128ctx, t); + tObj->DriverData = NULL; + } } +/* Determine if a texture is currently residing in either AGP/local + texture memory */ static GLboolean r128DDIsTextureResident(GLcontext *ctx, - struct gl_texture_object *t) + struct gl_texture_object *tObj) { - return GL_TRUE; + r128TexObjPtr t = (r128TexObjPtr)tObj->DriverData; + + return t && t->memBlock; } +/* Initialize the driver's texture functions */ void r128DDInitTextureFuncs(GLcontext *ctx) { ctx->Driver.TexEnv = r128DDTexEnv; diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_tex.h b/xc/lib/GL/mesa/src/drv/r128/r128_tex.h index 6543435a5..ff12f0a0d 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_tex.h +++ b/xc/lib/GL/mesa/src/drv/r128/r128_tex.h @@ -37,6 +37,13 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #ifdef GLX_DIRECT_RENDERING +extern void r128ResetGlobalLRU(r128ContextPtr r128ctx); +extern void r128TexturesGone(r128ContextPtr r128ctx, + int offset, int size, int in_use); +extern int r128UploadTexImages(r128ContextPtr r128ctx, r128TexObjPtr t); +extern void r128UpdateTextureState(r128ContextPtr r128ctx); +extern void r128DestroyTexObj(r128ContextPtr r128ctx, r128TexObjPtr t); + extern void r128DDInitTextureFuncs(GLcontext *ctx); #endif diff --git a/xc/lib/GL/mesa/src/drv/r128/r128_texobj.h b/xc/lib/GL/mesa/src/drv/r128/r128_texobj.h new file mode 100644 index 000000000..6b94d90d5 --- /dev/null +++ b/xc/lib/GL/mesa/src/drv/r128/r128_texobj.h @@ -0,0 +1,81 @@ +/* $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_TEXOBJ_H_ +#define _R128_TEXOBJ_H_ + +#include "mm.h" + +#define R128_TEX_MAXLEVELS 11 + +/* Setup registers for each texture */ +typedef struct { + CARD32 tex_cntl; + CARD32 size_pitch; + CARD32 border_color; +} r128TextureRegs; + +/* Individual texture image information */ +typedef struct { + int offset; /* Offset into locally shared texture space (i.e., + relative to bufAddr (below) */ + int width; /* Width of texture image */ +} r128TexImage; + +typedef struct r128_tex_obj r128TexObj, *r128TexObjPtr; + +/* Texture object in locally shared texture space */ +struct r128_tex_obj { + r128TexObjPtr next, prev; + + struct gl_texture_object *tObj; /* Mesa texture object */ + + PMemBlock memBlock; /* Memory block containing texture */ + unsigned char *bufAddr; /* Offset to start of locally + shared texture block */ + + CARD32 dirty_images; /* Flags for whether or not + images need to be uploaded to + local or AGP texture space */ + int bound; /* Texture unit currently bound to */ + r128TexImage image[R128_TEX_MAXLEVELS]; /* Image data for all + mipmap levels */ + int totalSize; /* Total size of the texture + including all mipmap levels */ + int internFormat; /* Internal format used to store + texture on card */ + r128TextureRegs regs; /* Setup regs for texture */ +}; + +#endif /* _R128_TEXOBJ_H_ */ 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 58e2b5980..26753de78 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_tris.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_tris.c @@ -48,24 +48,66 @@ static quad_func quad_tab[0x40]; /* only 0x20 actually used */ static line_func line_tab[0x40]; /* less than 0x20 used */ static points_func points_tab[0x40]; /* less than 0x20 used */ -static void r128DrawTriangle(r128ContextPtr r128ctx, - r128_vertex *v0, - r128_vertex *v1, - r128_vertex *v2) +/* Draw a triangle from the vertices in the vertex buffer */ +void r128DrawTriangle(r128ContextPtr r128ctx, + r128_vertex *v0, + r128_vertex *v1, + r128_vertex *v2) { +#if USE_VERTEX_BUFFERS + r128_vertex *vbptr = r128CCEAllocVBSpace(r128ctx, 3); + + *vbptr++ = *v0; + *vbptr++ = *v1; + *vbptr++ = *v2; +#else + unsigned char *R128MMIO = r128ctx->r128Screen->mmio; + + BEGIN_CLIP_LOOP(r128ctx); + +#if USE_RHW2 + R128CCE_WAIT_LOCKED(36); + R128CCE3(R128_CCE_PACKET3_3D_RNDR_GEN_PRIM, 34); +#else + R128CCE_WAIT_LOCKED(33); + R128CCE3(R128_CCE_PACKET3_3D_RNDR_GEN_PRIM, 31); +#endif + R128CCE(R128_FULL_VERTEX_FORMAT); + R128CCE(R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST | + R128_CCE_VC_CNTL_PRIM_WALK_RING | + (3 << R128_CCE_VC_CNTL_NUM_SHIFT)); + + R128CCE_SEND_VERTEX(v0); + R128CCE_SEND_VERTEX(v1); + R128CCE_SEND_VERTEX(v2); + + R128CCE_END_LOCKED(); + + END_CLIP_LOOP(r128ctx); +#endif } -static void r128DrawLine(r128ContextPtr r128ctx, - r128_vertex *tmp0, r128_vertex *tmp1, - float width) +/* Draw a line from the vertices in the vertex buffer */ +void r128DrawLine(r128ContextPtr r128ctx, + r128_vertex *tmp0, r128_vertex *tmp1, + float width) { } -static void r128DrawPoint(r128ContextPtr r128ctx, - r128_vertex *tmp, float sz) +/* Draw a point from the vertices in the vertex buffer */ +void r128DrawPoint(r128ContextPtr r128ctx, + r128_vertex *tmp, float sz) { } +#define R128_COLOR(to, from) \ +do { \ + (to)[0] = (from)[2]; \ + (to)[1] = (from)[1]; \ + (to)[2] = (from)[0]; \ + (to)[3] = (from)[3]; \ +} while (0) + #define IND (0) #define TAG(x) x #include "r128_tritmp.h" @@ -74,12 +116,46 @@ static void r128DrawPoint(r128ContextPtr r128ctx, #define TAG(x) x##_flat #include "r128_tritmp.h" +#define IND (R128_OFFSET_BIT) +#define TAG(x) x##_offset +#include "r128_tritmp.h" + +#define IND (R128_OFFSET_BIT | R128_FLAT_BIT) +#define TAG(x) x##_offset_flat +#include "r128_tritmp.h" + +#define IND (R128_TWOSIDE_BIT) +#define TAG(x) x##_twoside +#include "r128_tritmp.h" + +#define IND (R128_TWOSIDE_BIT | R128_FLAT_BIT) +#define TAG(x) x##_twoside_flat +#include "r128_tritmp.h" + +#define IND (R128_TWOSIDE_BIT | R128_OFFSET_BIT) +#define TAG(x) x##_twoside_offset +#include "r128_tritmp.h" + +#define IND (R128_TWOSIDE_BIT | R128_OFFSET_BIT | R128_FLAT_BIT) +#define TAG(x) x##_twoside_offset_flat +#include "r128_tritmp.h" + +/* Initialize the table of points, line and triangle drawing functions */ void r128TriangleFuncsInit(void) { init(); init_flat(); + init_offset(); + init_offset_flat(); + init_twoside(); + init_twoside_flat(); + init_twoside_offset(); + init_twoside_offset_flat(); } +/* Setup the Point, Line, Triangle and Quad functions based on the + current rendering state. Wherever possible, use the hardware to + render the primitive. Otherwise, fallback to software rendering. */ void r128ChooseRenderState(GLcontext *ctx) { r128ContextPtr r128ctx = R128_CONTEXT(ctx); @@ -92,25 +168,17 @@ void r128ChooseRenderState(GLcontext *ctx) CARD32 shared = 0; CARD32 fallback = R128_FALLBACK_BIT; -#if 0 - shared = fallback; /* Make everything a fallback */ -#endif - -#if 0 - fallback = 0; /* Turn off all fallbacks */ -#endif + if (r128ctx->SWfallbackDisable) fallback = 0; /* No fallbacks */ + if (r128ctx->SWonly) shared = fallback; /* Everything's a fallback */ if (flags & DD_FLATSHADE) shared |= R128_FLAT_BIT; if (flags & DD_MULTIDRAW) shared |= fallback; if (flags & DD_SELECT) shared |= R128_FALLBACK_BIT; if (flags & DD_FEEDBACK) shared |= R128_FALLBACK_BIT; + /* Setup PointFunc */ index = shared; -#if 1 if (flags & DD_POINT_SMOOTH) index |= fallback; -#else - if (flags & DD_POINT_SMOOTH) index |= R128_ANTIALIAS_BIT; -#endif if (flags & DD_POINT_ATTEN) index |= fallback; r128ctx->RenderIndex = index; @@ -118,12 +186,9 @@ void r128ChooseRenderState(GLcontext *ctx) if (index & R128_FALLBACK_BIT) r128ctx->IndirectTriangles |= DD_POINT_SW_RASTERIZE; + /* Setup LineFunc */ index = shared; -#if 1 if (flags & DD_LINE_SMOOTH) index |= fallback; -#else - if (flags & DD_LINE_SMOOTH) index |= R128_ANTIALIAS_BIT; -#endif if (flags & DD_LINE_STIPPLE) index |= fallback; r128ctx->RenderIndex |= index; @@ -131,14 +196,16 @@ void r128ChooseRenderState(GLcontext *ctx) if (index & R128_FALLBACK_BIT) r128ctx->IndirectTriangles |= DD_LINE_SW_RASTERIZE; + /* Setup TriangleFunc and QuadFunc */ index = shared; -#if 1 if (flags & DD_TRI_SMOOTH) index |= fallback; +#if 1 + if (flags & DD_TRI_OFFSET) index |= fallback; + if (flags & DD_TRI_LIGHT_TWOSIDE) index |= fallback; #else - if (flags & DD_TRI_SMOOTH) index |= R128_ANTIALIAS_BIT; -#endif if (flags & DD_TRI_OFFSET) index |= R128_OFFSET_BIT; if (flags & DD_TRI_LIGHT_TWOSIDE) index |= R128_TWOSIDE_BIT; +#endif if (flags & DD_TRI_UNFILLED) index |= fallback; if (flags & DD_TRI_STIPPLE) index |= fallback; 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 ba98eb3e7..91f30d80b 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_tris.h +++ b/xc/lib/GL/mesa/src/drv/r128/r128_tris.h @@ -37,6 +37,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #ifdef GLX_DIRECT_RENDERING +#include "r128_vb.h" + #define R128_ANTIALIAS_BIT 0x00 /* ignored for now, no fallback */ #define R128_FLAT_BIT 0x01 #define R128_OFFSET_BIT 0x02 @@ -47,6 +49,16 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define R128_SELECT_BIT 0x40 #define R128_POINT_PARAM_BIT 0x80 /* not needed? */ +extern void r128DrawTriangle(r128ContextPtr r128ctx, + r128_vertex *v0, + r128_vertex *v1, + r128_vertex *v2); +extern void r128DrawLine(r128ContextPtr r128ctx, + r128_vertex *tmp0, r128_vertex *tmp1, + float width); +extern void r128DrawPoint(r128ContextPtr r128ctx, + r128_vertex *tmp, float sz); + 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 ff0804c4e..5cd66a8cd 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_tritmp.h +++ b/xc/lib/GL/mesa/src/drv/r128/r128_tritmp.h @@ -33,9 +33,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if !defined(TAG) || !defined(IND) - this is an error; + this is an error #endif +/* Draw a single triangle. Note that the device-dependent vertex data + might need to be changed based on the render state. */ static void TAG(triangle)(GLcontext *ctx, GLuint e0, GLuint e1, GLuint e2, GLuint pv) @@ -101,60 +103,153 @@ static void TAG(triangle)(GLcontext *ctx, } #endif - BEGIN_CLIP_LOOP(r128ctx); + if (r128ctx->regs.tex_cntl_c & (R128_TEXMAP_ENABLE | + R128_SEC_TEXMAP_ENABLE)) { + BEGIN_CLIP_LOOP(r128ctx); - R128CCE_BEGIN_LOCKED(15); - R128CCE3(R128_CCE_PACKET3_3D_RNDR_GEN_PRIM, 13); - R128CCE(R128_CCE_VC_FRMT_DIFFUSE_ARGB); - R128CCE(R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST | - R128_CCE_VC_CNTL_PRIM_WALK_RING | - (3 << R128_CCE_VC_CNTL_NUM_SHIFT)); +#if USE_RHW2 + R128CCE_WAIT_LOCKED(36); + R128CCE3(R128_CCE_PACKET3_3D_RNDR_GEN_PRIM, 34); +#else + R128CCE_WAIT_LOCKED(33); + R128CCE3(R128_CCE_PACKET3_3D_RNDR_GEN_PRIM, 31); +#endif + R128CCE(R128_FULL_VERTEX_FORMAT); + R128CCE(R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST | + R128_CCE_VC_CNTL_PRIM_WALK_RING | + (3 << R128_CCE_VC_CNTL_NUM_SHIFT)); - R128CCEF(v0->x); - R128CCEF(v0->y); + R128CCEF(v0->x); + R128CCEF(v0->y); #if (IND & R128_OFFSET_BIT) - R128CCEF(v0->z + offset); + R128CCEF(v0->z + offset); #else - R128CCEF(v0->z); + R128CCEF(v0->z); #endif + R128CCEF(v0->rhw); #if (IND & (R128_FLAT_BIT | R128_TWOSIDE_BIT)) - R128CCE(c0); + R128CCE(c0); #else - R128CCE(*(int *)&v0->dif_argb); + R128CCE(*(int *)&v0->dif_argb); +#endif + R128CCE(*(int *)&v0->spec_frgb); + + R128CCEF(v0->tu0); + R128CCEF(v0->tv0); + R128CCEF(v0->tu1); + R128CCEF(v0->tv1); +#if USE_RHW2 + R128CCEF(v0->rhw2); #endif - R128CCEF(v1->x); - R128CCEF(v1->y); + R128CCEF(v1->x); + R128CCEF(v1->y); #if (IND & R128_OFFSET_BIT) - R128CCEF(v1->z + offset); + R128CCEF(v1->z + offset); #else - R128CCEF(v1->z); + R128CCEF(v1->z); #endif + R128CCEF(v1->rhw); #if (IND & (R128_FLAT_BIT | R128_TWOSIDE_BIT)) - R128CCE(c1); + R128CCE(c1); #else - R128CCE(*(int *)&v1->dif_argb); + R128CCE(*(int *)&v1->dif_argb); +#endif + R128CCE(*(int *)&v1->spec_frgb); + + R128CCEF(v1->tu0); + R128CCEF(v1->tv0); + R128CCEF(v1->tu1); + R128CCEF(v1->tv1); +#if USE_RHW2 + R128CCEF(v1->rhw2); #endif - R128CCEF(v2->x); - R128CCEF(v2->y); + R128CCEF(v2->x); + R128CCEF(v2->y); #if (IND & R128_OFFSET_BIT) - R128CCEF(v2->z + offset); + R128CCEF(v2->z + offset); #else - R128CCEF(v2->z); + R128CCEF(v2->z); #endif + R128CCEF(v2->rhw); #if (IND & (R128_FLAT_BIT | R128_TWOSIDE_BIT)) - R128CCE(c2); + R128CCE(c2); #else - R128CCE(*(int *)&v2->dif_argb); + R128CCE(*(int *)&v2->dif_argb); +#endif + R128CCE(*(int *)&v2->spec_frgb); + + R128CCEF(v2->tu0); + R128CCEF(v2->tv0); + R128CCEF(v2->tu1); + R128CCEF(v2->tv1); +#if USE_RHW2 + R128CCEF(v2->rhw2); #endif - R128CCE_END_LOCKED(); + R128CCE_END_LOCKED(); - END_CLIP_LOOP(r128ctx); + END_CLIP_LOOP(r128ctx); + } else { + BEGIN_CLIP_LOOP(r128ctx); + + R128CCE_WAIT_LOCKED(15); + R128CCE3(R128_CCE_PACKET3_3D_RNDR_GEN_PRIM, 13); + R128CCE(R128_CCE_VC_FRMT_DIFFUSE_ARGB); + R128CCE(R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST | + R128_CCE_VC_CNTL_PRIM_WALK_RING | + (3 << R128_CCE_VC_CNTL_NUM_SHIFT)); + + R128CCEF(v0->x); + R128CCEF(v0->y); +#if (IND & R128_OFFSET_BIT) + R128CCEF(v0->z + offset); +#else + R128CCEF(v0->z); +#endif + +#if (IND & (R128_FLAT_BIT | R128_TWOSIDE_BIT)) + R128CCE(c0); +#else + R128CCE(*(int *)&v0->dif_argb); +#endif + + R128CCEF(v1->x); + R128CCEF(v1->y); +#if (IND & R128_OFFSET_BIT) + R128CCEF(v1->z + offset); +#else + R128CCEF(v1->z); +#endif + +#if (IND & (R128_FLAT_BIT | R128_TWOSIDE_BIT)) + R128CCE(c1); +#else + R128CCE(*(int *)&v1->dif_argb); +#endif + + R128CCEF(v2->x); + R128CCEF(v2->y); +#if (IND & R128_OFFSET_BIT) + R128CCEF(v2->z + offset); +#else + R128CCEF(v2->z); +#endif + +#if (IND & (R128_FLAT_BIT | R128_TWOSIDE_BIT)) + R128CCE(c2); +#else + R128CCE(*(int *)&v2->dif_argb); +#endif + + R128CCE_END_LOCKED(); + + END_CLIP_LOOP(r128ctx); + } } static void TAG(quad)(GLcontext *ctx, @@ -167,15 +262,17 @@ static void TAG(quad)(GLcontext *ctx, #if ((IND & ~R128_FLAT_BIT) == 0) +/* Draw a single line. Note that the device-dependent vertex data might + need to be changed based on the render state. */ static void TAG(line)(GLcontext *ctx, GLuint v0, GLuint v1, GLuint pv) { - r128ContextPtr r128ctx = R128_CONTEXT(ctx); - r128VertexPtr r128verts = R128_DRIVER_DATA(ctx->VB)->verts; - r128_vertex tmp0 = r128verts[v0].v; - r128_vertex tmp1 = r128verts[v1].v; - float width = ctx->Line.Width; + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + r128VertexPtr r128verts = R128_DRIVER_DATA(ctx->VB)->verts; + r128_vertex tmp0 = r128verts[v0].v; + r128_vertex tmp1 = r128verts[v1].v; + float width = ctx->Line.Width; if (IND & R128_FLAT_BIT) { *(int *)&tmp1.dif_argb = @@ -190,6 +287,8 @@ static void TAG(line)(GLcontext *ctx, END_CLIP_LOOP(r128ctx); } +/* Draw a set of points. Note that the device-dependent vertex data + might need to be changed based on the render state. */ static void TAG(points)(GLcontext *ctx, GLuint first, GLuint last) { @@ -199,10 +298,6 @@ static void TAG(points)(GLcontext *ctx, GLfloat sz = ctx->Point.Size * 0.5; int i; - /* Culling is disabled automatically via. the - * ctx->Driver.ReducedPrimitiveChange() callback. - */ - BEGIN_CLIP_LOOP(r128ctx); for(i = first; i <= last; i++) { @@ -217,6 +312,7 @@ static void TAG(points)(GLcontext *ctx, #endif +/* Initialize the table of primitives to render. */ static void TAG(init)(void) { tri_tab[IND] = TAG(triangle); 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 e3062a603..af271f50f 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_vb.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_vb.c @@ -36,20 +36,24 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "r128_mesa.h" #include "r128_xmesa.h" #include "r128_context.h" +#include "r128_lock.h" +#include "r128_reg.h" +#include "r128_cce.h" +#include "r128_state.h" #include "r128_vb.h" #include "stages.h" #define TEX0 \ do { \ - v->v.tu1 = tc0[i][0]; \ - v->v.tv1 = tc0[i][1]; \ + v->v.tu0 = tc0[i][0]; \ + v->v.tv0 = tc0[i][1]; \ } while (0) #define TEX1 \ do { \ - v->v.tu2 = tc1[i][0]; \ - v->v.tv2 = tc1[i][1]; \ + v->v.tu1 = tc1[i][0]; \ + v->v.tv1 = tc1[i][1]; \ } while (0) #define SPC \ @@ -75,6 +79,11 @@ do { \ v->v.dif_argb.b = col[2]; \ } while (0) +#if 1 +/* FIXME: These are handled by the Rage 128 */ +#define TEX0_4 +#define TEX1_4 +#else #define TEX0_4 \ do { \ if (VB->TexCoordPtr[0]->size == 4) { \ @@ -83,22 +92,32 @@ do { \ for (i = start; i < end; i++, v++) { \ float oow = 1.0 / tc[i][3]; \ v->v.rhw *= tc[i][3]; \ - v->v.tu1 *= oow; \ - v->v.tv1 *= oow; \ + v->v.tu0 *= oow; \ + v->v.tv0 *= oow; \ } \ } \ +} while (0) + +#if USE_RHW2 +#define TEX1_4 \ +do { \ if (VB->TexCoordPtr[1]->size == 4) { \ GLfloat (*tc)[4] = VB->TexCoordPtr[1]->data; \ 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.tu2 *= oow; \ - v->v.tv2 *= oow; \ + v->v.tu1 *= oow; \ + v->v.tv1 *= oow; \ } \ } \ } while (0) +#else +#define TEX1_4 +#endif +#endif +#if USE_RHW2 #define COORD \ do { \ GLfloat *win = VB->Win.data[i]; \ @@ -107,10 +126,21 @@ do { \ v->v.z = (1.0/0x10000) * win[2]; \ v->v.rhw = v->v.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 = (1.0/0x10000) * win[2]; \ + v->v.rhw = win[3]; \ +} while (0) +#endif #define NOP -#define SETUPFUNC(name,win,col,tex0,tex1,tex0_4,spec,fog) \ +/* Setup the r128 vertex buffer entries */ +#define SETUPFUNC(name,win,col,tex0,tex1,tex0_4,tex1_4,spec,fog) \ static void name(struct vertex_buffer *VB, GLuint start, GLuint end) \ { \ r128ContextPtr r128ctx = R128_CONTEXT(VB->ctx); \ @@ -154,43 +184,56 @@ static void name(struct vertex_buffer *VB, GLuint start, GLuint end) \ col; \ } \ tex0_4; \ + tex1_4; \ } -SETUPFUNC(rs_wt0, COORD, NOP, TEX0, NOP, TEX0_4, NOP, NOP) -SETUPFUNC(rs_wt0t1, COORD, NOP, TEX0, TEX1, TEX0_4, NOP, NOP) -SETUPFUNC(rs_wft0, COORD, NOP, TEX0, NOP, TEX0_4, NOP, FOG) -SETUPFUNC(rs_wft0t1, COORD, NOP, TEX0, TEX1, TEX0_4, NOP, FOG) -SETUPFUNC(rs_wg, COORD, COL, NOP, NOP, NOP, NOP, NOP) -SETUPFUNC(rs_wgs, COORD, COL, NOP, NOP, NOP, SPC, NOP) -SETUPFUNC(rs_wgt0, COORD, COL, TEX0, NOP, TEX0_4, NOP, NOP) -SETUPFUNC(rs_wgt0t1, COORD, COL, TEX0, TEX1, TEX0_4, NOP, NOP) -SETUPFUNC(rs_wgst0, COORD, COL, TEX0, NOP, TEX0_4, SPC, NOP) -SETUPFUNC(rs_wgst0t1, COORD, COL, TEX0, TEX1, TEX0_4, SPC, NOP) -SETUPFUNC(rs_wgf, COORD, COL, NOP, NOP, NOP, NOP, FOG) -SETUPFUNC(rs_wgfs, COORD, COL, NOP, NOP, NOP, SPC, FOG) -SETUPFUNC(rs_wgft0, COORD, COL, TEX0, NOP, TEX0_4, NOP, FOG) -SETUPFUNC(rs_wgft0t1, COORD, COL, TEX0, TEX1, TEX0_4, NOP, FOG) -SETUPFUNC(rs_wgfst0, COORD, COL, TEX0, NOP, TEX0_4, SPC, FOG) -SETUPFUNC(rs_wgfst0t1, COORD, COL, TEX0, TEX1, TEX0_4, SPC, FOG) - -SETUPFUNC(rs_t0, NOP, NOP, TEX0, NOP, TEX0_4, NOP, NOP) -SETUPFUNC(rs_t0t1, NOP, NOP, TEX0, TEX1, TEX0_4, NOP, NOP) -SETUPFUNC(rs_f, NOP, NOP, NOP, NOP, NOP, NOP, FOG) -SETUPFUNC(rs_ft0, NOP, NOP, TEX0, NOP, TEX0_4, NOP, FOG) -SETUPFUNC(rs_ft0t1, NOP, NOP, TEX0, TEX1, TEX0_4, NOP, FOG) -SETUPFUNC(rs_g, NOP, COL, NOP, NOP, NOP, NOP, NOP) -SETUPFUNC(rs_gs, NOP, COL, NOP, NOP, NOP, SPC, NOP) -SETUPFUNC(rs_gt0, NOP, COL, TEX0, NOP, TEX0_4, NOP, NOP) -SETUPFUNC(rs_gt0t1, NOP, COL, TEX0, TEX1, TEX0_4, NOP, NOP) -SETUPFUNC(rs_gst0, NOP, COL, TEX0, NOP, TEX0_4, SPC, NOP) -SETUPFUNC(rs_gst0t1, NOP, COL, TEX0, TEX1, TEX0_4, SPC, NOP) -SETUPFUNC(rs_gf, NOP, COL, NOP, NOP, NOP, NOP, FOG) -SETUPFUNC(rs_gfs, NOP, COL, NOP, NOP, NOP, SPC, FOG) -SETUPFUNC(rs_gft0, NOP, COL, TEX0, NOP, TEX0_4, NOP, FOG) -SETUPFUNC(rs_gft0t1, NOP, COL, TEX0, TEX1, TEX0_4, NOP, FOG) -SETUPFUNC(rs_gfst0, NOP, COL, TEX0, NOP, TEX0_4, SPC, FOG) -SETUPFUNC(rs_gfst0t1, NOP, COL, TEX0, TEX1, TEX0_4, SPC, FOG) +SETUPFUNC(rs_wt0, COORD, NOP, TEX0, NOP, TEX0_4, NOP, NOP, NOP) +SETUPFUNC(rs_wt1, COORD, NOP, NOP, TEX1, NOP, TEX1_4, NOP, NOP) +SETUPFUNC(rs_wt0t1, COORD, NOP, TEX0, TEX1, TEX0_4, TEX1_4, NOP, NOP) +SETUPFUNC(rs_wft0, COORD, NOP, TEX0, NOP, TEX0_4, NOP, NOP, FOG) +SETUPFUNC(rs_wft1, COORD, NOP, NOP, TEX1, NOP, TEX1_4, NOP, FOG) +SETUPFUNC(rs_wft0t1, COORD, NOP, TEX0, TEX1, TEX0_4, TEX1_4, NOP, FOG) +SETUPFUNC(rs_wg, COORD, COL, NOP, NOP, NOP, NOP, NOP, NOP) +SETUPFUNC(rs_wgs, COORD, COL, NOP, NOP, NOP, NOP, SPC, NOP) +SETUPFUNC(rs_wgt0, COORD, COL, TEX0, NOP, TEX0_4, NOP, NOP, NOP) +SETUPFUNC(rs_wgt1, COORD, COL, NOP, TEX1, NOP, TEX1_4, NOP, NOP) +SETUPFUNC(rs_wgt0t1, COORD, COL, TEX0, TEX1, TEX0_4, TEX1_4, NOP, NOP) +SETUPFUNC(rs_wgst0, COORD, COL, TEX0, NOP, TEX0_4, NOP, SPC, NOP) +SETUPFUNC(rs_wgst1, COORD, COL, NOP, TEX1, NOP, TEX1_4, SPC, NOP) +SETUPFUNC(rs_wgst0t1, COORD, COL, TEX0, TEX1, TEX0_4, TEX1_4, SPC, NOP) +SETUPFUNC(rs_wgf, COORD, COL, NOP, NOP, NOP, NOP, NOP, FOG) +SETUPFUNC(rs_wgfs, COORD, COL, NOP, NOP, NOP, NOP, SPC, FOG) +SETUPFUNC(rs_wgft0, COORD, COL, TEX0, NOP, TEX0_4, NOP, NOP, FOG) +SETUPFUNC(rs_wgft1, COORD, COL, NOP, TEX1, NOP, TEX1_4, NOP, FOG) +SETUPFUNC(rs_wgft0t1, COORD, COL, TEX0, TEX1, TEX0_4, TEX1_4, NOP, FOG) +SETUPFUNC(rs_wgfst0, COORD, COL, TEX0, NOP, TEX0_4, NOP, SPC, FOG) +SETUPFUNC(rs_wgfst1 , COORD, COL, NOP, TEX1, NOP, TEX1_4, SPC, FOG) +SETUPFUNC(rs_wgfst0t1, COORD, COL, TEX0, TEX1, TEX0_4, TEX1_4, SPC, FOG) + +SETUPFUNC(rs_t0, NOP, NOP, TEX0, NOP, TEX0_4, NOP, NOP, NOP) +SETUPFUNC(rs_t1, NOP, NOP, NOP, TEX1, NOP, TEX1_4, NOP, NOP) +SETUPFUNC(rs_t0t1, NOP, NOP, TEX0, TEX1, TEX0_4, TEX1_4, NOP, NOP) +SETUPFUNC(rs_f, NOP, NOP, NOP, NOP, NOP, NOP, NOP, FOG) +SETUPFUNC(rs_ft0, NOP, NOP, TEX0, NOP, TEX0_4, NOP, NOP, FOG) +SETUPFUNC(rs_ft1, NOP, NOP, NOP, TEX1, NOP, TEX1_4, NOP, FOG) +SETUPFUNC(rs_ft0t1, NOP, NOP, TEX0, TEX1, TEX0_4, TEX1_4, NOP, FOG) +SETUPFUNC(rs_g, NOP, COL, NOP, NOP, NOP, NOP, NOP, NOP) +SETUPFUNC(rs_gs, NOP, COL, NOP, NOP, NOP, NOP, SPC, NOP) +SETUPFUNC(rs_gt0, NOP, COL, TEX0, NOP, TEX0_4, NOP, NOP, NOP) +SETUPFUNC(rs_gt1, NOP, COL, NOP, TEX1, NOP, TEX1_4, NOP, NOP) +SETUPFUNC(rs_gt0t1, NOP, COL, TEX0, TEX1, TEX0_4, TEX1_4, NOP, NOP) +SETUPFUNC(rs_gst0, NOP, COL, TEX0, NOP, TEX0_4, NOP, SPC, NOP) +SETUPFUNC(rs_gst1, NOP, COL, NOP, TEX1, NOP, TEX1_4, SPC, NOP) +SETUPFUNC(rs_gst0t1, NOP, COL, TEX0, TEX1, TEX0_4, TEX1_4, SPC, NOP) +SETUPFUNC(rs_gf, NOP, COL, NOP, NOP, NOP, NOP, NOP, FOG) +SETUPFUNC(rs_gfs, NOP, COL, NOP, NOP, NOP, NOP, SPC, FOG) +SETUPFUNC(rs_gft0, NOP, COL, TEX0, NOP, TEX0_4, NOP, NOP, FOG) +SETUPFUNC(rs_gft1, NOP, COL, NOP, TEX1, NOP, TEX1_4, NOP, FOG) +SETUPFUNC(rs_gft0t1, NOP, COL, TEX0, TEX1, TEX0_4, TEX1_4, NOP, FOG) +SETUPFUNC(rs_gfst0, NOP, COL, TEX0, NOP, TEX0_4, NOP, SPC, FOG) +SETUPFUNC(rs_gfst1, NOP, COL, NOP, TEX1, NOP, TEX1_4, SPC, FOG) +SETUPFUNC(rs_gfst0t1, NOP, COL, TEX0, TEX1, TEX0_4, TEX1_4, SPC, FOG) static void rs_invalid(struct vertex_buffer *VB, GLuint start, GLuint end) { @@ -200,6 +243,7 @@ static void rs_invalid(struct vertex_buffer *VB, GLuint start, GLuint end) typedef void (*setupFunc)(struct vertex_buffer *, GLuint, GLuint); static setupFunc setup_func[0x80]; +/* Initialize the table of vertex buffer setup functions */ void r128SetupInit(void) { int i; @@ -208,64 +252,167 @@ void r128SetupInit(void) /* Funcs to build vertices from scratch */ setup_func[R128_WIN_BIT|R128_TEX0_BIT] = rs_wt0; + setup_func[R128_WIN_BIT|R128_TEX1_BIT] = rs_wt1; setup_func[R128_WIN_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_wt0t1; setup_func[R128_WIN_BIT|R128_FOG_BIT|R128_TEX0_BIT] = rs_wft0; + setup_func[R128_WIN_BIT|R128_FOG_BIT|R128_TEX1_BIT] = rs_wft1; setup_func[R128_WIN_BIT|R128_FOG_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_wft0t1; setup_func[R128_WIN_BIT|R128_RGBA_BIT] = rs_wg; setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_SPEC_BIT] = rs_wgs; setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_TEX0_BIT] = rs_wgt0; + setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_TEX1_BIT] = rs_wgt1; setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_wgt0t1; setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT] = rs_wgst0; + setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX1_BIT] = rs_wgst1; setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_wgst0t1; setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_FOG_BIT] = rs_wgf; setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT] = rs_wgfs; setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT] = rs_wgft0; + setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_TEX1_BIT] = rs_wgft1; setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_wgft0t1; setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|R128_TEX0_BIT] = rs_wgfst0; + setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|R128_TEX1_BIT] = rs_wgfst1; setup_func[R128_WIN_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_wgfst0t1; /* Funcs to repair vertices */ setup_func[R128_TEX0_BIT] = rs_t0; + setup_func[R128_TEX1_BIT] = rs_t1; setup_func[R128_TEX0_BIT|R128_TEX1_BIT] = rs_t0t1; setup_func[R128_FOG_BIT] = rs_f; setup_func[R128_FOG_BIT|R128_TEX0_BIT] = rs_ft0; + setup_func[R128_FOG_BIT|R128_TEX1_BIT] = rs_ft1; setup_func[R128_FOG_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_ft0t1; setup_func[R128_RGBA_BIT] = rs_g; setup_func[R128_RGBA_BIT|R128_SPEC_BIT] = rs_gs; setup_func[R128_RGBA_BIT|R128_TEX0_BIT] = rs_gt0; + setup_func[R128_RGBA_BIT|R128_TEX1_BIT] = rs_gt1; setup_func[R128_RGBA_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_gt0t1; setup_func[R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT] = rs_gst0; + setup_func[R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX1_BIT] = rs_gst1; setup_func[R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_gst0t1; setup_func[R128_RGBA_BIT|R128_FOG_BIT] = rs_gf; setup_func[R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT] = rs_gfs; setup_func[R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT] = rs_gft0; + setup_func[R128_RGBA_BIT|R128_FOG_BIT|R128_TEX1_BIT] = rs_gft1; setup_func[R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_gft0t1; setup_func[R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|R128_TEX0_BIT] = rs_gfst0; + setup_func[R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|R128_TEX1_BIT] = rs_gfst1; setup_func[R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|R128_TEX0_BIT|R128_TEX1_BIT] = rs_gfst0t1; } +/* Initialize the vertex buffer setup functions based on the current + rendering state */ void r128ChooseRasterSetupFunc(GLcontext *ctx) { - int funcindex = R128_WIN_BIT | R128_RGBA_BIT; + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + int funcIndex = R128_WIN_BIT | R128_RGBA_BIT; if (ctx->Texture.Enabled & 0xf) { if (ctx->Texture.Unit[0].EnvMode == GL_REPLACE) - funcindex &= ~R128_RGBA_BIT; - funcindex |= R128_TEX0_BIT; + funcIndex &= ~R128_RGBA_BIT; + funcIndex |= R128_TEX0_BIT; } if (ctx->Texture.Enabled & 0xf0) - funcindex |= R128_TEX1_BIT; + funcIndex |= R128_TEX1_BIT; + /* FIXME: Verify this works properly */ if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) - funcindex |= R128_SPEC_BIT; + funcIndex |= R128_SPEC_BIT; if (ctx->FogMode == FOG_FRAGMENT) - funcindex |= R128_FOG_BIT; - - ctx->Driver.RasterSetup = setup_func[funcindex]; + funcIndex |= R128_FOG_BIT; + + r128ctx->SetupIndex = funcIndex; + ctx->Driver.RasterSetup = setup_func[funcIndex]; +} + +/* Check to see if any updates of the vertex buffer entries are needed */ +void r128CheckPartialRasterSetup(GLcontext *ctx, + struct gl_pipeline_stage *s) +{ + r128ContextPtr r128ctx = R128_CONTEXT(ctx); + int tmp = r128ctx->SetupDone; + + s->type = 0; + r128ctx->SetupDone = GL_FALSE; + + if ((ctx->Array.Summary & VERT_OBJ_ANY) == 0) return; + if (ctx->IndirectTriangles) return; + + r128ctx->SetupDone = tmp; +} + +/* Update the vertex buffer entries, if necessary */ +void r128PartialRasterSetup(struct vertex_buffer *VB) +{ + r128ContextPtr r128ctx = R128_CONTEXT(VB->ctx); + int new = VB->pipeline->new_outputs; + int available = VB->pipeline->outputs; + int index = 0; + + if (new & VERT_WIN) { + new = available; + index |= R128_WIN_BIT | R128_FOG_BIT; + } + + if (new & VERT_RGBA) index |= R128_RGBA_BIT | R128_SPEC_BIT; + if (new & VERT_TEX0_ANY) index |= R128_TEX0_BIT; + if (new & VERT_TEX1_ANY) index |= R128_TEX1_BIT; + if (new & VERT_FOG_COORD) index |= R128_FOG_BIT; + + r128ctx->SetupDone &= ~index; + index &= r128ctx->SetupIndex; + r128ctx->SetupDone |= index; + + if (index) setup_func[index & ~R128_ALPHA_BIT](VB, VB->Start, VB->Count); +} + +/* Perform the raster setup for the fast path, if using CVA */ +void r128DoRasterSetup(struct vertex_buffer *VB) +{ + GLcontext *ctx = VB->ctx; + + if (VB->Type == VB_CVA_PRECALC) r128PartialRasterSetup(VB); + else if (ctx->Driver.RasterSetup) ctx->Driver.RasterSetup(VB, + VB->CopyStart, + VB->Count); +} + +/* Resize an existing vertex buffer */ +void r128ResizeVB(struct vertex_buffer *VB, GLuint size) +{ + r128VertexBufferPtr r128vb = R128_DRIVER_DATA(VB); + + while (r128vb->size < size) + r128vb->size *= 2; + + free(r128vb->vert_store); + r128vb->vert_store = malloc(sizeof(r128Vertex) * r128vb->size + 31); + if (!r128vb->vert_store) { + fprintf(stderr, "Cannot allocate vertex store! Exiting...\n"); + exit(1); + } + + r128vb->verts = (r128VertexPtr)(((CARD32)r128vb->vert_store + 31) & ~31); + + gl_vector1ui_free(&r128vb->clipped_elements); + gl_vector1ui_alloc(&r128vb->clipped_elements, + VEC_WRITABLE, r128vb->size, 32); + if (!r128vb->clipped_elements.start) { + fprintf(stderr, "Cannot allocate clipped elements! Exiting...\n"); + exit(1); + } + + free(VB->ClipMask); + VB->ClipMask = (GLubyte *)malloc(sizeof(GLubyte) * r128vb->size); + if (!VB->ClipMask) { + fprintf(stderr, "Cannot allocate clipmask! Exiting...\n"); + exit(1); + } } +/* Create a new device-dependent vertex buffer */ void r128DDRegisterVB(struct vertex_buffer *VB) { r128VertexBufferPtr r128vb; @@ -278,7 +425,7 @@ void r128DDRegisterVB(struct vertex_buffer *VB) fprintf(stderr, "Cannot allocate vertex store! Exiting...\n"); exit(1); } - + r128vb->verts = (r128VertexPtr)(((CARD32)r128vb->vert_store + 31) & ~31); gl_vector1ui_alloc(&r128vb->clipped_elements, @@ -287,7 +434,7 @@ void r128DDRegisterVB(struct vertex_buffer *VB) fprintf(stderr, "Cannot allocate clipped elements! Exiting...\n"); exit(1); } - + free(VB->ClipMask); VB->ClipMask = (GLubyte *)malloc(sizeof(GLubyte) * r128vb->size); if (!VB->ClipMask) { @@ -295,26 +442,115 @@ void r128DDRegisterVB(struct vertex_buffer *VB) exit(1); } - r128vb->primitive = (GLuint *)malloc(sizeof(GLuint) * r128vb->size); - r128vb->next_primitive = (GLuint *)malloc(sizeof(GLuint) * r128vb->size); - if (!r128vb->primitive || !r128vb->next_primitive) { - fprintf(stderr, "Cannot allocate primitive list! Exiting...\n"); - exit(1); - } - VB->driver_data = r128vb; } +/* Destroy a device-dependent vertex buffer */ void r128DDUnregisterVB(struct vertex_buffer *VB) { r128VertexBufferPtr r128vb = R128_DRIVER_DATA(VB); if (r128vb) { if (r128vb->vert_store) free(r128vb->vert_store); - if (r128vb->primitive) free(r128vb->primitive); - if (r128vb->next_primitive) free(r128vb->next_primitive); gl_vector1ui_free(&r128vb->clipped_elements); free(r128vb); VB->driver_data = 0; } } + +/* Get a new VB from the pool of vertex buffers in AGP space */ +static r128CCEVertBufPtr r128CCEGetNewVB(r128ContextPtr r128ctx) +{ +#define R128_VB_SIZE 4096 + + /* FIXME: This only works for a single client right now!!! */ + if (r128ctx->vb) { + r128ctx->vb->start += R128_VB_SIZE; + if (r128ctx->vb->start > + r128ctx->r128Screen->vbStart + r128ctx->r128Screen->vbSize) + r128ctx->vb->start = r128ctx->r128Screen->vbStart; + } else { + r128ctx->vb = (r128CCEVertBufPtr)malloc(sizeof(*r128ctx->vb)); + r128ctx->vb->start = r128ctx->r128Screen->vbStart; + r128ctx->vb->size = R128_VB_SIZE/sizeof(r128_vertex); + } + + r128ctx->vb->count = 0; + r128ctx->vb->done = GL_FALSE; + + return r128ctx->vb; +} + +/* Release a VB back to the pool of vertex buffers in AGP space */ +static void r128CCEReleaseVB(r128ContextPtr r128ctx) +{ + r128ctx->vb->done = GL_TRUE; +} + +/* Reserve space in a VB to store `verts' vertices. 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, and reserve space in + the new VB for the `verts' vertices. */ +r128_vertex *r128CCEAllocVBSpace(r128ContextPtr r128ctx, int verts) +{ + r128_vertex *vbptr; + r128CCEVertBufPtr vb = r128ctx->vb; + + if (!vb || vb->done) vb = r128CCEGetNewVB(r128ctx); + + if (vb->count + verts > vb->size) { + r128CCEFlushVB(r128ctx); + vb = r128CCEGetNewVB(r128ctx); + } + + vbptr = (r128_vertex *)(r128ctx->r128Screen->agp + vb->start) + vb->count; + vb->count += verts; + return vbptr; +} + +/* Send a VB to the Rage 128 to be processed */ +void r128CCEFlushVB(r128ContextPtr r128ctx) +{ + unsigned char *R128MMIO = r128ctx->r128Screen->mmio; + + if (!r128ctx->vb || + !r128ctx->vb->count || + r128ctx->vb->done) return; + + /* Make sure vertices are in memory, and not stuck in the WC cache */ + R128FlushWCMemory(); + + /* FIXME: The textures referenced in this VB cannot be removed until + after this buffer has been processed. ATI suggests loading new + textures via HOSTDATA command packets to solve this problem. */ + + /* FIXME: We need a way to detect if the VB is free or if it is + still in use. By waiting for idle, we know that the currently + processing buffer is complete, but waiting is slow. A better + solution is to use a counter that is stored in one of the + GUI_SCRATCH_REGs, which gets incremented after each VB is + processed. Also, we will need to associate the count value with + each VB in the pool of VBs -- this will need to be stored in the + SAREA. */ + +#if 1 + /* FIXME: Is this _really_ needed? */ + R128CCEWaitForIdle(r128ctx->r128Screen); +#endif + + BEGIN_CLIP_LOOP(r128ctx); + + R128CCE_WAIT_LOCKED(5); + R128CCE3(R128_CCE_PACKET3_3D_RNDR_GEN_INDX_PRIM, 3); + R128CCE(r128ctx->vb->start); + R128CCE(r128ctx->vb->count); + R128CCE(R128_FULL_VERTEX_FORMAT); + R128CCE(R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST | + R128_CCE_VC_CNTL_PRIM_WALK_LIST | + (r128ctx->vb->count << R128_CCE_VC_CNTL_NUM_SHIFT)); + R128CCE_END_LOCKED(); + + END_CLIP_LOOP(r128ctx); + + r128CCEReleaseVB(r128ctx); +} 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 96a560411..9b0a3f7c7 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_vb.h +++ b/xc/lib/GL/mesa/src/drv/r128/r128_vb.h @@ -37,6 +37,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #ifdef GLX_DIRECT_RENDERING +#define USE_RHW2 0 + +/* FIXME: This is endian-specific */ typedef struct { GLubyte b; GLubyte g; @@ -45,34 +48,95 @@ typedef struct { } r128Color; typedef struct { - GLfloat x, y, z; - GLfloat rhw; - r128Color dif_argb; - r128Color spec_frgb; - GLfloat tu1; - GLfloat tv1; - GLfloat tu2; - GLfloat tv2; - GLfloat rhw2; + 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 */ + GLfloat tu1, tv1; /* Texture 1 coordinates */ +#if USE_RHW2 + GLfloat rhw2; /* Reciprocal homogeneous w */ +#endif } r128_vertex; +#if USE_RHW2 +/* Format of vertices in r128_vertex struct */ +#define R128_FULL_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 + +/* Send a single vertex to the ring buffer */ +#define R128CCE_SEND_VERTEX(v) \ +do { \ + R128CCEF((v)->x); \ + R128CCEF((v)->y); \ + R128CCEF((v)->z); \ + R128CCEF((v)->rhw); \ + R128CCE(*(int *)&(v)->dif_argb); \ + R128CCE(*(int *)&(v)->spec_frgb); \ + R128CCEF((v)->tu0); \ + R128CCEF((v)->tv0); \ + R128CCEF((v)->tu1); \ + R128CCEF((v)->tv1); \ + R128CCEF((v)->rhw2); \ +} while (0) + +#else /* !USE_RHW2 */ + +/* Format of vertices in r128_vertex struct */ +#define R128_FULL_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 + +/* Send a single vertex to the ring buffer */ +#define R128CCE_SEND_VERTEX(v) \ +do { \ + R128CCEF((v)->x); \ + R128CCEF((v)->y); \ + R128CCEF((v)->z); \ + R128CCEF((v)->rhw); \ + R128CCE(*(int *)&(v)->dif_argb); \ + R128CCE(*(int *)&(v)->spec_frgb); \ + R128CCEF((v)->tu0); \ + R128CCEF((v)->tv0); \ + R128CCEF((v)->tu1); \ + R128CCEF((v)->tv1); \ +} while (0) +#endif + +/* FIXME: We currently only have assembly for 16-stride vertices */ typedef union { r128_vertex v; float f[16]; } r128Vertex, *r128VertexPtr; +/* Vertex buffer for use when on the fast path */ typedef struct { - GLvector1ui clipped_elements; - r128VertexPtr verts; - int last_vert; - GLuint *primitive; - GLuint *next_primitive; - void *vert_store; - GLuint size; + GLuint size; /* Number of vertices in store */ + void *vert_store; /* Storage for vertex buffer */ + r128VertexPtr verts; /* Aligned start of verts in storage */ + int last_vert; /* Index of last vertex used */ + GLvector1ui clipped_elements; /* List of clipped elements */ } *r128VertexBufferPtr; #define R128_DRIVER_DATA(vb) ((r128VertexBufferPtr)((vb)->driver_data)) +#if USE_VERTEX_BUFFERS +#define R128_FLUSH_VB(CC) \ +do { \ + if ((CC)->vb) r128CCEFlushVB(CC); \ +} while (0) +#else +#define R128_FLUSH_VB(CC) (void)(CC) +#endif + #define R128_SPEC_BIT 0x01 #define R128_FOG_BIT 0x02 #define R128_ALPHA_BIT 0x04 /* GL_BLEND, not used */ @@ -81,10 +145,18 @@ typedef struct { #define R128_RGBA_BIT 0x20 #define R128_WIN_BIT 0x40 -extern void r128SetupInit(void); -extern void r128ChooseRasterSetupFunc(GLcontext *ctx); -extern void r128DDRegisterVB(struct vertex_buffer *VB); -extern void r128DDUnregisterVB(struct vertex_buffer *VB); +extern void r128SetupInit(void); +extern void r128ChooseRasterSetupFunc(GLcontext *ctx); +extern void r128CheckPartialRasterSetup(GLcontext *ctx, + struct gl_pipeline_stage *s); +extern void r128PartialRasterSetup(struct vertex_buffer *VB); +extern void r128DoRasterSetup(struct vertex_buffer *VB); +extern void r128ResizeVB(struct vertex_buffer *VB, GLuint size); +extern void r128DDRegisterVB(struct vertex_buffer *VB); +extern void r128DDUnregisterVB(struct vertex_buffer *VB); + +extern r128_vertex *r128CCEAllocVBSpace(r128ContextPtr r128ctx, int verts); +extern void r128CCEFlushVB(r128ContextPtr r128ctx); #endif #endif /* _R128_VB_H_ */ 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 c0d1697c6..a337b6ea7 100644 --- a/xc/lib/GL/mesa/src/drv/r128/r128_xmesa.c +++ b/xc/lib/GL/mesa/src/drv/r128/r128_xmesa.c @@ -34,37 +34,26 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #ifdef GLX_DIRECT_RENDERING -/* r128 DDX driver includes */ -#include "r128_dri.h" -#include "r128_reg.h" - /* r128 Mesa driver includes */ #include "r128_init.h" #include "r128_context.h" #include "r128_xmesa.h" -#include "r128_dd.h" #include "r128_state.h" -#include "r128_span.h" -#include "r128_depth.h" #include "r128_tex.h" #include "r128_swap.h" -#include "r128_tris.h" -#include "r128_vb.h" /* Mesa src includes */ #include "context.h" -#if 0 -#include "vbxform.h" -#include "matrix.h" -#endif +#include "simple_list.h" #ifdef DEBUG_LOCKING char *prevLockFile = NULL; int prevLockLine = 0; #endif -r128ContextPtr r128Context = NULL; +static r128ContextPtr r128Context = NULL; +/* Count the number of bits set */ static int count_bits(unsigned int n) { int bits = 0; @@ -76,100 +65,24 @@ static int count_bits(unsigned int n) return bits; } +/* FIXME: */ + +/* Initialize the driver specific screen private data */ GLboolean XMesaInitDriver(__DRIscreenPrivate *sPriv) { - r128ScreenPtr r128Screen; - R128DRIPtr r128DRIPriv = (R128DRIPtr)sPriv->pDevPriv; - - /* Allocate the private area */ - r128Screen = (r128ScreenPtr)Xmalloc(sizeof(*r128Screen)); - if (!r128Screen) return GL_FALSE; - - r128Screen->mmioRgn.handle = r128DRIPriv->registerHandle; - r128Screen->mmioRgn.size = r128DRIPriv->registerSize; - if (drmMap(sPriv->fd, - r128Screen->mmioRgn.handle, - r128Screen->mmioRgn.size, - (drmAddressPtr)&r128Screen->mmio)) { - Xfree(r128Screen); - return GL_FALSE; - } - - r128Screen->agpRgn.handle = r128DRIPriv->agpHandle; - r128Screen->agpRgn.size = r128DRIPriv->agpSize; - if (drmMap(sPriv->fd, - r128Screen->agpRgn.handle, - r128Screen->agpRgn.size, - (drmAddressPtr)&r128Screen->agp)) { - drmUnmap((drmAddress)r128Screen->mmio, r128Screen->mmioRgn.size); - Xfree(r128Screen); - return GL_FALSE; - } - - r128Screen->deviceID = r128DRIPriv->deviceID; - - r128Screen->width = r128DRIPriv->width; - r128Screen->height = r128DRIPriv->height; - r128Screen->depth = r128DRIPriv->depth; - r128Screen->bpp = r128DRIPriv->bpp; - - r128Screen->fb = sPriv->pFB; - r128Screen->fbOffset = sPriv->fbOrigin; - r128Screen->fbStride = sPriv->fbStride; - r128Screen->fbSize = sPriv->fbSize; - - r128Screen->fbX = r128DRIPriv->fbX; - r128Screen->fbY = r128DRIPriv->fbY; - r128Screen->backX = r128DRIPriv->backX; - r128Screen->backY = r128DRIPriv->backY; - r128Screen->depthX = r128DRIPriv->depthX; - r128Screen->depthY = r128DRIPriv->depthY; - r128Screen->textureX = r128DRIPriv->textureX; - r128Screen->textureY = r128DRIPriv->textureY; - r128Screen->textureSize = r128DRIPriv->textureSize; - -#if 0 - r128Screen->backX = 0; - r128Screen->backY = r128DRIPriv->height/2; - r128Screen->depthX = r128DRIPriv->width/2; - r128Screen->depthY = r128DRIPriv->height/2; -#endif - - r128Screen->CCEMode = r128DRIPriv->CCEMode; - r128Screen->CCEFifoSize = r128DRIPriv->CCEFifoSize; - - r128Screen->ringStart = r128DRIPriv->ringStart; - r128Screen->ringSize = r128DRIPriv->ringSize; - r128Screen->ringWritePtr = &r128DRIPriv->ringWrite; - r128Screen->ringReadPtr = (int *)(r128Screen->agp - + r128DRIPriv->ringReadOffset); - - r128Screen->MMIOFifoSlots = 0; - r128Screen->CCEFifoSlots = 0; - - r128Screen->CCEFifoAddr = R128_PM4_FIFO_DATA_EVEN; - - r128Screen->driScreen = sPriv; - - sPriv->private = (void *)r128Screen; - - r128TriangleFuncsInit(); - r128SetupInit(); + sPriv->private = (void *)r128CreateScreen(sPriv); + if (!sPriv->private) return GL_FALSE; return GL_TRUE; } +/* Reset the driver specific screen private data */ void XMesaResetDriver(__DRIscreenPrivate *sPriv) { - r128ScreenPtr r128Screen = (r128ScreenPtr)sPriv->private; - - drmUnmap((drmAddress)r128Screen->mmio, r128Screen->mmioRgn.size); - drmUnmap((drmAddress)r128Screen->agp, r128Screen->agpRgn.size); - - Xfree(r128Screen); - sPriv->private = NULL; + r128DestroyScreen(sPriv); } +/* Create and initialize the Mesa and driver specific visual data */ XMesaVisual XMesaCreateVisual(XMesaDisplay *display, XMesaVisualInfo visinfo, GLboolean rgb_flag, @@ -223,6 +136,7 @@ XMesaVisual XMesaCreateVisual(XMesaDisplay *display, return v; } +/* Destroy the Mesa and driver specific visual data */ void XMesaDestroyVisual(XMesaVisual v) { Xfree(v->gl_visual); @@ -230,91 +144,40 @@ void XMesaDestroyVisual(XMesaVisual v) Xfree(v); } +/* Create and initialize the Mesa and driver specific context data */ XMesaContext XMesaCreateContext(XMesaVisual v, XMesaContext share_list, __DRIcontextPrivate *driContextPriv) { XMesaContext c; - r128ContextPtr r128ctx; - GLcontext *shareCtx, *glCtx; c = (XMesaContext)Xmalloc(sizeof(*c)); if (!c) { return NULL; } - r128ctx = (r128ContextPtr)Xmalloc(sizeof(*r128ctx)); - if (!r128ctx) { - Xfree(c); - return NULL; - } - /* Initialize XMesaContext */ c->display = v->display; c->xm_visual = v; c->xm_buffer = NULL; /* Set by MakeCurrent */ c->driContextPriv = driContextPriv; - c->private = (void *)r128ctx; - - if (share_list) - shareCtx = ((r128ContextPtr)(share_list->private))->glCtx; - else - shareCtx = NULL; - - /* Initialize r128Context */ - r128ctx->xmCtx = c; - r128ctx->glCtx = gl_create_context(v->gl_visual, - shareCtx, - (void *)r128ctx, - GL_TRUE); - r128ctx->display = v->display; - r128ctx->driContext = driContextPriv; - r128ctx->driDrawable = NULL; /* Set by XMesaMakeCurrent */ - r128ctx->dirty = R128_ALL_DIRTY; - r128ctx->needClip = GL_TRUE; - r128ctx->r128Screen = - (r128ScreenPtr)(driContextPriv->driScreenPriv->private); - - /* Initialize GLcontext */ - glCtx = r128ctx->glCtx; - - r128DDInitExtensions(glCtx); - - r128DDInitDriverFuncs(glCtx); - r128DDInitStateFuncs(glCtx); - r128DDInitSpanFuncs(glCtx); - r128DDInitDepthFuncs(glCtx); - r128DDInitTextureFuncs(glCtx); - -#if 1 - /* FIXME: Move to r128_tris.c */ - glCtx->Driver.TriangleCaps = (DD_TRI_CULL - | DD_TRI_LIGHT_TWOSIDE - | DD_TRI_OFFSET); - glCtx->TriangleCaps |= DD_CLIP_FOG_COORD; - - if (glCtx->VB) r128DDRegisterVB(glCtx->VB); -#endif - - r128DDInitState(r128ctx); + c->private = (void *)r128CreateContext(v->gl_visual, c, share_list); + if (!c->private) { + Xfree(c); + return NULL; + } return c; } +/* Destroy the Mesa and driver specific context data */ void XMesaDestroyContext(XMesaContext c) { - r128ContextPtr r128ctx = (r128ContextPtr)c->private; - - if (r128ctx) { - gl_destroy_context(r128ctx->glCtx); - Xfree(r128ctx); - c->private = NULL; - } - - if (c->private == (void *)r128Context) { - r128Context = NULL; - } + if (c->private == (void *)r128Context) r128Context = NULL; + r128DestroyContext((r128ContextPtr)c->private); + Xfree(c); } +/* Create and initialize the Mesa and driver specific window buffer data */ XMesaBuffer XMesaCreateWindowBuffer(XMesaVisual v, XMesaWindow w, __DRIdrawablePrivate *driDrawPriv) @@ -328,6 +191,7 @@ XMesaBuffer XMesaCreateWindowBuffer(XMesaVisual v, return xm_buf; } +/* Create and initialize the Mesa and driver specific pixmap buffer data */ XMesaBuffer XMesaCreatePixmapBuffer(XMesaVisual v, XMesaPixmap p, XMesaColormap c, @@ -342,12 +206,14 @@ XMesaBuffer XMesaCreatePixmapBuffer(XMesaVisual v, return xm_buf; } +/* Destroy the Mesa and driver specific color buffer data */ void XMesaDestroyBuffer(XMesaBuffer b) { gl_destroy_framebuffer(b->gl_buffer); Xfree(b); } +/* Copy the back color buffer to the front color buffer */ void XMesaSwapBuffers(XMesaBuffer b) { /* @@ -356,36 +222,29 @@ void XMesaSwapBuffers(XMesaBuffer b) */ if (r128Context == NULL) return; + /* FIXME: Only swap buffers when a back buffer exists */ + + FLUSH_VB(R128_MESACTX(r128Context), "swap buffers"); r128SwapBuffers(r128Context); } +/* Force the context `c' to be the current context and associate with it + buffer `b' */ GLboolean XMesaMakeCurrent(XMesaContext c, XMesaBuffer b) { if (c) { - r128ContextPtr oldCtx = r128Context; - - if (r128Context - && c->private == (void *)r128Context - && b->driDrawPriv == r128Context->driDrawable) return GL_TRUE; - - r128Context = (r128ContextPtr)c->private; - - if (oldCtx) { - r128Context->dirty = R128_REQUIRE_QUIESCENCE | R128_START_CCE; - if (oldCtx != r128Context) - r128Context->dirty |= R128_UPDATE_CONTEXT; - if (oldCtx->driDrawable != b->driDrawPriv) - r128Context->dirty |= R128_UPDATE_CLIPRECTS; - } else { - r128Context->dirty = R128_ALL_DIRTY; - } + if (r128Context && + c->private == (void *)r128Context && + b->driDrawPriv == R128_DRIDRAWABLE(r128Context)) + return GL_TRUE; - r128Context->driDrawable = b->driDrawPriv; + r128Context = r128MakeCurrent(r128Context, (r128ContextPtr)c->private, + b->driDrawPriv); - gl_make_current(r128Context->glCtx, b->gl_buffer); + gl_make_current(R128_MESACTX(r128Context), b->gl_buffer); - if (!r128Context->glCtx->Viewport.Width) { - gl_Viewport(r128Context->glCtx, 0, 0, + if (!R128_MESACTX(r128Context)->Viewport.Width) { + gl_Viewport(R128_MESACTX(r128Context), 0, 0, b->driDrawPriv->w, b->driDrawPriv->h); } } else { @@ -396,29 +255,30 @@ GLboolean XMesaMakeCurrent(XMesaContext c, XMesaBuffer b) return GL_TRUE; } +/* Update the hardware state. This is called if another context has + grabbed the hardware lock, which includes the X server. This + function also updates the driver's window state after the X server + moves, resizes or restacks a window -- the change will be reflected + in the drawable position and clip rects. Since the X server grabs + the hardware lock when it changes the window state, this routine will + automatically be called after such a change. */ +/* NOTE: This routine is only called while holding the hardware lock. */ void XMesaUpdateState(XMesaContext c) { - r128ContextPtr r128ctx = (r128ContextPtr)c->private; - __DRIdrawablePrivate *dPriv = r128ctx->driDrawable; - __DRIscreenPrivate *sPriv = r128ctx->r128Screen->driScreen; - int stamp = dPriv->lastStamp; + __DRIscreenPrivate *sPriv = R128_DRISCREEN((r128ContextPtr)c->private); + __DRIdrawablePrivate *dPriv = R128_DRIDRAWABLE((r128ContextPtr)c->private); + int stamp = dPriv->lastStamp; - /* - * The window might have moved, so we might need to get new - * cliprects. - * - * NOTE: This releases and regrabs the hw lock, so all state - * checking must be done *after* this call. - */ - XMESA_VALIDATE_DRAWABLE_INFO(r128ctx->display, sPriv, dPriv); - - r128ctx->dirty |= R128_ALL_DIRTY; /* FIXME: Optimize this!! */ - - if (stamp != dPriv->lastStamp) { /* FIXME??: handle window moves */ - r128ctx->dirty |= R128_UPDATE_CLIPRECTS; - } + /* The window might have moved, so we might need to get new clip + rects. + + NOTE: This releases and regrabs the hw lock to allow the X server + to respond to the DRI protocol request for new drawable info. + Since the hardware state depends on having the latest drawable + clip rects, all state checking must be done _after_ this call. */ + XMESA_VALIDATE_DRAWABLE_INFO(c->display, sPriv, dPriv); - if (r128ctx->dirty) r128UpdateStateLocked(r128ctx); + r128UpdateState((r128ContextPtr)c->private, (stamp != dPriv->lastStamp)); } #endif diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128.h b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128.h index 92e55c85b..71771f42f 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128.h +++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128.h @@ -219,14 +219,30 @@ typedef struct { drmHandle agpHandle; /* Handle from drmAddMap */ unsigned char *AGP; /* Map */ - int CCEMode; - int CCEFifoSize; + Bool CCEInUse; /* CCE is currently active */ + int CCEMode; /* CCE mode that server/clients use */ + int CCEFifoSize; /* Size of the CCE command FIFO */ + /* CCE ring buffer data */ unsigned long ringStart; int ringSize; int ringWrite; unsigned long ringReadOffset; + /* CCE vertex buffer data */ + unsigned long vbStart; + int vbSize; + + /* CCE indirect buffer data */ + unsigned long indStart; + int indSize; + + /* CCE AGP Texture data */ + unsigned long agpTexStart; + int agpTexSize; + int log2AGPTexGran; + + /* DRI screen private data */ int fbX; int fbY; int backX; @@ -236,6 +252,7 @@ typedef struct { int textureX; int textureY; int textureSize; + int log2TexGran; #endif } R128InfoRec, *R128InfoPtr; @@ -256,13 +273,15 @@ extern void R128WaitForVerticalSync(ScrnInfoPtr pScrn); extern Bool R128AccelInit(ScreenPtr pScreen); extern Bool R128CursorInit(ScreenPtr pScreen); +extern int R128MinBits(int val); + #ifdef XF86DRI extern Bool R128DRIScreenInit(ScreenPtr pScreen); extern void R128DRICloseScreen(ScreenPtr pScreen); extern Bool R128DRIFinishScreenInit(ScreenPtr pScreen); extern void R128DRICCEInitRingBuffer(ScrnInfoPtr pScrn); -extern void R128LostContext(ScreenPtr pScreen); -extern void R128SwapContextPrivate(ScreenPtr pScreen); +extern void R128CCEStart(ScrnInfoPtr pScrn); +extern void R128CCEStop(ScrnInfoPtr pScrn); #endif #endif diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_accel.c b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_accel.c index 36a2a1092..4db9ba44e 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_accel.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_accel.c @@ -969,16 +969,20 @@ static void R128EngineInit(ScrnInfoPtr pScrn) R128WaitForIdle(pScrn); } -/* Initialize XAA for supported acceleration and also initialize the - graphics hardware for acceleration. */ -Bool R128AccelInit(ScreenPtr pScreen) +#if 0 +#ifdef XF86DRI + /* FIXME: When direct rendering is enabled, we should use the CCE to + draw 2D commands */ +static void R128CCEAccelInit(ScrnInfoPtr pScrn, XAAInfoRecPtr a) { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - R128InfoPtr info = R128PTR(pScrn); - XAAInfoRecPtr a; +} +#endif +#endif + +static void R128MMIOAccelInit(ScrnInfoPtr pScrn, XAAInfoRecPtr a) +{ + R128InfoPtr info = R128PTR(pScrn); - if (!(a = info->accel = XAACreateInfoRec())) return FALSE; - a->Flags = (PIXMAP_CACHE | OFFSCREEN_PIXMAPS | LINEAR_FRAMEBUFFER); @@ -1061,12 +1065,29 @@ Bool R128AccelInit(ScreenPtr pScreen) | SCANLINE_PAD_DWORD | SYNC_AFTER_IMAGE_WRITE); #endif - - R128EngineInit(pScrn); +} + +/* Initialize XAA for supported acceleration and also initialize the + graphics hardware for acceleration. */ +Bool R128AccelInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr info = R128PTR(pScrn); + XAAInfoRecPtr a; + if (!(a = info->accel = XAACreateInfoRec())) return FALSE; + +#if 0 #ifdef XF86DRI - R128DRICCEInitRingBuffer(pScrn); + /* FIXME: When direct rendering is enabled, we should use the CCE to + draw 2D commands */ + if (info->directRenderingEnabled) R128CCEAccelInit(pScrn, a); + else +#endif #endif + R128MMIOAccelInit(pScrn, a); + + R128EngineInit(pScrn); return XAAInit(pScreen, a); } diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.c b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.c index 07d7f1bf3..d14f8c574 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.c @@ -71,9 +71,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xf86DDC.h" /* DRI support */ -#if 0 -#include "GL/glxtokens.h" -#endif #include "GL/glxint.h" #include "xf86drm.h" #include "sarea.h" @@ -81,6 +78,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xf86dri.h" #include "dri.h" #include "r128_dri.h" +#include "r128_sarea.h" #include "r128_dripriv.h" /* Driver data structures */ @@ -100,6 +98,8 @@ do { \ CCEFifoSlots -= entries; \ } while (0) +/* Wait for at least `entries' slots are free. The actual number of + slots available is stored in info->CCEFifoSize. */ static void R128CCEWaitForFifoFunction(ScrnInfoPtr pScrn, int entries) { R128InfoPtr info = R128PTR(pScrn); @@ -115,6 +115,8 @@ static void R128CCEWaitForFifoFunction(ScrnInfoPtr pScrn, int entries) } } +/* Wait until the CCE is completely idle: the FIFO has drained and the + CCE is idle. */ static void R128CCEWaitForIdle(ScrnInfoPtr pScrn) { R128InfoPtr info = R128PTR(pScrn); @@ -135,7 +137,48 @@ static void R128CCEWaitForIdle(ScrnInfoPtr pScrn) } } - /* FIXME: this routine is from tdfx */ +/* Start the CCE, but only if it is not already in use and the requested + mode is a CCE mode. The mode is stored in info->CCEMode. */ +void R128CCEStart(ScrnInfoPtr pScrn) +{ + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + + if (info->CCEInUse || info->CCEMode == R128_PM4_NONPM4) return; + + R128WaitForIdle(pScrn); + OUTREG(R128_PM4_BUFFER_CNTL, info->CCEMode); + (void)INREG(R128_PM4_BUFFER_ADDR); /* as per the sample code */ + OUTREG(R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN); + info->CCEInUse = TRUE; +} + +/* Stop the CCE, but only if it is in use and the requested mode is not + the non-CCE mode. This function also flushes any outstanding + requests before switching modes.*/ +void R128CCEStop(ScrnInfoPtr pScrn) +{ + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + + if (!info->CCEInUse || info->CCEMode == R128_PM4_NONPM4) return; + + R128CCEWaitForIdle(pScrn); +#if 0 + /* FIXME: This is needed when we use the ring buffer to flush any + unfinished commands */ + OUTREGP(R128_PM4_BUFFER_DL_WPTR, + R128_PM4_BUFFER_DL_DONE, ~R128_PM4_BUFFER_DL_DONE); +#endif + OUTREG(R128_PM4_MICRO_CNTL, 0); + OUTREG(R128_PM4_BUFFER_CNTL, R128_PM4_NONPM4); + info->CCEInUse = FALSE; +} + +/* Initialize the visual configs that are supported by the hardware. + These are combined with the visual configs that the indirect + rendering core supports, and the intersection is exported to the + client. */ static Bool R128InitVisualConfigs(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; @@ -146,17 +189,15 @@ static Bool R128InitVisualConfigs(ScreenPtr pScreen) R128ConfigPrivPtr *pR128ConfigPtrs = 0; int i; - switch (pScrn->bitsPerPixel) { - case 8: + switch (pR128->pixel_code) { + case 8: /* 8bpp mode is not support */ + case 15: /* FIXME */ + case 24: /* FIXME */ + return FALSE; + case 16: - case 24: - break; case 32: -#if 0 numConfigs = 4; -#else - numConfigs = 1; -#endif if (!(pConfigs = (__GLXvisualConfig*)xnfcalloc(sizeof(__GLXvisualConfig), @@ -177,45 +218,55 @@ static Bool R128InitVisualConfigs(ScreenPtr pScreen) return FALSE; } - for (i = 0; i < numConfigs; i++) pR128ConfigPtrs[i] = &pR128Configs[i]; - - pConfigs[0].vid = -1; - pConfigs[0].class = -1; - pConfigs[0].rgba = TRUE; - if (pScrn->depth == 16) { - pConfigs[0].redSize = 5; - pConfigs[0].greenSize = 6; - pConfigs[0].blueSize = 5; - pConfigs[0].redMask = 0x0000F800; - pConfigs[0].greenMask = 0x000007E0; - pConfigs[0].blueMask = 0x0000001F; - } else { - pConfigs[0].redSize = 8; - pConfigs[0].greenSize = 8; - pConfigs[0].blueSize = 8; - pConfigs[0].redMask = 0x00FF0000; - pConfigs[0].greenMask = 0x0000FF00; - pConfigs[0].blueMask = 0x000000FF; + for (i = 0; i < numConfigs; i++) { + pR128ConfigPtrs[i] = &pR128Configs[i]; + + pConfigs[i].vid = -1; + pConfigs[i].class = -1; + pConfigs[i].rgba = TRUE; + if (pScrn->depth == 16) { + pConfigs[i].redSize = 5; + pConfigs[i].greenSize = 6; + pConfigs[i].blueSize = 5; + pConfigs[i].redMask = 0x0000F800; + pConfigs[i].greenMask = 0x000007E0; + pConfigs[i].blueMask = 0x0000001F; + } else { + pConfigs[i].redSize = 8; + pConfigs[i].greenSize = 8; + pConfigs[i].blueSize = 8; + pConfigs[i].redMask = 0x00FF0000; + pConfigs[i].greenMask = 0x0000FF00; + pConfigs[i].blueMask = 0x000000FF; + } + pConfigs[i].alphaMask = 0; + pConfigs[i].accumRedSize = 0; + pConfigs[i].accumGreenSize = 0; + pConfigs[i].accumBlueSize = 0; + pConfigs[i].accumAlphaSize = 0; + pConfigs[i].doubleBuffer = TRUE; + pConfigs[i].stereo = FALSE; + pConfigs[i].bufferSize = pScrn->depth; + pConfigs[i].depthSize = 16; /* FIXME: Support other depth */ + pConfigs[i].stencilSize = 0; /* buffer depths with the new */ + pConfigs[i].auxBuffers = 0; /* Mesa code. */ + pConfigs[i].level = 0; + pConfigs[i].visualRating = 0; + pConfigs[i].transparentPixel = 0; + pConfigs[i].transparentRed = 0; + pConfigs[i].transparentGreen = 0; + pConfigs[i].transparentBlue = 0; + pConfigs[i].transparentAlpha = 0; + pConfigs[i].transparentIndex = 0; } - pConfigs[0].alphaMask = 0; - pConfigs[0].accumRedSize = 0; - pConfigs[0].accumGreenSize = 0; - pConfigs[0].accumBlueSize = 0; - pConfigs[0].accumAlphaSize = 0; - pConfigs[0].doubleBuffer = TRUE; - pConfigs[0].stereo = FALSE; - pConfigs[0].bufferSize = pScrn->depth; - pConfigs[0].depthSize = 16; - pConfigs[0].stencilSize = 0; - pConfigs[0].auxBuffers = 0; - pConfigs[0].level = 0; - pConfigs[0].visualRating = 0; - pConfigs[0].transparentPixel = 0; - pConfigs[0].transparentRed = 0; - pConfigs[0].transparentGreen = 0; - pConfigs[0].transparentBlue = 0; - pConfigs[0].transparentAlpha = 0; - pConfigs[0].transparentIndex = 0; + + /* Turn off double buffer support for certain visuals */ + pConfigs[1].doubleBuffer = FALSE; + pConfigs[3].doubleBuffer = FALSE; + + /* Turn off depth buffer support for certain visuals */ + pConfigs[2].depthSize = 0; + pConfigs[3].depthSize = 0; break; } @@ -226,50 +277,83 @@ static Bool R128InitVisualConfigs(ScreenPtr pScreen) return TRUE; } +/* Create the Rage 128-specific context information */ static Bool R128CreateContext(ScreenPtr pScreen, VisualPtr visual, drmContext hwContext, void *pVisualConfigPriv, DRIContextType contextStore) { + /* Nothing yet */ return TRUE; } +/* Destroy the Rage 128-specific context information */ static void R128DestroyContext(ScreenPtr pScreen, drmContext hwContext, DRIContextType contextStore) { + /* Nothing yet */ } -void R128LostContext(ScreenPtr pScreen) +/* Called when the X server is woken up to allow the last client's + context to be saved and the X server's context to be loaded. This is + not necessary for the Rage 128 since the client detects when it's + context is not currently loaded and then load's it itself. Since the + registers to start and stop the CCE are privileged, only the X server + can start/stop the engine. */ +static void R128EnterServer(ScreenPtr pScreen) { + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + +#if 1 + /* FIXME: When the CCE is used for 2D drawing in the X server, we + will not need to stop/start the CCE when entering/leaving the X + server. */ + R128CCEStop(pScrn); +#else + R128CCEWaitForIdle(pScrn); +#endif } -void R128SwapContextPrivate(ScreenPtr pScreen) +/* Called when the X server goes to sleep to allow the X server's + context to be saved and the last client's context to be loaded. This + is not necessary for the Rage 128 since the client detects when it's + context is not currently loaded and then load's it itself. Since the + registers to start and stop the CCE are privileged, only the X server + can start/stop the engine. */ +static void R128LeaveServer(ScreenPtr pScreen) { +#if 1 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - unsigned char *R128MMIO = R128PTR(pScrn)->MMIO; - R128CCEWaitForIdle(pScrn); - OUTREGP(R128_PM4_BUFFER_DL_WPTR, - R128_PM4_BUFFER_DL_DONE, ~R128_PM4_BUFFER_DL_DONE); - OUTREG(R128_PM4_MICRO_CNTL, 0); - OUTREG(R128_PM4_BUFFER_CNTL, R128_PM4_NONPM4); + /* FIXME: When the CCE is used for 2D drawing in the X server, we + will not need to stop/start the CCE when entering/leaving the X + server. */ + R128CCEStart(pScrn); +#endif } +/* Contexts can be swapped by the X server if necessary. This callback + is currently only used to perform any functions necessary when + entering or leaving the X server, and in the future might not be + necessary. */ static void R128DRISwapContext(ScreenPtr pScreen, DRISyncType syncType, DRIContextType oldContextType, void *oldContext, DRIContextType newContextType, void *newContext) { if ((syncType==DRI_3D_SYNC) && (oldContextType==DRI_2D_CONTEXT) && (newContextType==DRI_2D_CONTEXT)) { /* Entering from Wakeup */ - R128SwapContextPrivate(pScreen); + R128EnterServer(pScreen); } if ((syncType==DRI_2D_SYNC) && (oldContextType==DRI_NO_CONTEXT) && (newContextType==DRI_2D_CONTEXT)) { /* Exiting from Block Handler */ - R128LostContext(pScreen); + R128LeaveServer(pScreen); } } +/* Initialize the state of the back and depth buffers. */ static void R128DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index) { +#if 0 + /* FIXME: This routine needs to have acceleration turned on */ ScreenPtr pScreen = pWin->drawable.pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; R128InfoPtr pR128 = R128PTR(pScrn); @@ -277,6 +361,8 @@ static void R128DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index) int nbox; /* FIXME: Copy XAAPaintWindow() and use REGION_TRANSLATE() */ + /* FIXME: Only initialize the back and depth buffers for contexts + that request them */ pbox = REGION_RECTS(prgn); nbox = REGION_NUM_RECTS(prgn); @@ -296,19 +382,28 @@ static void R128DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index) } pR128->accel->NeedToSync = TRUE; +#endif } +/* Copy the back and depth buffers when the X server moves a window. */ static void R128DRIMoveBuffers(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc, CARD32 index) { + /* FIXME: This routine needs to have acceleration turned on */ /* FIXME: Copy XAACopyWindow() and use REGION_TRANSLATE() */ + /* FIXME: Only initialize the back and depth buffers for contexts + that request them */ } +/* Initialize the AGP state. Request memory for use in AGP space, and + initialize the Rage 128 registers to point to that memory. */ static Bool R128DRIAgpInit(R128InfoPtr pR128, ScreenPtr pScreen) { + unsigned char *R128MMIO = pR128->MMIO; unsigned long mode; unsigned int vendor, device; int ret; + unsigned long cntl; if (drmAgpAcquire(pR128->drmFD) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] AGP not available\n"); @@ -319,11 +414,17 @@ static Bool R128DRIAgpInit(R128InfoPtr pR128, ScreenPtr pScreen) not appropriate for this particular combination of graphics card and AGP chipset. */ - + mode = drmAgpGetMode(pR128->drmFD); /* Default mode */ vendor = drmAgpVendorId(pR128->drmFD); device = drmAgpDeviceId(pR128->drmFD); +#if 0 + /* FIXME: This turns off AGP 2X mode */ + /* FIXME: Make this configurable */ + mode &= ~0x00000002; +#endif + xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n", mode, vendor, device, @@ -336,7 +437,8 @@ static Bool R128DRIAgpInit(R128InfoPtr pR128, ScreenPtr pScreen) return FALSE; } - pR128->agpSize = 4 * 1024 * 1024; /* FIXME -- arbitrary */ + /* FIXME: This size was chosen arbitrarily -- make it configurable */ + pR128->agpSize = 8 * 1024 * 1024; if ((ret = drmAgpAlloc(pR128->drmFD, pR128->agpSize, &pR128->agpMemHandle)) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret); @@ -347,7 +449,7 @@ static Bool R128DRIAgpInit(R128InfoPtr pR128, ScreenPtr pScreen) "[agp] %d kB allocated with handle 0x%08x\n", pR128->agpSize / 1024, pR128->agpMemHandle); - pR128->agpOffset = 0; /* FIXME -- arbitrary */ + pR128->agpOffset = 0; if (drmAgpBind(pR128->drmFD, pR128->agpMemHandle, pR128->agpOffset) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not bind\n"); drmAgpFree(pR128->drmFD, pR128->agpMemHandle); @@ -375,9 +477,35 @@ static Bool R128DRIAgpInit(R128InfoPtr pR128, ScreenPtr pScreen) "[agp] Aperture mapped at 0x%08lx\n", (unsigned long)pR128->AGP); + /* Initialize Rage 128's AGP registers */ + cntl = INREG(R128_AGP_CNTL); + cntl &= ~R128_AGP_APER_SIZE_MASK; + switch (pR128->agpSize) { + case 256*1024*1024: cntl |= R128_AGP_APER_SIZE_256MB; break; + case 128*1024*1024: cntl |= R128_AGP_APER_SIZE_128MB; break; + case 64*1024*1024: cntl |= R128_AGP_APER_SIZE_64MB; break; + case 32*1024*1024: cntl |= R128_AGP_APER_SIZE_32MB; break; + case 16*1024*1024: cntl |= R128_AGP_APER_SIZE_16MB; break; + case 8*1024*1024: cntl |= R128_AGP_APER_SIZE_8MB; break; + case 4*1024*1024: cntl |= R128_AGP_APER_SIZE_4MB; break; + default: + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[agp] Illegal aperture size %d kB\n", + pR128->agpSize / 1024); + drmUnmap(pR128->AGP, pR128->agpSize); + pR128->AGP = NULL; + drmAgpFree(pR128->drmFD, pR128->agpMemHandle); + drmAgpRelease(pR128->drmFD); + return FALSE; + } + OUTREG(R128_AGP_BASE, pR128->agpHandle); + OUTREG(R128_AGP_CNTL, cntl); + return TRUE; } +/* Add a map for the MMIO registers that will be accessed by any + DRI-based clients. */ static Bool R128DRIMapInit(R128InfoPtr pR128, ScreenPtr pScreen) { /* Map registers */ @@ -392,12 +520,13 @@ static Bool R128DRIMapInit(R128InfoPtr pR128, ScreenPtr pScreen) return TRUE; } +/* Load the microcode for the CCE */ static void R128DRILoadMicrocode(ScrnInfoPtr pScrn) { unsigned char *R128MMIO = R128PTR(pScrn)->MMIO; int i; unsigned long R128Microcode[] = { - /* Tedz Special Microcode */ + /* CCE microcode (from ATI) */ 0, 276838400, 0, 268449792, 2, 142, 2, 145, 0, 1076765731, 0, 1617039951, 0, 774592877, 0, 1987540286, 0, 2307490946U, 0, 599558925, 0, 589505315, 0, 596487092, 0, 589505315, 1, 11544576, 1, 206848, 1, 311296, 1, 198656, 2, @@ -444,26 +573,78 @@ static void R128DRILoadMicrocode(ScrnInfoPtr pScrn) } } +/* Initialize the CCE state, and reserve space in AGP memory for the + ring, vertex, indirect buffers (if used by the current CCEMode. + Allow the rest of AGP memory to be used for textures. */ static void R128DRICCEInit(ScrnInfoPtr pScrn) { - R128InfoPtr info = R128PTR(pScrn); + R128InfoPtr info = R128PTR(pScrn); + int s, l; + +/* FIXME: These sizes ware chosen arbitrarily -- make them configurable */ +/* NOTE: These must be page aligned */ +#define RING_SIZE 1*1024*1024 +#define VERTBUF_SIZE 1*1024*1024 +#define INDBUF_SIZE 1*1024*1024 + + /* FIXME: Currently, the ring, vertex and indirect buffers all take + space, even when the CCEMode does not use them. Make the use of + AGP space configurable by only reserving space for the buffers + that are required for the current CCEMode. */ /* Initialize the CCE ring buffer data */ info->ringStart = 0; - info->ringSize = 8192; /* FIXME */ + info->ringSize = RING_SIZE; info->ringWrite = 0; - info->ringReadOffset = 8192; /* FIXME */ - - info->CCEMode = R128_PM4_192_DWORD_CCE_PIO; /* FIXME */ - info->CCEFifoSize = 192; /* FIXME */ + info->ringReadOffset = info->ringStart + info->ringSize + 4096; + + /* Reserve space for the vertex buffer */ + info->vbStart = info->ringReadOffset + 4096; + info->vbSize = VERTBUF_SIZE; + + /* Reserve space for the indirect buffer */ + info->indStart = info->vbStart + info->vbSize; + info->indSize = INDBUF_SIZE; + + /* Reserve the rest for AGP textures */ + info->agpTexStart = info->indStart + info->indSize; + s = (info->agpSize - info->agpTexStart); + l = R128MinBits((s-1) / R128_NR_TEX_REGIONS); + if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY; + info->agpTexSize = (s >> l) << l; + info->log2AGPTexGran = l; + + /* Initialize the CCE ring buffer FIFO size */ + info->CCEInUse = FALSE; + info->CCEMode = R128_CCE_MODE; + switch (info->CCEMode) { + case R128_PM4_NONPM4: info->CCEFifoSize = 0; break; + case R128_PM4_192PIO: info->CCEFifoSize = 192; break; + case R128_PM4_192BM: info->CCEFifoSize = 192; break; + case R128_PM4_128PIO_64INDBM: info->CCEFifoSize = 128; break; + case R128_PM4_128BM_64INDBM: info->CCEFifoSize = 128; break; + case R128_PM4_64PIO_128INDBM: info->CCEFifoSize = 64; break; + case R128_PM4_64BM_128INDBM: info->CCEFifoSize = 64; break; + case R128_PM4_64PIO_64VCBM_64INDBM: info->CCEFifoSize = 64; break; + case R128_PM4_64BM_64VCBM_64INDBM: info->CCEFifoSize = 64; break; + case R128_PM4_64PIO_64VCPIO_64INDPIO: info->CCEFifoSize = 64; break; + } } +/* Initialize the ring buffer state for use in the X server and any + DRI-based clients. */ void R128DRICCEInitRingBuffer(ScrnInfoPtr pScrn) { R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; unsigned long addr; + /* FIXME: When we use the CCE for the X server, we should move this + function (and the support functions above) to r128_accel.c */ + + /* Initialize CCE data */ + R128DRICCEInit(pScrn); + /* The manual (p. 2) says this address is in "VM space". This means it's an offset from the start of AGP space. */ @@ -476,42 +657,41 @@ void R128DRICCEInitRingBuffer(ScrnInfoPtr pScrn) OUTREG(R128_PM4_BUFFER_DL_RPTR_ADDR, 0x00000000); #else /* DL_RPTR_ADDR is a physical address. - This should probably be in the SAREA. */ + This should be in the SAREA. */ *(volatile long unsigned *)(info->AGP + info->ringReadOffset) = 0; OUTREG(R128_PM4_BUFFER_DL_RPTR_ADDR, (info->agpHandle + info->ringReadOffset)); #endif /* Set watermark control */ -#if 1 - OUTREG(R128_PM4_BUFFER_WM_CNTL, 0x00000000); -#else OUTREG(R128_PM4_BUFFER_WM_CNTL, ((R128_WATERMARK_L/4) << R128_WMA_SHIFT) | ((R128_WATERMARK_M/4) << R128_WMB_SHIFT) | ((R128_WATERMARK_N/4) << R128_WMC_SHIFT) | ((R128_WATERMARK_K/64) << R128_WB_WM_SHIFT)); -#endif -#if 1 addr = INREG(R128_PM4_BUFFER_ADDR); /* Force read. Why? Because it's in the examples... */ -#endif R128CCEWaitForIdle(pScrn); /* Turn on bus mastering */ -#if 1 - OUTREGP(R128_BUS_CNTL, R128_BUS_MASTER_DIS, ~R128_BUS_MASTER_DIS); -#else OUTREGP(R128_BUS_CNTL, 0, ~R128_BUS_MASTER_DIS); -#endif +#if 0 + /* FIXME: If we use the CCE ring buffer for the X server, we need to + start the engine here for the X server. */ +#else /* Make sure the CCE is off for the X server */ OUTREG(R128_PM4_MICRO_CNTL, 0); OUTREG(R128_PM4_BUFFER_CNTL, R128_PM4_NONPM4); +#endif } +/* Initialize the screen-specific data structures for the DRI and the + Rage 128. This is the main entry point to the device-specific + initialization code. It calls device-independent DRI functions to + create the DRI data structures and initialize the DRI state. */ Bool R128DRIScreenInit(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; @@ -519,6 +699,21 @@ Bool R128DRIScreenInit(ScreenPtr pScreen) DRIInfoPtr pDRIInfo; R128DRIPtr pR128DRI; + switch (pR128->pixel_code) { + case 8: + /* These modes are not supported (yet). */ + case 15: + case 24: + return FALSE; + + /* Only 16 and 32 color depths are supports currently. */ + case 16: + case 32: + break; + } + + /* Create the DRI data structure, and fill it in before calling the + DRIScreenInit(). */ if (!(pDRIInfo = DRICreateInfoRec())) return FALSE; pR128->pDRIInfo = pDRIInfo; @@ -614,56 +809,25 @@ Bool R128DRIScreenInit(ScreenPtr pScreen) /* Reset the Graphics Engine */ R128EngineReset(pScrn); - /* Initialize CCE */ - R128DRICCEInit(pScrn); - return TRUE; } -void R128DRICloseScreen(ScreenPtr pScreen) +/* Finish initializing the device-dependent DRI state, and call + DRIFinishScreenInit() to complete the device-independent DRI + initialization. */ +Bool R128DRIFinishScreenInit(ScreenPtr pScreen) { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - R128InfoPtr pR128 = R128PTR(pScrn); - - /* De-allocate all AGP resources */ - if (pR128->AGP) { - drmUnmap(pR128->AGP, pR128->agpSize); - pR128->AGP = NULL; - } - if (pR128->agpMemHandle) { - drmAgpUnbind(pR128->drmFD, pR128->agpMemHandle); - drmAgpFree(pR128->drmFD, pR128->agpMemHandle); - pR128->agpMemHandle = 0; - drmAgpRelease(pR128->drmFD); - } + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr pR128 = R128PTR(pScrn); + R128SAREAPrivPtr pSAREAPriv; + R128DRIPtr pR128DRI; - DRICloseScreen(pScreen); - - if (pR128->pDRIInfo) { - if (pR128->pDRIInfo->devPrivate) { - xfree(pR128->pDRIInfo->devPrivate); - pR128->pDRIInfo->devPrivate = NULL; - } - DRIDestroyInfoRec(pR128->pDRIInfo); - pR128->pDRIInfo = NULL; - } - if (pR128->pVisualConfigs) { - xfree(pR128->pVisualConfigs); - pR128->pVisualConfigs = NULL; - } - if (pR128->pVisualConfigsPriv) { - xfree(pR128->pVisualConfigsPriv); - pR128->pVisualConfigsPriv = NULL; - } -} + pSAREAPriv = (R128SAREAPrivPtr)DRIGetSAREAPrivate(pScreen); + memset(pSAREAPriv, 0, sizeof(*pSAREAPriv)); + R128DRICCEInitRingBuffer(pScrn); + /* FIXME: R128CCEStart(pScrn); */ -Bool R128DRIFinishScreenInit(ScreenPtr pScreen) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - R128InfoPtr pR128 = R128PTR(pScrn); - R128DRIPtr pR128DRI; - pR128->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT; /* pR128->pDRIInfo->driverSwapMethod = DRI_SERVER_SWAP; */ @@ -688,6 +852,7 @@ Bool R128DRIFinishScreenInit(ScreenPtr pScreen) pR128DRI->textureX = pR128->textureX; pR128DRI->textureY = pR128->textureY; pR128DRI->textureSize = pR128->textureSize; + pR128DRI->log2TexGran = pR128->log2TexGran; pR128DRI->CCEMode = pR128->CCEMode; pR128DRI->CCEFifoSize = pR128->CCEFifoSize; @@ -697,7 +862,58 @@ Bool R128DRIFinishScreenInit(ScreenPtr pScreen) pR128DRI->ringWrite = pR128->ringWrite; pR128DRI->ringReadOffset = pR128->ringReadOffset; + pR128DRI->vbStart = pR128->vbStart; + pR128DRI->vbSize = pR128->vbSize; + + pR128DRI->indStart = pR128->indStart; + pR128DRI->indSize = pR128->indSize; + + pR128DRI->agpTexStart = pR128->agpTexStart; + pR128DRI->agpTexSize = pR128->agpTexSize; + pR128DRI->log2AGPTexGran = pR128->log2AGPTexGran; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "0x%08lx %d\n", pR128DRI->registerHandle, pR128DRI->registerSize); return DRIFinishScreenInit(pScreen); } + +/* The screen is being closed, so clean up any state and free any + resources used by the DRI. */ +void R128DRICloseScreen(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + R128InfoPtr pR128 = R128PTR(pScrn); + + /* De-allocate all AGP resources */ + if (pR128->AGP) { + drmUnmap(pR128->AGP, pR128->agpSize); + pR128->AGP = NULL; + } + if (pR128->agpMemHandle) { + drmAgpUnbind(pR128->drmFD, pR128->agpMemHandle); + drmAgpFree(pR128->drmFD, pR128->agpMemHandle); + pR128->agpMemHandle = 0; + drmAgpRelease(pR128->drmFD); + } + + /* De-allocate all DRI resources */ + DRICloseScreen(pScreen); + + /* De-allocate all DRI data structures */ + if (pR128->pDRIInfo) { + if (pR128->pDRIInfo->devPrivate) { + xfree(pR128->pDRIInfo->devPrivate); + pR128->pDRIInfo->devPrivate = NULL; + } + DRIDestroyInfoRec(pR128->pDRIInfo); + pR128->pDRIInfo = NULL; + } + if (pR128->pVisualConfigs) { + xfree(pR128->pVisualConfigs); + pR128->pVisualConfigs = NULL; + } + if (pR128->pVisualConfigsPriv) { + xfree(pR128->pVisualConfigsPriv); + pR128->pVisualConfigsPriv = NULL; + } +} diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.h b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.h index a443c060c..911cde1b5 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.h +++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dri.h @@ -28,8 +28,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* * Authors: - * Rickard E. Faith <faith@precisioninsight.com> * Kevin E. Martin <kevin@precisioninsight.com> + * Rickard E. Faith <faith@precisioninsight.com> * */ @@ -38,36 +38,62 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include <xf86drm.h> +/* The CCE will default to the following mode: */ +#define R128_CCE_MODE R128_PM4_64PIO_64VCBM_64INDBM typedef struct { + /* FIXME: There needs to be two register regions. One to allow + read-only access to the block of non-FIFO'd GUI registers + (0x0000-0x0FFC), and one to allow read/write acces to the block + of FIFO'd GUI registers (0x1000-0x1FFC) */ + + /* MMIO register data */ drmHandle registerHandle; drmSize registerSize; + + /* AGP data */ drmHandle agpHandle; drmSize agpSize; - int deviceID; - int width; - int height; - int depth; - int bpp; + /* DRI screen private data */ + int deviceID; /* PCI device ID */ + int width; /* Width in pixels of display */ + int height; /* Height in scanlines of display */ + int depth; /* Depth of display (8, 15, 16, 24) */ + int bpp; /* Bit depth of display (8, 16, 24, 32) */ - int fbX; + int fbX; /* Start of frame buffer */ int fbY; - int backX; + int backX; /* Start of shared back buffer */ int backY; - int depthX; + int depthX; /* Start of shared depth buffer */ int depthY; - int textureX; + int textureX; /* Start of texture data in frame buffer */ int textureY; int textureSize; + int log2TexGran; - int CCEMode; - int CCEFifoSize; + int CCEMode; /* CCE mode that server/clients use */ + int CCEFifoSize; /* Size of the CCE command FIFO */ + /* CCE ring buffer data */ unsigned long ringStart; int ringSize; int ringWrite; unsigned long ringReadOffset; + + /* CCE vertex buffer data */ + unsigned long vbStart; + int vbSize; + + /* CCE indirect buffer data */ + unsigned long indStart; + int indSize; + + /* CCE AGP Texture data */ + unsigned long agpTexStart; + int agpTexSize; + int log2AGPTexGran; } R128DRIRec, *R128DRIPtr; #endif diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dripriv.h b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dripriv.h index 81c6f2ba8..acec5e269 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dripriv.h +++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_dripriv.h @@ -51,9 +51,4 @@ typedef struct { int dummy; } R128DRIContextRec, *R128DRIContextPtr; -typedef struct { - /* Nothing here yet */ - int dummy; -} R128SAREAPriv; - #endif diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_driver.c b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_driver.c index 944034b1e..df6f0e1e5 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_driver.c +++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_driver.c @@ -109,6 +109,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "dri.h" #include "r128_dri.h" #include "r128_dripriv.h" +#include "r128_sarea.h" #endif /* Driver data structures */ @@ -495,7 +496,7 @@ static void R128Unblank(ScrnInfoPtr pScrn) } /* Compute log base 2 of val. */ -static int R128MinBits(int val) +int R128MinBits(int val) { int bits; @@ -1111,6 +1112,12 @@ static Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, R128TRACE(("R128ScreenInit %x %d\n", pScrn->memPhysBase, pScrn->fbOffset)); +#ifdef XF86DRI + /* Turn off the CCE for now. */ + info->CCEInUse = FALSE; + info->CCEMode = R128_PM4_NONPM4; +#endif + if (!R128MapMem(pScrn)) return FALSE; pScrn->fbOffset = 0; #ifdef XF86DRI @@ -1138,8 +1145,6 @@ static Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, call into the driver's InitGLXVisuals call back. */ info->directRenderingEnabled = R128DRIScreenInit(pScreen); - /* Force the initialization of the context */ - R128LostContext(pScreen); #endif @@ -1288,10 +1293,16 @@ static Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, } #ifdef XF86DRI + /* Allocate frame buffer space for the + shared back and depth buffers as well + as for local textures. */ if (info->directRenderingEnabled) { FBAreaPtr fbarea; + int width_bytes = pScrn->displayWidth * info->pixel_bytes; + int maxy = info->FbMapSize / width_bytes; + int l; - /* Back buffer setup */ + /* Allocate the shared back buffer */ if ((fbarea = xf86AllocateOffscreenArea(pScreen, pScrn->virtualX, pScrn->virtualY, @@ -1309,7 +1320,7 @@ static Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, info->backY = -1; } - /* Depth buffer setup */ + /* Allocate the shared depth buffer */ if ((fbarea = xf86AllocateOffscreenArea(pScreen, pScrn->virtualX, pScrn->virtualY, @@ -1326,6 +1337,53 @@ static Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, info->depthX = -1; info->depthY = -1; } + + /* Allocate local texture space */ + if (((maxy - MemBox.y2 - 1) * width_bytes) > + (pScrn->virtualX * pScrn->virtualY * 2 * info->pixel_bytes)) { + info->textureX = 0; + info->textureY = MemBox.y2 + 1; + info->textureSize = (maxy - MemBox.y2 - 1) * width_bytes; + + l = R128MinBits((info->textureSize-1) / R128_NR_TEX_REGIONS); + if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY; + + info->log2TexGran = l; + info->textureSize = (info->textureSize >> l) << l; + + xf86DrvMsg(scrnIndex, X_INFO, + "Reserved %d kb for textures: (%d,%d)-(%d,%d)\n", + info->textureSize/1024, + info->textureX, info->textureY, + pScrn->displayWidth, maxy); + } else if ((fbarea = xf86AllocateOffscreenArea(pScreen, + pScrn->virtualX, + pScrn->virtualY * 2, + 32, + NULL, NULL, NULL))) { + info->textureX = fbarea->box.x1; + info->textureY = fbarea->box.y1; + info->textureSize = ((fbarea->box.y2 - fbarea->box.y1) * + (fbarea->box.x2 - fbarea->box.x1) * + info->pixel_bytes); + + l = R128MinBits((info->textureSize-1) / R128_NR_TEX_REGIONS); + if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY; + + info->log2TexGran = l; + info->textureSize = (info->textureSize >> l) << l; + + xf86DrvMsg(scrnIndex, X_INFO, + "Reserved %d kb for textures: (%d,%d)-(%d,%d)\n", + info->textureSize/1024, + fbarea->box.x1, fbarea->box.y1, + fbarea->box.x2, fbarea->box.y2); + } else { + xf86DrvMsg(scrnIndex, X_ERROR, + "Unable to reserve texture space in frame buffer\n"); + info->textureX = -1; + info->textureY = -1; + } } #endif /* Hardware cursor setup */ @@ -1375,8 +1433,8 @@ static Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, if (serverGeneration == 1) xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); - /* DRI finalization */ #ifdef XF86DRI + /* DRI finalization */ if (info->directRenderingEnabled) { /* Now that mi, cfb, drm and others have done their thing, complete the DRI @@ -2050,6 +2108,7 @@ static Bool R128CloseScreen(int scrnIndex, ScreenPtr pScreen) R128TRACE(("R128CloseScreen\n")); #ifdef XF86DRI + /* Disable direct rendering */ if (info->directRenderingEnabled) { R128DRICloseScreen(pScreen); info->directRenderingEnabled = FALSE; diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_reg.h b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_reg.h index 50ed5b1d7..64c414a8d 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_reg.h +++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_reg.h @@ -108,6 +108,14 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define R128_AGP_APER_OFFSET 0x0178 #define R128_AGP_BASE 0x0170 #define R128_AGP_CNTL 0x0174 +# define R128_AGP_APER_SIZE_256MB (0x00 << 0) +# define R128_AGP_APER_SIZE_128MB (0x20 << 0) +# define R128_AGP_APER_SIZE_64MB (0x30 << 0) +# define R128_AGP_APER_SIZE_32MB (0x38 << 0) +# define R128_AGP_APER_SIZE_16MB (0x3c << 0) +# define R128_AGP_APER_SIZE_8MB (0x3e << 0) +# define R128_AGP_APER_SIZE_4MB (0x3f << 0) +# define R128_AGP_APER_SIZE_MASK (0x3f << 0) #define R128_AGP_COMMAND 0x0f58 /* PCI */ #define R128_AGP_PLL_CNTL 0x0010 /* PLL */ #define R128_AGP_STATUS 0x0f54 /* PCI */ @@ -556,6 +564,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define R128_PC_GUI_CTLSTAT 0x1748 #define R128_PC_GUI_MODE 0x1744 #define R128_PC_NGUI_CTLSTAT 0x0184 +# define R128_PC_FLUSH_GUI (3 << 0) # define R128_PC_FLUSH_ALL 0x00ff # define R128_PC_BUSY (1 << 31) #define R128_PC_NGUI_MODE 0x0180 @@ -660,9 +669,16 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define R128_PM4_BUFFER_OFFSET 0x0700 #define R128_PM4_BUFFER_CNTL 0x0704 -# define R128_PM4_NONPM4 (0 << 28) -# define R128_PM4_192_DWORD_CCE_PIO (1 << 28) -# define R128_PM4_192_DWORD_CCE_BM (2 << 28) +# define R128_PM4_NONPM4 (0 << 28) +# define R128_PM4_192PIO (1 << 28) +# define R128_PM4_192BM (2 << 28) +# define R128_PM4_128PIO_64INDBM (3 << 28) +# define R128_PM4_128BM_64INDBM (4 << 28) +# define R128_PM4_64PIO_128INDBM (5 << 28) +# define R128_PM4_64BM_128INDBM (6 << 28) +# define R128_PM4_64PIO_64VCBM_64INDBM (7 << 28) +# define R128_PM4_64BM_64VCBM_64INDBM (8 << 28) +# define R128_PM4_64PIO_64VCPIO_64INDPIO (15 << 28) #define R128_PM4_BUFFER_WM_CNTL 0x0708 # define R128_WMA_SHIFT 0 # define R128_WMB_SHIFT 8 @@ -810,6 +826,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R128_WINDOW_Y_SHIFT 4 # define R128_WINDOW_X_SHIFT 20 +#define R128_Z_OFFSET_C 0x1c90 +#define R128_Z_PITCH_C 0x1c94 #define R128_Z_STEN_CNTL_C 0x1c98 # define R128_Z_PIX_WIDTH_16 (0 << 1) # define R128_Z_PIX_WIDTH_24 (1 << 1) @@ -856,7 +874,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R128_STENCIL_ENABLE (1 << 3) # define R128_SHADE_ENABLE (0 << 4) # define R128_TEXMAP_ENABLE (1 << 4) -# define R128_SECONDARY_TEX_ENABLE (1 << 5) +# define R128_SEC_TEXMAP_ENABLE (1 << 5) # define R128_FOG_ENABLE (1 << 7) # define R128_DITHER_ENABLE (1 << 8) # define R128_ALPHA_ENABLE (1 << 9) @@ -918,7 +936,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R128_ALPHA_BLEND_DST_DESTCOLOR (8 << 20) # define R128_ALPHA_BLEND_DST_INVDESTCOLOR (9 << 20) # define R128_ALPHA_BLEND_DST_SRCALPHASAT (10 << 20) -# define R128_ALPHA_BLEND_DST_MASK (15 << 16) +# define R128_ALPHA_BLEND_DST_MASK (15 << 20) # define R128_ALPHA_TEST_NEVER (0 << 24) # define R128_ALPHA_TEST_LESS (1 << 24) # define R128_ALPHA_TEST_LESSEQUAL (2 << 24) @@ -941,18 +959,22 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R128_MIN_BLEND_MIPLINEAR (3 << 1) # define R128_MIN_BLEND_LINEARMIPNEAREST (4 << 1) # define R128_MIN_BLEND_LINEARMIPLINEAR (5 << 1) +# define R128_MIN_BLEND_MASK (7 << 1) # define R128_MAG_BLEND_NEAREST (0 << 4) # define R128_MAG_BLEND_LINEAR (1 << 4) +# define R128_MAG_BLEND_MASK (7 << 4) # define R128_MIP_MAP_DISABLE (1 << 7) # define R128_TEX_CLAMP_S_WRAP (0 << 8) # define R128_TEX_CLAMP_S_MIRROR (1 << 8) # define R128_TEX_CLAMP_S_CLAMP (2 << 8) # define R128_TEX_CLAMP_S_BORDER_COLOR (3 << 8) +# define R128_TEX_CLAMP_S_MASK (3 << 8) # define R128_TEX_WRAP_S (1 << 10) # define R128_TEX_CLAMP_T_WRAP (0 << 11) # define R128_TEX_CLAMP_T_MIRROR (1 << 11) # define R128_TEX_CLAMP_T_CLAMP (2 << 11) # define R128_TEX_CLAMP_T_BORDER_COLOR (3 << 11) +# define R128_TEX_CLAMP_T_MASK (3 << 11) # define R128_TEX_WRAP_T (1 << 13) # define R128_TEX_PERSPECTIVE_DISABLE (1 << 14) # define R128_DATATYPE_VQ (0 << 16) @@ -968,8 +990,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R128_DATATYPE_CI16 (10 << 16) # define R128_DATATYPE_YUV422 (11 << 16) # define R128_DATATYPE_YUV422_2 (12 << 16) -# define R128_DATATYPE_AYUV444 (13 << 16) -# define R128_DATATYPE_ARGB4444 (14 << 16) +# define R128_DATATYPE_AYUV444 (14 << 16) +# define R128_DATATYPE_ARGB4444 (15 << 16) # define R128_PALLETE_EITHER (0 << 20) # define R128_PALLETE_1 (1 << 20) # define R128_PALLETE_2 (2 << 20) @@ -993,14 +1015,17 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R128_COMB_BLEND_PREMULT_INV (13 << 0) # define R128_COMB_ADD_SIGNED2X (14 << 0) # define R128_COMB_BLEND_CONST_COLOR (15 << 0) +# define R128_COMB_MASK (15 << 0) # define R128_COLOR_FACTOR_TEX (4 << 4) # define R128_COLOR_FACTOR_NTEX (5 << 4) # define R128_COLOR_FACTOR_ALPHA (6 << 4) # define R128_COLOR_FACTOR_NALPHA (7 << 4) +# define R128_COLOR_FACTOR_MASK (15 << 4) # define R128_INPUT_FACTOR_CONST_COLOR (2 << 10) # define R128_INPUT_FACTOR_CONST_ALPHA (3 << 10) # define R128_INPUT_FACTOR_INT_COLOR (4 << 10) # define R128_INPUT_FACTOR_INT_ALPHA (5 << 10) +# define R128_INPUT_FACTOR_MASK (15 << 10) # define R128_COMB_ALPHA_DIS (0 << 14) # define R128_COMB_ALPHA_COPY (1 << 14) # define R128_COMB_ALPHA_COPY_INP (2 << 14) @@ -1010,19 +1035,34 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R128_COMB_ALPHA_ADD (6 << 14) # define R128_COMB_ALPHA_ADD_SIGNED (7 << 14) # define R128_COMB_ALPHA_ADD_SIGNED2X (14 << 14) +# define R128_COMB_ALPHA_MASK (15 << 14) # define R128_ALPHA_FACTOR_TEX_ALPHA (6 << 18) # define R128_ALPHA_FACTOR_NTEX_ALPHA (7 << 18) +# define R128_ALPHA_FACTOR_MASK (15 << 18) # define R128_INP_FACTOR_A_CONST_ALPHA (1 << 25) # define R128_INP_FACTOR_A_INT_ALPHA (2 << 25) +# define R128_INP_FACTOR_A_MASK (7 << 25) #define R128_TEX_SIZE_PITCH_C 0x1cb8 -# define R128_TEX_PITCH_SHIFT 0 -# define R128_TEX_SIZE_SHIFT 4 -# define R128_TEX_HEIGHT_SHIFT 8 -# define R128_TEX_MIN_SIZE_SHIFT 12 -# define R128_SEC_TEX_PITCH_SHIFT 16 -# define R128_SEC_TEX_SIZE_SHIFT 20 -# define R128_SEC_TEX_HEIGHT_SHIFT 24 -# define R128_SEC_TEX_MIN_SIZE_SHIFT 28 +# define R128_TEX_PITCH_SHIFT 0 +# define R128_TEX_SIZE_SHIFT 4 +# define R128_TEX_HEIGHT_SHIFT 8 +# define R128_TEX_MIN_SIZE_SHIFT 12 +# define R128_SEC_TEX_PITCH_SHIFT 16 +# define R128_SEC_TEX_SIZE_SHIFT 20 +# define R128_SEC_TEX_HEIGHT_SHIFT 24 +# define R128_SEC_TEX_MIN_SIZE_SHIFT 28 +# define R128_TEX_PITCH_MASK (0x0f << 0) +# define R128_TEX_SIZE_MASK (0x0f << 4) +# define R128_TEX_HEIGHT_MASK (0x0f << 8) +# define R128_TEX_MIN_SIZE_MASK (0x0f << 12) +# define R128_SEC_TEX_PITCH_MASK (0x0f << 16) +# define R128_SEC_TEX_SIZE_MASK (0x0f << 20) +# define R128_SEC_TEX_HEIGHT_MASK (0x0f << 24) +# define R128_SEC_TEX_MIN_SIZE_MASK (0x0f << 28) +# define R128_TEX_SIZE_PITCH_SHIFT 0 +# define R128_SEC_TEX_SIZE_PITCH_SHIFT 16 +# define R128_TEX_SIZE_PITCH_MASK (0xffff << 0) +# define R128_SEC_TEX_SIZE_PITCH_MASK (0xffff << 16) #define R128_PRIM_TEX_0_OFFSET_C 0x1cbc #define R128_PRIM_TEX_1_OFFSET_C 0x1cc0 #define R128_PRIM_TEX_2_OFFSET_C 0x1cc4 diff --git a/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_sarea.h b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_sarea.h new file mode 100644 index 000000000..2b835472e --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/drivers/r128/r128_sarea.h @@ -0,0 +1,69 @@ +/* $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_SAREA_H_ +#define _R128_SAREA_H_ + +/* Each region is a minimum of 64k, and there are at most 128 of them */ +#define R128_NR_TEX_REGIONS 128 +#define R128_LOG_TEX_GRANULARITY 16 + +typedef struct { + unsigned char next, prev; /* indices to form a circular LRU */ + unsigned char in_use; /* owned by a client, or free? */ + int age; /* tracked by clients to update local LRU's */ +} R128TexRegion; + +typedef struct { + /* Maintain an LRU of contiguous regions of texture space. If you + * think you own a region of texture memory, and it has an age + * different to the one you set, then you are mistaken and it has + * been stolen by another client. If global texAge hasn't changed, + * there is no need to walk the list. + * + * These regions can be used as a proxy for the fine-grained texture + * information of other clients - by maintaining them in the same + * lru which is used to age their own textures, clients have an + * approximate lru for the whole of global texture space, and can + * make informed decisions as to which areas to kick out. There is + * no need to choose whether to kick out your own texture or someone + * else's - simply eject them all in LRU order. + */ + R128TexRegion texList[R128_NR_TEX_REGIONS+1]; /* Last elt is sentinal */ + int texAge; /* last time texture was uploaded */ + + int ctxOwner; /* last context to upload state */ +} R128SAREAPriv, *R128SAREAPrivPtr; + +#endif |