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