3 * Copyright (C) 1997-1998 Uwe Maurer - uwe_maurer@t-online.de
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 * ---------------------------------------------------------------------
19 * This code was derived from the following source of information:
21 * svgamesa.c and ddsample.c by Brian Paul
31 #include <ggi/mesa/ggimesa_int.h>
32 #include <ggi/mesa/debug.h>
36 #define VIS (GGIMesa->ggi_vis)
37 #define FLIP(y) (GGIMesa->flip_y-(y))
39 GGIMesaContext GGIMesa
= NULL
; /* the current context */
41 ggi_extid ggiMesaID
= -1;
42 static int _ggimesaLibIsUp
= 0;
43 static void *_ggimesaConfigHandle
;
45 /* FIXME: These should really be defined in the make system using -Dxxx */
46 #define GGIMESACONFFILE "/usr/local/etc/ggi/ggimesa.conf"
47 #define GGIMESATAGLEN 0
48 static char ggimesaconfstub
[512] = GGIMESACONFFILE
;
49 static char *ggimesaconffile
= ggimesaconfstub
+ GGIMESATAGLEN
;
51 int gl_ggi_init
= GL_FALSE
;
52 int gl_ggi_debug
= GL_FALSE
;
54 static void gl_ggiUpdateState(GLcontext
*ctx
);
55 static int changed(ggi_visual_t vis
, int whatchanged
);
58 /* FIXME: Move this debugging stuff to include/ggi/mesa/internal/ */
59 void gl_ggiPrint(char *format
,...)
62 va_start(args
,format
);
63 fprintf(stderr
,"GGIMesa: ");
64 vfprintf(stderr
,format
,args
);
68 void gl_ggiDEBUG(char *format
,...)
73 va_start(args
,format
);
74 fprintf(stderr
,"GGIMesa: ");
75 vfprintf(stderr
,format
,args
);
81 static void gl_ggiGetSize(GLcontext
*ctx
, GLuint
*width
, GLuint
*height
)
83 *width
= GGIMesa
->width
;
84 *height
= GGIMesa
->height
;
87 static void gl_ggiSetIndex(GLcontext
*ctx
, GLuint ci
)
89 ggiSetGCForeground(VIS
, ci
);
90 GGICTX
->color
= (ggi_pixel
)ci
;
93 static void gl_ggiSetClearIndex(GLcontext
*ctx
, GLuint ci
)
95 ggiSetGCForeground(VIS
, ci
);
96 GGICTX
->clearcolor
= (ggi_pixel
)ci
;
99 static void gl_ggiSetColor(GLcontext
*ctx
, GLubyte red
, GLubyte green
,
100 GLubyte blue
, GLubyte alpha
)
105 rgb
.r
= (uint16
)red
<< SHIFT
;
106 rgb
.g
= (uint16
)green
<< SHIFT
;
107 rgb
.b
= (uint16
)blue
<< SHIFT
;
108 col
= ggiMapColor(VIS
, &rgb
);
109 ggiSetGCForeground(VIS
, col
);
113 static void gl_ggiSetClearColor(GLcontext
*ctx
, GLubyte red
, GLubyte green
,
114 GLubyte blue
, GLubyte alpha
)
118 rgb
.r
= (uint16
)red
<< SHIFT
;
119 rgb
.g
= (uint16
)green
<< SHIFT
;
120 rgb
.b
= (uint16
)blue
<< SHIFT
;
121 col
= ggiMapColor(VIS
, &rgb
);
122 ggiSetGCForeground(VIS
, col
);
123 GGICTX
->clearcolor
= col
;
126 static GLbitfield
gl_ggiClear(GLcontext
*ctx
,GLbitfield mask
, GLboolean all
,
127 GLint x
, GLint y
, GLint width
, GLint height
)
130 if (mask
& GL_COLOR_BUFFER_BIT
)
132 ggiSetGCForeground(VIS
, GGICTX
->clearcolor
);
136 ggiDrawBox(VIS
, 0, GGIMesa
->origin
.y
,
137 GGIMesa
->width
, GGIMesa
->height
);
141 ggiDrawBox(VIS
, x
, FLIP(y
), width
, height
);
144 ggiSetGCForeground(VIS
, GGICTX
->color
);
146 return mask
& (~GL_COLOR_BUFFER_BIT
);
150 static GLboolean
gl_ggiSetBuffer(GLcontext
*ctx
, GLenum mode
)
152 if (mode
== GL_FRONT
)
153 GGICTX
->active_buffer
= 1;
155 GGICTX
->active_buffer
= 0;
161 /* Set the buffer used for drawing */
162 static GLboolean
gl_ggiSetDrawBuffer(GLcontext
*ctx
, GLenum mode
)
164 if (mode
== GL_FRONT_LEFT
)
166 GGICTX
->active_buffer
= 1;
169 else if (mode
== GL_BACK_LEFT
)
171 GGICTX
->active_buffer
= 0;
181 /* Set the buffer used for reading */
182 /* XXX support for separate read/draw buffers hasn't been tested */
183 static void gl_ggiSetReadBuffer(GLcontext
*ctx
, GLframebuffer
*buffer
, GLenum mode
)
185 if (mode
== GL_FRONT_LEFT
)
187 GGICTX
->active_buffer
= 1;
189 else if (mode
== GL_BACK_LEFT
)
191 GGICTX
->active_buffer
= 0;
196 static const GLubyte
* gl_ggiGetString(GLcontext
*ctx
, GLenum name
)
198 if (name
== GL_RENDERER
)
199 return (GLubyte
*) "Mesa GGI";
204 static void gl_ggiFlush(GLcontext
*ctx
)
209 static void gl_ggiSetupPointers( GLcontext
*ctx
)
211 /* Initialize all the pointers in the DD struct. Do this whenever */
212 /* a new context is made current or we change buffers via set_buffer! */
214 ctx
->Driver
.GetString
= gl_ggiGetString
;
215 ctx
->Driver
.UpdateState
= gl_ggiUpdateState
;
217 ctx
->Driver
.ClearIndex
= gl_ggiSetClearIndex
;
218 ctx
->Driver
.ClearColor
= gl_ggiSetClearColor
;
219 ctx
->Driver
.Clear
= gl_ggiClear
;
220 ctx
->Driver
.Index
= gl_ggiSetIndex
;
221 ctx
->Driver
.Color
= gl_ggiSetColor
;
223 ctx
->Driver
.SetDrawBuffer
= gl_ggiSetDrawBuffer
;
224 ctx
->Driver
.SetReadBuffer
= gl_ggiSetReadBuffer
;
226 ctx
->Driver
.GetBufferSize
= gl_ggiGetSize
;
227 ctx
->Driver
.Finish
= gl_ggiFlush
;
228 ctx
->Driver
.Flush
= gl_ggiFlush
;
232 static int gl_ggiInitInfo(GGIMesaContext ctx
, struct ggi_mesa_info
*info
)
236 ggiGetMode(ctx
->ggi_vis
, &mode
);
238 info
->depth_bits
= DEFAULT_SOFTWARE_DEPTH_BITS
;
239 info
->stencil_bits
= STENCIL_BITS
;
240 info
->accum_bits
= ACCUM_BITS
;
244 info
->rgb_flag
= GL_TRUE
;
245 info
->alpha_flag
= GL_FALSE
;
246 info
->index_bits
= 0;
249 info
->green_bits
= 8;
252 info
->alpha_bits
= 0;
256 info
->alpha_flag
= GL_FALSE
;
258 info
->index_bits
= GT_SIZE(mode
.graphtype
);
259 info
->red_bits
= info
->green_bits
=
260 info
->blue_bits
= info
->alpha_bits
= 0;
271 if (_ggimesaLibIsUp
> 1)
272 return 0; /* Initialize only at first call */
274 err
= ggLoadConfig(ggimesaconffile
, &_ggimesaConfigHandle
);
277 fprintf(stderr
, "GGIMesa: Couldn't open %s\n", ggimesaconffile
);
282 ggiMesaID
= ggiExtensionRegister("GGIMesa", sizeof(struct mesa_ext
), changed
);
286 fprintf(stderr
, "GGIMesa: failed to register as extension\n");
288 ggFreeConfig(_ggimesaConfigHandle
);
296 GGIMesaContext
GGIMesaCreateContext(void)
301 s
= getenv("GGIMESA_DEBUG");
302 gl_ggi_debug
= (s
&& atoi(s
));
304 if (ggiMesaInit() < 0) /* register extensions*/
309 ctx
= (GGIMesaContext
)calloc(1, sizeof(struct ggi_mesa_context
));
313 ctx
->gl_vis
= (GLvisual
*)calloc(1, sizeof(GLvisual
));
317 ctx
->viewport_init
= GL_FALSE
;
318 ctx
->gl_vis
->DBflag
= GL_FALSE
;
320 ctx
->gl_ctx
= gl_create_context(ctx
->gl_vis
, NULL
, (void *)ctx
, GL_TRUE
);
327 void GGIMesaDestroyContext(GGIMesaContext ctx
)
331 gl_destroy_visual(ctx
->gl_vis
);
332 gl_destroy_context(ctx
->gl_ctx
);
333 gl_destroy_framebuffer(ctx
->gl_buffer
);
337 ggiExtensionDetach(ctx
->ggi_vis
, ggiMesaID
);
338 ggiExtensionUnregister(ggiMesaID
);
343 int GGIMesaSetVisual(GGIMesaContext ctx
, ggi_visual_t vis
,
344 GLboolean rgb_flag
, GLboolean db_flag
)
346 struct ggi_mesa_info info
;
359 ggiExtensionDetach(ctx
->ggi_vis
, ggiMesaID
);
363 err
= ggiExtensionAttach(vis
, ggiMesaID
);
367 changed(vis
, GGI_CHG_APILIST
);
370 gl_destroy_visual(ctx
->gl_vis
);
373 gl_destroy_framebuffer(ctx
->gl_buffer
);
375 info
.rgb_flag
= rgb_flag
;
376 info
.db_flag
= db_flag
;
378 err
= gl_ggiInitInfo(ctx
, &info
);
382 gl_ggiSetupPointers(ctx
->gl_ctx
);
384 func
= (void *)LIBGGI_MESAEXT(ctx
->ggi_vis
)->setup_driver
;
388 fprintf(stderr
, "setup_driver==NULL!\n");
389 fprintf(stderr
, "Please check your config files!\n");
393 err
= LIBGGI_MESAEXT(ctx
->ggi_vis
)->setup_driver(ctx
, &info
);
397 ctx
->gl_vis
= gl_create_visual(info
.rgb_flag
,
405 info
.red_bits
, info
.green_bits
,
406 info
.blue_bits
, info
.alpha_bits
);
409 fprintf(stderr
, "Can't create gl_visual!\n");
413 ctx
->gl_buffer
= gl_create_framebuffer(ctx
->gl_vis
,
414 ctx
->gl_vis
->DepthBits
> 0,
415 ctx
->gl_vis
->StencilBits
> 0,
416 ctx
->gl_vis
->AccumRedBits
> 0,
417 ctx
->gl_vis
->AlphaBits
> 0);
422 fprintf(stderr
, "Can't create gl_buffer!\n");
426 ggiGetMode(ctx
->ggi_vis
, &mode
);
427 ctx
->width
= mode
.visible
.x
;
428 ctx
->height
= mode
.visible
.y
;
429 ctx
->stride
= mode
.virt
.x
;
432 ctx
->flip_y
= ctx
->origin
.y
+ ctx
->height
- 1;
436 ctx
->lfb
[0] = ctx
->lfb
[1] = NULL
;
437 num_buf
= ggiDBGetNumBuffers(ctx
->ggi_vis
);
439 for (i
= 0; i
< num_buf
; i
++)
441 if (ggiDBGetBuffer(ctx
->ggi_vis
,i
)->layout
== blPixelLinearBuffer
)
443 ctx
->stride
= ggiDBGetBuffer(ctx
->ggi_vis
, i
)->buffer
.plb
.stride
/
444 (ggiDBGetBuffer(ctx
->ggi_vis
, i
)->buffer
.plb
.pixelformat
->size
/ 8);
445 ctx
->lfb
[0] = ggiDBGetBuffer(ctx
->ggi_vis
, i
)->write
;
449 if (ctx
->lfb
[0] == NULL
)
451 fprintf(stderr
, "No linear frame buffer!\n");
455 /* FIXME: Use separate buffers */
456 ctx
->lfb
[1] = malloc(ctx
->stride
* ctx
->height
);
457 ctx
->bufsize
= (ctx
->stride
* ctx
->height
);
459 ctx
->gl_ctx
->Visual
= ctx
->gl_vis
;
460 ctx
->gl_ctx
->Pixel
.ReadBuffer
=
461 ctx
->gl_ctx
->Color
.DrawBuffer
= (db_flag
) ? GL_BACK
: GL_FRONT
;
464 gl_make_current(ctx
->gl_ctx
, ctx
->gl_buffer
);
466 if (rgb_flag
&& mode
.graphtype
==GT_8BIT
)
468 for (i
= r
= 0; r
< 8; r
++)
469 for (g
= 0; g
< 8; g
++)
470 for (b
= 0; b
< 4; b
++, i
++)
472 pal
[i
].r
= r
<< (GGI_COLOR_PRECISION
- 3);
473 pal
[i
].g
= g
<< (GGI_COLOR_PRECISION
- 3);
474 pal
[i
].b
= b
<< (GGI_COLOR_PRECISION
- 2);
476 ggiSetPalette(ctx
->ggi_vis
, 0, 256, pal
);
482 void GGIMesaMakeCurrent(GGIMesaContext ctx
)
488 gl_make_current(ctx
->gl_ctx
, ctx
->gl_buffer
);
490 if (!ctx
->viewport_init
)
492 gl_Viewport(ctx
->gl_ctx
, 0, 0, ctx
->width
, ctx
->height
);
493 ctx
->viewport_init
= GL_TRUE
;
498 GGIMesaContext
GGIMesaGetCurrentContext(void)
504 * Swap front/back buffers for current context if double buffered.
506 void GGIMesaSwapBuffers(void)
508 GGIMESADPRINT_CORE("GGIMesaSwapBuffers\n");
510 FLUSH_VB(GGIMesa
->gl_ctx
, "swap buffers");
511 gl_ggiFlush(GGIMesa
->gl_ctx
);
513 if (GGIMesa
->gl_vis
->DBflag
)
515 memcpy(GGIMesa
->lfb
[0], GGIMesa
->lfb
[1], GGIMesa
->bufsize
);
519 static void gl_ggiUpdateState(GLcontext
*ctx
)
523 func
= (void *)CTX_OPMESA(ctx
)->update_state
;
526 fprintf(stderr
, "update_state == NULL!\n");
527 fprintf(stderr
, "Please check your config files!\n");
531 CTX_OPMESA(ctx
)->update_state(ctx
);
534 static int changed(ggi_visual_t vis
, int whatchanged
)
538 case GGI_CHG_APILIST
:
546 for (i
= 0; ggiGetAPI(vis
, i
, api
, args
) == 0; i
++)
548 strcat(api
, "-mesa");
549 fname
= ggMatchConfig(_ggimesaConfigHandle
, api
, NULL
);
552 /* No special implementation for this sublib */
555 lib
= ggiExtensionLoadDL(vis
, fname
, args
, NULL
, GGI_SYMNAME_PREFIX
);
564 int ggiMesaExit(void)
568 if (!_ggimesaLibIsUp
)
571 if (_ggimesaLibIsUp
> 1)
573 /* Exit only at last call */
578 rc
= ggiExtensionUnregister(ggiMesaID
);
579 ggFreeConfig(_ggimesaConfigHandle
);
586 static int _ggi_error(void)
591 int ggiMesaAttach(ggi_visual_t vis
)
595 rc
= ggiExtensionAttach(vis
, ggiMesaID
);
598 /* We are creating the primary instance */
599 memset(LIBGGI_MESAEXT(vis
), 0, sizeof(mesaext
));
600 LIBGGI_MESAEXT(vis
)->update_state
= (void *)_ggi_error
;
601 LIBGGI_MESAEXT(vis
)->setup_driver
= (void *)_ggi_error
;
603 /* Now fake an "API change" so the right libs get loaded */
604 changed(vis
, GGI_CHG_APILIST
);
610 int ggiMesaDetach(ggi_visual_t vis
)
612 return ggiExtensionDetach(vis
, ggiMesaID
);
618 * Need this to provide at least one external definition when GGI is
619 * not defined on the compiler command line.
622 int gl_ggi_dummy_function(void)