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
29 #include <ggi/mesa/ggimesa_int.h>
30 #include <ggi/mesa/debug.h>
31 #include "extensions.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 _ggimesaDebugSync
= 0;
52 uint32 _ggimesaDebugState
= 0;
54 static void gl_ggiUpdateState(GLcontext
*ctx
);
55 static int changed(ggi_visual_t vis
, int whatchanged
);
57 static void gl_ggiGetSize(GLcontext
*ctx
, GLuint
*width
, GLuint
*height
)
59 GGIMESADPRINT_CORE("gl_ggiGetSize() called\n");
61 *width
= GGIMesa
->width
;
62 *height
= GGIMesa
->height
;
65 static void gl_ggiSetIndex(GLcontext
*ctx
, GLuint ci
)
67 GGIMESADPRINT_CORE("gl_ggiSetIndex() called\n");
69 ggiSetGCForeground(VIS
, ci
);
70 GGICTX
->color
= (ggi_pixel
)ci
;
73 static void gl_ggiSetClearIndex(GLcontext
*ctx
, GLuint ci
)
75 GGIMESADPRINT_CORE("gl_ggiSetClearIndex() called\n");
77 ggiSetGCForeground(VIS
, ci
);
78 GGICTX
->clearcolor
= (ggi_pixel
)ci
;
81 static void gl_ggiSetColor(GLcontext
*ctx
, GLubyte red
, GLubyte green
,
82 GLubyte blue
, GLubyte alpha
)
87 GGIMESADPRINT_CORE("gl_ggiSetColor() called\n");
89 rgb
.r
= (uint16
)red
<< SHIFT
;
90 rgb
.g
= (uint16
)green
<< SHIFT
;
91 rgb
.b
= (uint16
)blue
<< SHIFT
;
92 col
= ggiMapColor(VIS
, &rgb
);
93 ggiSetGCForeground(VIS
, col
);
97 static void gl_ggiSetClearColor(GLcontext
*ctx
, GLubyte red
, GLubyte green
,
98 GLubyte blue
, GLubyte alpha
)
103 GGIMESADPRINT_CORE("gl_ggiSetClearColor() called\n");
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
);
110 GGICTX
->clearcolor
= col
;
113 static GLbitfield
gl_ggiClear(GLcontext
*ctx
,GLbitfield mask
, GLboolean all
,
114 GLint x
, GLint y
, GLint width
, GLint height
)
116 GGIMESADPRINT_CORE("gl_ggiClear() called\n");
118 if (mask
& GL_COLOR_BUFFER_BIT
)
120 ggiSetGCForeground(VIS
, GGICTX
->clearcolor
);
124 ggiDrawBox(VIS
, 0, GGIMesa
->origin
.y
,
125 GGIMesa
->width
, GGIMesa
->height
);
129 ggiDrawBox(VIS
, x
, FLIP(y
), width
, height
);
132 ggiSetGCForeground(VIS
, GGICTX
->color
);
134 return mask
& (~GL_COLOR_BUFFER_BIT
);
138 static GLboolean
gl_ggiSetBuffer(GLcontext
*ctx
, GLenum mode
)
140 GGIMESADPRINT_CORE("gl_ggiSetBuffer() called\n");
142 if (mode
== GL_FRONT
)
143 GGICTX
->active_buffer
= 1;
145 GGICTX
->active_buffer
= 0;
151 /* Set the buffer used for drawing */
152 static GLboolean
gl_ggiSetDrawBuffer(GLcontext
*ctx
, GLenum mode
)
154 GGIMESADPRINT_CORE("gl_ggiSetDrawBuffer() called\n");
156 if (mode
== GL_FRONT_LEFT
)
158 GGICTX
->active_buffer
= 1;
161 else if (mode
== GL_BACK_LEFT
)
163 GGICTX
->active_buffer
= 0;
173 /* Set the buffer used for reading */
174 /* XXX support for separate read/draw buffers hasn't been tested */
175 static void gl_ggiSetReadBuffer(GLcontext
*ctx
, GLframebuffer
*buffer
, GLenum mode
)
177 GGIMESADPRINT_CORE("gl_ggiSetReadBuffer() called\n");
179 if (mode
== GL_FRONT_LEFT
)
181 GGICTX
->active_buffer
= 1;
183 else if (mode
== GL_BACK_LEFT
)
185 GGICTX
->active_buffer
= 0;
190 static const GLubyte
* gl_ggiGetString(GLcontext
*ctx
, GLenum name
)
192 GGIMESADPRINT_CORE("gl_ggiGetString() called\n");
194 if (name
== GL_RENDERER
)
195 return (GLubyte
*) "Mesa GGI";
200 static void gl_ggiFlush(GLcontext
*ctx
)
202 GGIMESADPRINT_CORE("gl_ggiFlush() called\n");
207 static void gl_ggiSetupPointers(GLcontext
*ctx
)
209 GGIMESADPRINT_CORE("gl_ggiSetupPointers() called\n");
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
;
221 ctx
->Driver
.SetDrawBuffer
= gl_ggiSetDrawBuffer
;
222 ctx
->Driver
.SetReadBuffer
= gl_ggiSetReadBuffer
;
224 ctx
->Driver
.GetBufferSize
= gl_ggiGetSize
;
225 ctx
->Driver
.Finish
= gl_ggiFlush
;
226 ctx
->Driver
.Flush
= gl_ggiFlush
;
229 static int gl_ggiInitInfo(GGIMesaContext ctx
, struct ggi_mesa_info
*info
)
233 GGIMESADPRINT_CORE("gl_ggiInitInfo() called\n");
235 ggiGetMode(ctx
->ggi_vis
, &mode
);
237 info
->depth_bits
= DEFAULT_SOFTWARE_DEPTH_BITS
;
238 info
->stencil_bits
= STENCIL_BITS
;
239 info
->accum_bits
= ACCUM_BITS
;
243 info
->rgb_flag
= GL_TRUE
;
244 info
->alpha_flag
= GL_FALSE
;
245 info
->index_bits
= 0;
248 info
->green_bits
= 8;
251 info
->alpha_bits
= 0;
255 info
->alpha_flag
= GL_FALSE
;
257 info
->index_bits
= GT_SIZE(mode
.graphtype
);
258 info
->red_bits
= info
->green_bits
=
259 info
->blue_bits
= info
->alpha_bits
= 0;
270 GGIMESADPRINT_CORE("ggiMesaInit() called\n");
272 str
= getenv("GGIMESA_DEBUG");
274 _ggimesaDebugState
= atoi(str
);
275 GGIMESADPRINT_CORE("Debugging=%d\n", _ggimesaDebugState
);
278 str
= getenv("GGIMESA_DEBUGSYNC");
280 _ggimesaDebugSync
= 1;
283 GGIMESADPRINT_CORE("ggiMesaInit()\n");
286 if (_ggimesaLibIsUp
> 1)
287 return 0; /* Initialize only at first call */
289 err
= ggLoadConfig(ggimesaconffile
, &_ggimesaConfigHandle
);
292 GGIMESADPRINT_CORE("GGIMesa: Couldn't open %s\n", ggimesaconffile
);
297 ggiMesaID
= ggiExtensionRegister("GGIMesa", sizeof(struct mesa_ext
), changed
);
301 GGIMESADPRINT_CORE("GGIMesa: failed to register as extension\n");
303 ggFreeConfig(_ggimesaConfigHandle
);
311 GGIMesaContext
GGIMesaCreateContext(void)
316 GGIMESADPRINT_CORE("ggiMesaCreateContext() called\n");
318 if (ggiMesaInit() < 0) /* register extensions*/
323 ctx
= (GGIMesaContext
)calloc(1, sizeof(struct ggi_mesa_context
));
327 ctx
->gl_vis
= (GLvisual
*)calloc(1, sizeof(GLvisual
));
331 ctx
->viewport_init
= GL_FALSE
;
332 ctx
->gl_vis
->DBflag
= GL_FALSE
;
334 ctx
->gl_ctx
= _mesa_create_context(ctx
->gl_vis
, NULL
, (void *)ctx
, GL_TRUE
);
338 _mesa_enable_sw_extensions(ctx
->gl_ctx
);
343 void GGIMesaDestroyContext(GGIMesaContext ctx
)
345 GGIMESADPRINT_CORE("ggiMesaDestroyContext() called\n");
349 _mesa_destroy_visual(ctx
->gl_vis
);
350 _mesa_destroy_context(ctx
->gl_ctx
);
351 _mesa_destroy_framebuffer(ctx
->gl_buffer
);
355 ggiExtensionDetach(ctx
->ggi_vis
, ggiMesaID
);
356 ggiExtensionUnregister(ggiMesaID
);
361 int GGIMesaSetVisual(GGIMesaContext ctx
, ggi_visual_t vis
,
362 GLboolean rgb_flag
, GLboolean db_flag
)
364 struct ggi_mesa_info info
;
373 GGIMESADPRINT_CORE("ggiMesaSetVisual() called\n");
379 ggiExtensionDetach(ctx
->ggi_vis
, ggiMesaID
);
383 err
= ggiExtensionAttach(vis
, ggiMesaID
);
387 changed(vis
, GGI_CHG_APILIST
);
390 _mesa_destroy_visual(ctx
->gl_vis
);
393 _mesa_destroy_framebuffer(ctx
->gl_buffer
);
395 info
.rgb_flag
= rgb_flag
;
396 info
.db_flag
= db_flag
;
398 err
= gl_ggiInitInfo(ctx
, &info
);
402 gl_ggiSetupPointers(ctx
->gl_ctx
);
404 func
= (void *)LIBGGI_MESAEXT(ctx
->ggi_vis
)->setup_driver
;
408 GGIMESADPRINT_CORE("setup_driver==NULL!\n");
409 GGIMESADPRINT_CORE("Please check your config files!\n");
413 err
= LIBGGI_MESAEXT(ctx
->ggi_vis
)->setup_driver(ctx
, &info
);
417 ctx
->gl_vis
= _mesa_create_visual(info
.rgb_flag
,
420 info
.red_bits
, info
.green_bits
,
421 info
.blue_bits
, info
.alpha_bits
,
432 GGIMESADPRINT_CORE("Can't create gl_visual!\n");
436 ctx
->gl_buffer
= _mesa_create_framebuffer(ctx
->gl_vis
,
437 ctx
->gl_vis
->DepthBits
> 0,
438 ctx
->gl_vis
->StencilBits
> 0,
439 ctx
->gl_vis
->AccumRedBits
> 0,
440 ctx
->gl_vis
->AlphaBits
> 0);
445 GGIMESADPRINT_CORE("Can't create gl_buffer!\n");
449 ggiGetMode(ctx
->ggi_vis
, &mode
);
450 ctx
->width
= mode
.visible
.x
;
451 ctx
->height
= mode
.visible
.y
;
452 ctx
->stride
= mode
.virt
.x
;
455 ctx
->flip_y
= ctx
->origin
.y
+ ctx
->height
- 1;
459 ctx
->lfb
[0] = ctx
->lfb
[1] = NULL
;
460 num_buf
= ggiDBGetNumBuffers(ctx
->ggi_vis
);
462 for (i
= 0; i
< num_buf
; i
++)
464 if (ggiDBGetBuffer(ctx
->ggi_vis
,i
)->layout
== blPixelLinearBuffer
)
466 ctx
->stride
= ggiDBGetBuffer(ctx
->ggi_vis
, i
)->buffer
.plb
.stride
/
467 (ggiDBGetBuffer(ctx
->ggi_vis
, i
)->buffer
.plb
.pixelformat
->size
/ 8);
468 ctx
->lfb
[0] = ggiDBGetBuffer(ctx
->ggi_vis
, i
)->write
;
472 if (ctx
->lfb
[0] == NULL
)
474 GGIMESADPRINT_CORE("No linear frame buffer!\n");
478 /* FIXME: Use separate buffers */
479 ctx
->lfb
[1] = malloc(ctx
->stride
* ctx
->height
);
480 ctx
->bufsize
= (ctx
->stride
* ctx
->height
);
482 ctx
->gl_ctx
->Visual
= *ctx
->gl_vis
;
483 ctx
->gl_ctx
->Pixel
.ReadBuffer
=
484 ctx
->gl_ctx
->Color
.DrawBuffer
= (db_flag
) ? GL_BACK
: GL_FRONT
;
487 _mesa_make_current(ctx
->gl_ctx
, ctx
->gl_buffer
);
489 if (rgb_flag
&& mode
.graphtype
==GT_8BIT
)
491 for (i
= r
= 0; r
< 8; r
++)
492 for (g
= 0; g
< 8; g
++)
493 for (b
= 0; b
< 4; b
++, i
++)
495 pal
[i
].r
= r
<< (GGI_COLOR_PRECISION
- 3);
496 pal
[i
].g
= g
<< (GGI_COLOR_PRECISION
- 3);
497 pal
[i
].b
= b
<< (GGI_COLOR_PRECISION
- 2);
499 ggiSetPalette(ctx
->ggi_vis
, 0, 256, pal
);
505 void GGIMesaMakeCurrent(GGIMesaContext ctx
)
507 GGIMESADPRINT_CORE("ggiMesaMakeCurrent(ctx = %p) called\n", ctx
);
513 _mesa_make_current(ctx
->gl_ctx
, ctx
->gl_buffer
);
515 if (!ctx
->viewport_init
)
517 gl_Viewport(ctx
->gl_ctx
, 0, 0, ctx
->width
, ctx
->height
);
518 ctx
->viewport_init
= GL_TRUE
;
523 GGIMesaContext
GGIMesaGetCurrentContext(void)
525 GGIMESADPRINT_CORE("ggiMesaGetCurrentContext() called\n");
531 * Swap front/back buffers for current context if double buffered.
533 void GGIMesaSwapBuffers(void)
535 GGIMESADPRINT_CORE("ggiMesaSwapBuffers() called\n");
537 _mesa_swapbuffers( GGIMesa
->gl_ctx
);
538 gl_ggiFlush(GGIMesa
->gl_ctx
);
540 if (GGIMesa
->gl_vis
->DBflag
)
542 memcpy(GGIMesa
->lfb
[0], GGIMesa
->lfb
[1], GGIMesa
->bufsize
);
546 static void gl_ggiUpdateState(GLcontext
*ctx
)
550 GGIMESADPRINT_CORE("gl_ggiUpdateState() called\n");
552 func
= (void *)CTX_OPMESA(ctx
)->update_state
;
555 GGIMESADPRINT_CORE("update_state == NULL!\n");
556 GGIMESADPRINT_CORE("Please check your config files!\n");
560 CTX_OPMESA(ctx
)->update_state(ctx
);
563 static int changed(ggi_visual_t vis
, int whatchanged
)
565 GGIMESADPRINT_CORE("changed() called\n");
569 case GGI_CHG_APILIST
:
577 for (i
= 0; ggiGetAPI(vis
, i
, api
, args
) == 0; i
++)
579 strcat(api
, "-mesa");
580 fname
= ggMatchConfig(_ggimesaConfigHandle
, api
, NULL
);
583 /* No special implementation for this sublib */
586 lib
= ggiExtensionLoadDL(vis
, fname
, args
, NULL
, GGI_SYMNAME_PREFIX
);
595 int ggiMesaExit(void)
599 GGIMESADPRINT_CORE("ggiMesaExit() called\n");
601 if (!_ggimesaLibIsUp
)
604 if (_ggimesaLibIsUp
> 1)
606 /* Exit only at last call */
611 rc
= ggiExtensionUnregister(ggiMesaID
);
612 ggFreeConfig(_ggimesaConfigHandle
);
619 static int _ggi_error(void)
621 GGIMESADPRINT_CORE("_ggi_error() called\n");
626 int ggiMesaAttach(ggi_visual_t vis
)
630 GGIMESADPRINT_CORE("ggiMesaAttach() called\n");
632 rc
= ggiExtensionAttach(vis
, ggiMesaID
);
635 /* We are creating the primary instance */
636 memset(LIBGGI_MESAEXT(vis
), 0, sizeof(mesaext
));
637 LIBGGI_MESAEXT(vis
)->update_state
= (void *)_ggi_error
;
638 LIBGGI_MESAEXT(vis
)->setup_driver
= (void *)_ggi_error
;
640 /* Now fake an "API change" so the right libs get loaded */
641 changed(vis
, GGI_CHG_APILIST
);
647 int ggiMesaDetach(ggi_visual_t vis
)
649 GGIMESADPRINT_CORE("ggiMesaDetach() called\n");
651 return ggiExtensionDetach(vis
, ggiMesaID
);