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
, GLuint new_state
);
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
);
140 /* Set the buffer used for drawing */
141 static GLboolean
gl_ggiSetDrawBuffer(GLcontext
*ctx
, GLenum mode
)
143 GGIMESADPRINT_CORE("gl_ggiSetDrawBuffer() called\n");
145 if (mode
== GL_FRONT_LEFT
)
147 GGICTX
->active_buffer
= 1;
150 else if (mode
== GL_BACK_LEFT
)
152 GGICTX
->active_buffer
= 0;
162 /* Set the buffer used for reading */
163 /* XXX support for separate read/draw buffers hasn't been tested */
164 static void gl_ggiSetReadBuffer(GLcontext
*ctx
, GLframebuffer
*buffer
, GLenum mode
)
166 GGIMESADPRINT_CORE("gl_ggiSetReadBuffer() called\n");
168 if (mode
== GL_FRONT_LEFT
)
170 GGICTX
->active_buffer
= 1;
172 else if (mode
== GL_BACK_LEFT
)
174 GGICTX
->active_buffer
= 0;
179 static const GLubyte
* gl_ggiGetString(GLcontext
*ctx
, GLenum name
)
181 GGIMESADPRINT_CORE("gl_ggiGetString() called\n");
183 if (name
== GL_RENDERER
)
184 return (GLubyte
*) "Mesa GGI";
189 static void gl_ggiFlush(GLcontext
*ctx
)
191 GGIMESADPRINT_CORE("gl_ggiFlush() called\n");
196 static void gl_ggiIndexMask(GLcontext
*ctx
, GLuint mask
)
198 GGIMESADPRINT_CORE("gl_ggiIndexMask() called\n");
201 static void gl_ggiColorMask(GLcontext
*ctx
, GLboolean rmask
, GLboolean gmask
, GLboolean bmask
, GLboolean amask
)
203 GGIMESADPRINT_CORE("gl_ggiColorMask() called\n");
206 static void gl_ggiEnable(GLcontext
*ctx
, GLenum pname
, GLboolean state
)
208 GGIMESADPRINT_CORE("gl_ggiEnable() called\n");
211 static void gl_ggiSetupPointers(GLcontext
*ctx
)
213 GGIMESADPRINT_CORE("gl_ggiSetupPointers() called\n");
215 /* Initialize all the pointers in the DD struct. Do this whenever */
216 /* a new context is made current or we change buffers via set_buffer! */
218 ctx
->Driver
.GetString
= gl_ggiGetString
;
219 ctx
->Driver
.UpdateState
= gl_ggiUpdateState
;
221 ctx
->Driver
.ClearIndex
= gl_ggiSetClearIndex
;
222 ctx
->Driver
.ClearColor
= gl_ggiSetClearColor
;
223 ctx
->Driver
.Clear
= gl_ggiClear
;
224 ctx
->Driver
.IndexMask
= gl_ggiIndexMask
;
225 ctx
->Driver
.ColorMask
= gl_ggiColorMask
;
226 ctx
->Driver
.Enable
= gl_ggiEnable
;
228 ctx
->Driver
.SetDrawBuffer
= gl_ggiSetDrawBuffer
;
229 ctx
->Driver
.SetReadBuffer
= gl_ggiSetReadBuffer
;
231 ctx
->Driver
.GetBufferSize
= gl_ggiGetSize
;
233 ctx
->Driver
.Finish
= gl_ggiFlush
;
234 ctx
->Driver
.Flush
= gl_ggiFlush
;
236 ctx
->Driver
.RenderStart
= 0;
237 ctx
->Driver
.RenderFinish
= _swrast_flush
;
239 ctx
->Driver
.PointsFunc
= _swsetup_Points
;
240 ctx
->Driver
.LineFunc
= _swsetup_Line
;
241 ctx
->Driver
.TriangleFunc
= _swsetup_Triangle
;
242 ctx
->Driver
.QuadFunc
= _swsetup_Quad
;
246 static int gl_ggiInitInfo(GGIMesaContext ctx
, struct ggi_mesa_info
*info
)
250 GGIMESADPRINT_CORE("gl_ggiInitInfo() called\n");
252 ggiGetMode(ctx
->ggi_vis
, &mode
);
254 info
->depth_bits
= DEFAULT_SOFTWARE_DEPTH_BITS
;
255 info
->stencil_bits
= STENCIL_BITS
;
256 info
->accum_bits
= ACCUM_BITS
;
260 info
->rgb_flag
= GL_TRUE
;
261 info
->alpha_flag
= GL_FALSE
;
262 info
->index_bits
= 0;
265 info
->green_bits
= 8;
268 info
->alpha_bits
= 0;
272 info
->alpha_flag
= GL_FALSE
;
274 info
->index_bits
= GT_SIZE(mode
.graphtype
);
275 info
->red_bits
= info
->green_bits
=
276 info
->blue_bits
= info
->alpha_bits
= 0;
287 GGIMESADPRINT_CORE("ggiMesaInit() called\n");
289 str
= getenv("GGIMESA_DEBUG");
291 _ggimesaDebugState
= atoi(str
);
292 GGIMESADPRINT_CORE("Debugging=%d\n", _ggimesaDebugState
);
295 str
= getenv("GGIMESA_DEBUGSYNC");
297 _ggimesaDebugSync
= 1;
300 GGIMESADPRINT_CORE("ggiMesaInit()\n");
303 if (_ggimesaLibIsUp
> 1)
304 return 0; /* Initialize only at first call */
306 err
= ggLoadConfig(ggimesaconffile
, &_ggimesaConfigHandle
);
309 GGIMESADPRINT_CORE("GGIMesa: Couldn't open %s\n", ggimesaconffile
);
314 ggiMesaID
= ggiExtensionRegister("GGIMesa", sizeof(struct mesa_ext
), changed
);
318 GGIMESADPRINT_CORE("GGIMesa: failed to register as extension\n");
320 ggFreeConfig(_ggimesaConfigHandle
);
328 GGIMesaContext
GGIMesaCreateContext(void)
333 GGIMESADPRINT_CORE("ggiMesaCreateContext() called\n");
335 if (ggiMesaInit() < 0) /* register extensions*/
340 ctx
= (GGIMesaContext
)calloc(1, sizeof(struct ggi_mesa_context
));
344 ctx
->gl_vis
= (GLvisual
*)calloc(1, sizeof(GLvisual
));
348 ctx
->viewport_init
= GL_FALSE
;
349 ctx
->gl_vis
->DBflag
= GL_FALSE
;
351 ctx
->gl_ctx
= _mesa_create_context(ctx
->gl_vis
, NULL
, (void *)ctx
, GL_TRUE
);
355 _mesa_enable_sw_extensions(ctx
->gl_ctx
);
357 _swrast_CreateContext(ctx
->gl_ctx
);
358 _swsetup_CreateContext(ctx
->gl_ctx
);
359 _tnl_CreateContext(ctx
->gl_ctx
);
364 void GGIMesaDestroyContext(GGIMesaContext ctx
)
366 GGIMESADPRINT_CORE("ggiMesaDestroyContext() called\n");
370 _mesa_destroy_visual(ctx
->gl_vis
);
371 _mesa_destroy_context(ctx
->gl_ctx
);
372 _mesa_destroy_framebuffer(ctx
->gl_buffer
);
376 ggiExtensionDetach(ctx
->ggi_vis
, ggiMesaID
);
377 ggiExtensionUnregister(ggiMesaID
);
382 int GGIMesaSetVisual(GGIMesaContext ctx
, ggi_visual_t vis
,
383 GLboolean rgb_flag
, GLboolean db_flag
)
385 struct ggi_mesa_info info
;
394 GGIMESADPRINT_CORE("ggiMesaSetVisual() called\n");
400 ggiExtensionDetach(ctx
->ggi_vis
, ggiMesaID
);
404 err
= ggiExtensionAttach(vis
, ggiMesaID
);
408 changed(vis
, GGI_CHG_APILIST
);
411 _mesa_destroy_visual(ctx
->gl_vis
);
414 _mesa_destroy_framebuffer(ctx
->gl_buffer
);
416 info
.rgb_flag
= rgb_flag
;
417 info
.db_flag
= db_flag
;
419 err
= gl_ggiInitInfo(ctx
, &info
);
423 gl_ggiSetupPointers(ctx
->gl_ctx
);
425 func
= (void *)LIBGGI_MESAEXT(ctx
->ggi_vis
)->setup_driver
;
429 GGIMESADPRINT_CORE("setup_driver==NULL!\n");
430 GGIMESADPRINT_CORE("Please check your config files!\n");
434 err
= LIBGGI_MESAEXT(ctx
->ggi_vis
)->setup_driver(ctx
, &info
);
438 ctx
->gl_vis
= _mesa_create_visual(info
.rgb_flag
,
441 info
.red_bits
, info
.green_bits
,
442 info
.blue_bits
, info
.alpha_bits
,
453 GGIMESADPRINT_CORE("Can't create gl_visual!\n");
457 ctx
->gl_buffer
= _mesa_create_framebuffer(ctx
->gl_vis
,
458 ctx
->gl_vis
->DepthBits
> 0,
459 ctx
->gl_vis
->StencilBits
> 0,
460 ctx
->gl_vis
->AccumRedBits
> 0,
461 ctx
->gl_vis
->AlphaBits
> 0);
466 GGIMESADPRINT_CORE("Can't create gl_buffer!\n");
470 ggiGetMode(ctx
->ggi_vis
, &mode
);
471 ctx
->width
= mode
.visible
.x
;
472 ctx
->height
= mode
.visible
.y
;
473 ctx
->stride
= mode
.virt
.x
;
476 ctx
->flip_y
= ctx
->origin
.y
+ ctx
->height
- 1;
480 ctx
->lfb
[0] = ctx
->lfb
[1] = NULL
;
481 num_buf
= ggiDBGetNumBuffers(ctx
->ggi_vis
);
483 for (i
= 0; i
< num_buf
; i
++)
485 if (ggiDBGetBuffer(ctx
->ggi_vis
,i
)->layout
== blPixelLinearBuffer
)
487 ctx
->stride
= ggiDBGetBuffer(ctx
->ggi_vis
, i
)->buffer
.plb
.stride
/
488 (ggiDBGetBuffer(ctx
->ggi_vis
, i
)->buffer
.plb
.pixelformat
->size
/ 8);
489 ctx
->lfb
[0] = ggiDBGetBuffer(ctx
->ggi_vis
, i
)->write
;
493 if (ctx
->lfb
[0] == NULL
)
495 GGIMESADPRINT_CORE("No linear frame buffer!\n");
499 /* FIXME: Use separate buffers */
500 ctx
->lfb
[1] = malloc(ctx
->stride
* ctx
->height
);
501 ctx
->bufsize
= (ctx
->stride
* ctx
->height
);
503 ctx
->gl_ctx
->Visual
= *ctx
->gl_vis
;
504 ctx
->gl_ctx
->Pixel
.ReadBuffer
=
505 ctx
->gl_ctx
->Color
.DrawBuffer
= (db_flag
) ? GL_BACK
: GL_FRONT
;
508 _mesa_make_current(ctx
->gl_ctx
, ctx
->gl_buffer
);
510 if (rgb_flag
&& mode
.graphtype
==GT_8BIT
)
512 for (i
= r
= 0; r
< 8; r
++)
513 for (g
= 0; g
< 8; g
++)
514 for (b
= 0; b
< 4; b
++, i
++)
516 pal
[i
].r
= r
<< (GGI_COLOR_PRECISION
- 3);
517 pal
[i
].g
= g
<< (GGI_COLOR_PRECISION
- 3);
518 pal
[i
].b
= b
<< (GGI_COLOR_PRECISION
- 2);
520 ggiSetPalette(ctx
->ggi_vis
, 0, 256, pal
);
526 void GGIMesaMakeCurrent(GGIMesaContext ctx
)
528 GGIMESADPRINT_CORE("ggiMesaMakeCurrent(ctx = %p) called\n", ctx
);
534 _mesa_make_current(ctx
->gl_ctx
, ctx
->gl_buffer
);
536 if (!ctx
->viewport_init
)
538 gl_Viewport(ctx
->gl_ctx
, 0, 0, ctx
->width
, ctx
->height
);
539 ctx
->viewport_init
= GL_TRUE
;
544 GGIMesaContext
GGIMesaGetCurrentContext(void)
546 GGIMESADPRINT_CORE("ggiMesaGetCurrentContext() called\n");
552 * Swap front/back buffers for current context if double buffered.
554 void GGIMesaSwapBuffers(void)
556 GGIMESADPRINT_CORE("ggiMesaSwapBuffers() called\n");
558 _mesa_swapbuffers( GGIMesa
->gl_ctx
);
559 gl_ggiFlush(GGIMesa
->gl_ctx
);
561 if (GGIMesa
->gl_vis
->DBflag
)
563 memcpy(GGIMesa
->lfb
[0], GGIMesa
->lfb
[1], GGIMesa
->bufsize
);
567 static void gl_ggiUpdateState(GLcontext
*ctx
, GLuint new_state
)
571 GGIMESADPRINT_CORE("gl_ggiUpdateState() called\n");
573 /* Propogate statechange information to swrast and swrast_setup
574 * modules. The GGI driver has no internal GL-dependent state.
576 _swrast_InvalidateState(ctx
, new_state
);
577 _swsetup_InvalidateState(ctx
, new_state
);
578 _tnl_InvalidateState(ctx
, new_state
);
580 func
= (void *)CTX_OPMESA(ctx
)->update_state
;
583 GGIMESADPRINT_CORE("update_state == NULL!\n");
584 GGIMESADPRINT_CORE("Please check your config files!\n");
588 CTX_OPMESA(ctx
)->update_state(ctx
);
591 static int changed(ggi_visual_t vis
, int whatchanged
)
593 GGIMESADPRINT_CORE("changed() called\n");
597 case GGI_CHG_APILIST
:
605 for (i
= 0; ggiGetAPI(vis
, i
, api
, args
) == 0; i
++)
607 strcat(api
, "-mesa");
608 fname
= ggMatchConfig(_ggimesaConfigHandle
, api
, NULL
);
611 /* No special implementation for this sublib */
614 lib
= ggiExtensionLoadDL(vis
, fname
, args
, NULL
, GGI_SYMNAME_PREFIX
);
623 int ggiMesaExit(void)
627 GGIMESADPRINT_CORE("ggiMesaExit() called\n");
629 if (!_ggimesaLibIsUp
)
632 if (_ggimesaLibIsUp
> 1)
634 /* Exit only at last call */
639 rc
= ggiExtensionUnregister(ggiMesaID
);
640 ggFreeConfig(_ggimesaConfigHandle
);
647 static int _ggi_error(void)
649 GGIMESADPRINT_CORE("_ggi_error() called\n");
654 int ggiMesaAttach(ggi_visual_t vis
)
658 GGIMESADPRINT_CORE("ggiMesaAttach() called\n");
660 rc
= ggiExtensionAttach(vis
, ggiMesaID
);
663 /* We are creating the primary instance */
664 memset(LIBGGI_MESAEXT(vis
), 0, sizeof(mesaext
));
665 LIBGGI_MESAEXT(vis
)->update_state
= (void *)_ggi_error
;
666 LIBGGI_MESAEXT(vis
)->setup_driver
= (void *)_ggi_error
;
668 /* Now fake an "API change" so the right libs get loaded */
669 changed(vis
, GGI_CHG_APILIST
);
675 int ggiMesaDetach(ggi_visual_t vis
)
677 GGIMESADPRINT_CORE("ggiMesaDetach() called\n");
679 return ggiExtensionDetach(vis
, ggiMesaID
);