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