blob: cbd69b011a1d15e7dcc33013ab43d5a3c1101f51 [file] [log] [blame]
/*
* Mesa 3-D graphics library
* Version: 6.5
*
* Copyright (C) 1999-2006 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.
*/
#include "glxheader.h"
#include "xmesaP.h"
#ifdef FX
#include "../glide/fxdrv.h"
void
FXcreateContext(XMesaVisual v, XMesaWindow w, XMesaContext c, XMesaBuffer b)
{
char *fxEnvVar = _mesa_getenv("MESA_GLX_FX");
if (fxEnvVar) {
if (fxEnvVar[0]!='d') {
int attribs[100];
int numAttribs = 0;
int hw;
if (v->mesa_visual.depthBits > 0) {
attribs[numAttribs++] = FXMESA_DEPTH_SIZE;
attribs[numAttribs++] = v->mesa_visual.depthBits;
}
if (v->mesa_visual.doubleBufferMode) {
attribs[numAttribs++] = FXMESA_DOUBLEBUFFER;
}
if (v->mesa_visual.accumRedBits > 0) {
attribs[numAttribs++] = FXMESA_ACCUM_SIZE;
attribs[numAttribs++] = v->mesa_visual.accumRedBits;
}
if (v->mesa_visual.stencilBits > 0) {
attribs[numAttribs++] = FXMESA_STENCIL_SIZE;
attribs[numAttribs++] = v->mesa_visual.stencilBits;
}
if (v->mesa_visual.alphaBits > 0) {
attribs[numAttribs++] = FXMESA_ALPHA_SIZE;
attribs[numAttribs++] = v->mesa_visual.alphaBits;
}
if (1) {
attribs[numAttribs++] = FXMESA_SHARE_CONTEXT;
attribs[numAttribs++] = (int) &(c->mesa);
}
attribs[numAttribs++] = FXMESA_NONE;
/* [dBorca] we should take an envvar for `fxMesaSelectCurrentBoard'!!! */
/* hw = fxMesaSelectCurrentBoard(0); */
hw = GR_SSTTYPE_Voodoo2;
/* if these fail, there's a new bug somewhere */
ASSERT(b->mesa_buffer.Width > 0);
ASSERT(b->mesa_buffer.Height > 0);
if ((hw == GR_SSTTYPE_VOODOO) || (hw == GR_SSTTYPE_Voodoo2)) {
b->FXctx = fxMesaCreateBestContext(0, b->mesa_buffer.Width,
b->mesa_buffer.Height, attribs);
if ((v->undithered_pf!=PF_Index) && (b->backxrb->ximage)) {
b->FXisHackUsable = b->FXctx ? GL_TRUE : GL_FALSE;
if (b->FXctx && (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')) {
b->FXwindowHack = GL_TRUE;
FX_grSstControl(GR_CONTROL_DEACTIVATE);
}
else {
b->FXwindowHack = GL_FALSE;
}
}
}
else {
if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')
b->FXctx = fxMesaCreateContext(w, GR_RESOLUTION_NONE,
GR_REFRESH_75Hz, attribs);
else
b->FXctx = fxMesaCreateBestContext(0, b->mesa_buffer.Width,
b->mesa_buffer.Height, attribs);
b->FXisHackUsable = GL_FALSE;
b->FXwindowHack = GL_FALSE;
}
/*
fprintf(stderr,
"voodoo %d, wid %d height %d hack: usable %d active %d\n",
hw, b->mesa_buffer.Width, b->mesa_buffer.Height,
b->FXisHackUsable, b->FXwindowHack);
*/
}
}
else {
_mesa_warning(NULL, "WARNING: This Mesa Library includes the Glide driver but\n");
_mesa_warning(NULL, " you have not defined the MESA_GLX_FX env. var.\n");
_mesa_warning(NULL, " (check the README.3DFX file for more information).\n\n");
_mesa_warning(NULL, " you can disable this message with a 'export MESA_GLX_FX=disable'.\n");
}
}
void FXdestroyContext( XMesaBuffer b )
{
if (b && b->FXctx)
fxMesaDestroyContext(b->FXctx);
}
GLboolean FXmakeCurrent( XMesaBuffer b )
{
if (b->FXctx) {
fxMesaMakeCurrent(b->FXctx);
return GL_TRUE;
}
return GL_FALSE;
}
/*
* Read image from VooDoo frame buffer into X/Mesa's back XImage.
*/
static void FXgetImage( XMesaBuffer b )
{
GET_CURRENT_CONTEXT(ctx);
static unsigned short pixbuf[MAX_WIDTH];
GLuint x, y;
GLuint width, height;
#ifdef XFree86Server
x = b->frontxrb->pixmap->x;
y = b->frontxrb->pixmap->y;
width = b->frontxrb->pixmap->width;
height = b->frontxrb->pixmap->height;
depth = b->frontxrb->pixmap->depth;
#else
xmesa_get_window_size(b->display, b, &width, &height);
x = y = 0;
#endif
if (b->mesa_buffer.Width != width || b->mesa_buffer.Height != height) {
b->mesa_buffer.Width = MIN2((int)width, b->FXctx->width);
b->mesa_buffer.Height = MIN2((int)height, b->FXctx->height);
if (b->mesa_buffer.Width & 1)
b->mesa_buffer.Width--; /* prevent odd width */
}
/* [dBorca] we're always in the right GR_COLORFORMAT... aren't we? */
/* grLfbWriteColorFormat(GR_COLORFORMAT_ARGB); */
if (b->xm_visual->undithered_pf==PF_5R6G5B) {
/* Special case: 16bpp RGB */
grLfbReadRegion( GR_BUFFER_FRONTBUFFER, /* src buffer */
0, b->FXctx->height - b->mesa_buffer.Height, /*pos*/
b->mesa_buffer.Width, b->mesa_buffer.Height, /* size */
b->mesa_buffer.Width * sizeof(GLushort), /* stride */
b->backxrb->ximage->data); /* dest buffer */
}
else if (b->xm_visual->dithered_pf==PF_Dither
&& GET_VISUAL_DEPTH(b->xm_visual)==8) {
/* Special case: 8bpp RGB */
for (y=0;y<b->mesa_buffer.Height;y++) {
GLubyte *ptr = (GLubyte*) b->backxrb->ximage->data
+ b->backxrb->ximage->bytes_per_line * y;
XDITHER_SETUP(y);
/* read row from 3Dfx frame buffer */
grLfbReadRegion( GR_BUFFER_FRONTBUFFER,
0, b->FXctx->height-(b->mesa_buffer.Height-y),
b->mesa_buffer.Width, 1,
0,
pixbuf );
/* write to XImage back buffer */
for (x=0;x<b->mesa_buffer.Width;x++) {
GLubyte r = (pixbuf[x] & 0xf800) >> 8;
GLubyte g = (pixbuf[x] & 0x07e0) >> 3;
GLubyte b = (pixbuf[x] & 0x001f) << 3;
*ptr++ = XDITHER( x, r, g, b);
}
}
}
else {
/* General case: slow! */
for (y=0;y<b->mesa_buffer.Height;y++) {
/* read row from 3Dfx frame buffer */
grLfbReadRegion( GR_BUFFER_FRONTBUFFER,
0, b->FXctx->height-(b->mesa_buffer.Height-y),
b->mesa_buffer.Width, 1,
0,
pixbuf );
/* write to XImage back buffer */
for (x=0;x<b->mesa_buffer.Width;x++) {
XMesaPutPixel(b->backxrb->ximage,x,y,
xmesa_color_to_pixel(ctx,
(pixbuf[x] & 0xf800) >> 8,
(pixbuf[x] & 0x07e0) >> 3,
(pixbuf[x] & 0x001f) << 3,
0xff,
b->xm_visual->undithered_pf));
}
}
}
/* grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); */
}
GLboolean FXswapBuffers( XMesaBuffer b )
{
if (b->FXctx) {
fxMesaSwapBuffers();
if (!b->FXwindowHack)
return GL_TRUE;
FXgetImage(b);
}
return GL_FALSE;
}
/*
* Switch 3Dfx support hack between window and full-screen mode.
*/
GLboolean XMesaSetFXmode( GLint mode )
{
const char *fx = _mesa_getenv("MESA_GLX_FX");
if (fx && fx[0] != 'd') {
GET_CURRENT_CONTEXT(ctx);
GrHwConfiguration hw;
if (!FX_grSstQueryHardware(&hw)) {
/*fprintf(stderr, "!grSstQueryHardware\n");*/
return GL_FALSE;
}
if (hw.num_sst < 1) {
/*fprintf(stderr, "hw.num_sst < 1\n");*/
return GL_FALSE;
}
if (ctx) {
/* [dBorca] Hack alert:
* oh, this is sooo wrong: ctx above is
* really an fxMesaContext, not an XMesaContext
*/
XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
if (mode == XMESA_FX_WINDOW) {
if (xmbuf->FXisHackUsable) {
FX_grSstControl(GR_CONTROL_DEACTIVATE);
xmbuf->FXwindowHack = GL_TRUE;
return GL_TRUE;
}
}
else if (mode == XMESA_FX_FULLSCREEN) {
FX_grSstControl(GR_CONTROL_ACTIVATE);
xmbuf->FXwindowHack = GL_FALSE;
return GL_TRUE;
}
else {
/* Error: Bad mode value */
}
}
}
/*fprintf(stderr, "fallthrough\n");*/
return GL_FALSE;
}
#endif