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