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