3 * Copyright (C) 1997-1998 Uwe Maurer - uwe_maurer@t-online.de
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 * ---------------------------------------------------------------------
20 * This code was derived from the following source of information:
22 * svgamesa.c and ddsample.c by Brian Paul
30 #include <ggi/mesa/ggimesa_int.h>
31 #include <ggi/mesa/debug.h>
32 #include "extensions.h"
35 #include "swrast/swrast.h"
36 #include "swrast_setup/swrast_setup.h"
38 #include "tnl/t_context.h"
39 #include "tnl/t_pipeline.h"
40 #include "array_cache/acache.h"
41 #include "texformat.h"
44 ggi_extid ggiMesaID
= -1;
45 static int _ggimesaLibIsUp
= 0;
46 static void *_ggimesaConfigHandle
;
48 static char ggimesaconffile
[] = GGIMESACONFFILE
;
50 int _ggimesaDebugSync
= 0;
51 uint32 _ggimesaDebugState
= 0;
53 static void gl_ggiUpdateState(GLcontext
*ctx
, GLuint new_state
);
54 static int changed(ggi_visual_t vis
, int whatchanged
);
57 static int _ggi_error(void)
59 GGIMESADPRINT_CORE("_ggi_error() called\n");
64 static void gl_ggiGetSize(GLframebuffer
*fb
, GLuint
*width
, GLuint
*height
)
66 /* FIXME: this is a hack to work around the new interface */
68 ggi_mesa_context_t ggi_ctx
;
69 ctx
= _mesa_get_current_context();
70 ggi_ctx
= (ggi_mesa_context_t
)ctx
->DriverCtx
;
72 GGIMESADPRINT_CORE("gl_ggiGetSize() called\n");
74 *width
= LIBGGI_MODE(ggi_ctx
->ggi_visual
)->visible
.x
;
75 *height
= LIBGGI_MODE(ggi_ctx
->ggi_visual
)->visible
.y
;
76 printf("returning %d, %d\n", *width
, *height
);
79 static void gl_ggiSetIndex(GLcontext
*ctx
, GLuint ci
)
81 ggi_mesa_context_t ggi_ctx
= (ggi_mesa_context_t
)ctx
->DriverCtx
;
83 GGIMESADPRINT_CORE("gl_ggiSetIndex() called\n");
85 ggiSetGCForeground(ggi_ctx
->ggi_visual
, ci
);
86 ggi_ctx
->color
= (ggi_pixel
)ci
;
89 static void gl_ggiSetClearIndex(GLcontext
*ctx
, GLuint ci
)
91 ggi_mesa_context_t ggi_ctx
= (ggi_mesa_context_t
)ctx
->DriverCtx
;
93 GGIMESADPRINT_CORE("gl_ggiSetClearIndex() called\n");
95 ggiSetGCForeground(ggi_ctx
->ggi_visual
, ci
);
96 ggi_ctx
->clearcolor
= (ggi_pixel
)ci
;
99 static void gl_ggiSetClearColor(GLcontext
*ctx
, const GLchan color
[4])
101 ggi_mesa_context_t ggi_ctx
= (ggi_mesa_context_t
)ctx
->DriverCtx
;
105 GGIMESADPRINT_CORE("gl_ggiSetClearColor() called\n");
107 rgb
.r
= (uint16
)color
[0] << SHIFT
;
108 rgb
.g
= (uint16
)color
[1] << SHIFT
;
109 rgb
.b
= (uint16
)color
[2] << SHIFT
;
110 col
= ggiMapColor(ggi_ctx
->ggi_visual
, &rgb
);
111 ggiSetGCForeground(ggi_ctx
->ggi_visual
, col
);
112 ggi_ctx
->clearcolor
= col
;
115 static void gl_ggiClear(GLcontext
*ctx
, GLbitfield mask
, GLboolean all
,
116 GLint x
, GLint y
, GLint width
, GLint height
)
118 ggi_mesa_context_t ggi_ctx
= (ggi_mesa_context_t
)ctx
->DriverCtx
;
120 GGIMESADPRINT_CORE("gl_ggiClear() called\n");
122 if (mask
& (DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
))
124 ggiSetGCForeground(ggi_ctx
->ggi_visual
, ggi_ctx
->clearcolor
);
129 w
= LIBGGI_MODE(ggi_ctx
->ggi_visual
)->visible
.x
;
130 h
= LIBGGI_MODE(ggi_ctx
->ggi_visual
)->visible
.y
;
131 ggiDrawBox(ggi_ctx
->ggi_visual
, 0, 0, w
, h
);
135 ggiDrawBox(ggi_ctx
->ggi_visual
, x
, y
, //FLIP(y),
138 ggiSetGCForeground(ggi_ctx
->ggi_visual
, ggi_ctx
->color
);
140 mask
&= ~(DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
);
142 _swrast_Clear(ctx
, mask
, all
, x
, y
, width
, height
);
146 /* Set the buffer used for drawing */
147 static GLboolean
gl_ggiSetDrawBuffer(GLcontext
*ctx
, GLenum mode
)
149 ggi_mesa_context_t ggi_ctx
= (ggi_mesa_context_t
)ctx
->DriverCtx
;
151 printf("set draw %d\n", mode
);
152 GGIMESADPRINT_CORE("gl_ggiSetDrawBuffer() called\n");
154 if (mode
== GL_FRONT_LEFT
)
156 ggiSetWriteFrame(ggi_ctx
->ggi_visual
,
157 ggiGetDisplayFrame(ggi_ctx
->ggi_visual
));
160 else if (mode
== GL_BACK_LEFT
)
162 ggiSetWriteFrame(ggi_ctx
->ggi_visual
,
163 ggiGetDisplayFrame(ggi_ctx
->ggi_visual
)?0 : 1);
173 /* Set the buffer used for reading */
174 /* XXX support for separate read/draw buffers hasn't been tested */
175 static GLboolean
gl_ggiSetReadBuffer(GLcontext
*ctx
, GLframebuffer
*buffer
, GLenum mode
)
177 ggi_mesa_context_t ggi_ctx
= (ggi_mesa_context_t
)ctx
->DriverCtx
;
179 printf("set read %d\n", mode
);
180 GGIMESADPRINT_CORE("gl_ggiSetReadBuffer() called\n");
182 if (mode
== GL_FRONT_LEFT
)
184 ggiSetReadFrame(ggi_ctx
->ggi_visual
,
185 ggiGetDisplayFrame(ggi_ctx
->ggi_visual
));
188 else if (mode
== GL_BACK_LEFT
)
190 ggiSetReadFrame(ggi_ctx
->ggi_visual
,
191 ggiGetDisplayFrame(ggi_ctx
->ggi_visual
)?0 : 1);
199 static const GLubyte
* gl_ggiGetString(GLcontext
*ctx
, GLenum name
)
201 GGIMESADPRINT_CORE("gl_ggiGetString() called\n");
203 if (name
== GL_RENDERER
)
204 return (GLubyte
*) "Mesa GGI";
209 static void gl_ggiFlush(GLcontext
*ctx
)
211 ggi_mesa_context_t ggi_ctx
= (ggi_mesa_context_t
)ctx
->DriverCtx
;
213 GGIMESADPRINT_CORE("gl_ggiFlush() called\n");
215 ggiFlush(ggi_ctx
->ggi_visual
);
218 static void gl_ggiIndexMask(GLcontext
*ctx
, GLuint mask
)
220 GGIMESADPRINT_CORE("gl_ggiIndexMask() called\n");
223 static void gl_ggiColorMask(GLcontext
*ctx
, GLboolean rmask
, GLboolean gmask
,
224 GLboolean bmask
, GLboolean amask
)
226 GGIMESADPRINT_CORE("gl_ggiColorMask() called\n");
229 static void gl_ggiEnable(GLcontext
*ctx
, GLenum pname
, GLboolean state
)
231 GGIMESADPRINT_CORE("gl_ggiEnable() called\n");
234 static void gl_ggiSetupPointers(GLcontext
*ctx
)
238 GGIMESADPRINT_CORE("gl_ggiSetupPointers() called\n");
240 /* General information */
241 ctx
->Driver
.GetString
= gl_ggiGetString
;
242 ctx
->Driver
.GetBufferSize
= gl_ggiGetSize
;
243 ctx
->Driver
.Finish
= gl_ggiFlush
;
244 ctx
->Driver
.Flush
= gl_ggiFlush
;
246 /* Software rasterizer pixel paths */
247 ctx
->Driver
.Accum
= _swrast_Accum
;
248 ctx
->Driver
.Bitmap
= _swrast_Bitmap
;
249 ctx
->Driver
.Clear
= gl_ggiClear
;
250 ctx
->Driver
.ResizeBuffers
= _swrast_alloc_buffers
;
251 ctx
->Driver
.CopyPixels
= _swrast_CopyPixels
;
252 ctx
->Driver
.DrawPixels
= _swrast_DrawPixels
;
253 ctx
->Driver
.ReadPixels
= _swrast_ReadPixels
;
255 /* Software texturing */
256 ctx
->Driver
.ChooseTextureFormat
= _mesa_choose_tex_format
;
257 ctx
->Driver
.TexImage1D
= _mesa_store_teximage1d
;
258 ctx
->Driver
.TexImage2D
= _mesa_store_teximage2d
;
259 ctx
->Driver
.TexImage3D
= _mesa_store_teximage3d
;
260 ctx
->Driver
.TexSubImage1D
= _mesa_store_texsubimage1d
;
261 ctx
->Driver
.TexSubImage2D
= _mesa_store_texsubimage2d
;
262 ctx
->Driver
.TexSubImage3D
= _mesa_store_texsubimage3d
;
263 ctx
->Driver
.TestProxyTexImage
= _mesa_test_proxy_teximage
;
265 ctx
->Driver
.CopyTexImage1D
= _swrast_copy_teximage1d
;
266 ctx
->Driver
.CopyTexImage2D
= _swrast_copy_teximage2d
;
267 ctx
->Driver
.CopyTexSubImage1D
= _swrast_copy_texsubimage1d
;
268 ctx
->Driver
.CopyTexSubImage2D
= _swrast_copy_texsubimage2d
;
269 ctx
->Driver
.CopyTexSubImage3D
= _swrast_copy_texsubimage3d
;
271 ctx
->Driver
.BaseCompressedTexFormat
= _mesa_base_compressed_texformat
;
272 ctx
->Driver
.CompressedTextureSize
= _mesa_compressed_texture_size
;
273 ctx
->Driver
.GetCompressedTexImage
= _mesa_get_compressed_teximage
;
275 /* Imaging extensions */
276 ctx
->Driver
.CopyColorTable
= _swrast_CopyColorTable
;
277 ctx
->Driver
.CopyColorSubTable
= _swrast_CopyColorSubTable
;
278 ctx
->Driver
.CopyConvolutionFilter1D
= _swrast_CopyConvolutionFilter1D
;
279 ctx
->Driver
.CopyConvolutionFilter2D
= _swrast_CopyConvolutionFilter2D
;
281 /* State change callbacks */
282 ctx
->Driver
.SetDrawBuffer
= gl_ggiSetDrawBuffer
;
283 ctx
->Driver
.ClearIndex
= gl_ggiSetClearIndex
;
284 ctx
->Driver
.ClearColor
= gl_ggiSetClearColor
;
285 ctx
->Driver
.IndexMask
= gl_ggiIndexMask
;
286 ctx
->Driver
.ColorMask
= gl_ggiColorMask
;
287 ctx
->Driver
.Enable
= gl_ggiEnable
;
289 ctx
->Driver
.UpdateState
= gl_ggiUpdateState
;
291 /* Initialize TNL driver interface */
292 tnl
= TNL_CONTEXT(ctx
);
293 tnl
->Driver
.RunPipeline
= _tnl_run_pipeline
;
295 /* Install setup for tnl */
296 _swsetup_Wakeup(ctx
);
299 static void get_mode_info(ggi_visual_t vis
, int *r
, int *g
, int *b
,
300 GLboolean
*rgb
, GLboolean
*db
, int *ci
)
308 for(i
= 0; i
< sizeof(ggi_pixel
)*8; ++i
){
310 if(LIBGGI_PIXFMT(vis
)->red_mask
& mask
)
312 if(LIBGGI_PIXFMT(vis
)->green_mask
& mask
)
314 if(LIBGGI_PIXFMT(vis
)->blue_mask
& mask
)
318 *rgb
= GT_SCHEME(LIBGGI_MODE(vis
)->graphtype
) == GT_TRUECOLOR
;
319 *db
= LIBGGI_MODE(vis
)->frames
> 1;
320 *ci
= GT_SIZE(LIBGGI_MODE(vis
)->graphtype
);
322 printf("rgb (%d, %d, %d) db %d, rgb %d ci %d\n",*r
,*g
,*b
,*db
,*rgb
,*ci
);
330 GGIMESADPRINT_CORE("ggiMesaInit() called\n");
332 str
= getenv("GGIMESA_DEBUG");
334 _ggimesaDebugState
= atoi(str
);
335 GGIMESADPRINT_CORE("Debugging=%d\n", _ggimesaDebugState
);
338 str
= getenv("GGIMESA_DEBUGSYNC");
340 _ggimesaDebugSync
= 1;
343 GGIMESADPRINT_CORE("ggiMesaInit()\n");
346 if (_ggimesaLibIsUp
> 1)
347 return 0; /* Initialize only at first call */
349 err
= ggLoadConfig(ggimesaconffile
, &_ggimesaConfigHandle
);
352 GGIMESADPRINT_CORE("GGIMesa: Couldn't open %s\n",
358 ggiMesaID
= ggiExtensionRegister("GGIMesa",
359 sizeof(struct ggi_mesa_ext
), changed
);
363 GGIMESADPRINT_CORE("GGIMesa: failed to register as extension\n");
365 ggFreeConfig(_ggimesaConfigHandle
);
372 int ggiMesaExit(void)
376 GGIMESADPRINT_CORE("ggiMesaExit() called\n");
378 if (!_ggimesaLibIsUp
)
381 if (_ggimesaLibIsUp
> 1)
383 /* Exit only at last call */
388 rc
= ggiExtensionUnregister(ggiMesaID
);
389 ggFreeConfig(_ggimesaConfigHandle
);
396 int ggiMesaAttach(ggi_visual_t vis
)
400 GGIMESADPRINT_CORE("ggiMesaAttach() called\n");
402 rc
= ggiExtensionAttach(vis
, ggiMesaID
);
408 GLframebuffer
*gl_fb
;
410 /* We are creating the primary instance */
411 memset(LIBGGI_MESAEXT(vis
), 0, sizeof(struct ggi_mesa_ext
));
412 LIBGGI_MESAEXT(vis
)->update_state
= (void *)_ggi_error
;
413 LIBGGI_MESAEXT(vis
)->setup_driver
= (void *)_ggi_error
;
415 /* Initialize default mesa visual */
416 get_mode_info(vis
, &r
, &g
, &b
, &rgb
, &db
, &ci
);
417 gl_visual
= &(LIBGGI_MESAEXT(vis
)->mesa_visual
.gl_visual
);
418 _mesa_initialize_visual(gl_visual
,
419 rgb
, db
, 0 /* No stereo */,
420 r
, g
, b
, 0 /* No alpha */, ci
,
421 0 /* No depth */, 0 /* No stencil */,
422 0, 0, 0, 0 /* No accum */, 0);
424 /* Now fake an "API change" so the right libs get loaded */
425 changed(vis
, GGI_CHG_APILIST
);
431 int ggiMesaDetach(ggi_visual_t vis
)
433 GGIMESADPRINT_CORE("ggiMesaDetach() called\n");
435 return ggiExtensionDetach(vis
, ggiMesaID
);
438 int ggiMesaExtendVisual(ggi_visual_t vis
, GLboolean alpha_flag
,
439 GLboolean stereo_flag
, GLint depth_size
,
440 GLint stencil_size
, GLint accum_red_size
,
441 GLint accum_green_size
, GLint accum_blue_size
,
442 GLint accum_alpha_size
, GLint num_samples
)
444 GLvisual
*gl_vis
= &(LIBGGI_MESAEXT(vis
)->mesa_visual
.gl_visual
);
448 get_mode_info(vis
, &r
, &g
, &b
, &rgb
, &db
, &ci
);
450 /* Initialize the visual with the provided information */
451 _mesa_initialize_visual(&(LIBGGI_MESAEXT(vis
)->mesa_visual
.gl_visual
),
452 rgb
, db
, stereo_flag
,
453 r
, g
, b
, 0 /* FIXME */, ci
,
454 depth_size
, stencil_size
,
455 accum_red_size
, accum_green_size
,
456 accum_blue_size
, accum_alpha_size
, 0);
458 /* Now fake an "API change" so the right libs get loaded. After all,
459 extending the visual by all these new buffers could be considered
460 a "mode change" which requires an "API change".
462 changed(vis
, GGI_CHG_APILIST
);
468 ggi_mesa_context_t
ggiMesaCreateContext(ggi_visual_t vis
)
470 ggi_mesa_context_t ctx
;
476 GGIMESADPRINT_CORE("ggiMesaCreateContext() called\n");
478 ctx
= (ggi_mesa_context_t
)malloc(sizeof(struct ggi_mesa_context
));
482 ctx
->ggi_visual
= vis
;
485 _mesa_init_default_imports( &imports
, (void *) ctx
);
487 _mesa_create_context(&(LIBGGI_MESAEXT(vis
)->mesa_visual
.gl_visual
),
492 _mesa_enable_sw_extensions(ctx
->gl_ctx
);
494 _swrast_CreateContext(ctx
->gl_ctx
);
495 _ac_CreateContext(ctx
->gl_ctx
);
496 _tnl_CreateContext(ctx
->gl_ctx
);
497 _swsetup_CreateContext(ctx
->gl_ctx
);
499 gl_ggiSetupPointers(ctx
->gl_ctx
);
501 /* Make sure that an appropriate sublib has been loaded */
502 if (!LIBGGI_MESAEXT(ctx
->ggi_visual
)->setup_driver
){
503 GGIMESADPRINT_CORE("setup_driver==NULL!\n");
504 GGIMESADPRINT_CORE("Please check your config files!\n");
508 /* Set up the sublib driver */
509 err
= LIBGGI_MESAEXT(ctx
->ggi_visual
)->setup_driver(ctx
);
511 GGIMESADPRINT_CORE("setup_driver failed (err = %d)", err
);
512 goto free_gl_context
;
518 _mesa_destroy_context(ctx
->gl_ctx
);
525 void ggiMesaDestroyContext(ggi_mesa_context_t ctx
)
527 GGIMESADPRINT_CORE("ggiMesaDestroyContext() called\n");
532 _mesa_destroy_context(ctx
->gl_ctx
);
536 void ggiMesaMakeCurrent(ggi_mesa_context_t ctx
, ggi_visual_t vis
)
538 GGIMESADPRINT_CORE("ggiMesaMakeCurrent(ctx = %p) called\n", ctx
);
540 /* FIXME: clean up where are ggi_vis */
541 if (ctx
->ggi_visual
!= vis
) {
542 GGIMESADPRINT_CORE("Cannot migrate GL contexts\n");
546 _mesa_make_current(ctx
->gl_ctx
, &LIBGGI_MESAEXT(vis
)->mesa_buffer
);
548 if (ctx
->gl_ctx
->Viewport
.Width
== 0)
551 LIBGGI_MODE(vis
)->visible
.x
,
552 LIBGGI_MODE(vis
)->visible
.y
);
553 ctx
->gl_ctx
->Scissor
.Width
= LIBGGI_MODE(vis
)->visible
.x
;
554 ctx
->gl_ctx
->Scissor
.Height
= LIBGGI_MODE(vis
)->visible
.y
;
560 * Swap front/back buffers for current context if double buffered.
562 void ggiMesaSwapBuffers(void)
565 ggi_mesa_context_t ggi_ctx
;
566 ctx
= _mesa_get_current_context();
567 ggi_ctx
= (ggi_mesa_context_t
)ctx
->DriverCtx
;
569 GGIMESADPRINT_CORE("ggiMesaSwapBuffers() called\n");
571 _mesa_swapbuffers(ctx
);
574 ggiSetDisplayFrame(ggi_ctx
->ggi_visual
,
575 !ggiGetDisplayFrame(ggi_ctx
->ggi_visual
));
576 ggiSetWriteFrame(ggi_ctx
->ggi_visual
,
577 !ggiGetWriteFrame(ggi_ctx
->ggi_visual
));
578 ggiSetReadFrame(ggi_ctx
->ggi_visual
,
579 !ggiGetReadFrame(ggi_ctx
->ggi_visual
));
581 GGIMESADPRINT_CORE("swap disp: %d, write %d\n",
582 ggiGetDisplayFrame(ggi_ctx
->ggi_visual
),
583 ggiGetWriteFrame(ggi_ctx
->ggi_visual
));
586 static void gl_ggiUpdateState(GLcontext
*ctx
, GLuint new_state
)
588 ggi_mesa_context_t ggi_ctx
= (ggi_mesa_context_t
)ctx
->DriverCtx
;
590 GGIMESADPRINT_CORE("gl_ggiUpdateState() called\n");
592 /* Propogate statechange information to swrast and swrast_setup
593 * modules. The GGI driver has no internal GL-dependent state.
595 _swrast_InvalidateState(ctx
, new_state
);
596 _swsetup_InvalidateState(ctx
, new_state
);
597 _tnl_InvalidateState(ctx
, new_state
);
599 if (!LIBGGI_MESAEXT(ggi_ctx
->ggi_visual
)->update_state
) {
600 GGIMESADPRINT_CORE("update_state == NULL!\n");
601 GGIMESADPRINT_CORE("Please check your config files!\n");
605 LIBGGI_MESAEXT(ggi_ctx
->ggi_visual
)->update_state(ggi_ctx
);
608 static int changed(ggi_visual_t vis
, int whatchanged
)
611 ctx
= _mesa_get_current_context();
613 GGIMESADPRINT_CORE("changed() called\n");
617 case GGI_CHG_APILIST
:
624 GLvisual
*gl_vis
=&(LIBGGI_MESAEXT(vis
)->mesa_visual
.gl_visual
);
625 GLframebuffer
*gl_fb
= &(LIBGGI_MESAEXT(vis
)->mesa_buffer
);
627 /* Initialize the framebuffer to provide all necessary
628 buffers in software. The target libraries that are loaded
629 next are free to modify this according to their
632 /* FIXME: if the target changes capabilities we'll leak
633 swrast's memory !!! Need to deallocate first */
634 _mesa_initialize_framebuffer(gl_fb
, gl_vis
,
635 gl_vis
->depthBits
> 0,
636 gl_vis
->stencilBits
> 0,
637 gl_vis
->accumRedBits
> 0,
638 gl_vis
->alphaBits
> 0);
640 for (i
= 0; ggiGetAPI(vis
, i
, api
, args
) == 0; i
++)
642 strcat(api
, "-mesa");
643 fname
= ggMatchConfig(_ggimesaConfigHandle
, api
, NULL
);
646 /* No special implementation for this sublib */
649 lib
= ggiExtensionLoadDL(vis
, fname
, args
, NULL
,
653 /* The targets have cleared everything they can do from
654 the framebuffer structure so we provide the rest in sw
656 _swrast_alloc_buffers(gl_fb
);