diff options
Diffstat (limited to 'src/mesa/drivers/dri/tdfx/tdfx_span.c')
-rw-r--r-- | src/mesa/drivers/dri/tdfx/tdfx_span.c | 1387 |
1 files changed, 1387 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/tdfx/tdfx_span.c b/src/mesa/drivers/dri/tdfx/tdfx_span.c new file mode 100644 index 0000000000..d9d52d2b6f --- /dev/null +++ b/src/mesa/drivers/dri/tdfx/tdfx_span.c @@ -0,0 +1,1387 @@ +/* -*- mode: c; c-basic-offset: 3 -*- + * + * Copyright 2000 VA Linux Systems Inc., Fremont, California. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEMS 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. + */ +/* $XFree86: xc/lib/GL/mesa/src/drv/tdfx/tdfx_span.c,v 1.7 2002/10/30 12:52:00 alanh Exp $ */ + +/* + * Original rewrite: + * Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000 + * + * Authors: + * Gareth Hughes <gareth@valinux.com> + * Brian Paul <brianp@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> + * + */ + +#include "tdfx_context.h" +#include "tdfx_lock.h" +#include "tdfx_span.h" +#include "tdfx_render.h" +#include "swrast/swrast.h" + + +#define DBG 0 + + +#define LOCAL_VARS \ + driRenderbuffer *drb = (driRenderbuffer *) rb; \ + __DRIdrawablePrivate *const dPriv = drb->dPriv; \ + GLuint pitch = drb->backBuffer ? info.strideInBytes \ + : (drb->pitch * drb->cpp); \ + const GLuint bottom = dPriv->h - 1; \ + char *buf = (char *)((char *)info.lfbPtr + \ + (dPriv->x * drb->cpp) + \ + (dPriv->y * pitch)); \ + GLuint p; \ + (void) buf; (void) p; + + +#define Y_FLIP(_y) (bottom - _y) + + +#define HW_WRITE_LOCK() \ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); \ + GrLfbInfo_t info; \ + FLUSH_BATCH( fxMesa ); \ + UNLOCK_HARDWARE( fxMesa ); \ + LOCK_HARDWARE( fxMesa ); \ + info.size = sizeof(GrLfbInfo_t); \ + if (fxMesa->Glide.grLfbLock(GR_LFB_WRITE_ONLY, fxMesa->DrawBuffer, \ + LFB_MODE, GR_ORIGIN_UPPER_LEFT, FXFALSE, \ + &info)) { + +#define HW_WRITE_UNLOCK() \ + fxMesa->Glide.grLfbUnlock( GR_LFB_WRITE_ONLY, fxMesa->DrawBuffer );\ + } + + +#define HW_READ_LOCK() \ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); \ + GrLfbInfo_t info; \ + FLUSH_BATCH( fxMesa ); \ + UNLOCK_HARDWARE( fxMesa ); \ + LOCK_HARDWARE( fxMesa ); \ + info.size = sizeof(GrLfbInfo_t); \ + if ( fxMesa->Glide.grLfbLock( GR_LFB_READ_ONLY, fxMesa->ReadBuffer, \ + LFB_MODE, GR_ORIGIN_UPPER_LEFT, FXFALSE, &info ) ) \ + { + +#define HW_READ_UNLOCK() \ + fxMesa->Glide.grLfbUnlock( GR_LFB_READ_ONLY, fxMesa->ReadBuffer );\ + } + + +#define HW_WRITE_CLIPLOOP() \ + do { \ + int _nc = fxMesa->numClipRects; \ + while (_nc--) { \ + int minx = fxMesa->pClipRects[_nc].x1 - fxMesa->x_offset; \ + int miny = fxMesa->pClipRects[_nc].y1 - fxMesa->y_offset; \ + int maxx = fxMesa->pClipRects[_nc].x2 - fxMesa->x_offset; \ + int maxy = fxMesa->pClipRects[_nc].y2 - fxMesa->y_offset; + +#define HW_READ_CLIPLOOP() \ + do { \ + const __DRIdrawablePrivate *dPriv = fxMesa->driDrawable; \ + drm_clip_rect_t *rect = dPriv->pClipRects; \ + int _nc = dPriv->numClipRects; \ + while (_nc--) { \ + const int minx = rect->x1 - fxMesa->x_offset; \ + const int miny = rect->y1 - fxMesa->y_offset; \ + const int maxx = rect->x2 - fxMesa->x_offset; \ + const int maxy = rect->y2 - fxMesa->y_offset; \ + rect++; + +#define HW_ENDCLIPLOOP() \ + } \ + } while (0) + + + +#define LFB_MODE GR_LFBWRITEMODE_565 + + +/* 16 bit, RGB565 color spanline and pixel functions */ \ + +#undef INIT_MONO_PIXEL +#define INIT_MONO_PIXEL(p, color) \ + p = TDFXPACKCOLOR565( color[0], color[1], color[2] ) + + +#define WRITE_RGBA( _x, _y, r, g, b, a ) \ + *(GLushort *)(buf + _x*2 + _y*pitch) = ((((int)r & 0xf8) << 8) | \ + (((int)g & 0xfc) << 3) | \ + (((int)b & 0xf8) >> 3)) + +#define WRITE_PIXEL( _x, _y, p ) \ + *(GLushort *)(buf + _x*2 + _y*pitch) = p + +#define READ_RGBA( rgba, _x, _y ) \ + do { \ + GLushort p = *(GLushort *)(buf + _x*2 + _y*pitch); \ + rgba[0] = (((p >> 11) & 0x1f) * 255) / 31; \ + rgba[1] = (((p >> 5) & 0x3f) * 255) / 63; \ + rgba[2] = (((p >> 0) & 0x1f) * 255) / 31; \ + rgba[3] = 0xff; \ + } while (0) + +#define TAG(x) tdfx##x##_RGB565 +#define BYTESPERPIXEL 2 +#include "spantmp.h" +#undef BYTESPERPIXEL + + +/* 16 bit, BGR565 color spanline and pixel functions */ \ +#if 0 + +#define WRITE_RGBA( _x, _y, r, g, b, a ) \ + *(GLushort *)(buf + _x*2 + _y*pitch) = ((((int)b & 0xf8) << 8) | \ + (((int)g & 0xfc) << 3) | \ + (((int)r & 0xf8) >> 3)) + +#define WRITE_PIXEL( _x, _y, p ) \ + *(GLushort *)(buf + _x*2 + _y*pitch) = p + +#define READ_RGBA( rgba, _x, _y ) \ + do { \ + GLushort p = *(GLushort *)(buf + _x*2 + _y*pitch); \ + rgba[0] = (p << 3) & 0xf8; \ + rgba[1] = (p >> 3) & 0xfc; \ + rgba[2] = (p >> 8) & 0xf8; \ + rgba[3] = 0xff; \ + } while (0) + +#define TAG(x) tdfx##x##_BGR565 +#define BYTESPERPIXEL 2 +#include "spantmp.h" +#undef BYTESPERPIXEL +#endif + + +#undef LFB_MODE +#define LFB_MODE GR_LFBWRITEMODE_888 + + +/* 24 bit, RGB888 color spanline and pixel functions */ +#undef INIT_MONO_PIXEL +#define INIT_MONO_PIXEL(p, color) \ + p = TDFXPACKCOLOR888( color[0], color[1], color[2] ) + +#define WRITE_RGBA( _x, _y, r, g, b, a ) \ + *(GLuint *)(buf + _x*3 + _y*pitch) = ((b << 0) | \ + (g << 8) | \ + (r << 16)) + +#define WRITE_PIXEL( _x, _y, p ) \ + *(GLuint *)(buf + _x*3 + _y*pitch) = p + +#define READ_RGBA( rgba, _x, _y ) \ +do { \ + GLuint p = *(GLuint *)(buf + _x*3 + _y*pitch); \ + rgba[0] = (p >> 16) & 0xff; \ + rgba[1] = (p >> 8) & 0xff; \ + rgba[2] = (p >> 0) & 0xff; \ + rgba[3] = 0xff; \ +} while (0) + +#define TAG(x) tdfx##x##_RGB888 +#define BYTESPERPIXEL 4 +#include "spantmp.h" +#undef BYTESPERPIXEL + + +#undef LFB_MODE +#define LFB_MODE GR_LFBWRITEMODE_8888 + + +/* 32 bit, ARGB8888 color spanline and pixel functions */ +#undef INIT_MONO_PIXEL +#define INIT_MONO_PIXEL(p, color) \ + p = TDFXPACKCOLOR8888( color[0], color[1], color[2], color[3] ) + +#define WRITE_RGBA( _x, _y, r, g, b, a ) \ + *(GLuint *)(buf + _x*4 + _y*pitch) = ((b << 0) | \ + (g << 8) | \ + (r << 16) | \ + (a << 24) ) + +#define WRITE_PIXEL( _x, _y, p ) \ + *(GLuint *)(buf + _x*4 + _y*pitch) = p + +#define READ_RGBA( rgba, _x, _y ) \ +do { \ + GLuint p = *(GLuint *)(buf + _x*4 + _y*pitch); \ + rgba[0] = (p >> 16) & 0xff; \ + rgba[1] = (p >> 8) & 0xff; \ + rgba[2] = (p >> 0) & 0xff; \ + rgba[3] = (p >> 24) & 0xff; \ +} while (0) + +#define TAG(x) tdfx##x##_ARGB8888 +#define BYTESPERPIXEL 4 +#include "spantmp.h" +#undef BYTESPERPIXEL + + + +/* ================================================================ + * Old span functions below... + */ + + +/* + * Examine the cliprects to generate an array of flags to indicate + * which pixels in a span are visible. Note: (x,y) is a screen + * coordinate. + */ +static void +generate_vismask(const tdfxContextPtr fxMesa, GLint x, GLint y, GLint n, + GLubyte vismask[]) +{ + GLboolean initialized = GL_FALSE; + GLint i, j; + + /* Ensure we clear the visual mask */ + MEMSET(vismask, 0, n); + + /* turn on flags for all visible pixels */ + for (i = 0; i < fxMesa->numClipRects; i++) { + const drm_clip_rect_t *rect = &fxMesa->pClipRects[i]; + + if (y >= rect->y1 && y < rect->y2) { + if (x >= rect->x1 && x + n <= rect->x2) { + /* common case, whole span inside cliprect */ + MEMSET(vismask, 1, n); + return; + } + if (x < rect->x2 && x + n >= rect->x1) { + /* some of the span is inside the rect */ + GLint start, end; + if (!initialized) { + MEMSET(vismask, 0, n); + initialized = GL_TRUE; + } + if (x < rect->x1) + start = rect->x1 - x; + else + start = 0; + if (x + n > rect->x2) + end = rect->x2 - x; + else + end = n; + assert(start >= 0); + assert(end <= n); + for (j = start; j < end; j++) + vismask[j] = 1; + } + } + } +} + +/* + * Examine cliprects and determine if the given screen pixel is visible. + */ +static GLboolean +visible_pixel(const tdfxContextPtr fxMesa, int scrX, int scrY) +{ + int i; + for (i = 0; i < fxMesa->numClipRects; i++) { + const drm_clip_rect_t *rect = &fxMesa->pClipRects[i]; + if (scrX >= rect->x1 && + scrX < rect->x2 && + scrY >= rect->y1 && scrY < rect->y2) return GL_TRUE; + } + return GL_FALSE; +} + + + +/* + * Depth buffer read/write functions. + */ +/* + * To read the frame buffer, we need to lock and unlock it. The + * four macros {READ,WRITE}_FB_SPAN_{LOCK,UNLOCK} + * do this for us. + * + * Note that the lock must be matched with an unlock. These + * macros include a spare curly brace, so they must + * be syntactically matched. + * + * Note, also, that you can't lock a buffer twice with different + * modes. That is to say, you can't lock a buffer in both read + * and write modes. The strideInBytes and LFB pointer will be + * the same with read and write locks, so you can use either. + * o The HW has different state for reads and writes, so + * locking it twice may give screwy results. + * o The DRM won't let you lock twice. It hangs. This is probably + * because of the LOCK_HARDWARE IN THE *_FB_SPAN_LOCK macros, + * and could be eliminated with nonlocking lock routines. But + * what's the point after all. + */ +#define READ_FB_SPAN_LOCK(fxMesa, info, target_buffer) \ + UNLOCK_HARDWARE(fxMesa); \ + LOCK_HARDWARE(fxMesa); \ + (info).size=sizeof(info); \ + if (fxMesa->Glide.grLfbLock(GR_LFB_READ_ONLY, \ + target_buffer, \ + GR_LFBWRITEMODE_ANY, \ + GR_ORIGIN_UPPER_LEFT, \ + FXFALSE, \ + &(info))) { + +#define READ_FB_SPAN_UNLOCK(fxMesa, target_buffer) \ + fxMesa->Glide.grLfbUnlock(GR_LFB_READ_ONLY, target_buffer); \ + } else { \ + fprintf(stderr, "tdfxDriver: Can't get %s (%d) read lock\n", \ + (target_buffer == GR_BUFFER_BACKBUFFER) \ + ? "back buffer" \ + : ((target_buffer == GR_BUFFER_AUXBUFFER) \ + ? "depth buffer" \ + : "unknown buffer"), \ + target_buffer); \ + } + +#define WRITE_FB_SPAN_LOCK(fxMesa, info, target_buffer, write_mode) \ + UNLOCK_HARDWARE(fxMesa); \ + LOCK_HARDWARE(fxMesa); \ + info.size=sizeof(info); \ + if (fxMesa->Glide.grLfbLock(GR_LFB_WRITE_ONLY, \ + target_buffer, \ + write_mode, \ + GR_ORIGIN_UPPER_LEFT, \ + FXFALSE, \ + &info)) { + +#define WRITE_FB_SPAN_UNLOCK(fxMesa, target_buffer) \ + fxMesa->Glide.grLfbUnlock(GR_LFB_WRITE_ONLY, target_buffer); \ + } else { \ + fprintf(stderr, "tdfxDriver: Can't get %s (%d) write lock\n", \ + (target_buffer == GR_BUFFER_BACKBUFFER) \ + ? "back buffer" \ + : ((target_buffer == GR_BUFFER_AUXBUFFER) \ + ? "depth buffer" \ + : "unknown buffer"), \ + target_buffer); \ + } + +/* + * Because the Linear Frame Buffer is not necessarily aligned + * with the depth buffer, we have to do some fiddling + * around to get the right addresses. + * + * Perhaps a picture is in order. The Linear Frame Buffer + * looks like this: + * + * |<----------------------info.strideInBytes------------->| + * |<-----physicalStrideInBytes------->| + * +-----------------------------------+xxxxxxxxxxxxxxxxxxx+ + * | | | + * | Legal Memory | Forbidden Zone | + * | | | + * +-----------------------------------+xxxxxxxxxxxxxxxxxxx+ + * + * You can only reliably read and write legal locations. Reads + * and writes from the Forbidden Zone will return undefined values, + * and may cause segmentation faults. + * + * Now, the depth buffer may not end up in a location such each + * scan line is an LFB line. For example, the depth buffer may + * look like this: + * + * wrapped ordinary. + * +-----------------------------------+xxxxxxxxxxxxxxxxxxx+ + * |0000000000000000000000 | | back + * |1111111111111111111111 | | buffer + * |2222222222222222222222 | | + * |4096b align. padxx00000000000000000| Forbidden Zone | depth + * |0000 11111111111111111| | buffer + * |1111 22222222222222222| | + * |2222 | | + * +-----------------------------------+xxxxxxxxxxxxxxxxxxx+ + * where each number is the scan line number. We know it will + * be aligned on 128 byte boundaries, at least. Aligning this + * on a scanline boundary causes the back and depth buffers to + * thrash in the SST1 cache. (Note that the back buffer is always + * allocated at the beginning of LFB memory, and so it is always + * properly aligned with the LFB stride.) + * + * We call the beginning of the line (which is the rightmost + * part of the depth line in the picture above) the *ordinary* part + * of the scanline, and the end of the line (which is the + * leftmost part, one line below) the *wrapped* part of the scanline. + * a.) We need to know what x value to subtract from the screen + * x coordinate to index into the wrapped part. + * b.) We also need to figure out if we need to read from the ordinary + * part scan line, or from the wrapped part of the scan line. + * + * [ad a] + * The first wrapped x coordinate is that coordinate such that + * depthBufferOffset&(info.strideInBytes) + x*elmentSize {*} + * > physicalStrideInBytes + * where depthBufferOffset is the LFB distance in bytes + * from the back buffer to the depth buffer. The expression + * depthBufferOffset&(info.strideInBytes) + * is then the offset (in bytes) from the beginining of (any) + * depth buffer line to first element in the line. + * Simplifying inequation {*} above we see that x is the smallest + * value such that + * x*elementSize > physicalStrideInBytes {**} + * - depthBufferOffset&(info.strideInBytes) + * Now, we know that both the summands on the right are multiples of + * 128, and elementSize <= 4, so if equality holds in {**}, x would + * be a multiple of 32. Thus we can set x to + * xwrapped = (physicalStrideInBytes + * - depthBufferOffset&(info.strideInBytes))/elementSize + * + 1 + * + * [ad b] + * Question b is now simple. We read from the wrapped scan line if + * x is greater than xwrapped. + */ +#define TILE_WIDTH_IN_BYTES 128 +#define TILE_WIDTH_IN_ZOXELS(bpz) (TILE_WIDTH_IN_BYTES/(bpz)) +#define TILE_HEIGHT_IN_LINES 32 +typedef struct +{ + void *lfbPtr; + void *lfbWrapPtr; + FxU32 LFBStrideInElts; + GLint firstWrappedX; +} +LFBParameters; + +/* + * We need information about the back buffer. Note that + * this function *cannot be called* while the aux buffer + * is locked, or the caller will hang. + * + * Only Glide knows the LFB address of the back and depth + * offsets. The upper levels of Mesa know the depth offset, + * but that is not in LFB space, it is tiled memory space, + * and is not useable for us. + */ +static void +GetBackBufferInfo(tdfxContextPtr fxMesa, GrLfbInfo_t * backBufferInfo) +{ + READ_FB_SPAN_LOCK(fxMesa, *backBufferInfo, GR_BUFFER_BACKBUFFER); + READ_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_BACKBUFFER); +} + +static void +GetFbParams(tdfxContextPtr fxMesa, + GrLfbInfo_t * info, + GrLfbInfo_t * backBufferInfo, + LFBParameters * ReadParamsp, FxU32 elementSize) +{ + FxU32 physicalStrideInBytes, bufferOffset; + FxU32 strideInBytes = info->strideInBytes; + char *lfbPtr = (char *) (info->lfbPtr); /* For arithmetic, use char * */ + + /* + * These two come directly from the info structure. + */ + ReadParamsp->lfbPtr = (void *) lfbPtr; + ReadParamsp->LFBStrideInElts = strideInBytes / elementSize; + /* + * Now, calculate the value of firstWrappedX. + * + * The physical stride is the screen width in bytes rounded up to + * the next highest multiple of 128 bytes. Note that this fails + * when TILE_WIDTH_IN_BYTES is not a power of two. + * + * The buffer Offset is the distance between the beginning of + * the LFB space, which is the beginning of the back buffer, + * and the buffer we are gathering information about. + * We want to make this routine usable for operations on the + * back buffer, though we don't actually use it on the back + * buffer. Note, then, that if bufferOffset == 0, the firstWrappedX + * is in the forbidden zone, and is therefore never reached. + * + * Note that if + * physicalStrideInBytes + * < bufferOffset&(info->strideInBytes-1) + * the buffer begins in the forbidden zone. We assert for this. + */ + bufferOffset = (FxU32)(lfbPtr - (char *) backBufferInfo->lfbPtr); + physicalStrideInBytes + = (fxMesa->screen_width * elementSize + TILE_WIDTH_IN_BYTES - 1) + & ~(TILE_WIDTH_IN_BYTES - 1); + assert(physicalStrideInBytes > (bufferOffset & (strideInBytes - 1))); + ReadParamsp->firstWrappedX + = (physicalStrideInBytes + - (bufferOffset & (strideInBytes - 1))) / elementSize; + /* + * This is the address of the next physical line. + */ + ReadParamsp->lfbWrapPtr + = (void *) ((char *) backBufferInfo->lfbPtr + + (bufferOffset & ~(strideInBytes - 1)) + + (TILE_HEIGHT_IN_LINES) * strideInBytes); +} + +/* + * These macros fetch data from the frame buffer. The type is + * the type of data we want to fetch. It should match the type + * whose size was used with GetFbParams to fill in the structure + * in *ReadParamsp. We have a macro to read the ordinary + * part, a second macro to read the wrapped part, and one which + * will do either. When we are reading a span, we will know + * when the ordinary part ends, so there's no need to test for + * it. However, when reading and writing pixels, we don't + * necessarily know. I suppose it's a matter of taste whether + * it's better in the macro or in the call. + * + * Recall that x and y are screen coordinates. + */ +#define GET_ORDINARY_FB_DATA(ReadParamsp, type, x, y) \ + (((type *)((ReadParamsp)->lfbPtr)) \ + [(y) * ((ReadParamsp)->LFBStrideInElts) \ + + (x)]) +#define GET_WRAPPED_FB_DATA(ReadParamsp, type, x, y) \ + (((type *)((ReadParamsp)->lfbWrapPtr)) \ + [((y)) * ((ReadParamsp)->LFBStrideInElts) \ + + ((x) - (ReadParamsp)->firstWrappedX)]) +#define GET_FB_DATA(ReadParamsp, type, x, y) \ + (((x) < (ReadParamsp)->firstWrappedX) \ + ? GET_ORDINARY_FB_DATA(ReadParamsp, type, x, y) \ + : GET_WRAPPED_FB_DATA(ReadParamsp, type, x, y)) +#define PUT_ORDINARY_FB_DATA(ReadParamsp, type, x, y, value) \ + (GET_ORDINARY_FB_DATA(ReadParamsp, type, x, y) = (type)(value)) +#define PUT_WRAPPED_FB_DATA(ReadParamsp, type, x, y, value) \ + (GET_WRAPPED_FB_DATA(ReadParamsp, type, x, y) = (type)(value)) +#define PUT_FB_DATA(ReadParamsp, type, x, y, value) \ + do { \ + if ((x) < (ReadParamsp)->firstWrappedX) \ + PUT_ORDINARY_FB_DATA(ReadParamsp, type, x, y, value); \ + else \ + PUT_WRAPPED_FB_DATA(ReadParamsp, type, x, y, value); \ + } while (0) + + +static void +tdfxDDWriteDepthSpan(GLcontext * ctx, struct gl_renderbuffer *rb, + GLuint n, GLint x, GLint y, const void *values, + const GLubyte mask[]) +{ + const GLuint *depth = (const GLuint *) values; + tdfxContextPtr fxMesa = (tdfxContextPtr) ctx->DriverCtx; + GLint bottom = fxMesa->y_offset + fxMesa->height - 1; + GLuint depth_size = fxMesa->glCtx->Visual.depthBits; + GLuint stencil_size = fxMesa->glCtx->Visual.stencilBits; + GrLfbInfo_t info; + GLubyte visMask[MAX_WIDTH]; + + if (MESA_VERBOSE & VERBOSE_DRIVER) { + fprintf(stderr, "tdfxmesa: tdfxDDWriteDepthSpan(...)\n"); + } + + assert((depth_size == 16) || (depth_size == 24) || (depth_size == 32)); + /* + * Convert x and y to screen coordinates. + */ + x += fxMesa->x_offset; + y = bottom - y; + if (mask) { + GLint i; + GLushort d16; + GrLfbInfo_t backBufferInfo; + + switch (depth_size) { + case 16: + GetBackBufferInfo(fxMesa, &backBufferInfo); + /* + * Note that the _LOCK macro adds a curly brace, + * and the UNLOCK macro removes it. + */ + WRITE_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER, + GR_LFBWRITEMODE_ANY); + generate_vismask(fxMesa, x, y, n, visMask); + { + LFBParameters ReadParams; + int wrappedPartStart; + GetFbParams(fxMesa, &info, &backBufferInfo, + &ReadParams, sizeof(GLushort)); + if (ReadParams.firstWrappedX <= x) { + wrappedPartStart = 0; + } + else if (n <= (ReadParams.firstWrappedX - x)) { + wrappedPartStart = n; + } + else { + wrappedPartStart = (ReadParams.firstWrappedX - x); + } + for (i = 0; i < wrappedPartStart; i++) { + if (mask[i] && visMask[i]) { + d16 = depth[i]; + PUT_ORDINARY_FB_DATA(&ReadParams, GLushort, x + i, y, d16); + } + } + for (; i < n; i++) { + if (mask[i] && visMask[i]) { + d16 = depth[i]; + PUT_WRAPPED_FB_DATA(&ReadParams, GLushort, x + i, y, d16); + } + } + } + WRITE_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER); + break; + case 24: + case 32: + GetBackBufferInfo(fxMesa, &backBufferInfo); + /* + * Note that the _LOCK macro adds a curly brace, + * and the UNLOCK macro removes it. + */ + WRITE_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER, + GR_LFBWRITEMODE_ANY); + generate_vismask(fxMesa, x, y, n, visMask); + { + LFBParameters ReadParams; + int wrappedPartStart; + GetFbParams(fxMesa, &info, &backBufferInfo, + &ReadParams, sizeof(GLuint)); + if (ReadParams.firstWrappedX <= x) { + wrappedPartStart = 0; + } + else if (n <= (ReadParams.firstWrappedX - x)) { + wrappedPartStart = n; + } + else { + wrappedPartStart = (ReadParams.firstWrappedX - x); + } + for (i = 0; i < wrappedPartStart; i++) { + GLuint d32; + if (mask[i] && visMask[i]) { + if (stencil_size > 0) { + d32 = + GET_ORDINARY_FB_DATA(&ReadParams, GLuint, + x + i, y); + d32 = + (d32 & 0xFF000000) | (depth[i] & 0x00FFFFFF); + } + else { + d32 = depth[i]; + } + PUT_ORDINARY_FB_DATA(&ReadParams, GLuint, x + i, y, d32); + } + } + for (; i < n; i++) { + GLuint d32; + if (mask[i] && visMask[i]) { + if (stencil_size > 0) { + d32 = + GET_WRAPPED_FB_DATA(&ReadParams, GLuint, + x + i, y); + d32 = + (d32 & 0xFF000000) | (depth[i] & 0x00FFFFFF); + } + else { + d32 = depth[i]; + } + PUT_WRAPPED_FB_DATA(&ReadParams, GLuint, x + i, y, d32); + } + } + } + WRITE_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER); + break; + } + } + else { + GLint i; + GLuint d32; + GLushort d16; + GrLfbInfo_t backBufferInfo; + + switch (depth_size) { + case 16: + GetBackBufferInfo(fxMesa, &backBufferInfo); + /* + * Note that the _LOCK macro adds a curly brace, + * and the UNLOCK macro removes it. + */ + WRITE_FB_SPAN_LOCK(fxMesa, info, + GR_BUFFER_AUXBUFFER, GR_LFBWRITEMODE_ANY); + generate_vismask(fxMesa, x, y, n, visMask); + { + LFBParameters ReadParams; + GLuint wrappedPartStart; + GetFbParams(fxMesa, &info, &backBufferInfo, + &ReadParams, sizeof(GLushort)); + if (ReadParams.firstWrappedX <= x) { + wrappedPartStart = 0; + } + else if (n <= (ReadParams.firstWrappedX - x)) { + wrappedPartStart = n; + } + else { + wrappedPartStart = (ReadParams.firstWrappedX - x); + } + for (i = 0; i < wrappedPartStart; i++) { + if (visMask[i]) { + d16 = depth[i]; + PUT_ORDINARY_FB_DATA(&ReadParams, + GLushort, + x + i, y, + d16); + } + } + for (; i < n; i++) { + if (visMask[i]) { + d16 = depth[i]; + PUT_WRAPPED_FB_DATA(&ReadParams, + GLushort, + x + i, y, + d16); + } + } + } + WRITE_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER); + break; + case 24: + case 32: + GetBackBufferInfo(fxMesa, &backBufferInfo); + /* + * Note that the _LOCK macro adds a curly brace, + * and the UNLOCK macro removes it. + */ + WRITE_FB_SPAN_LOCK(fxMesa, info, + GR_BUFFER_AUXBUFFER, GR_LFBWRITEMODE_ANY); + generate_vismask(fxMesa, x, y, n, visMask); + { + LFBParameters ReadParams; + GLuint wrappedPartStart; + + GetFbParams(fxMesa, &info, &backBufferInfo, + &ReadParams, sizeof(GLuint)); + if (ReadParams.firstWrappedX <= x) { + wrappedPartStart = 0; + } + else if (n <= (ReadParams.firstWrappedX - x)) { + wrappedPartStart = n; + } + else { + wrappedPartStart = (ReadParams.firstWrappedX - x); + } + for (i = 0; i < wrappedPartStart; i++) { + if (visMask[i]) { + if (stencil_size > 0) { + d32 = GET_ORDINARY_FB_DATA(&ReadParams, GLuint, x + i, y); + d32 = + (d32 & 0xFF000000) | (depth[i] & 0x00FFFFFF); + } + else { + d32 = depth[i]; + } + PUT_ORDINARY_FB_DATA(&ReadParams, GLuint, x + i, y, d32); + } + } + for (; i < n; i++) { + if (visMask[i]) { + if (stencil_size > 0) { + d32 = GET_WRAPPED_FB_DATA(&ReadParams, GLuint, x + i, y); + d32 = + (d32 & 0xFF000000) | (depth[i] & 0x00FFFFFF); + } + else { + d32 = depth[i]; + } + PUT_WRAPPED_FB_DATA(&ReadParams, GLuint, x + i, y, d32); + } + } + } + WRITE_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER); + break; + } + } +} + +static void +tdfxDDWriteMonoDepthSpan(GLcontext * ctx, struct gl_renderbuffer *rb, + GLuint n, GLint x, GLint y, const void *value, + const GLubyte mask[]) +{ + GLuint depthVal = *((GLuint *) value); + GLuint depths[MAX_WIDTH]; + GLuint i; + for (i = 0; i < n; i++) + depths[i] = depthVal; + tdfxDDWriteDepthSpan(ctx, rb, n, x, y, depths, mask); +} + + +static void +tdfxDDReadDepthSpan(GLcontext * ctx, struct gl_renderbuffer *rb, + GLuint n, GLint x, GLint y, void *values) +{ + GLuint *depth = (GLuint *) values; + tdfxContextPtr fxMesa = (tdfxContextPtr) ctx->DriverCtx; + GLint bottom = fxMesa->height + fxMesa->y_offset - 1; + GLuint i; + GLuint depth_size = fxMesa->glCtx->Visual.depthBits; + GrLfbInfo_t info; + + if (MESA_VERBOSE & VERBOSE_DRIVER) { + fprintf(stderr, "tdfxmesa: tdfxDDReadDepthSpan(...)\n"); + } + + /* + * Convert to screen coordinates. + */ + x += fxMesa->x_offset; + y = bottom - y; + switch (depth_size) { + case 16: + { + LFBParameters ReadParams; + GrLfbInfo_t backBufferInfo; + int wrappedPartStart; + GetBackBufferInfo(fxMesa, &backBufferInfo); + /* + * Note that the _LOCK macro adds a curly brace, + * and the UNLOCK macro removes it. + */ + READ_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER); + GetFbParams(fxMesa, &info, &backBufferInfo, + &ReadParams, sizeof(GLushort)); + if (ReadParams.firstWrappedX <= x) { + wrappedPartStart = 0; + } + else if (n <= (ReadParams.firstWrappedX - x)) { + wrappedPartStart = n; + } + else { + wrappedPartStart = (ReadParams.firstWrappedX - x); + } + /* + * Read the line. + */ + for (i = 0; i < wrappedPartStart; i++) { + depth[i] = + GET_ORDINARY_FB_DATA(&ReadParams, GLushort, x + i, y); + } + for (; i < n; i++) { + depth[i] = GET_WRAPPED_FB_DATA(&ReadParams, GLushort, + x + i, y); + } + READ_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER); + break; + } + case 24: + case 32: + { + LFBParameters ReadParams; + GrLfbInfo_t backBufferInfo; + int wrappedPartStart; + GLuint stencil_size = fxMesa->glCtx->Visual.stencilBits; + GetBackBufferInfo(fxMesa, &backBufferInfo); + /* + * Note that the _LOCK macro adds a curly brace, + * and the UNLOCK macro removes it. + */ + READ_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER); + GetFbParams(fxMesa, &info, &backBufferInfo, + &ReadParams, sizeof(GLuint)); + if (ReadParams.firstWrappedX <= x) { + wrappedPartStart = 0; + } + else if (n <= (ReadParams.firstWrappedX - x)) { + wrappedPartStart = n; + } + else { + wrappedPartStart = (ReadParams.firstWrappedX - x); + } + /* + * Read the line. + */ + for (i = 0; i < wrappedPartStart; i++) { + const GLuint mask = + (stencil_size > 0) ? 0x00FFFFFF : 0xFFFFFFFF; + depth[i] = + GET_ORDINARY_FB_DATA(&ReadParams, GLuint, x + i, y); + depth[i] &= mask; + } + for (; i < n; i++) { + const GLuint mask = + (stencil_size > 0) ? 0x00FFFFFF : 0xFFFFFFFF; + depth[i] = GET_WRAPPED_FB_DATA(&ReadParams, GLuint, x + i, y); + depth[i] &= mask; + } + READ_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER); + break; + } + } +} + + +static void +tdfxDDWriteDepthPixels(GLcontext * ctx, struct gl_renderbuffer *rb, + GLuint n, const GLint x[], const GLint y[], + const void *values, const GLubyte mask[]) +{ + const GLuint *depth = (const GLuint *) values; + tdfxContextPtr fxMesa = (tdfxContextPtr) ctx->DriverCtx; + GLint bottom = fxMesa->height + fxMesa->y_offset - 1; + GLuint i; + GLushort d16; + GLuint d32; + GLuint depth_size = fxMesa->glCtx->Visual.depthBits; + GLuint stencil_size = fxMesa->glCtx->Visual.stencilBits; + GrLfbInfo_t info; + int xpos; + int ypos; + GrLfbInfo_t backBufferInfo; + + if (MESA_VERBOSE & VERBOSE_DRIVER) { + fprintf(stderr, "tdfxmesa: tdfxDDWriteDepthPixels(...)\n"); + } + + switch (depth_size) { + case 16: + GetBackBufferInfo(fxMesa, &backBufferInfo); + /* + * Note that the _LOCK macro adds a curly brace, + * and the UNLOCK macro removes it. + */ + WRITE_FB_SPAN_LOCK(fxMesa, info, + GR_BUFFER_AUXBUFFER, GR_LFBWRITEMODE_ANY); + { + LFBParameters ReadParams; + GetFbParams(fxMesa, &info, &backBufferInfo, + &ReadParams, sizeof(GLushort)); + for (i = 0; i < n; i++) { + if ((!mask || mask[i]) && visible_pixel(fxMesa, x[i], y[i])) { + xpos = x[i] + fxMesa->x_offset; + ypos = bottom - y[i]; + d16 = depth[i]; + PUT_FB_DATA(&ReadParams, GLushort, xpos, ypos, d16); + } + } + } + WRITE_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER); + break; + case 24: + case 32: + GetBackBufferInfo(fxMesa, &backBufferInfo); + /* + * Note that the _LOCK macro adds a curly brace, + * and the UNLOCK macro removes it. + */ + WRITE_FB_SPAN_LOCK(fxMesa, info, + GR_BUFFER_AUXBUFFER, GR_LFBWRITEMODE_ANY); + { + LFBParameters ReadParams; + GetFbParams(fxMesa, &info, &backBufferInfo, + &ReadParams, sizeof(GLuint)); + for (i = 0; i < n; i++) { + if (!mask || mask[i]) { + if (visible_pixel(fxMesa, x[i], y[i])) { + xpos = x[i] + fxMesa->x_offset; + ypos = bottom - y[i]; + if (stencil_size > 0) { + d32 = + GET_FB_DATA(&ReadParams, GLuint, xpos, ypos); + d32 = (d32 & 0xFF000000) | (depth[i] & 0xFFFFFF); + } + else { + d32 = depth[i]; + } + PUT_FB_DATA(&ReadParams, GLuint, xpos, ypos, d32); + } + } + } + } + WRITE_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER); + break; + } +} + + +static void +tdfxDDReadDepthPixels(GLcontext * ctx, struct gl_renderbuffer *rb, GLuint n, + const GLint x[], const GLint y[], void *values) +{ + GLuint *depth = (GLuint *) values; + tdfxContextPtr fxMesa = (tdfxContextPtr) ctx->DriverCtx; + GLint bottom = fxMesa->height + fxMesa->y_offset - 1; + GLuint i; + GLuint depth_size = fxMesa->glCtx->Visual.depthBits; + GLushort d16; + int xpos; + int ypos; + GrLfbInfo_t info; + GLuint stencil_size; + GrLfbInfo_t backBufferInfo; + + if (MESA_VERBOSE & VERBOSE_DRIVER) { + fprintf(stderr, "tdfxmesa: tdfxDDReadDepthPixels(...)\n"); + } + + assert((depth_size == 16) || (depth_size == 24) || (depth_size == 32)); + switch (depth_size) { + case 16: + GetBackBufferInfo(fxMesa, &backBufferInfo); + /* + * Note that the _LOCK macro adds a curly brace, + * and the UNLOCK macro removes it. + */ + READ_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER); + { + LFBParameters ReadParams; + GetFbParams(fxMesa, &info, &backBufferInfo, + &ReadParams, sizeof(GLushort)); + for (i = 0; i < n; i++) { + /* + * Convert to screen coordinates. + */ + xpos = x[i] + fxMesa->x_offset; + ypos = bottom - y[i]; + d16 = GET_FB_DATA(&ReadParams, GLushort, xpos, ypos); + depth[i] = d16; + } + } + READ_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER); + break; + case 24: + case 32: + GetBackBufferInfo(fxMesa, &backBufferInfo); + /* + * Note that the _LOCK macro adds a curly brace, + * and the UNLOCK macro removes it. + */ + READ_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER); + stencil_size = fxMesa->glCtx->Visual.stencilBits; + { + LFBParameters ReadParams; + GetFbParams(fxMesa, &info, &backBufferInfo, + &ReadParams, sizeof(GLuint)); + for (i = 0; i < n; i++) { + GLuint d32; + + /* + * Convert to screen coordinates. + */ + xpos = x[i] + fxMesa->x_offset; + ypos = bottom - y[i]; + d32 = GET_FB_DATA(&ReadParams, GLuint, xpos, ypos); + if (stencil_size > 0) { + d32 &= 0x00FFFFFF; + } + depth[i] = d32; + } + } + READ_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER); + break; + default: + assert(0); + } +} + +/* + * Stencil buffer read/write functions. + */ +#define EXTRACT_S_FROM_ZS(zs) (((zs) >> 24) & 0xFF) +#define EXTRACT_Z_FROM_ZS(zs) ((zs) & 0xffffff) +#define BUILD_ZS(z, s) (((s) << 24) | (z)) + +static void +write_stencil_span(GLcontext * ctx, struct gl_renderbuffer *rb, + GLuint n, GLint x, GLint y, + const void *values, const GLubyte mask[]) +{ + const GLubyte *stencil = (const GLubyte *) values; + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + GrLfbInfo_t info; + GrLfbInfo_t backBufferInfo; + + GetBackBufferInfo(fxMesa, &backBufferInfo); + /* + * Note that the _LOCK macro adds a curly brace, + * and the UNLOCK macro removes it. + */ + WRITE_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER, GR_LFBWRITEMODE_ANY); + { + const GLint winY = fxMesa->y_offset + fxMesa->height - 1; + const GLint winX = fxMesa->x_offset; + const GLint scrX = winX + x; + const GLint scrY = winY - y; + LFBParameters ReadParams; + GLubyte visMask[MAX_WIDTH]; + GLuint i; + int wrappedPartStart; + + GetFbParams(fxMesa, &info, &backBufferInfo, &ReadParams, + sizeof(GLuint)); + if (ReadParams.firstWrappedX <= x) { + wrappedPartStart = 0; + } + else if (n <= (ReadParams.firstWrappedX - x)) { + wrappedPartStart = n; + } + else { + wrappedPartStart = (ReadParams.firstWrappedX - x); + } + generate_vismask(fxMesa, scrX, scrY, n, visMask); + for (i = 0; i < wrappedPartStart; i++) { + if (visMask[i] && (!mask || mask[i])) { + GLuint z = GET_ORDINARY_FB_DATA(&ReadParams, GLuint, + scrX + i, scrY) & 0x00FFFFFF; + z |= (stencil[i] & 0xFF) << 24; + PUT_ORDINARY_FB_DATA(&ReadParams, GLuint, scrX + i, scrY, z); + } + } + for (; i < n; i++) { + if (visMask[i] && (!mask || mask[i])) { + GLuint z = GET_WRAPPED_FB_DATA(&ReadParams, GLuint, + scrX + i, scrY) & 0x00FFFFFF; + z |= (stencil[i] & 0xFF) << 24; + PUT_WRAPPED_FB_DATA(&ReadParams, GLuint, scrX + i, scrY, z); + } + } + } + WRITE_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER); +} + + +static void +write_mono_stencil_span(GLcontext * ctx, struct gl_renderbuffer *rb, + GLuint n, GLint x, GLint y, + const void *value, const GLubyte mask[]) +{ + GLbyte stencilVal = *((GLbyte *) value); + GLbyte stencils[MAX_WIDTH]; + GLuint i; + for (i = 0; i < n; i++) + stencils[i] = stencilVal; + write_stencil_span(ctx, rb, n, x, y, stencils, mask); +} + + +static void +read_stencil_span(GLcontext * ctx, struct gl_renderbuffer *rb, + GLuint n, GLint x, GLint y, + void *values) +{ + GLubyte *stencil = (GLubyte *) values; + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + GrLfbInfo_t info; + GrLfbInfo_t backBufferInfo; + + GetBackBufferInfo(fxMesa, &backBufferInfo); + /* + * Note that the _LOCK macro adds a curly brace, + * and the UNLOCK macro removes it. + */ + READ_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER); + { + const GLint winY = fxMesa->y_offset + fxMesa->height - 1; + const GLint winX = fxMesa->x_offset; + GLuint i; + LFBParameters ReadParams; + int wrappedPartStart; + + /* + * Convert to screen coordinates. + */ + x += winX; + y = winY - y; + GetFbParams(fxMesa, &info, &backBufferInfo, &ReadParams, + sizeof(GLuint)); + if (ReadParams.firstWrappedX <= x) { + wrappedPartStart = 0; + } + else if (n <= (ReadParams.firstWrappedX - x)) { + wrappedPartStart = n; + } + else { + wrappedPartStart = (ReadParams.firstWrappedX - x); + } + for (i = 0; i < wrappedPartStart; i++) { + stencil[i] = (GET_ORDINARY_FB_DATA(&ReadParams, GLuint, + x + i, y) >> 24) & 0xFF; + } + for (; i < n; i++) { + stencil[i] = (GET_WRAPPED_FB_DATA(&ReadParams, GLuint, + x + i, y) >> 24) & 0xFF; + } + } + READ_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER); +} + + +static void +write_stencil_pixels(GLcontext * ctx, struct gl_renderbuffer *rb, + GLuint n, const GLint x[], const GLint y[], + const void *values, const GLubyte mask[]) +{ + const GLubyte *stencil = (const GLubyte *) values; + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + GrLfbInfo_t info; + GrLfbInfo_t backBufferInfo; + + GetBackBufferInfo(fxMesa, &backBufferInfo); + /* + * Note that the _LOCK macro adds a curly brace, + * and the UNLOCK macro removes it. + */ + WRITE_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER, GR_LFBWRITEMODE_ANY); + { + const GLint winY = fxMesa->y_offset + fxMesa->height - 1; + const GLint winX = fxMesa->x_offset; + LFBParameters ReadParams; + GLuint i; + + GetFbParams(fxMesa, &info, &backBufferInfo, &ReadParams, + sizeof(GLuint)); + for (i = 0; i < n; i++) { + const GLint scrX = winX + x[i]; + const GLint scrY = winY - y[i]; + if ((!mask || mask[i]) && visible_pixel(fxMesa, scrX, scrY)) { + GLuint z = + GET_FB_DATA(&ReadParams, GLuint, scrX, scrY) & 0x00FFFFFF; + z |= (stencil[i] & 0xFF) << 24; + PUT_FB_DATA(&ReadParams, GLuint, scrX, scrY, z); + } + } + } + WRITE_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER); +} + + +static void +read_stencil_pixels(GLcontext * ctx, struct gl_renderbuffer *rb, + GLuint n, const GLint x[], const GLint y[], + void *values) +{ + GLubyte *stencil = (GLubyte *) values; + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + GrLfbInfo_t info; + GrLfbInfo_t backBufferInfo; + + GetBackBufferInfo(fxMesa, &backBufferInfo); + /* + * Note that the _LOCK macro adds a curly brace, + * and the UNLOCK macro removes it. + */ + READ_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER); + { + const GLint winY = fxMesa->y_offset + fxMesa->height - 1; + const GLint winX = fxMesa->x_offset; + GLuint i; + LFBParameters ReadParams; + + GetFbParams(fxMesa, &info, &backBufferInfo, &ReadParams, + sizeof(GLuint)); + for (i = 0; i < n; i++) { + const GLint scrX = winX + x[i]; + const GLint scrY = winY - y[i]; + stencil[i] = + (GET_FB_DATA(&ReadParams, GLuint, scrX, scrY) >> 24) & 0xFF; + } + } + READ_FB_SPAN_UNLOCK(fxMesa, GR_BUFFER_AUXBUFFER); +} + +#define VISUAL_EQUALS_RGBA(vis, r, g, b, a) \ + ((vis.redBits == r) && \ + (vis.greenBits == g) && \ + (vis.blueBits == b) && \ + (vis.alphaBits == a)) + + + + +/**********************************************************************/ +/* Locking for swrast */ +/**********************************************************************/ + + +static void tdfxSpanRenderStart( GLcontext *ctx ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + LOCK_HARDWARE(fxMesa); +} + +static void tdfxSpanRenderFinish( GLcontext *ctx ) +{ + tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx); + _swrast_flush( ctx ); + UNLOCK_HARDWARE(fxMesa); +} + +/**********************************************************************/ +/* Initialize swrast device driver */ +/**********************************************************************/ + +void tdfxDDInitSpanFuncs( GLcontext *ctx ) +{ + struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx ); + swdd->SpanRenderStart = tdfxSpanRenderStart; + swdd->SpanRenderFinish = tdfxSpanRenderFinish; +} + + + +/** + * Plug in the Get/Put routines for the given driRenderbuffer. + */ +void +tdfxSetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis) +{ + if (drb->Base.InternalFormat == GL_RGBA) { + if (vis->redBits == 5 && vis->greenBits == 6 && vis->blueBits == 5) { + tdfxInitPointers_RGB565(&drb->Base); + } + else if (vis->redBits == 8 && vis->greenBits == 8 + && vis->blueBits == 8 && vis->alphaBits == 0) { + tdfxInitPointers_RGB888(&drb->Base); + } + else if (vis->redBits == 8 && vis->greenBits == 8 + && vis->blueBits == 8 && vis->alphaBits == 8) { + tdfxInitPointers_ARGB8888(&drb->Base); + } + else { + _mesa_problem(NULL, "problem in tdfxSetSpanFunctions"); + } + } + else if (drb->Base.InternalFormat == GL_DEPTH_COMPONENT16 || + drb->Base.InternalFormat == GL_DEPTH_COMPONENT24) { + drb->Base.GetRow = tdfxDDReadDepthSpan; + drb->Base.GetValues = tdfxDDReadDepthPixels; + drb->Base.PutRow = tdfxDDWriteDepthSpan; + drb->Base.PutMonoRow = tdfxDDWriteMonoDepthSpan; + drb->Base.PutValues = tdfxDDWriteDepthPixels; + drb->Base.PutMonoValues = NULL; + } + else if (drb->Base.InternalFormat == GL_STENCIL_INDEX8_EXT) { + drb->Base.GetRow = read_stencil_span; + drb->Base.GetValues = read_stencil_pixels; + drb->Base.PutRow = write_stencil_span; + drb->Base.PutMonoRow = write_mono_stencil_span; + drb->Base.PutValues = write_stencil_pixels; + drb->Base.PutMonoValues = NULL; + } +} |