#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 \
__DRIdrawablePrivate *dPriv = fxMesa->driDrawable; \
tdfxScreenPrivate *fxPriv = fxMesa->fxScreen; \
GLuint pitch = (fxMesa->glCtx->Color.DrawBuffer == GL_FRONT) \
? (fxMesa->screen_width * BYTESPERPIXEL) : \
(info.strideInBytes); \
GLuint height = fxMesa->height; \
char *buf = (char *)((char *)info.lfbPtr + \
dPriv->x * fxPriv->cpp + \
dPriv->y * pitch); \
GLuint p; \
(void) buf; (void) p;
#define CLIPPIXEL( _x, _y ) ( _x >= minx && _x < maxx && \
_y >= miny && _y < maxy )
#define CLIPSPAN( _x, _y, _n, _x1, _n1, _i ) \
if ( _y < miny || _y >= maxy ) { \
_n1 = 0, _x1 = x; \
} else { \
_n1 = _n; \
_x1 = _x; \
if ( _x1 < minx ) _i += (minx-_x1), n1 -= (minx-_x1), _x1 = minx; \
if ( _x1 + _n1 >= maxx ) n1 -= (_x1 + n1 - maxx); \
}
#define Y_FLIP(_y) (height - _y - 1)
#define HW_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; \
XF86DRIClipRectPtr 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
\
#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
\
#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
#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
#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
static void
generate_vismask(const tdfxContextPtr fxMesa, GLint x, GLint y, GLint n,
GLubyte vismask[])
{
GLboolean initialized = GL_FALSE;
GLint i, j;
MEMSET(vismask, 0, n);
for (i = 0; i < fxMesa->numClipRects; i++) {
const XF86DRIClipRectPtr rect = &fxMesa->pClipRects[i];
if (y >= rect->y1 && y < rect->y2) {
if (x >= rect->x1 && x + n <= rect->x2) {
MEMSET(vismask, 1, n);
return;
}
if (x < rect->x2 && x + n >= rect->x1) {
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;
}
}
}
}
static GLboolean
visible_pixel(const tdfxContextPtr fxMesa, int scrX, int scrY)
{
int i;
for (i = 0; i < fxMesa->numClipRects; i++) {
const XF86DRIClipRectPtr rect = &fxMesa->pClipRects[i];
if (scrX >= rect->x1 &&
scrX < rect->x2 &&
scrY >= rect->y1 && scrY < rect->y2) return GL_TRUE;
}
return GL_FALSE;
}
#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); \
}
#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;
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);
ReadParamsp->lfbPtr = (void *) lfbPtr;
ReadParamsp->LFBStrideInElts = strideInBytes / elementSize;
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;
ReadParamsp->lfbWrapPtr
= (void *) ((char *) backBufferInfo->lfbPtr
+ (bufferOffset & ~(strideInBytes - 1))
+ (TILE_HEIGHT_IN_LINES) * strideInBytes);
}
#define GET_FB_DATA(ReadParamsp, type, x, y) \
(((x) < (ReadParamsp)->firstWrappedX) \
? (((type *)((ReadParamsp)->lfbPtr)) \
[(y) * ((ReadParamsp)->LFBStrideInElts) \
+ (x)]) \
: (((type *)((ReadParamsp)->lfbWrapPtr)) \
[((y)) * ((ReadParamsp)->LFBStrideInElts) \
+ ((x) - (ReadParamsp)->firstWrappedX)]))
#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 PUT_FB_DATA(ReadParamsp, type, x, y, value) \
(GET_FB_DATA(ReadParamsp, type, x, y) = (type)(value))
#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))
static void
tdfxDDWriteDepthSpan(GLcontext * ctx,
GLuint n, GLint x, GLint y, const GLdepth depth[],
const GLubyte mask[])
{
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));
x += fxMesa->x_offset;
y = bottom - y;
if (mask) {
GLint i;
GLushort d16;
GrLfbInfo_t backBufferInfo;
switch (depth_size) {
case 16:
GetBackBufferInfo(fxMesa, &backBufferInfo);
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);
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);
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);
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
tdfxDDReadDepthSpan(GLcontext * ctx,
GLuint n, GLint x, GLint y, GLdepth depth[])
{
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");
}
x += fxMesa->x_offset;
y = bottom - y;
switch (depth_size) {
case 16:
{
LFBParameters ReadParams;
GrLfbInfo_t backBufferInfo;
int wrappedPartStart;
GetBackBufferInfo(fxMesa, &backBufferInfo);
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);
}
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);
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);
}
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,
GLuint n, const GLint x[], const GLint y[],
const GLdepth depth[], const GLubyte mask[])
{
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);
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[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);
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[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, GLuint n,
const GLint x[], const GLint y[], GLdepth depth[])
{
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);
READ_FB_SPAN_LOCK(fxMesa, info, GR_BUFFER_AUXBUFFER);
{
LFBParameters ReadParams;
GetFbParams(fxMesa, &info, &backBufferInfo,
&ReadParams, sizeof(GLushort));
for (i = 0; i < n; i++) {
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);
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;
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);
}
}
#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, GLuint n, GLint x, GLint y,
const GLstencil stencil[], const GLubyte mask[])
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
GrLfbInfo_t info;
GrLfbInfo_t backBufferInfo;
GetBackBufferInfo(fxMesa, &backBufferInfo);
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
read_stencil_span(GLcontext * ctx, GLuint n, GLint x, GLint y,
GLstencil stencil[])
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
GrLfbInfo_t info;
GrLfbInfo_t backBufferInfo;
GetBackBufferInfo(fxMesa, &backBufferInfo);
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;
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, GLuint n,
const GLint x[], const GLint y[],
const GLstencil stencil[], const GLubyte mask[])
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
GrLfbInfo_t info;
GrLfbInfo_t backBufferInfo;
GetBackBufferInfo(fxMesa, &backBufferInfo);
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, GLuint n, const GLint x[],
const GLint y[], GLstencil stencil[])
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
GrLfbInfo_t info;
GrLfbInfo_t backBufferInfo;
GetBackBufferInfo(fxMesa, &backBufferInfo);
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))
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);
}
static void tdfxDDSetBuffer( GLcontext *ctx,
GLframebuffer *buffer, GLuint bufferBit )
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
(void) buffer;
switch ( bufferBit ) {
case FRONT_LEFT_BIT:
fxMesa->DrawBuffer = fxMesa->ReadBuffer = GR_BUFFER_FRONTBUFFER;
break;
case BACK_LEFT_BIT:
fxMesa->DrawBuffer = fxMesa->ReadBuffer = GR_BUFFER_BACKBUFFER;
break;
default:
break;
}
}
void tdfxDDInitSpanFuncs( GLcontext *ctx )
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx );
swdd->SetBuffer = tdfxDDSetBuffer;
if ( VISUAL_EQUALS_RGBA(ctx->Visual, 5, 6, 5, 0) )
{
swdd->WriteRGBASpan = tdfxWriteRGBASpan_RGB565;
swdd->WriteRGBSpan = tdfxWriteRGBSpan_RGB565;
swdd->WriteMonoRGBASpan = tdfxWriteMonoRGBASpan_RGB565;
swdd->WriteRGBAPixels = tdfxWriteRGBAPixels_RGB565;
swdd->WriteMonoRGBAPixels = tdfxWriteMonoRGBAPixels_RGB565;
swdd->ReadRGBASpan = tdfxReadRGBASpan_RGB565;
swdd->ReadRGBAPixels = tdfxReadRGBAPixels_RGB565;
}
else if ( VISUAL_EQUALS_RGBA(ctx->Visual, 8, 8, 8, 0) )
{
swdd->WriteRGBASpan = tdfxWriteRGBASpan_RGB888;
swdd->WriteRGBSpan = tdfxWriteRGBSpan_RGB888;
swdd->WriteMonoRGBASpan = tdfxWriteMonoRGBASpan_RGB888;
swdd->WriteRGBAPixels = tdfxWriteRGBAPixels_RGB888;
swdd->WriteMonoRGBAPixels = tdfxWriteMonoRGBAPixels_RGB888;
swdd->ReadRGBASpan = tdfxReadRGBASpan_RGB888;
swdd->ReadRGBAPixels = tdfxReadRGBAPixels_RGB888;
}
else if ( VISUAL_EQUALS_RGBA(ctx->Visual, 8, 8, 8, 8) )
{
swdd->WriteRGBASpan = tdfxWriteRGBASpan_ARGB8888;
swdd->WriteRGBSpan = tdfxWriteRGBSpan_ARGB8888;
swdd->WriteMonoRGBASpan = tdfxWriteMonoRGBASpan_ARGB8888;
swdd->WriteRGBAPixels = tdfxWriteRGBAPixels_ARGB8888;
swdd->WriteMonoRGBAPixels = tdfxWriteMonoRGBAPixels_ARGB8888;
swdd->ReadRGBAPixels = tdfxReadRGBAPixels_ARGB8888;
swdd->ReadRGBASpan = tdfxReadRGBASpan_ARGB8888;
}
else
{
abort();
}
if ( fxMesa->haveHwStencil ) {
swdd->WriteStencilSpan = write_stencil_span;
swdd->ReadStencilSpan = read_stencil_span;
swdd->WriteStencilPixels = write_stencil_pixels;
swdd->ReadStencilPixels = read_stencil_pixels;
}
swdd->WriteDepthSpan = tdfxDDWriteDepthSpan;
swdd->WriteDepthPixels = tdfxDDWriteDepthPixels;
swdd->ReadDepthSpan = tdfxDDReadDepthSpan;
swdd->ReadDepthPixels = tdfxDDReadDepthPixels;
swdd->WriteCI8Span = NULL;
swdd->WriteCI32Span = NULL;
swdd->WriteMonoCISpan = NULL;
swdd->WriteCI32Pixels = NULL;
swdd->WriteMonoCIPixels = NULL;
swdd->ReadCI32Span = NULL;
swdd->ReadCI32Pixels = NULL;
swdd->SpanRenderStart = tdfxSpanRenderStart;
swdd->SpanRenderFinish = tdfxSpanRenderFinish;
}