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"
33 #include "swrast/swrast.h"
34 #include "swrast_setup/swrast_setup.h"
39 #define VIS (GGIMesa->ggi_vis)
40 #define FLIP(y) (GGIMesa->flip_y-(y))
42 GGIMesaContext GGIMesa
= NULL
; /* the current context */
44 ggi_extid ggiMesaID
= -1;
45 static int _ggimesaLibIsUp
= 0;
46 static void *_ggimesaConfigHandle
;
48 /* FIXME: These should really be defined in the make system using -Dxxx */
49 #define GGIMESACONFFILE "/usr/local/etc/ggi/ggimesa.conf"
50 #define GGIMESATAGLEN 0
51 static char ggimesaconfstub
[512] = GGIMESACONFFILE
;
52 static char *ggimesaconffile
= ggimesaconfstub
+ GGIMESATAGLEN
;
54 int _ggimesaDebugSync
= 0;
55 uint32 _ggimesaDebugState
= 0;
57 static void gl_ggiUpdateState(GLcontext
*ctx
);
58 static int changed(ggi_visual_t vis
, int whatchanged
);
60 static void gl_ggiGetSize(GLcontext
*ctx
, GLuint
*width
, GLuint
*height
)
62 GGIMESADPRINT_CORE("gl_ggiGetSize() called\n");
64 *width
= GGIMesa
->width
;
65 *height
= GGIMesa
->height
;
68 static void gl_ggiSetIndex(GLcontext
*ctx
, GLuint ci
)
70 GGIMESADPRINT_CORE("gl_ggiSetIndex() called\n");
72 ggiSetGCForeground(VIS
, ci
);
73 GGICTX
->color
= (ggi_pixel
)ci
;
76 static void gl_ggiSetClearIndex(GLcontext
*ctx
, GLuint ci
)
78 GGIMESADPRINT_CORE("gl_ggiSetClearIndex() called\n");
80 ggiSetGCForeground(VIS
, ci
);
81 GGICTX
->clearcolor
= (ggi_pixel
)ci
;
84 static void gl_ggiSetColor(GLcontext
*ctx
, GLubyte red
, GLubyte green
,
85 GLubyte blue
, GLubyte alpha
)
90 GGIMESADPRINT_CORE("gl_ggiSetColor() called\n");
92 rgb
.r
= (uint16
)red
<< SHIFT
;
93 rgb
.g
= (uint16
)green
<< SHIFT
;
94 rgb
.b
= (uint16
)blue
<< SHIFT
;
95 col
= ggiMapColor(VIS
, &rgb
);
96 ggiSetGCForeground(VIS
, col
);
100 static void gl_ggiSetClearColor(GLcontext
*ctx
, GLubyte red
, GLubyte green
,
101 GLubyte blue
, GLubyte alpha
)
106 GGIMESADPRINT_CORE("gl_ggiSetClearColor() called\n");
108 rgb
.r
= (uint16
)red
<< SHIFT
;
109 rgb
.g
= (uint16
)green
<< SHIFT
;
110 rgb
.b
= (uint16
)blue
<< SHIFT
;
111 col
= ggiMapColor(VIS
, &rgb
);
112 ggiSetGCForeground(VIS
, col
);
113 GGICTX
->clearcolor
= col
;
116 static GLbitfield
gl_ggiClear(GLcontext
*ctx
,GLbitfield mask
, GLboolean all
,
117 GLint x
, GLint y
, GLint width
, GLint height
)
119 GGIMESADPRINT_CORE("gl_ggiClear() called\n");
121 if (mask
& GL_COLOR_BUFFER_BIT
)
123 ggiSetGCForeground(VIS
, GGICTX
->clearcolor
);
127 ggiDrawBox(VIS
, 0, GGIMesa
->origin
.y
,
128 GGIMesa
->width
, GGIMesa
->height
);
132 ggiDrawBox(VIS
, x
, FLIP(y
), width
, height
);
135 ggiSetGCForeground(VIS
, GGICTX
->color
);
137 return mask
& (~GL_COLOR_BUFFER_BIT
);
141 static GLboolean
gl_ggiSetBuffer(GLcontext
*ctx
, GLenum mode
)
143 GGIMESADPRINT_CORE("gl_ggiSetBuffer() called\n");
145 if (mode
== GL_FRONT
)
146 GGICTX
->active_buffer
= 1;
148 GGICTX
->active_buffer
= 0;
154 /* Set the buffer used for drawing */
155 static GLboolean
gl_ggiSetDrawBuffer(GLcontext
*ctx
, GLenum mode
)
157 GGIMESADPRINT_CORE("gl_ggiSetDrawBuffer() called\n");
159 if (mode
== GL_FRONT_LEFT
)
161 GGICTX
->active_buffer
= 1;
164 else if (mode
== GL_BACK_LEFT
)
166 GGICTX
->active_buffer
= 0;
176 /* Set the buffer used for reading */
177 /* XXX support for separate read/draw buffers hasn't been tested */
178 static void gl_ggiSetReadBuffer(GLcontext
*ctx
, GLframebuffer
*buffer
, GLenum mode
)
180 GGIMESADPRINT_CORE("gl_ggiSetReadBuffer() called\n");
182 if (mode
== GL_FRONT_LEFT
)
184 GGICTX
->active_buffer
= 1;
186 else if (mode
== GL_BACK_LEFT
)
188 GGICTX
->active_buffer
= 0;
193 static const GLubyte
* gl_ggiGetString(GLcontext
*ctx
, GLenum name
)
195 GGIMESADPRINT_CORE("gl_ggiGetString() called\n");
197 if (name
== GL_RENDERER
)
198 return (GLubyte
*) "Mesa GGI";
203 static void gl_ggiFlush(GLcontext
*ctx
)
205 GGIMESADPRINT_CORE("gl_ggiFlush() called\n");
210 static void gl_ggiIndexMask(GLcontext
*ctx
, GLuint mask
)
212 GGIMESADPRINT_CORE("gl_ggiIndexMask() called\n");
215 static void gl_ggiColorMask(GLcontext
*ctx
, GLboolean rmask
, GLboolean gmask
, GLboolean bmask
, GLboolean amask
)
217 GGIMESADPRINT_CORE("gl_ggiColorMask() called\n");
220 static void gl_ggiEnable(GLcontext
*ctx
, GLenum pname
, GLboolean state
)
222 GGIMESADPRINT_CORE("gl_ggiEnable() called\n");
225 static void gl_ggiSetupPointers(GLcontext
*ctx
)
227 GGIMESADPRINT_CORE("gl_ggiSetupPointers() called\n");
229 /* Initialize all the pointers in the DD struct. Do this whenever */
230 /* a new context is made current or we change buffers via set_buffer! */
232 ctx
->Driver
.GetString
= gl_ggiGetString
;
233 ctx
->Driver
.UpdateState
= gl_ggiUpdateState
;
235 ctx
->Driver
.ClearIndex
= gl_ggiSetClearIndex
;
236 ctx
->Driver
.ClearColor
= gl_ggiSetClearColor
;
237 ctx
->Driver
.Clear
= gl_ggiClear
;
238 ctx
->Driver
.IndexMask
= gl_ggiIndexMask
;
239 ctx
->Driver
.ColorMask
= gl_ggiColorMask
;
240 ctx
->Driver
.Enable
= gl_ggiEnable
;
242 ctx
->Driver
.SetDrawBuffer
= gl_ggiSetDrawBuffer
;
243 ctx
->Driver
.SetReadBuffer
= gl_ggiSetReadBuffer
;
245 ctx
->Driver
.GetBufferSize
= gl_ggiGetSize
;
247 ctx
->Driver
.Finish
= gl_ggiFlush
;
248 ctx
->Driver
.Flush
= gl_ggiFlush
;
250 ctx
->Driver
.RenderStart
= 0;
251 ctx
->Driver
.RenderFinish
= _swrast_flush
;
253 ctx
->Driver
.PointsFunc
= _swsetup_Points
;
254 ctx
->Driver
.LineFunc
= _swsetup_Line
;
255 ctx
->Driver
.TriangleFunc
= _swsetup_Triangle
;
256 ctx
->Driver
.QuadFunc
= _swsetup_Quad
;
257 ctx
->Driver
.RasterSetup
= _swsetup_RasterSetup
;
258 ctx
->Driver
.RegisterVB
= _swsetup_RegisterVB
;
259 ctx
->Driver
.UnregisterVB
= _swsetup_UnregisterVB
;
262 static int gl_ggiInitInfo(GGIMesaContext ctx
, struct ggi_mesa_info
*info
)
266 GGIMESADPRINT_CORE("gl_ggiInitInfo() called\n");
268 ggiGetMode(ctx
->ggi_vis
, &mode
);
270 info
->depth_bits
= DEFAULT_SOFTWARE_DEPTH_BITS
;
271 info
->stencil_bits
= STENCIL_BITS
;
272 info
->accum_bits
= ACCUM_BITS
;
276 info
->rgb_flag
= GL_TRUE
;
277 info
->alpha_flag
= GL_FALSE
;
278 info
->index_bits
= 0;
281 info
->green_bits
= 8;
284 info
->alpha_bits
= 0;
288 info
->alpha_flag
= GL_FALSE
;
290 info
->index_bits
= GT_SIZE(mode
.graphtype
);
291 info
->red_bits
= info
->green_bits
=
292 info
->blue_bits
= info
->alpha_bits
= 0;
303 GGIMESADPRINT_CORE("ggiMesaInit() called\n");
305 str
= getenv("GGIMESA_DEBUG");
307 _ggimesaDebugState
= atoi(str
);
308 GGIMESADPRINT_CORE("Debugging=%d\n", _ggimesaDebugState
);
311 str
= getenv("GGIMESA_DEBUGSYNC");
313 _ggimesaDebugSync
= 1;
316 GGIMESADPRINT_CORE("ggiMesaInit()\n");
319 if (_ggimesaLibIsUp
> 1)
320 return 0; /* Initialize only at first call */
322 err
= ggLoadConfig(ggimesaconffile
, &_ggimesaConfigHandle
);
325 GGIMESADPRINT_CORE("GGIMesa: Couldn't open %s\n", ggimesaconffile
);
330 ggiMesaID
= ggiExtensionRegister("GGIMesa", sizeof(struct mesa_ext
), changed
);
334 GGIMESADPRINT_CORE("GGIMesa: failed to register as extension\n");
336 ggFreeConfig(_ggimesaConfigHandle
);
344 GGIMesaContext
GGIMesaCreateContext(void)
349 GGIMESADPRINT_CORE("ggiMesaCreateContext() called\n");
351 if (ggiMesaInit() < 0) /* register extensions*/
356 ctx
= (GGIMesaContext
)calloc(1, sizeof(struct ggi_mesa_context
));
360 ctx
->gl_vis
= (GLvisual
*)calloc(1, sizeof(GLvisual
));
364 ctx
->viewport_init
= GL_FALSE
;
365 ctx
->gl_vis
->DBflag
= GL_FALSE
;
367 ctx
->gl_ctx
= _mesa_create_context(ctx
->gl_vis
, NULL
, (void *)ctx
, GL_TRUE
);
371 _mesa_enable_sw_extensions(ctx
->gl_ctx
);
373 _swrast_CreateContext(ctx
->gl_ctx
);
374 _swsetup_CreateContext(ctx
->gl_ctx
);
375 _tnl_CreateContext(ctx
->gl_ctx
);
380 void GGIMesaDestroyContext(GGIMesaContext ctx
)
382 GGIMESADPRINT_CORE("ggiMesaDestroyContext() called\n");
386 _mesa_destroy_visual(ctx
->gl_vis
);
387 _mesa_destroy_context(ctx
->gl_ctx
);
388 _mesa_destroy_framebuffer(ctx
->gl_buffer
);
392 ggiExtensionDetach(ctx
->ggi_vis
, ggiMesaID
);
393 ggiExtensionUnregister(ggiMesaID
);
398 int GGIMesaSetVisual(GGIMesaContext ctx
, ggi_visual_t vis
,
399 GLboolean rgb_flag
, GLboolean db_flag
)
401 struct ggi_mesa_info info
;
410 GGIMESADPRINT_CORE("ggiMesaSetVisual() called\n");
416 ggiExtensionDetach(ctx
->ggi_vis
, ggiMesaID
);
420 err
= ggiExtensionAttach(vis
, ggiMesaID
);
424 changed(vis
, GGI_CHG_APILIST
);
427 _mesa_destroy_visual(ctx
->gl_vis
);
430 _mesa_destroy_framebuffer(ctx
->gl_buffer
);
432 info
.rgb_flag
= rgb_flag
;
433 info
.db_flag
= db_flag
;
435 err
= gl_ggiInitInfo(ctx
, &info
);
439 gl_ggiSetupPointers(ctx
->gl_ctx
);
441 func
= (void *)LIBGGI_MESAEXT(ctx
->ggi_vis
)->setup_driver
;
445 GGIMESADPRINT_CORE("setup_driver==NULL!\n");
446 GGIMESADPRINT_CORE("Please check your config files!\n");
450 err
= LIBGGI_MESAEXT(ctx
->ggi_vis
)->setup_driver(ctx
, &info
);
454 ctx
->gl_vis
= _mesa_create_visual(info
.rgb_flag
,
457 info
.red_bits
, info
.green_bits
,
458 info
.blue_bits
, info
.alpha_bits
,
469 GGIMESADPRINT_CORE("Can't create gl_visual!\n");
473 ctx
->gl_buffer
= _mesa_create_framebuffer(ctx
->gl_vis
,
474 ctx
->gl_vis
->DepthBits
> 0,
475 ctx
->gl_vis
->StencilBits
> 0,
476 ctx
->gl_vis
->AccumRedBits
> 0,
477 ctx
->gl_vis
->AlphaBits
> 0);
482 GGIMESADPRINT_CORE("Can't create gl_buffer!\n");
486 ggiGetMode(ctx
->ggi_vis
, &mode
);
487 ctx
->width
= mode
.visible
.x
;
488 ctx
->height
= mode
.visible
.y
;
489 ctx
->stride
= mode
.virt
.x
;
492 ctx
->flip_y
= ctx
->origin
.y
+ ctx
->height
- 1;
496 ctx
->lfb
[0] = ctx
->lfb
[1] = NULL
;
497 num_buf
= ggiDBGetNumBuffers(ctx
->ggi_vis
);
499 for (i
= 0; i
< num_buf
; i
++)
501 if (ggiDBGetBuffer(ctx
->ggi_vis
,i
)->layout
== blPixelLinearBuffer
)
503 ctx
->stride
= ggiDBGetBuffer(ctx
->ggi_vis
, i
)->buffer
.plb
.stride
/
504 (ggiDBGetBuffer(ctx
->ggi_vis
, i
)->buffer
.plb
.pixelformat
->size
/ 8);
505 ctx
->lfb
[0] = ggiDBGetBuffer(ctx
->ggi_vis
, i
)->write
;
509 if (ctx
->lfb
[0] == NULL
)
511 GGIMESADPRINT_CORE("No linear frame buffer!\n");
515 /* FIXME: Use separate buffers */
516 ctx
->lfb
[1] = malloc(ctx
->stride
* ctx
->height
);
517 ctx
->bufsize
= (ctx
->stride
* ctx
->height
);
519 ctx
->gl_ctx
->Visual
= *ctx
->gl_vis
;
520 ctx
->gl_ctx
->Pixel
.ReadBuffer
=
521 ctx
->gl_ctx
->Color
.DrawBuffer
= (db_flag
) ? GL_BACK
: GL_FRONT
;
524 _mesa_make_current(ctx
->gl_ctx
, ctx
->gl_buffer
);
526 if (rgb_flag
&& mode
.graphtype
==GT_8BIT
)
528 for (i
= r
= 0; r
< 8; r
++)
529 for (g
= 0; g
< 8; g
++)
530 for (b
= 0; b
< 4; b
++, i
++)
532 pal
[i
].r
= r
<< (GGI_COLOR_PRECISION
- 3);
533 pal
[i
].g
= g
<< (GGI_COLOR_PRECISION
- 3);
534 pal
[i
].b
= b
<< (GGI_COLOR_PRECISION
- 2);
536 ggiSetPalette(ctx
->ggi_vis
, 0, 256, pal
);
542 void GGIMesaMakeCurrent(GGIMesaContext ctx
)
544 GGIMESADPRINT_CORE("ggiMesaMakeCurrent(ctx = %p) called\n", ctx
);
550 _mesa_make_current(ctx
->gl_ctx
, ctx
->gl_buffer
);
552 if (!ctx
->viewport_init
)
554 gl_Viewport(ctx
->gl_ctx
, 0, 0, ctx
->width
, ctx
->height
);
555 ctx
->viewport_init
= GL_TRUE
;
560 GGIMesaContext
GGIMesaGetCurrentContext(void)
562 GGIMESADPRINT_CORE("ggiMesaGetCurrentContext() called\n");
568 * Swap front/back buffers for current context if double buffered.
570 void GGIMesaSwapBuffers(void)
572 GGIMESADPRINT_CORE("ggiMesaSwapBuffers() called\n");
574 _mesa_swapbuffers( GGIMesa
->gl_ctx
);
575 gl_ggiFlush(GGIMesa
->gl_ctx
);
577 if (GGIMesa
->gl_vis
->DBflag
)
579 memcpy(GGIMesa
->lfb
[0], GGIMesa
->lfb
[1], GGIMesa
->bufsize
);
583 static void gl_ggiUpdateState(GLcontext
*ctx
, GLuint new_state
)
587 GGIMESADPRINT_CORE("gl_ggiUpdateState() called\n");
589 /* Propogate statechange information to swrast and swrast_setup
590 * modules. The GGI driver has no internal GL-dependent state.
592 _swrast_InvalidateState(ctx
, new_state
);
593 _swsetup_InvalidateState(ctx
, new_state
);
594 _tnl_InvalidateState(ctx
, new_state
);
596 func
= (void *)CTX_OPMESA(ctx
)->update_state
;
599 GGIMESADPRINT_CORE("update_state == NULL!\n");
600 GGIMESADPRINT_CORE("Please check your config files!\n");
604 CTX_OPMESA(ctx
)->update_state(ctx
);
607 static int changed(ggi_visual_t vis
, int whatchanged
)
609 GGIMESADPRINT_CORE("changed() called\n");
613 case GGI_CHG_APILIST
:
621 for (i
= 0; ggiGetAPI(vis
, i
, api
, args
) == 0; i
++)
623 strcat(api
, "-mesa");
624 fname
= ggMatchConfig(_ggimesaConfigHandle
, api
, NULL
);
627 /* No special implementation for this sublib */
630 lib
= ggiExtensionLoadDL(vis
, fname
, args
, NULL
, GGI_SYMNAME_PREFIX
);
639 int ggiMesaExit(void)
643 GGIMESADPRINT_CORE("ggiMesaExit() called\n");
645 if (!_ggimesaLibIsUp
)
648 if (_ggimesaLibIsUp
> 1)
650 /* Exit only at last call */
655 rc
= ggiExtensionUnregister(ggiMesaID
);
656 ggFreeConfig(_ggimesaConfigHandle
);
663 static int _ggi_error(void)
665 GGIMESADPRINT_CORE("_ggi_error() called\n");
670 int ggiMesaAttach(ggi_visual_t vis
)
674 GGIMESADPRINT_CORE("ggiMesaAttach() called\n");
676 rc
= ggiExtensionAttach(vis
, ggiMesaID
);
679 /* We are creating the primary instance */
680 memset(LIBGGI_MESAEXT(vis
), 0, sizeof(mesaext
));
681 LIBGGI_MESAEXT(vis
)->update_state
= (void *)_ggi_error
;
682 LIBGGI_MESAEXT(vis
)->setup_driver
= (void *)_ggi_error
;
684 /* Now fake an "API change" so the right libs get loaded */
685 changed(vis
, GGI_CHG_APILIST
);
691 int ggiMesaDetach(ggi_visual_t vis
)
693 GGIMESADPRINT_CORE("ggiMesaDetach() called\n");
695 return ggiExtensionDetach(vis
, ggiMesaID
);