diff options
author | kem <kem> | 2000-03-19 07:19:20 +0000 |
---|---|---|
committer | kem <kem> | 2000-03-19 07:19:20 +0000 |
commit | a055d658bfbdc26b86a5ccd899000bcd09b8f7a5 (patch) | |
tree | db39a371f5921a9f5019f1532e5840bf80fffccb | |
parent | e1572cc91ad4cf2cd477a519801b02fe98a26cb7 (diff) |
Preparing for alpha releaseati-4-0-0-20000319ati-4-0-0-branch
- Still need to merge with 4.0
Added texture support
- single and multi-texture
Added both local and AGP texturing
- not yet simultaneously
- local by default, AGP can be enabled at compile time
Added window clipping
- prim rendering, clears, and swap bufs
Added initial hardware vertex buffer support
- only works for a single client (just for testing)
- disabled by default
Added software fallback support when not drawing to front or back color bufs
Added alpha test support
Added more rendering funcs
Added preliminary fast path support
Added code to allocate the ring buffer, vertex buffer pool, index buffer
pool, and space for textures in AGP memory
Added code to allocate local texture memory from the off-screen memory
outside of the hw clip rect range (and thus not managed by the OSMM)
and, if that fails, from the off-screen memory managed by the OSMM
Moved code to start/stop CCE to X server
Fixed hardware state update
Fixed flat shaded color initialization bug
Fixed rhw support
Fixed to only allow 16 and 32bpp color buffer support
- other bit depths possible, but not yet implemented
Fixed depth buffer initialization in 32bpp mode
Fixed CCE initialization
Fixed visual config initialization
Fixed AGP aperture initialization
- vertex buffers and AGP texturing now works
- ring buffer and indirect buffers should also now work
Cleaned up code
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 |