fix GL_BACK color material bug
[mesa.git] / src / mesa / drivers / svga / svgamesa.c
1 /* $Id: svgamesa.c,v 1.5 2000/03/31 01:07:14 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.3
6 * Copyright (C) 1995-2000 Brian Paul
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the Free
20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23
24 /*
25 * SVGA driver for Mesa.
26 * Original author: Brian Paul
27 * Additional authors: Slawomir Szczyrba <steev@hot.pl> (Mesa 3.2)
28 */
29
30
31 #ifdef HAVE_CONFIG_H
32 #include "conf.h"
33 #endif
34
35 #ifdef SVGA
36
37 #ifdef PC_HEADER
38 #include "all.h"
39 #else
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <vga.h>
43 #include "GL/svgamesa.h"
44 #include "context.h"
45 #include "matrix.h"
46 #include "types.h"
47 #include <string.h>
48 #endif
49
50 #include "svgapix.h"
51 #include "svgamesa8.h"
52 #include "svgamesa15.h"
53 #include "svgamesa16.h"
54 #include "svgamesa24.h"
55 #include "svgamesa32.h"
56
57 struct svga_buffer SVGABuffer;
58 vga_modeinfo * SVGAInfo;
59 SVGAMesaContext SVGAMesa; /* the current context */
60
61 #ifdef SVGA_DEBUG
62
63 #include <sys/types.h>
64 #include <signal.h>
65
66 FILE * logfile;
67 char cbuf[1024]={0};
68
69 void SVGAlog(char * what)
70 {
71 logfile=fopen("svgamesa.log","a");
72 if (!logfile) return;
73 fprintf(logfile,"%s\n",what);
74 fclose(logfile);
75 }
76 #endif
77
78 /**********************************************************************/
79 /***** Init stuff... *****/
80 /**********************************************************************/
81
82 int SVGAMesaInit( int GraphMode )
83 {
84 vga_init();
85 if (!vga_hasmode(GraphMode))
86 {
87 fprintf(stderr,"GraphMode %d unavailable...",GraphMode);
88 #ifdef SVGA_DEBUG
89 SVGAlog("SVGAMesaInit: invalid GraphMode (doesn't exist)");
90 #endif
91 return(1);
92 }
93 SVGAInfo=vga_getmodeinfo(GraphMode);
94 if (SVGAInfo->flags & IS_MODEX)
95 {
96 fprintf(stderr,"ModeX not implemented...");
97 #ifdef SVGA_DEBUG
98 SVGAlog("SVGAMesaInit: invalid GraphMode (ModeX)");
99 #endif
100 return(2);
101 }
102 if (!SVGAInfo->bytesperpixel)
103 {
104 fprintf(stderr,"1 / 4 bit color not implemented...");
105 #ifdef SVGA_DEBUG
106 SVGAlog("SVGAMesaInit: invalid GraphMode (1 or 4 bit)");
107 #endif
108 return(3);
109 }
110 switch (SVGAInfo->colors) {
111 case 256: SVGABuffer.Depth = 8; break;
112 case 32768: SVGABuffer.Depth = 15; break;
113 case 65536: SVGABuffer.Depth = 16; break;
114 default: SVGABuffer.Depth = SVGAInfo->bytesperpixel<<3; break;
115 }
116 SVGABuffer.BufferSize=SVGAInfo->linewidth*SVGAInfo->height;
117 #ifdef SVGA_DEBUG
118 sprintf(cbuf,"SVGAMesaInit: double buffer info.\n" \
119 " depth : %d\n" \
120 " mode : %d\n" \
121 " width : %d\n" \
122 " height : %d\n" \
123 " bufsize: %d\n", \
124 SVGABuffer.Depth,GraphMode,SVGAInfo->linewidth, \
125 SVGAInfo->height,SVGABuffer.BufferSize);
126 SVGAlog(cbuf);
127 #endif
128 SVGABuffer.FrontBuffer=(void*)malloc(SVGABuffer.BufferSize + 4);
129 if (!SVGABuffer.FrontBuffer) {
130 {
131 fprintf(stderr,"Not enough RAM for FRONT_LEFT_BUFFER...");
132 #ifdef SVGA_DEBUG
133 SVGAlog("SVGAMesaInit: Not enough RAM (front buffer)");
134 #endif
135 return(4);
136 }
137 }
138 #ifdef SVGA_DEBUG
139 sprintf(cbuf,"SVGAMesaInit: FrontBuffer - %p",SVGABuffer.FrontBuffer);
140 SVGAlog(cbuf);
141 #endif
142 SVGABuffer.BackBuffer=(void*)malloc(SVGABuffer.BufferSize + 4);
143 if (!SVGABuffer.BackBuffer) {
144 {
145 free(SVGABuffer.FrontBuffer);
146 fprintf(stderr,"Not enough RAM for BACK_LEFT_BUFFER...");
147 #ifdef SVGA_DEBUG
148 SVGAlog("SVGAMesaInit: Not enough RAM (back buffer)");
149 #endif
150 return(5);
151 }
152 }
153 #ifdef SVGA_DEBUG
154 sprintf(cbuf,"SVGAMesaInit: BackBuffer - %p",SVGABuffer.BackBuffer);
155 SVGAlog(cbuf);
156 #endif
157
158 vga_setmode(GraphMode);
159 SVGABuffer.VideoRam=vga_getgraphmem();
160 #ifdef SVGA_DEBUG
161 sprintf(cbuf,"SVGAMesaInit: VRAM - %p",SVGABuffer.VideoRam);
162 SVGAlog(cbuf);
163 sprintf(cbuf,"SVGAMesaInit: done. (Mode %d)",GraphMode);
164 SVGAlog(cbuf);
165 #endif
166
167 SVGABuffer.DrawBuffer = SVGABuffer.BackBuffer;
168 SVGABuffer.ReadBuffer = SVGABuffer.BackBuffer;
169
170 return 0;
171 }
172
173 int SVGAMesaClose( void )
174 {
175 vga_setmode(TEXT);
176 free(SVGABuffer.FrontBuffer);
177 free(SVGABuffer.BackBuffer);
178 return 0;
179 }
180
181 void SVGAMesaSetCI(int ndx, GLubyte red, GLubyte green, GLubyte blue)
182 {
183 if (ndx<256)
184 vga_setpalette(ndx, red>>2, green>>2, blue>>2);
185 }
186
187 /**********************************************************************/
188 /***** Miscellaneous functions *****/
189 /**********************************************************************/
190
191 static void copy_buffer( const GLubyte * buffer) {
192 int size = SVGABuffer.BufferSize, page = 0;
193
194 #ifdef SVGA_DEBUG
195 sprintf(cbuf,"copy_buffer: copy %p to %p",buffer,SVGABuffer.VideoRam);
196 SVGAlog(cbuf);
197 #endif
198
199 while(size>0) {
200 vga_setpage(page++);
201 if (size>>16) {
202 memcpy(SVGABuffer.VideoRam,buffer,0x10000);
203 buffer+=0x10000;
204 }else{
205 memcpy(SVGABuffer.VideoRam,buffer,size & 0xffff);
206 }
207 size-=0xffff;
208 }
209 }
210
211 static void get_buffer_size( GLcontext *ctx, GLuint *width, GLuint *height )
212 {
213 *width = SVGAMesa->width = vga_getxdim();
214 *height = SVGAMesa->height = vga_getydim();
215 }
216
217 static GLboolean set_draw_buffer( GLcontext *ctx, GLenum buffer )
218 {
219 if (buffer == GL_FRONT_LEFT) {
220 SVGABuffer.DrawBuffer = SVGABuffer.FrontBuffer;
221 #if 0
222 /* vga_waitretrace(); */
223 void * tmpptr;
224 copy_buffer(SVGABuffer.FrontBuffer);
225 tmpptr=SVGABuffer.BackBuffer;
226 SVGABuffer.BackBuffer=SVGABuffer.FrontBuffer;
227 SVGABuffer.FrontBuffer=tmpptr;
228 #endif
229 return GL_TRUE;
230 }
231 else if (buffer == GL_BACK_LEFT) {
232 SVGABuffer.DrawBuffer = SVGABuffer.BackBuffer;
233 #if 0
234 /* vga_waitretrace(); */
235 copy_buffer(SVGABuffer.BackBuffer);
236 #endif
237 return GL_TRUE;
238 }
239 else
240 return GL_FALSE;
241 }
242
243
244 static void set_read_buffer( GLcontext *ctx, GLframebuffer *colorBuffer,
245 GLenum buffer )
246 {
247 /* We can ignore colorBuffer since we don't support a MakeCurrentRead()
248 * function.
249 */
250 (void) colorBuffer;
251
252 if (buffer == GL_FRONT_LEFT) {
253 SVGABuffer.ReadBuffer = SVGABuffer.FrontBuffer;
254 #if 0
255 void * tmpptr;
256 /* vga_waitretrace(); */
257 copy_buffer(SVGABuffer.FrontBuffer);
258 tmpptr=SVGABuffer.BackBuffer;
259 SVGABuffer.BackBuffer=SVGABuffer.FrontBuffer;
260 SVGABuffer.FrontBuffer=tmpptr;
261 #endif
262 }
263 else if (buffer == GL_BACK_LEFT) {
264 SVGABuffer.ReadBuffer = SVGABuffer.BackBuffer;
265 #if 0
266 /* vga_waitretrace(); */
267 copy_buffer(SVGABuffer.BackBuffer);
268 #endif
269 }
270 }
271
272 /**********************************************************************/
273 /***** *****/
274 /**********************************************************************/
275
276 static void svgamesa_update_state( GLcontext *ctx )
277 {
278 /* Initialize all the pointers in the DD struct. Do this whenever */
279 /* a new context is made current or we change buffers via set_buffer! */
280
281 ctx->Driver.UpdateState = svgamesa_update_state;
282
283 ctx->Driver.GetBufferSize = get_buffer_size;
284 ctx->Driver.SetDrawBuffer = set_draw_buffer;
285 ctx->Driver.SetReadBuffer = set_read_buffer;
286
287 ctx->Driver.PointsFunc = NULL;
288 ctx->Driver.LineFunc = NULL;
289 ctx->Driver.TriangleFunc = NULL;
290
291 switch (SVGABuffer.Depth) {
292 case 8: ctx->Driver.ClearIndex = __clear_index8;
293 ctx->Driver.Clear = __clear8;
294 ctx->Driver.Index = __set_index8;
295
296 ctx->Driver.ReadCI32Span = __read_ci32_span8;
297 ctx->Driver.ReadCI32Pixels = __read_ci32_pixels8;
298 ctx->Driver.WriteCI8Span = __write_ci8_span8;
299 ctx->Driver.WriteCI32Span = __write_ci32_span8;
300 ctx->Driver.WriteCI32Pixels = __write_ci32_pixels8;
301 ctx->Driver.WriteMonoCISpan = __write_mono_ci_span8;
302 ctx->Driver.WriteMonoCIPixels = __write_mono_ci_pixels8;
303 #ifdef SVGA_DEBUG
304 SVGAlog("SVGAUpdateState: 8 bit mode.");
305 #endif
306
307 break;
308 case 15: ctx->Driver.ClearColor = __clear_color15;
309 ctx->Driver.Clear = __clear15;
310 ctx->Driver.Color = __set_color15;
311
312 ctx->Driver.ReadRGBASpan = __read_rgba_span15;
313 ctx->Driver.ReadRGBAPixels = __read_rgba_pixels15;
314 ctx->Driver.WriteRGBASpan = __write_rgba_span15;
315 ctx->Driver.WriteRGBAPixels = __write_rgba_pixels15;
316 ctx->Driver.WriteMonoRGBASpan = __write_mono_rgba_span15;
317 ctx->Driver.WriteMonoRGBAPixels = __write_mono_rgba_pixels15;
318 #ifdef SVGA_DEBUG
319 SVGAlog("SVGAUpdateState: 15 bit mode.");
320 #endif
321 break;
322 case 16: ctx->Driver.ClearColor = __clear_color16;
323 ctx->Driver.Clear = __clear16;
324 ctx->Driver.Color = __set_color16;
325
326 ctx->Driver.ReadRGBASpan = __read_rgba_span16;
327 ctx->Driver.ReadRGBAPixels = __read_rgba_pixels16;
328 ctx->Driver.WriteRGBASpan = __write_rgba_span16;
329 ctx->Driver.WriteRGBAPixels = __write_rgba_pixels16;
330 ctx->Driver.WriteMonoRGBASpan = __write_mono_rgba_span16;
331 ctx->Driver.WriteMonoRGBAPixels = __write_mono_rgba_pixels16;
332 break;
333 #ifdef SVGA_DEBUG
334 SVGAlog("SVGAUpdateState: 16 bit mode.");
335 #endif
336 case 24: ctx->Driver.ClearColor = __clear_color24;
337 ctx->Driver.Clear = __clear24;
338 ctx->Driver.Color = __set_color24;
339
340 ctx->Driver.ReadRGBASpan = __read_rgba_span24;
341 ctx->Driver.ReadRGBAPixels = __read_rgba_pixels24;
342 ctx->Driver.WriteRGBASpan = __write_rgba_span24;
343 ctx->Driver.WriteRGBAPixels = __write_rgba_pixels24;
344 ctx->Driver.WriteMonoRGBASpan = __write_mono_rgba_span24;
345 ctx->Driver.WriteMonoRGBAPixels = __write_mono_rgba_pixels24;
346 break;
347 #ifdef SVGA_DEBUG
348 SVGAlog("SVGAUpdateState: 32 bit mode.");
349 #endif
350 case 32: ctx->Driver.ClearColor = __clear_color32;
351 ctx->Driver.Clear = __clear32;
352 ctx->Driver.Color = __set_color32;
353
354 ctx->Driver.ReadRGBASpan = __read_rgba_span32;
355 ctx->Driver.ReadRGBAPixels = __read_rgba_pixels32;
356 ctx->Driver.WriteRGBASpan = __write_rgba_span32;
357 ctx->Driver.WriteRGBAPixels = __write_rgba_pixels32;
358 ctx->Driver.WriteMonoRGBASpan = __write_mono_rgba_span32;
359 ctx->Driver.WriteMonoRGBAPixels = __write_mono_rgba_pixels32;
360 }
361 }
362
363 /*
364 * Create a new VGA/Mesa context and return a handle to it.
365 */
366 SVGAMesaContext SVGAMesaCreateContext( GLboolean doubleBuffer )
367 {
368 SVGAMesaContext ctx;
369 #ifndef DEV
370 GLboolean rgb_flag;
371 GLfloat redscale, greenscale, bluescale, alphascale;
372 GLboolean alpha_flag = GL_FALSE;
373 GLint index_bits;
374 GLint redbits, greenbits, bluebits, alphabits;
375 /* determine if we're in RGB or color index mode */
376 if ((SVGABuffer.Depth==32) || (SVGABuffer.Depth==24)) {
377 rgb_flag = GL_TRUE;
378 redscale = greenscale = bluescale = alphascale = 255.0;
379 redbits = greenbits = bluebits = 8;
380 alphabits = 0;
381 index_bits = 0;
382 }
383 else if (SVGABuffer.Depth==8) {
384 rgb_flag = GL_FALSE;
385 redscale = greenscale = bluescale = alphascale = 0.0;
386 redbits = greenbits = bluebits = alphabits = 0;
387 index_bits = 8;
388 }
389 else if (SVGABuffer.Depth==15) {
390 rgb_flag = GL_TRUE;
391 redscale = greenscale = bluescale = alphascale = 31.0;
392 redbits = greenbits = bluebits = 5;
393 alphabits = 0;
394 index_bits = 0;
395 }
396 else if (SVGABuffer.Depth==16) {
397 rgb_flag = GL_TRUE;
398 redscale = bluescale = alphascale = 31.0;
399 greenscale = 63.0;
400 redbits = bluebits = 5;
401 greenbits = 6;
402 alphabits = 0;
403 index_bits = 0;
404 }
405
406 ctx = (SVGAMesaContext) calloc( 1, sizeof(struct svgamesa_context) );
407 if (!ctx) {
408 return NULL;
409 }
410
411 ctx->gl_vis = gl_create_visual( rgb_flag,
412 alpha_flag,
413 doubleBuffer,
414 GL_FALSE, /* stereo */
415 16, /* depth_size */
416 8, /* stencil_size */
417 16, /* accum_size */
418 index_bits,
419 redbits, greenbits,
420 bluebits, alphabits );
421
422 ctx->gl_ctx = gl_create_context( ctx->gl_vis,
423 NULL, /* share list context */
424 (void *) ctx, GL_TRUE );
425
426 ctx->gl_buffer = gl_create_framebuffer( ctx->gl_vis,
427 ctx->gl_vis->DepthBits > 0,
428 ctx->gl_vis->StencilBits > 0,
429 ctx->gl_vis->AccumRedBits > 0,
430 ctx->gl_vis->AlphaBits > 0 );
431
432 ctx->index = 1;
433 ctx->red = ctx->green = ctx->blue = 255;
434
435 ctx->width = ctx->height = 0; /* temporary until first "make-current" */
436 #endif
437 return ctx;
438 }
439
440 /*
441 * Destroy the given VGA/Mesa context.
442 */
443 void SVGAMesaDestroyContext( SVGAMesaContext ctx )
444 {
445 #ifndef DEV
446 if (ctx) {
447 gl_destroy_visual( ctx->gl_vis );
448 gl_destroy_context( ctx->gl_ctx );
449 gl_destroy_framebuffer( ctx->gl_buffer );
450 free( ctx );
451 if (ctx==SVGAMesa) {
452 SVGAMesa = NULL;
453 }
454 }
455 #endif
456 }
457
458 /*
459 * Make the specified VGA/Mesa context the current one.
460 */
461 void SVGAMesaMakeCurrent( SVGAMesaContext ctx )
462 {
463 #ifndef DEV
464 SVGAMesa = ctx;
465 svgamesa_update_state( ctx->gl_ctx );
466 gl_make_current( ctx->gl_ctx, ctx->gl_buffer );
467
468 if (ctx->width==0 || ctx->height==0) {
469 /* setup initial viewport */
470 ctx->width = vga_getxdim();
471 ctx->height = vga_getydim();
472 gl_Viewport( ctx->gl_ctx, 0, 0, ctx->width, ctx->height );
473 }
474 #endif
475 }
476
477 /*
478 * Return a handle to the current VGA/Mesa context.
479 */
480 SVGAMesaContext SVGAMesaGetCurrentContext( void )
481 {
482 return SVGAMesa;
483 }
484
485 /*
486 * Swap front/back buffers for current context if double buffered.
487 */
488 void SVGAMesaSwapBuffers( void )
489 {
490 #if 000
491 void * tmpptr;
492 #endif
493
494 /* vga_waitretrace(); */
495 copy_buffer(SVGABuffer.BackBuffer);
496
497 #ifndef DEV
498 FLUSH_VB( SVGAMesa->gl_ctx, "swap buffers" );
499 if (SVGAMesa->gl_vis->DBflag)
500 #endif /* DEV */
501 {
502 #ifdef SVGA_DEBUG
503 sprintf(cbuf,"SVGAMesaSwapBuffers : Swapping...");
504 SVGAlog(cbuf);
505 #endif /* SVGA_DEBUG */
506 #if 000
507 tmpptr=SVGABuffer.BackBuffer;
508 SVGABuffer.BackBuffer=SVGABuffer.FrontBuffer;
509 SVGABuffer.FrontBuffer=tmpptr;
510 #endif
511 #ifdef SVGA_DEBUG
512 sprintf(cbuf,"SVGAMesaSwapBuffers : WriteBuffer : %p\n"
513 " Readbuffer : %p", \
514 SVGABuffer.BackBuffer, SVGABuffer.FrontBuffer );
515 SVGAlog(cbuf);
516 #endif /* SVGA_DEBUG */
517 }
518 }
519
520 #else /*SVGA*/
521
522 /*
523 * Need this to provide at least one external definition when SVGA is
524 * not defined on the compiler command line.
525 */
526
527 int gl_svga_dummy_function(void)
528 {
529 return 0;
530 }
531
532 #endif /*SVGA*/
533