#include "tdfx_context.h"
#include "tdfx_dd.h"
#include "tdfx_lock.h"
#include "tdfx_vb.h"
#include "tdfx_pixels.h"
#include "tdfx_render.h"
#include "swrast/swrast.h"
#include "image.h"
#define FX_grLfbWriteRegion(fxMesa,dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data) \
do { \
LOCK_HARDWARE(fxMesa); \
fxMesa->Glide.grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,FXFALSE,src_stride,src_data); \
UNLOCK_HARDWARE(fxMesa); \
} while(0)
#define FX_grLfbReadRegion(fxMesa,src_buffer,src_x,src_y,src_width,src_height,dst_stride,dst_data) \
do { \
LOCK_HARDWARE(fxMesa); \
fxMesa->Glide.grLfbReadRegion(src_buffer,src_x,src_y,src_width,src_height,dst_stride,dst_data); \
UNLOCK_HARDWARE(fxMesa); \
} while (0);
#if 0
static FxBool
FX_grLfbLock(tdfxContextPtr fxMesa, GrLock_t type, GrBuffer_t buffer,
GrLfbWriteMode_t writeMode, GrOriginLocation_t origin,
FxBool pixelPipeline, GrLfbInfo_t * info)
{
FxBool result;
LOCK_HARDWARE(fxMesa);
result = fxMesa->Glide.grLfbLock(type, buffer, writeMode, origin, pixelPipeline, info);
UNLOCK_HARDWARE(fxMesa);
return result;
}
#endif
#define FX_grLfbUnlock(fxMesa, t, b) \
do { \
LOCK_HARDWARE(fxMesa); \
fxMesa->Glide.grLfbUnlock(t, b); \
UNLOCK_HARDWARE(fxMesa); \
} while (0)
#if 0
static GLboolean
inClipRects(tdfxContextPtr fxMesa, int px, int py)
{
int i;
for (i = 0; i < fxMesa->numClipRects; i++) {
if ((px >= fxMesa->pClipRects[i].x1) &&
(px < fxMesa->pClipRects[i].x2) &&
(py >= fxMesa->pClipRects[i].y1) &&
(py < fxMesa->pClipRects[i].y2)) return GL_TRUE;
}
return GL_FALSE;
}
#endif
static GLboolean
inClipRects_Region(tdfxContextPtr fxMesa, int x, int y, int width, int height)
{
int i;
int x1, y1, x2, y2;
int xmin, xmax, ymin, ymax, pixelsleft;
y1 = y - height + 1; y2 = y;
x1 = x; x2 = x + width - 1;
pixelsleft = width * height;
for (i = 0; i < fxMesa->numClipRects; i++)
{
if ((fxMesa->pClipRects[i].x1 < fxMesa->pClipRects[i].x2)) {
xmin = fxMesa->pClipRects[i].x1;
xmax = fxMesa->pClipRects[i].x2-1;
} else {
xmin = fxMesa->pClipRects[i].x2;
xmax = fxMesa->pClipRects[i].x1-1;
}
if ((fxMesa->pClipRects[i].y1 < fxMesa->pClipRects[i].y2)) {
ymin = fxMesa->pClipRects[i].y1;
ymax = fxMesa->pClipRects[i].y2-1;
} else {
ymin = fxMesa->pClipRects[i].y2;
ymax = fxMesa->pClipRects[i].y1-1;
}
if (xmax < x1) continue;
if (ymax < y1) continue;
if (xmin > x2) continue;
if (ymin > y2) continue;
if (xmin < x1) xmin = x1;
if (ymin < y1) ymin = y1;
if (xmax > x2) xmax = x2;
if (ymax > y2) ymax = y2;
pixelsleft -= (xmax-xmin+1) * (ymax-ymin+1);
}
return pixelsleft == 0;
}
#if 0
GLboolean
tdfx_bitmap_R5G6B5(GLcontext * ctx, GLint px, GLint py,
GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte * bitmap)
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
GrLfbInfo_t info;
TdfxU16 color;
const struct gl_pixelstore_attrib *finalUnpack;
struct gl_pixelstore_attrib scissoredUnpack;
if (ctx->RasterMask & (ALPHATEST_BIT |
BLEND_BIT |
DEPTH_BIT |
FOG_BIT |
LOGIC_OP_BIT |
SCISSOR_BIT |
STENCIL_BIT |
MASKING_BIT |
ALPHABUF_BIT | MULTI_DRAW_BIT)) return GL_FALSE;
if (ctx->Scissor.Enabled) {
finalUnpack = &scissoredUnpack;
scissoredUnpack = *unpack;
if (scissoredUnpack.RowLength == 0)
scissoredUnpack.RowLength = width;
if (px < ctx->Scissor.X) {
scissoredUnpack.SkipPixels += (ctx->Scissor.X - px);
width -= (ctx->Scissor.X - px);
px = ctx->Scissor.X;
}
if (px + width >= ctx->Scissor.X + ctx->Scissor.Width) {
width -= (px + width - (ctx->Scissor.X + ctx->Scissor.Width));
}
if (py < ctx->Scissor.Y) {
scissoredUnpack.SkipRows += (ctx->Scissor.Y - py);
height -= (ctx->Scissor.Y - py);
py = ctx->Scissor.Y;
}
if (py + height >= ctx->Scissor.Y + ctx->Scissor.Height) {
height -= (py + height - (ctx->Scissor.Y + ctx->Scissor.Height));
}
if (width <= 0 || height <= 0)
return GL_TRUE;
}
else {
finalUnpack = unpack;
}
{
GLint r = (GLint) (ctx->Current.RasterColor[0] * 255.0f);
GLint g = (GLint) (ctx->Current.RasterColor[1] * 255.0f);
GLint b = (GLint) (ctx->Current.RasterColor[2] * 255.0f);
if (fxMesa->bgrOrder) {
color = (TdfxU16)
(((TdfxU16) 0xf8 & b) << (11 - 3)) |
(((TdfxU16) 0xfc & g) << (5 - 3 + 1)) |
(((TdfxU16) 0xf8 & r) >> 3);
}
else
color = (TdfxU16)
(((TdfxU16) 0xf8 & r) << (11 - 3)) |
(((TdfxU16) 0xfc & g) << (5 - 3 + 1)) |
(((TdfxU16) 0xf8 & b) >> 3);
}
info.size = sizeof(info);
if (!TDFX_grLfbLock(fxMesa,
GR_LFB_WRITE_ONLY,
fxMesa->currentFB,
GR_LFBWRITEMODE_565,
GR_ORIGIN_UPPER_LEFT, FXFALSE, &info)) {
#ifndef TDFX_SILENT
fprintf(stderr, "tdfx Driver: error locking the linear frame buffer\n");
#endif
return GL_TRUE;
}
{
const GLint winX = fxMesa->x_offset;
const GLint winY = fxMesa->y_offset + fxMesa->height - 1;
const GLint dstStride = (fxMesa->glCtx->Color.DrawBuffer == GL_FRONT)
? (fxMesa->screen_width) : (info.strideInBytes / 2);
GLint row;
GLushort *dst = (GLushort *) info.lfbPtr
+ (winY - py) * dstStride + (winX + px);
for (row = 0; row < height; row++) {
const GLubyte *src =
(const GLubyte *) _mesa_image_address(finalUnpack,
bitmap, width, height,
GL_COLOR_INDEX,
GL_BITMAP, 0, row, 0);
if (finalUnpack->LsbFirst) {
GLubyte mask = 1U << (finalUnpack->SkipPixels & 0x7);
GLint col;
for (col = 0; col < width; col++) {
if (*src & mask) {
if (inClipRects(fxMesa, winX + px + col, winY - py - row))
dst[col] = color;
}
if (mask == 128U) {
src++;
mask = 1U;
}
else {
mask = mask << 1;
}
}
if (mask != 1)
src++;
}
else {
GLubyte mask = 128U >> (finalUnpack->SkipPixels & 0x7);
GLint col;
for (col = 0; col < width; col++) {
if (*src & mask) {
if (inClipRects(fxMesa, winX + px + col, winY - py - row))
dst[col] = color;
}
if (mask == 1U) {
src++;
mask = 128U;
}
else {
mask = mask >> 1;
}
}
if (mask != 128)
src++;
}
dst -= dstStride;
}
}
TDFX_grLfbUnlock(fxMesa, GR_LFB_WRITE_ONLY, fxMesa->currentFB);
return GL_TRUE;
}
#endif
#if 0
GLboolean
tdfx_bitmap_R8G8B8A8(GLcontext * ctx, GLint px, GLint py,
GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte * bitmap)
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
GrLfbInfo_t info;
GLuint color;
const struct gl_pixelstore_attrib *finalUnpack;
struct gl_pixelstore_attrib scissoredUnpack;
if (ctx->RasterMask & (ALPHATEST_BIT |
BLEND_BIT |
DEPTH_BIT |
FOG_BIT |
LOGIC_OP_BIT |
SCISSOR_BIT |
STENCIL_BIT |
MASKING_BIT |
ALPHABUF_BIT | MULTI_DRAW_BIT)) return GL_FALSE;
if (ctx->Scissor.Enabled) {
finalUnpack = &scissoredUnpack;
scissoredUnpack = *unpack;
if (scissoredUnpack.RowLength == 0)
scissoredUnpack.RowLength = width;
if (px < ctx->Scissor.X) {
scissoredUnpack.SkipPixels += (ctx->Scissor.X - px);
width -= (ctx->Scissor.X - px);
px = ctx->Scissor.X;
}
if (px + width >= ctx->Scissor.X + ctx->Scissor.Width) {
width -= (px + width - (ctx->Scissor.X + ctx->Scissor.Width));
}
if (py < ctx->Scissor.Y) {
scissoredUnpack.SkipRows += (ctx->Scissor.Y - py);
height -= (ctx->Scissor.Y - py);
py = ctx->Scissor.Y;
}
if (py + height >= ctx->Scissor.Y + ctx->Scissor.Height) {
height -= (py + height - (ctx->Scissor.Y + ctx->Scissor.Height));
}
if (width <= 0 || height <= 0)
return GL_TRUE;
}
else {
finalUnpack = unpack;
}
{
GLint r = (GLint) (ctx->Current.RasterColor[0] * 255.0f);
GLint g = (GLint) (ctx->Current.RasterColor[1] * 255.0f);
GLint b = (GLint) (ctx->Current.RasterColor[2] * 255.0f);
GLint a = (GLint) (ctx->Current.RasterColor[3] * 255.0f);
color = PACK_BGRA32(r, g, b, a);
}
info.size = sizeof(info);
if (!TDFX_grLfbLock(fxMesa, GR_LFB_WRITE_ONLY,
fxMesa->currentFB, GR_LFBWRITEMODE_8888,
GR_ORIGIN_UPPER_LEFT, FXFALSE, &info)) {
#ifndef TDFX_SILENT
fprintf(stderr, "tdfx Driver: error locking the linear frame buffer\n");
#endif
return GL_TRUE;
}
{
const GLint winX = fxMesa->x_offset;
const GLint winY = fxMesa->y_offset + fxMesa->height - 1;
GLint dstStride;
GLuint *dst;
GLint row;
if (fxMesa->glCtx->Color.DrawBuffer == GL_FRONT) {
dstStride = fxMesa->screen_width;
dst =
(GLuint *) info.lfbPtr + (winY - py) * dstStride + (winX +
px);
}
else {
dstStride = info.strideInBytes / 4;
dst =
(GLuint *) info.lfbPtr + (winY - py) * dstStride + (winX +
px);
}
for (row = 0; row < height; row++) {
const GLubyte *src =
(const GLubyte *) _mesa_image_address(finalUnpack,
bitmap, width, height,
GL_COLOR_INDEX,
GL_BITMAP, 0, row, 0);
if (finalUnpack->LsbFirst) {
GLubyte mask = 1U << (finalUnpack->SkipPixels & 0x7);
GLint col;
for (col = 0; col < width; col++) {
if (*src & mask) {
if (inClipRects(fxMesa, winX + px + col, winY - py - row))
dst[col] = color;
}
if (mask == 128U) {
src++;
mask = 1U;
}
else {
mask = mask << 1;
}
}
if (mask != 1)
src++;
}
else {
GLubyte mask = 128U >> (finalUnpack->SkipPixels & 0x7);
GLint col;
for (col = 0; col < width; col++) {
if (*src & mask) {
if (inClipRects(fxMesa, winX + px + col, winY - py - row))
dst[col] = color;
}
if (mask == 1U) {
src++;
mask = 128U;
}
else {
mask = mask >> 1;
}
}
if (mask != 128)
src++;
}
dst -= dstStride;
}
}
TDFX_grLfbUnlock(fxMesa, GR_LFB_WRITE_ONLY, fxMesa->currentFB);
return GL_TRUE;
}
#endif
void
tdfx_readpixels_R5G6B5(GLcontext * ctx, GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *packing,
GLvoid * dstImage)
{
if (format != GL_RGB ||
type != GL_UNSIGNED_SHORT_5_6_5 ||
(ctx->_ImageTransferState & (IMAGE_SCALE_BIAS_BIT|
IMAGE_MAP_COLOR_BIT)))
{
_swrast_ReadPixels( ctx, x, y, width, height, format, type, packing,
dstImage );
return;
}
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
GrLfbInfo_t info;
const GLint winX = fxMesa->x_offset;
const GLint winY = fxMesa->y_offset + fxMesa->height - 1;
const GLint scrX = winX + x;
const GLint scrY = winY - y;
LOCK_HARDWARE( fxMesa );
info.size = sizeof(info);
if (fxMesa->Glide.grLfbLock(GR_LFB_READ_ONLY,
fxMesa->ReadBuffer,
GR_LFBWRITEMODE_ANY,
GR_ORIGIN_UPPER_LEFT, FXFALSE, &info)) {
const GLint srcStride = (fxMesa->glCtx->Color.DrawBuffer ==
GL_FRONT) ? (fxMesa->screen_width) : (info.strideInBytes / 2);
const GLushort *src = (const GLushort *) info.lfbPtr
+ scrY * srcStride + scrX;
GLubyte *dst = (GLubyte *) _mesa_image_address(packing,
dstImage, width, height, format, type, 0, 0, 0);
const GLint dstStride = _mesa_image_row_stride(packing,
width, format, type);
const GLint widthInBytes = width * 2;
GLint row;
for (row = 0; row < height; row++) {
MEMCPY(dst, src, widthInBytes);
dst += dstStride;
src -= srcStride;
}
fxMesa->Glide.grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->ReadBuffer);
}
UNLOCK_HARDWARE( fxMesa );
return;
}
}
void
tdfx_readpixels_R8G8B8A8(GLcontext * ctx, GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *packing,
GLvoid * dstImage)
{
if ((!(format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8) &&
!(format == GL_BGRA && type == GL_UNSIGNED_BYTE)) ||
(ctx->_ImageTransferState & (IMAGE_SCALE_BIAS_BIT|
IMAGE_MAP_COLOR_BIT)))
{
_swrast_ReadPixels( ctx, x, y, width, height, format, type, packing,
dstImage );
return;
}
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
GrLfbInfo_t info;
const GLint winX = fxMesa->x_offset;
const GLint winY = fxMesa->y_offset + fxMesa->height - 1;
const GLint scrX = winX + x;
const GLint scrY = winY - y;
LOCK_HARDWARE(fxMesa);
info.size = sizeof(info);
if (fxMesa->Glide.grLfbLock(GR_LFB_READ_ONLY,
fxMesa->ReadBuffer,
GR_LFBWRITEMODE_ANY,
GR_ORIGIN_UPPER_LEFT, FXFALSE, &info))
{
const GLint srcStride = (fxMesa->glCtx->Color.DrawBuffer == GL_FRONT)
? (fxMesa->screen_width) : (info.strideInBytes / 4);
const GLuint *src = (const GLuint *) info.lfbPtr
+ scrY * srcStride + scrX;
const GLint dstStride =
_mesa_image_row_stride(packing, width, format, type);
GLubyte *dst = (GLubyte *) _mesa_image_address(packing,
dstImage, width, height, format, type, 0, 0, 0);
const GLint widthInBytes = width * 4;
{
GLint row;
for (row = 0; row < height; row++) {
MEMCPY(dst, src, widthInBytes);
dst += dstStride;
src -= srcStride;
}
}
fxMesa->Glide.grLfbUnlock(GR_LFB_READ_ONLY, fxMesa->ReadBuffer);
}
UNLOCK_HARDWARE(fxMesa);
}
}
void
tdfx_drawpixels_R8G8B8A8(GLcontext * ctx, GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid * pixels)
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
if ((!(format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8) &&
!(format == GL_BGRA && type == GL_UNSIGNED_BYTE)) ||
ctx->Pixel.ZoomX != 1.0F ||
ctx->Pixel.ZoomY != 1.0F ||
(ctx->_ImageTransferState & (IMAGE_SCALE_BIAS_BIT|
IMAGE_MAP_COLOR_BIT)) ||
ctx->Color.AlphaEnabled ||
ctx->Depth.Test ||
ctx->Fog.Enabled ||
ctx->Scissor.Enabled ||
ctx->Stencil.Enabled ||
!ctx->Color.ColorMask[0] ||
!ctx->Color.ColorMask[1] ||
!ctx->Color.ColorMask[2] ||
!ctx->Color.ColorMask[3] ||
ctx->Color.ColorLogicOpEnabled ||
ctx->Texture._EnabledUnits ||
ctx->Depth.OcclusionTest ||
fxMesa->Fallback)
{
_swrast_DrawPixels( ctx, x, y, width, height, format, type,
unpack, pixels );
return;
}
{
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
GrLfbInfo_t info;
GLboolean result = GL_FALSE;
const GLint winX = fxMesa->x_offset;
const GLint winY = fxMesa->y_offset + fxMesa->height - 1;
const GLint scrX = winX + x;
const GLint scrY = winY - y;
LOCK_HARDWARE(fxMesa);
if (ctx->Color.BlendEnabled) {
fxMesa->dirty |= TDFX_UPLOAD_BLEND_FUNC;
tdfxEmitHwStateLocked( fxMesa );
}
if (fxMesa->glCtx->Color.DrawBuffer == GL_FRONT) {
if (!inClipRects_Region(fxMesa, scrX, scrY, width, height)) {
UNLOCK_HARDWARE(fxMesa);
_swrast_DrawPixels( ctx, x, y, width, height, format, type,
unpack, pixels );
return;
}
}
info.size = sizeof(info);
if (fxMesa->Glide.grLfbLock(GR_LFB_WRITE_ONLY,
fxMesa->DrawBuffer,
GR_LFBWRITEMODE_8888,
GR_ORIGIN_UPPER_LEFT, FXTRUE, &info))
{
const GLint dstStride = (fxMesa->glCtx->Color.DrawBuffer == GL_FRONT)
? (fxMesa->screen_width * 4) : (info.strideInBytes);
GLubyte *dst = (GLubyte *) info.lfbPtr
+ scrY * dstStride + scrX * 4;
const GLint srcStride =
_mesa_image_row_stride(unpack, width, format, type);
const GLubyte *src = (GLubyte *) _mesa_image_address(unpack,
pixels, width, height, format, type, 0, 0, 0);
const GLint widthInBytes = width * 4;
if ((format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8) ||
(format == GL_BGRA && type == GL_UNSIGNED_BYTE)) {
GLint row;
for (row = 0; row < height; row++) {
MEMCPY(dst, src, widthInBytes);
dst -= dstStride;
src += srcStride;
}
result = GL_TRUE;
}
fxMesa->Glide.grLfbUnlock(GR_LFB_WRITE_ONLY, fxMesa->DrawBuffer);
}
UNLOCK_HARDWARE(fxMesa);
}
}