Files
mesa/src/mesa/drivers/glide/fxddspan.c
T
Brian Paul 8ad1076dc2 Another round of glRead/DrawBuffer() clean-ups and simplifications.
Replaced ctx->Color._DriverDrawBuffer with swrast->CurrentBuffer.
Replaced ctx->Pixel._DriverReadBuffer with ctx->Pixel._ReadSrcMask.
swrast->Driver.SetBuffer() takes FRONT/BACK_LEFT/RIGHT_BIT values now.
Added tokens and code for GL_AUX buffers, for completeness.
2002-10-11 17:41:03 +00:00

602 lines
16 KiB
C

/* $Id: fxddspan.c,v 1.21 2002/10/11 17:41:05 brianp Exp $ */
/*
* Mesa 3-D graphics library
* Version: 4.0
*
* Copyright (C) 1999-2001 Brian Paul 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 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
* BRIAN PAUL 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:
* David Bucciarelli
* Brian Paul
* Daryll Strauss
* Keith Whitwell
*/
/* fxdd.c - 3Dfx VooDoo Mesa span and pixel functions */
#ifdef HAVE_CONFIG_H
#include "conf.h"
#endif
#if defined(FX)
#include "fxdrv.h"
#include "swrast/swrast.h"
#ifdef _MSC_VER
#ifdef _WIN32
#pragma warning( disable : 4090 4022 )
/* 4101 : "different 'const' qualifier"
* 4022 : "pointer mistmatch for actual parameter 'n'
*/
#endif
#endif
#if !defined(FXMESA_USE_ARGB)
#define writeRegionClipped(fxm,dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data) \
FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data)
/* KW: Rearranged the args in the call to grLfbWriteRegion().
*/
#define LFB_WRITE_SPAN_MESA(dst_buffer, \
dst_x, \
dst_y, \
src_width, \
src_stride, \
src_data) \
writeRegionClipped(fxMesa, dst_buffer, \
dst_x, \
dst_y, \
GR_LFB_SRC_FMT_8888, \
src_width, \
1, \
src_stride, \
src_data) \
#else /* !defined(FXMESA_USE_RGBA) */
#define writeRegionClipped(fxm,dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data) \
FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data)
#define MESACOLOR_TO_ARGB(c) ( \
( ((unsigned int)(c[ACOMP]))<<24 ) | \
( ((unsigned int)(c[RCOMP]))<<16 ) | \
( ((unsigned int)(c[GCOMP]))<<8 ) | \
( (unsigned int)(c[BCOMP])) )
inline void
LFB_WRITE_SPAN_MESA(GrBuffer_t dst_buffer,
FxU32 dst_x,
FxU32 dst_y,
FxU32 src_width, FxI32 src_stride, void *src_data)
{
/* Covert to ARGB */
GLubyte(*rgba)[4] = src_data;
GLuint argb[MAX_WIDTH];
int i;
for (i = 0; i < src_width; i++) {
argb[i] = MESACOLOR_TO_ARGB(rgba[i]);
}
writeRegionClipped( /*fxMesa, */ NULL, dst_buffer,
dst_x,
dst_y,
GR_LFB_SRC_FMT_8888,
src_width, 1, src_stride, (void *) argb);
}
#endif /* !defined(FXMESA_USE_RGBA) */
/************************************************************************/
/***** Span functions *****/
/************************************************************************/
static void
fxDDWriteRGBASpan(const GLcontext * ctx,
GLuint n, GLint x, GLint y,
const GLubyte rgba[][4], const GLubyte mask[])
{
fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
GLuint i;
GLint bottom = fxMesa->height - 1;
if (MESA_VERBOSE & VERBOSE_DRIVER) {
fprintf(stderr, "fxmesa: fxDDWriteRGBASpan(...)\n");
}
if (mask) {
int span = 0;
for (i = 0; i < n; i++) {
if (mask[i]) {
++span;
}
else {
if (span > 0) {
LFB_WRITE_SPAN_MESA(fxMesa->currentFB, x + i - span,
bottom - y,
/* GR_LFB_SRC_FMT_8888, */ span, /*1, */ 0,
(void *) rgba[i - span]);
span = 0;
}
}
}
if (span > 0)
LFB_WRITE_SPAN_MESA(fxMesa->currentFB, x + n - span, bottom - y,
/* GR_LFB_SRC_FMT_8888, */ span, /*1, */ 0,
(void *) rgba[n - span]);
}
else
LFB_WRITE_SPAN_MESA(fxMesa->currentFB, x, bottom - y, /* GR_LFB_SRC_FMT_8888, */
n, /* 1, */ 0, (void *) rgba);
}
static void
fxDDWriteRGBSpan(const GLcontext * ctx,
GLuint n, GLint x, GLint y,
const GLubyte rgb[][3], const GLubyte mask[])
{
fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
GLuint i;
GLint bottom = fxMesa->height - 1;
GLubyte rgba[MAX_WIDTH][4];
if (MESA_VERBOSE & VERBOSE_DRIVER) {
fprintf(stderr, "fxmesa: fxDDWriteRGBSpan()\n");
}
if (mask) {
int span = 0;
for (i = 0; i < n; i++) {
if (mask[i]) {
rgba[span][RCOMP] = rgb[i][0];
rgba[span][GCOMP] = rgb[i][1];
rgba[span][BCOMP] = rgb[i][2];
rgba[span][ACOMP] = 255;
++span;
}
else {
if (span > 0) {
LFB_WRITE_SPAN_MESA(fxMesa->currentFB, x + i - span,
bottom - y,
/*GR_LFB_SRC_FMT_8888, */ span, /* 1, */ 0,
(void *) rgba);
span = 0;
}
}
}
if (span > 0)
LFB_WRITE_SPAN_MESA(fxMesa->currentFB, x + n - span, bottom - y,
/*GR_LFB_SRC_FMT_8888, */ span, /* 1, */ 0,
(void *) rgba);
}
else {
for (i = 0; i < n; i++) {
rgba[i][RCOMP] = rgb[i][0];
rgba[i][GCOMP] = rgb[i][1];
rgba[i][BCOMP] = rgb[i][2];
rgba[i][ACOMP] = 255;
}
LFB_WRITE_SPAN_MESA(fxMesa->currentFB, x, bottom - y, /* GR_LFB_SRC_FMT_8888, */
n, /* 1, */ 0, (void *) rgba);
}
}
static void
fxDDWriteMonoRGBASpan(const GLcontext * ctx,
GLuint n, GLint x, GLint y,
const GLchan color[4], const GLubyte mask[])
{
fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
GLuint i;
GLint bottom = fxMesa->height - 1;
GLuint data[MAX_WIDTH];
GrColor_t gColor = FXCOLOR4(color);
if (MESA_VERBOSE & VERBOSE_DRIVER) {
fprintf(stderr, "fxmesa: fxDDWriteMonoRGBASpan(...)\n");
}
if (mask) {
int span = 0;
for (i = 0; i < n; i++) {
if (mask[i]) {
data[span] = (GLuint) gColor;
++span;
}
else {
if (span > 0) {
writeRegionClipped(fxMesa, fxMesa->currentFB, x + i - span,
bottom - y, GR_LFB_SRC_FMT_8888, span, 1, 0,
(void *) data);
span = 0;
}
}
}
if (span > 0)
writeRegionClipped(fxMesa, fxMesa->currentFB, x + n - span,
bottom - y, GR_LFB_SRC_FMT_8888, span, 1, 0,
(void *) data);
}
else {
for (i = 0; i < n; i++) {
data[i] = (GLuint) gColor;
}
writeRegionClipped(fxMesa, fxMesa->currentFB, x, bottom - y,
GR_LFB_SRC_FMT_8888, n, 1, 0, (void *) data);
}
}
#if 0
static void
fxDDReadRGBASpan(const GLcontext * ctx,
GLuint n, GLint x, GLint y, GLubyte rgba[][4])
{
fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
GLushort data[MAX_WIDTH];
GLuint i;
GLint bottom = fxMesa->height - 1;
printf("read span %d, %d, %d\n", x, y, n);
if (MESA_VERBOSE & VERBOSE_DRIVER) {
fprintf(stderr, "fxmesa: fxDDReadRGBASpan(...)\n");
}
assert(n < MAX_WIDTH);
FX_grLfbReadRegion(fxMesa->currentFB, x, bottom - y, n, 1, 0, data);
for (i = 0; i < n; i++) {
GLushort pixel = data[i];
rgba[i][RCOMP] = FX_PixelToR[pixel];
rgba[i][GCOMP] = FX_PixelToG[pixel];
rgba[i][BCOMP] = FX_PixelToB[pixel];
rgba[i][ACOMP] = 255;
}
}
#endif
/*
* Read a span of 16-bit RGB pixels. Note, we don't worry about cliprects
* since OpenGL says obscured pixels have undefined values.
*/
static void
read_R5G6B5_span(const GLcontext * ctx,
GLuint n, GLint x, GLint y, GLubyte rgba[][4])
{
fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
GrLfbInfo_t info;
BEGIN_BOARD_LOCK();
if (grLfbLock(GR_LFB_READ_ONLY,
fxMesa->currentFB,
GR_LFBWRITEMODE_ANY, GR_ORIGIN_UPPER_LEFT, FXFALSE, &info)) {
const GLint winX = 0;
const GLint winY = fxMesa->height - 1;
const GLint srcStride = info.strideInBytes / 2; /* stride in GLushorts */
const GLushort *data16 = (const GLushort *) info.lfbPtr
+ (winY - y) * srcStride + (winX + x);
const GLuint *data32 = (const GLuint *) data16;
GLuint i, j;
GLuint extraPixel = (n & 1);
n -= extraPixel;
for (i = j = 0; i < n; i += 2, j++) {
GLuint pixel = data32[j];
GLuint pixel0 = pixel & 0xffff;
GLuint pixel1 = pixel >> 16;
rgba[i][RCOMP] = FX_PixelToR[pixel0];
rgba[i][GCOMP] = FX_PixelToG[pixel0];
rgba[i][BCOMP] = FX_PixelToB[pixel0];
rgba[i][ACOMP] = 255;
rgba[i + 1][RCOMP] = FX_PixelToR[pixel1];
rgba[i + 1][GCOMP] = FX_PixelToG[pixel1];
rgba[i + 1][BCOMP] = FX_PixelToB[pixel1];
rgba[i + 1][ACOMP] = 255;
}
if (extraPixel) {
GLushort pixel = data16[n];
rgba[n][RCOMP] = FX_PixelToR[pixel];
rgba[n][GCOMP] = FX_PixelToG[pixel];
rgba[n][BCOMP] = FX_PixelToB[pixel];
rgba[n][ACOMP] = 255;
}
grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
}
END_BOARD_LOCK();
}
/************************************************************************/
/***** Pixel functions *****/
/************************************************************************/
static void
fxDDWriteRGBAPixels(const GLcontext * ctx,
GLuint n, const GLint x[], const GLint y[],
CONST GLubyte rgba[][4], const GLubyte mask[])
{
fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
GLuint i;
GLint bottom = fxMesa->height - 1;
if (MESA_VERBOSE & VERBOSE_DRIVER) {
fprintf(stderr, "fxmesa: fxDDWriteRGBAPixels(...)\n");
}
for (i = 0; i < n; i++)
if (mask[i])
LFB_WRITE_SPAN_MESA(fxMesa->currentFB, x[i], bottom - y[i],
1, 1, (void *) rgba[i]);
}
static void
fxDDWriteMonoRGBAPixels(const GLcontext * ctx,
GLuint n, const GLint x[], const GLint y[],
const GLchan color[4], const GLubyte mask[])
{
fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
GLuint i;
GLint bottom = fxMesa->height - 1;
GrColor_t gColor = FXCOLOR4(color);
if (MESA_VERBOSE & VERBOSE_DRIVER) {
fprintf(stderr, "fxmesa: fxDDWriteMonoRGBAPixels(...)\n");
}
for (i = 0; i < n; i++)
if (mask[i])
writeRegionClipped(fxMesa, fxMesa->currentFB, x[i], bottom - y[i],
GR_LFB_SRC_FMT_8888, 1, 1, 0, (void *) &gColor);
}
static void
read_R5G6B5_pixels(const GLcontext * ctx,
GLuint n, const GLint x[], const GLint y[],
GLubyte rgba[][4], const GLubyte mask[])
{
fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
GrLfbInfo_t info;
BEGIN_BOARD_LOCK();
if (grLfbLock(GR_LFB_READ_ONLY,
fxMesa->currentFB,
GR_LFBWRITEMODE_ANY, GR_ORIGIN_UPPER_LEFT, FXFALSE, &info)) {
const GLint srcStride = info.strideInBytes / 2; /* stride in GLushorts */
const GLint winX = 0;
const GLint winY = fxMesa->height - 1;
GLuint i;
for (i = 0; i < n; i++) {
if (mask[i]) {
const GLushort *data16 = (const GLushort *) info.lfbPtr
+ (winY - y[i]) * srcStride + (winX + x[i]);
const GLushort pixel = *data16;
rgba[i][RCOMP] = FX_PixelToR[pixel];
rgba[i][GCOMP] = FX_PixelToG[pixel];
rgba[i][BCOMP] = FX_PixelToB[pixel];
rgba[i][ACOMP] = 255;
}
}
grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->currentFB);
}
END_BOARD_LOCK();
}
/************************************************************************/
/***** Depth functions *****/
/************************************************************************/
void
fxDDWriteDepthSpan(GLcontext * ctx,
GLuint n, GLint x, GLint y, const GLdepth depth[],
const GLubyte mask[])
{
fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
GLint bottom = fxMesa->height - 1;
if (MESA_VERBOSE & VERBOSE_DRIVER) {
fprintf(stderr, "fxmesa: fxDDWriteDepthSpan(...)\n");
}
if (mask) {
GLint i;
for (i = 0; i < n; i++) {
if (mask[i]) {
GLshort d = depth[i];
writeRegionClipped(fxMesa, GR_BUFFER_AUXBUFFER, x + i, bottom - y,
GR_LFB_SRC_FMT_ZA16, 1, 1, 0, (void *) &d);
}
}
}
else {
GLushort depth16[MAX_WIDTH];
GLint i;
for (i = 0; i < n; i++) {
depth16[i] = depth[i];
}
writeRegionClipped(fxMesa, GR_BUFFER_AUXBUFFER, x, bottom - y,
GR_LFB_SRC_FMT_ZA16, n, 1, 0, (void *) depth16);
}
}
void
fxDDReadDepthSpan(GLcontext * ctx,
GLuint n, GLint x, GLint y, GLdepth depth[])
{
fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
GLint bottom = fxMesa->height - 1;
GLushort depth16[MAX_WIDTH];
GLuint i;
if (MESA_VERBOSE & VERBOSE_DRIVER) {
fprintf(stderr, "fxmesa: fxDDReadDepthSpan(...)\n");
}
FX_grLfbReadRegion(GR_BUFFER_AUXBUFFER, x, bottom - y, n, 1, 0, depth16);
for (i = 0; i < n; i++) {
depth[i] = depth16[i];
}
}
void
fxDDWriteDepthPixels(GLcontext * ctx,
GLuint n, const GLint x[], const GLint y[],
const GLdepth depth[], const GLubyte mask[])
{
fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
GLint bottom = fxMesa->height - 1;
GLuint i;
if (MESA_VERBOSE & VERBOSE_DRIVER) {
fprintf(stderr, "fxmesa: fxDDWriteDepthPixels(...)\n");
}
for (i = 0; i < n; i++) {
if (mask[i]) {
int xpos = x[i];
int ypos = bottom - y[i];
GLushort d = depth[i];
writeRegionClipped(fxMesa, GR_BUFFER_AUXBUFFER, xpos, ypos,
GR_LFB_SRC_FMT_ZA16, 1, 1, 0, (void *) &d);
}
}
}
void
fxDDReadDepthPixels(GLcontext * ctx, GLuint n,
const GLint x[], const GLint y[], GLdepth depth[])
{
fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
GLint bottom = fxMesa->height - 1;
GLuint i;
if (MESA_VERBOSE & VERBOSE_DRIVER) {
fprintf(stderr, "fxmesa: fxDDReadDepthPixels(...)\n");
}
for (i = 0; i < n; i++) {
int xpos = x[i];
int ypos = bottom - y[i];
GLushort d;
FX_grLfbReadRegion(GR_BUFFER_AUXBUFFER, xpos, ypos, 1, 1, 0, &d);
depth[i] = d;
}
}
/* Set the buffer used for reading */
/* XXX support for separate read/draw buffers hasn't been tested */
static void
fxDDSetBuffer(GLcontext * ctx, GLframebuffer * buffer, GLuint bufferBit)
{
fxMesaContext fxMesa = (fxMesaContext) ctx->DriverCtx;
(void) buffer;
if (MESA_VERBOSE & VERBOSE_DRIVER) {
fprintf(stderr, "fxmesa: fxDDSetBuffer(%x)\n", (int) mode);
}
if (bufferBit == FRONT_LEFT_BIT) {
fxMesa->currentFB = GR_BUFFER_FRONTBUFFER;
FX_grRenderBuffer(fxMesa->currentFB);
}
else if (bufferBit == BACK_LEFT_BIT) {
fxMesa->currentFB = GR_BUFFER_BACKBUFFER;
FX_grRenderBuffer(fxMesa->currentFB);
}
}
/************************************************************************/
void
fxSetupDDSpanPointers(GLcontext * ctx)
{
struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx );
swdd->SetBuffer = fxDDSetBuffer;
swdd->WriteRGBASpan = fxDDWriteRGBASpan;
swdd->WriteRGBSpan = fxDDWriteRGBSpan;
swdd->WriteMonoRGBASpan = fxDDWriteMonoRGBASpan;
swdd->WriteRGBAPixels = fxDDWriteRGBAPixels;
swdd->WriteMonoRGBAPixels = fxDDWriteMonoRGBAPixels;
swdd->WriteDepthSpan = fxDDWriteDepthSpan;
swdd->WriteDepthPixels = fxDDWriteDepthPixels;
swdd->ReadDepthSpan = fxDDReadDepthSpan;
swdd->ReadDepthPixels = fxDDReadDepthPixels;
/* swdd->ReadRGBASpan =fxDDReadRGBASpan; */
swdd->ReadRGBASpan = read_R5G6B5_span;
swdd->ReadRGBAPixels = read_R5G6B5_pixels;
}
#else
/*
* Need this to provide at least one external definition.
*/
extern int gl_fx_dummy_function_span(void);
int
gl_fx_dummy_function_span(void)
{
return 0;
}
#endif /* FX */