b13846060ed10008103d40c902c018afcde4a619
[mesa.git] / src / mesa / drivers / ggi / ggimesa.c
1 /* GGI-Driver for MESA
2 *
3 * Copyright (C) 1997-1998 Uwe Maurer - uwe_maurer@t-online.de
4 *
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.
9 *
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.
14 *
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:
20 *
21 * svgamesa.c and ddsample.c by Brian Paul
22 *
23 */
24
25 #ifdef HAVE_CONFIG_H
26 #include "conf.h"
27 #endif
28
29 #include <ggi/mesa/ggimesa_int.h>
30 #include <ggi/mesa/debug.h>
31 #include "extensions.h"
32 #include "matrix.h"
33
34 #undef VIS
35 #undef FLIP
36 #define VIS (GGIMesa->ggi_vis)
37 #define FLIP(y) (GGIMesa->flip_y-(y))
38
39 GGIMesaContext GGIMesa = NULL; /* the current context */
40
41 ggi_extid ggiMesaID = -1;
42 static int _ggimesaLibIsUp = 0;
43 static void *_ggimesaConfigHandle;
44
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;
50
51 int _ggimesaDebugSync = 0;
52 uint32 _ggimesaDebugState = 0;
53
54 static void gl_ggiUpdateState(GLcontext *ctx);
55 static int changed(ggi_visual_t vis, int whatchanged);
56
57 static void gl_ggiGetSize(GLcontext *ctx, GLuint *width, GLuint *height)
58 {
59 GGIMESADPRINT_CORE("gl_ggiGetSize() called\n");
60
61 *width = GGIMesa->width;
62 *height = GGIMesa->height;
63 }
64
65 static void gl_ggiSetIndex(GLcontext *ctx, GLuint ci)
66 {
67 GGIMESADPRINT_CORE("gl_ggiSetIndex() called\n");
68
69 ggiSetGCForeground(VIS, ci);
70 GGICTX->color = (ggi_pixel)ci;
71 }
72
73 static void gl_ggiSetClearIndex(GLcontext *ctx, GLuint ci)
74 {
75 GGIMESADPRINT_CORE("gl_ggiSetClearIndex() called\n");
76
77 ggiSetGCForeground(VIS, ci);
78 GGICTX->clearcolor = (ggi_pixel)ci;
79 }
80
81 static void gl_ggiSetColor(GLcontext *ctx, GLubyte red, GLubyte green,
82 GLubyte blue, GLubyte alpha)
83 {
84 ggi_color rgb;
85 ggi_pixel col;
86
87 GGIMESADPRINT_CORE("gl_ggiSetColor() called\n");
88
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);
94 GGICTX->color = col;
95 }
96
97 static void gl_ggiSetClearColor(GLcontext *ctx, GLubyte red, GLubyte green,
98 GLubyte blue, GLubyte alpha)
99 {
100 ggi_color rgb;
101 ggi_pixel col;
102
103 GGIMESADPRINT_CORE("gl_ggiSetClearColor() called\n");
104
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;
111 }
112
113 static GLbitfield gl_ggiClear(GLcontext *ctx,GLbitfield mask, GLboolean all,
114 GLint x, GLint y, GLint width, GLint height)
115 {
116 GGIMESADPRINT_CORE("gl_ggiClear() called\n");
117
118 if (mask & GL_COLOR_BUFFER_BIT)
119 {
120 ggiSetGCForeground(VIS, GGICTX->clearcolor);
121
122 if (all)
123 {
124 ggiDrawBox(VIS, 0, GGIMesa->origin.y,
125 GGIMesa->width, GGIMesa->height);
126 }
127 else
128 {
129 ggiDrawBox(VIS, x, FLIP(y), width, height);
130 }
131
132 ggiSetGCForeground(VIS, GGICTX->color);
133 }
134 return mask & (~GL_COLOR_BUFFER_BIT);
135 }
136
137 #if 0
138 static GLboolean gl_ggiSetBuffer(GLcontext *ctx, GLenum mode)
139 {
140 GGIMESADPRINT_CORE("gl_ggiSetBuffer() called\n");
141
142 if (mode == GL_FRONT)
143 GGICTX->active_buffer = 1;
144 else
145 GGICTX->active_buffer = 0;
146
147 return GL_TRUE;
148 }
149 #endif
150
151 /* Set the buffer used for drawing */
152 static GLboolean gl_ggiSetDrawBuffer(GLcontext *ctx, GLenum mode)
153 {
154 GGIMESADPRINT_CORE("gl_ggiSetDrawBuffer() called\n");
155
156 if (mode == GL_FRONT_LEFT)
157 {
158 GGICTX->active_buffer = 1;
159 return GL_TRUE;
160 }
161 else if (mode == GL_BACK_LEFT)
162 {
163 GGICTX->active_buffer = 0;
164 return GL_TRUE;
165 }
166 else
167 {
168 return GL_FALSE;
169 }
170 }
171
172
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)
176 {
177 GGIMESADPRINT_CORE("gl_ggiSetReadBuffer() called\n");
178
179 if (mode == GL_FRONT_LEFT)
180 {
181 GGICTX->active_buffer = 1;
182 }
183 else if (mode == GL_BACK_LEFT)
184 {
185 GGICTX->active_buffer = 0;
186 }
187 }
188
189
190 static const GLubyte * gl_ggiGetString(GLcontext *ctx, GLenum name)
191 {
192 GGIMESADPRINT_CORE("gl_ggiGetString() called\n");
193
194 if (name == GL_RENDERER)
195 return (GLubyte *) "Mesa GGI";
196 else
197 return NULL;
198 }
199
200 static void gl_ggiFlush(GLcontext *ctx)
201 {
202 GGIMESADPRINT_CORE("gl_ggiFlush() called\n");
203
204 ggiFlush(VIS);
205 }
206
207 static void gl_ggiSetupPointers(GLcontext *ctx)
208 {
209 GGIMESADPRINT_CORE("gl_ggiSetupPointers() called\n");
210
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! */
213
214 ctx->Driver.GetString = gl_ggiGetString;
215 ctx->Driver.UpdateState = gl_ggiUpdateState;
216
217 ctx->Driver.ClearIndex = gl_ggiSetClearIndex;
218 ctx->Driver.ClearColor = gl_ggiSetClearColor;
219 ctx->Driver.Clear = gl_ggiClear;
220
221 ctx->Driver.SetDrawBuffer = gl_ggiSetDrawBuffer;
222 ctx->Driver.SetReadBuffer = gl_ggiSetReadBuffer;
223
224 ctx->Driver.GetBufferSize = gl_ggiGetSize;
225 ctx->Driver.Finish = gl_ggiFlush;
226 ctx->Driver.Flush = gl_ggiFlush;
227 }
228
229 static int gl_ggiInitInfo(GGIMesaContext ctx, struct ggi_mesa_info *info)
230 {
231 ggi_mode mode;
232
233 GGIMESADPRINT_CORE("gl_ggiInitInfo() called\n");
234
235 ggiGetMode(ctx->ggi_vis, &mode);
236
237 info->depth_bits = DEFAULT_SOFTWARE_DEPTH_BITS;
238 info->stencil_bits = STENCIL_BITS;
239 info->accum_bits = ACCUM_BITS;
240
241 if (info->rgb_flag)
242 {
243 info->rgb_flag = GL_TRUE;
244 info->alpha_flag = GL_FALSE;
245 info->index_bits = 0;
246
247 info->red_bits = 8;
248 info->green_bits = 8;
249 info->blue_bits = 8;
250
251 info->alpha_bits = 0;
252 }
253 else
254 {
255 info->alpha_flag = GL_FALSE;
256
257 info->index_bits = GT_SIZE(mode.graphtype);
258 info->red_bits = info->green_bits =
259 info->blue_bits = info->alpha_bits = 0;
260 }
261
262 return 0;
263 }
264
265 int ggiMesaInit()
266 {
267 int err;
268 char *str;
269
270 GGIMESADPRINT_CORE("ggiMesaInit() called\n");
271
272 str = getenv("GGIMESA_DEBUG");
273 if (str != NULL) {
274 _ggimesaDebugState = atoi(str);
275 GGIMESADPRINT_CORE("Debugging=%d\n", _ggimesaDebugState);
276 }
277
278 str = getenv("GGIMESA_DEBUGSYNC");
279 if (str != NULL) {
280 _ggimesaDebugSync = 1;
281 }
282
283 GGIMESADPRINT_CORE("ggiMesaInit()\n");
284
285 _ggimesaLibIsUp++;
286 if (_ggimesaLibIsUp > 1)
287 return 0; /* Initialize only at first call */
288
289 err = ggLoadConfig(ggimesaconffile, &_ggimesaConfigHandle);
290 if (err != GGI_OK)
291 {
292 GGIMESADPRINT_CORE("GGIMesa: Couldn't open %s\n", ggimesaconffile);
293 _ggimesaLibIsUp--;
294 return err;
295 }
296
297 ggiMesaID = ggiExtensionRegister("GGIMesa", sizeof(struct mesa_ext), changed);
298
299 if (ggiMesaID < 0)
300 {
301 GGIMESADPRINT_CORE("GGIMesa: failed to register as extension\n");
302 _ggimesaLibIsUp--;
303 ggFreeConfig(_ggimesaConfigHandle);
304 return ggiMesaID;
305 }
306
307 return 0;
308 }
309
310
311 GGIMesaContext GGIMesaCreateContext(void)
312 {
313 GGIMesaContext ctx;
314 char *str;
315
316 GGIMESADPRINT_CORE("ggiMesaCreateContext() called\n");
317
318 if (ggiMesaInit() < 0) /* register extensions*/
319 {
320 return NULL;
321 }
322
323 ctx = (GGIMesaContext)calloc(1, sizeof(struct ggi_mesa_context));
324 if (!ctx)
325 return NULL;
326
327 ctx->gl_vis = (GLvisual *)calloc(1, sizeof(GLvisual));
328 if (!ctx->gl_vis)
329 return NULL;
330
331 ctx->viewport_init = GL_FALSE;
332 ctx->gl_vis->DBflag = GL_FALSE;
333
334 ctx->gl_ctx = _mesa_create_context(ctx->gl_vis, NULL, (void *)ctx, GL_TRUE);
335 if (!ctx->gl_ctx)
336 return NULL;
337
338 _mesa_enable_sw_extensions(ctx->gl_ctx);
339
340 return ctx;
341 }
342
343 void GGIMesaDestroyContext(GGIMesaContext ctx)
344 {
345 GGIMESADPRINT_CORE("ggiMesaDestroyContext() called\n");
346
347 if (ctx)
348 {
349 _mesa_destroy_visual(ctx->gl_vis);
350 _mesa_destroy_context(ctx->gl_ctx);
351 _mesa_destroy_framebuffer(ctx->gl_buffer);
352 if (ctx == GGIMesa)
353 GGIMesa = NULL;
354 if (ctx->ggi_vis)
355 ggiExtensionDetach(ctx->ggi_vis, ggiMesaID);
356 ggiExtensionUnregister(ggiMesaID);
357 free(ctx);
358 }
359 }
360
361 int GGIMesaSetVisual(GGIMesaContext ctx, ggi_visual_t vis,
362 GLboolean rgb_flag, GLboolean db_flag)
363 {
364 struct ggi_mesa_info info;
365 int err;
366 uint16 r,g,b;
367 ggi_color pal[256];
368 int i;
369 void *func;
370 ggi_mode mode;
371 int num_buf;
372
373 GGIMESADPRINT_CORE("ggiMesaSetVisual() called\n");
374
375 if (!ctx) return -1;
376 if (!vis) return -1;
377
378 if (ctx->ggi_vis)
379 ggiExtensionDetach(ctx->ggi_vis, ggiMesaID);
380
381 ctx->ggi_vis=vis;
382
383 err = ggiExtensionAttach(vis, ggiMesaID);
384 if (err < 0)
385 return -1;
386 if (err == 0)
387 changed(vis, GGI_CHG_APILIST);
388
389 if (ctx->gl_vis)
390 _mesa_destroy_visual(ctx->gl_vis);
391
392 if (ctx->gl_buffer)
393 _mesa_destroy_framebuffer(ctx->gl_buffer);
394
395 info.rgb_flag = rgb_flag;
396 info.db_flag = db_flag;
397
398 err = gl_ggiInitInfo(ctx, &info);
399 if (err)
400 return -1;
401
402 gl_ggiSetupPointers(ctx->gl_ctx);
403
404 func = (void *)LIBGGI_MESAEXT(ctx->ggi_vis)->setup_driver;
405
406 if (!func)
407 {
408 GGIMESADPRINT_CORE("setup_driver==NULL!\n");
409 GGIMESADPRINT_CORE("Please check your config files!\n");
410 return -1;
411 }
412
413 err = LIBGGI_MESAEXT(ctx->ggi_vis)->setup_driver(ctx, &info);
414 if (err)
415 return -1;
416
417 ctx->gl_vis = _mesa_create_visual(info.rgb_flag,
418 info.db_flag,
419 GL_FALSE, /*stereo*/
420 info.red_bits, info.green_bits,
421 info.blue_bits, info.alpha_bits,
422 info.index_bits,
423 info.depth_bits,
424 info.stencil_bits,
425 info.accum_bits,
426 info.accum_bits,
427 info.accum_bits,
428 info.accum_bits,
429 1);
430 if (!ctx->gl_vis)
431 {
432 GGIMESADPRINT_CORE("Can't create gl_visual!\n");
433 return -1;
434 }
435
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);
441
442
443 if (!ctx->gl_buffer)
444 {
445 GGIMESADPRINT_CORE("Can't create gl_buffer!\n");
446 return -1;
447 }
448
449 ggiGetMode(ctx->ggi_vis, &mode);
450 ctx->width = mode.visible.x;
451 ctx->height = mode.visible.y;
452 ctx->stride = mode.virt.x;
453 ctx->origin.x = 0;
454 ctx->origin.y = 0;
455 ctx->flip_y = ctx->origin.y + ctx->height - 1;
456
457 ctx->color = 0;
458
459 ctx->lfb[0] = ctx->lfb[1] = NULL;
460 num_buf = ggiDBGetNumBuffers(ctx->ggi_vis);
461
462 for (i = 0; i < num_buf; i++)
463 {
464 if (ggiDBGetBuffer(ctx->ggi_vis,i)->layout == blPixelLinearBuffer)
465 {
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;
469 }
470 }
471
472 if (ctx->lfb[0] == NULL)
473 {
474 GGIMESADPRINT_CORE("No linear frame buffer!\n");
475 return -1;
476 }
477
478 /* FIXME: Use separate buffers */
479 ctx->lfb[1] = malloc(ctx->stride * ctx->height);
480 ctx->bufsize = (ctx->stride * ctx->height);
481
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;
485
486 if (GGIMesa == ctx)
487 _mesa_make_current(ctx->gl_ctx, ctx->gl_buffer);
488
489 if (rgb_flag && mode.graphtype==GT_8BIT)
490 {
491 for (i = r = 0; r < 8; r++)
492 for (g = 0; g < 8; g++)
493 for (b = 0; b < 4; b++, i++)
494 {
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);
498 }
499 ggiSetPalette(ctx->ggi_vis, 0, 256, pal);
500 }
501
502 return 0;
503 }
504
505 void GGIMesaMakeCurrent(GGIMesaContext ctx)
506 {
507 GGIMESADPRINT_CORE("ggiMesaMakeCurrent(ctx = %p) called\n", ctx);
508
509 if (!ctx->ggi_vis)
510 return;
511
512 GGIMesa = ctx;
513 _mesa_make_current(ctx->gl_ctx, ctx->gl_buffer);
514
515 if (!ctx->viewport_init)
516 {
517 gl_Viewport(ctx->gl_ctx, 0, 0, ctx->width, ctx->height);
518 ctx->viewport_init = GL_TRUE;
519 }
520 }
521
522
523 GGIMesaContext GGIMesaGetCurrentContext(void)
524 {
525 GGIMESADPRINT_CORE("ggiMesaGetCurrentContext() called\n");
526
527 return GGIMesa;
528 }
529
530 /*
531 * Swap front/back buffers for current context if double buffered.
532 */
533 void GGIMesaSwapBuffers(void)
534 {
535 GGIMESADPRINT_CORE("ggiMesaSwapBuffers() called\n");
536
537 _mesa_swapbuffers( GGIMesa->gl_ctx );
538 gl_ggiFlush(GGIMesa->gl_ctx);
539
540 if (GGIMesa->gl_vis->DBflag)
541 {
542 memcpy(GGIMesa->lfb[0], GGIMesa->lfb[1], GGIMesa->bufsize);
543 }
544 }
545
546 static void gl_ggiUpdateState(GLcontext *ctx)
547 {
548 void *func;
549
550 GGIMESADPRINT_CORE("gl_ggiUpdateState() called\n");
551
552 func = (void *)CTX_OPMESA(ctx)->update_state;
553
554 if (!func) {
555 GGIMESADPRINT_CORE("update_state == NULL!\n");
556 GGIMESADPRINT_CORE("Please check your config files!\n");
557 ggiPanic("");
558 }
559
560 CTX_OPMESA(ctx)->update_state(ctx);
561 }
562
563 static int changed(ggi_visual_t vis, int whatchanged)
564 {
565 GGIMESADPRINT_CORE("changed() called\n");
566
567 switch (whatchanged)
568 {
569 case GGI_CHG_APILIST:
570 {
571 char api[256];
572 char args[256];
573 int i;
574 const char *fname;
575 ggi_dlhandle *lib;
576
577 for (i = 0; ggiGetAPI(vis, i, api, args) == 0; i++)
578 {
579 strcat(api, "-mesa");
580 fname = ggMatchConfig(_ggimesaConfigHandle, api, NULL);
581 if (fname == NULL)
582 {
583 /* No special implementation for this sublib */
584 continue;
585 }
586 lib = ggiExtensionLoadDL(vis, fname, args, NULL, GGI_SYMNAME_PREFIX);
587 }
588 }
589 break;
590 }
591 return 0;
592 }
593
594
595 int ggiMesaExit(void)
596 {
597 int rc;
598
599 GGIMESADPRINT_CORE("ggiMesaExit() called\n");
600
601 if (!_ggimesaLibIsUp)
602 return -1;
603
604 if (_ggimesaLibIsUp > 1)
605 {
606 /* Exit only at last call */
607 _ggimesaLibIsUp--;
608 return 0;
609 }
610
611 rc = ggiExtensionUnregister(ggiMesaID);
612 ggFreeConfig(_ggimesaConfigHandle);
613
614 _ggimesaLibIsUp = 0;
615
616 return rc;
617 }
618
619 static int _ggi_error(void)
620 {
621 GGIMESADPRINT_CORE("_ggi_error() called\n");
622
623 return -1;
624 }
625
626 int ggiMesaAttach(ggi_visual_t vis)
627 {
628 int rc;
629
630 GGIMESADPRINT_CORE("ggiMesaAttach() called\n");
631
632 rc = ggiExtensionAttach(vis, ggiMesaID);
633 if (rc == 0)
634 {
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;
639
640 /* Now fake an "API change" so the right libs get loaded */
641 changed(vis, GGI_CHG_APILIST);
642 }
643
644 return rc;
645 }
646
647 int ggiMesaDetach(ggi_visual_t vis)
648 {
649 GGIMESADPRINT_CORE("ggiMesaDetach() called\n");
650
651 return ggiExtensionDetach(vis, ggiMesaID);
652 }