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