xmesa: split FX functions to separate file, part 1.
[mesa.git] / src / mesa / drivers / x11 / xm_glide.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 *
5 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26 #include "glxheader.h"
27 #include "xmesaP.h"
28
29 #ifdef FX
30 void
31 FXcreateContext(XMesaVisual v, XMesaWindow w, XMesaContext c, XMesaBuffer b)
32 {
33 char *fxEnvVar = _mesa_getenv("MESA_GLX_FX");
34 if (fxEnvVar) {
35 if (fxEnvVar[0]!='d') {
36 int attribs[100];
37 int numAttribs = 0;
38 int hw;
39 if (v->mesa_visual.depthBits > 0) {
40 attribs[numAttribs++] = FXMESA_DEPTH_SIZE;
41 attribs[numAttribs++] = v->mesa_visual.depthBits;
42 }
43 if (v->mesa_visual.doubleBufferMode) {
44 attribs[numAttribs++] = FXMESA_DOUBLEBUFFER;
45 }
46 if (v->mesa_visual.accumRedBits > 0) {
47 attribs[numAttribs++] = FXMESA_ACCUM_SIZE;
48 attribs[numAttribs++] = v->mesa_visual.accumRedBits;
49 }
50 if (v->mesa_visual.stencilBits > 0) {
51 attribs[numAttribs++] = FXMESA_STENCIL_SIZE;
52 attribs[numAttribs++] = v->mesa_visual.stencilBits;
53 }
54 if (v->mesa_visual.alphaBits > 0) {
55 attribs[numAttribs++] = FXMESA_ALPHA_SIZE;
56 attribs[numAttribs++] = v->mesa_visual.alphaBits;
57 }
58 if (1) {
59 attribs[numAttribs++] = FXMESA_SHARE_CONTEXT;
60 attribs[numAttribs++] = (int) &(c->mesa);
61 }
62 attribs[numAttribs++] = FXMESA_NONE;
63
64 /* [dBorca] we should take an envvar for `fxMesaSelectCurrentBoard'!!! */
65 hw = fxMesaSelectCurrentBoard(0);
66
67 /* if these fail, there's a new bug somewhere */
68 ASSERT(b->mesa_buffer.Width > 0);
69 ASSERT(b->mesa_buffer.Height > 0);
70
71 if ((hw == GR_SSTTYPE_VOODOO) || (hw == GR_SSTTYPE_Voodoo2)) {
72 b->FXctx = fxMesaCreateBestContext(0, b->mesa_buffer.Width,
73 b->mesa_buffer.Height, attribs);
74 if ((v->undithered_pf!=PF_Index) && (b->backxrb->ximage)) {
75 b->FXisHackUsable = b->FXctx ? GL_TRUE : GL_FALSE;
76 if (b->FXctx && (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')) {
77 b->FXwindowHack = GL_TRUE;
78 FX_grSstControl(GR_CONTROL_DEACTIVATE);
79 }
80 else {
81 b->FXwindowHack = GL_FALSE;
82 }
83 }
84 }
85 else {
86 if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')
87 b->FXctx = fxMesaCreateContext(w, GR_RESOLUTION_NONE,
88 GR_REFRESH_75Hz, attribs);
89 else
90 b->FXctx = fxMesaCreateBestContext(0, b->mesa_buffer.Width,
91 b->mesa_buffer.Height, attribs);
92 b->FXisHackUsable = GL_FALSE;
93 b->FXwindowHack = GL_FALSE;
94 }
95 /*
96 fprintf(stderr,
97 "voodoo %d, wid %d height %d hack: usable %d active %d\n",
98 hw, b->mesa_buffer.Width, b->mesa_buffer.Height,
99 b->FXisHackUsable, b->FXwindowHack);
100 */
101 }
102 }
103 else {
104 _mesa_warning(NULL, "WARNING: This Mesa Library includes the Glide driver but\n");
105 _mesa_warning(NULL, " you have not defined the MESA_GLX_FX env. var.\n");
106 _mesa_warning(NULL, " (check the README.3DFX file for more information).\n\n");
107 _mesa_warning(NULL, " you can disable this message with a 'export MESA_GLX_FX=disable'.\n");
108 }
109 }
110
111
112 /*
113 * Read image from VooDoo frame buffer into X/Mesa's back XImage.
114 */
115 static void FXgetImage( XMesaBuffer b )
116 {
117 GET_CURRENT_CONTEXT(ctx);
118 static unsigned short pixbuf[MAX_WIDTH];
119 GLuint x, y;
120 GLuint width, height;
121 XMesaContext xmesa = XMESA_CONTEXT(ctx);
122
123 #ifdef XFree86Server
124 x = b->frontxrb->pixmap->x;
125 y = b->frontxrb->pixmap->y;
126 width = b->frontxrb->pixmap->width;
127 height = b->frontxrb->pixmap->height;
128 depth = b->frontxrb->pixmap->depth;
129 #else
130 xmesa_get_window_size(b->display, b, &width, &height);
131 x = y = 0;
132 #endif
133 if (b->mesa_buffer.Width != width || b->mesa_buffer.Height != height) {
134 b->mesa_buffer.Width = MIN2((int)width, b->FXctx->width);
135 b->mesa_buffer.Height = MIN2((int)height, b->FXctx->height);
136 if (b->mesa_buffer.Width & 1)
137 b->mesa_buffer.Width--; /* prevent odd width */
138 }
139
140 /* [dBorca] we're always in the right GR_COLORFORMAT... aren't we? */
141 /* grLfbWriteColorFormat(GR_COLORFORMAT_ARGB); */
142 if (b->xm_visual->undithered_pf==PF_5R6G5B) {
143 /* Special case: 16bpp RGB */
144 grLfbReadRegion( GR_BUFFER_FRONTBUFFER, /* src buffer */
145 0, b->FXctx->height - b->mesa_buffer.Height, /*pos*/
146 b->mesa_buffer.Width, b->mesa_buffer.Height, /* size */
147 b->mesa_buffer.Width * sizeof(GLushort), /* stride */
148 b->backxrb->ximage->data); /* dest buffer */
149 }
150 else if (b->xm_visual->dithered_pf==PF_Dither
151 && GET_VISUAL_DEPTH(b->xm_visual)==8) {
152 /* Special case: 8bpp RGB */
153 for (y=0;y<b->mesa_buffer.Height;y++) {
154 GLubyte *ptr = (GLubyte*) b->backxrb->ximage->data
155 + b->backxrb->ximage->bytes_per_line * y;
156 XDITHER_SETUP(y);
157
158 /* read row from 3Dfx frame buffer */
159 grLfbReadRegion( GR_BUFFER_FRONTBUFFER,
160 0, b->FXctx->height-(b->mesa_buffer.Height-y),
161 b->mesa_buffer.Width, 1,
162 0,
163 pixbuf );
164
165 /* write to XImage back buffer */
166 for (x=0;x<b->mesa_buffer.Width;x++) {
167 GLubyte r = (pixbuf[x] & 0xf800) >> 8;
168 GLubyte g = (pixbuf[x] & 0x07e0) >> 3;
169 GLubyte b = (pixbuf[x] & 0x001f) << 3;
170 *ptr++ = XDITHER( x, r, g, b);
171 }
172 }
173 }
174 else {
175 /* General case: slow! */
176 for (y=0;y<b->mesa_buffer.Height;y++) {
177 /* read row from 3Dfx frame buffer */
178 grLfbReadRegion( GR_BUFFER_FRONTBUFFER,
179 0, b->FXctx->height-(b->mesa_buffer.Height-y),
180 b->mesa_buffer.Width, 1,
181 0,
182 pixbuf );
183
184 /* write to XImage back buffer */
185 for (x=0;x<b->mesa_buffer.Width;x++) {
186 XMesaPutPixel(b->backxrb->ximage,x,y,
187 xmesa_color_to_pixel(ctx,
188 (pixbuf[x] & 0xf800) >> 8,
189 (pixbuf[x] & 0x07e0) >> 3,
190 (pixbuf[x] & 0x001f) << 3,
191 0xff,
192 b->xm_visual->undithered_pf));
193 }
194 }
195 }
196 /* grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); */
197 }
198
199
200 GLboolean FXswapBuffers( XMesaBuffer b )
201 {
202 if (b->FXctx) {
203 fxMesaSwapBuffers();
204
205 if (!b->FXwindowHack)
206 return GL_TRUE;
207
208 FXgetImage(b);
209 }
210 return GL_FALSE;
211 }
212
213
214 /*
215 * Switch 3Dfx support hack between window and full-screen mode.
216 */
217 GLboolean XMesaSetFXmode( GLint mode )
218 {
219 const char *fx = _mesa_getenv("MESA_GLX_FX");
220 if (fx && fx[0] != 'd') {
221 GET_CURRENT_CONTEXT(ctx);
222 GrHwConfiguration hw;
223 if (!FX_grSstQueryHardware(&hw)) {
224 /*fprintf(stderr, "!grSstQueryHardware\n");*/
225 return GL_FALSE;
226 }
227 if (hw.num_sst < 1) {
228 /*fprintf(stderr, "hw.num_sst < 1\n");*/
229 return GL_FALSE;
230 }
231 if (ctx) {
232 /* [dBorca] Hack alert:
233 * oh, this is sooo wrong: ctx above is
234 * really an fxMesaContext, not an XMesaContext
235 */
236 XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
237 if (mode == XMESA_FX_WINDOW) {
238 if (xmbuf->FXisHackUsable) {
239 FX_grSstControl(GR_CONTROL_DEACTIVATE);
240 xmbuf->FXwindowHack = GL_TRUE;
241 return GL_TRUE;
242 }
243 }
244 else if (mode == XMESA_FX_FULLSCREEN) {
245 FX_grSstControl(GR_CONTROL_ACTIVATE);
246 xmbuf->FXwindowHack = GL_FALSE;
247 return GL_TRUE;
248 }
249 else {
250 /* Error: Bad mode value */
251 }
252 }
253 }
254 /*fprintf(stderr, "fallthrough\n");*/
255 return GL_FALSE;
256 }
257 #endif