Major rework of tnl module
[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);
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 #if 0
141 static GLboolean gl_ggiSetBuffer(GLcontext *ctx, GLenum mode)
142 {
143 GGIMESADPRINT_CORE("gl_ggiSetBuffer() called\n");
144
145 if (mode == GL_FRONT)
146 GGICTX->active_buffer = 1;
147 else
148 GGICTX->active_buffer = 0;
149
150 return GL_TRUE;
151 }
152 #endif
153
154 /* Set the buffer used for drawing */
155 static GLboolean gl_ggiSetDrawBuffer(GLcontext *ctx, GLenum mode)
156 {
157 GGIMESADPRINT_CORE("gl_ggiSetDrawBuffer() called\n");
158
159 if (mode == GL_FRONT_LEFT)
160 {
161 GGICTX->active_buffer = 1;
162 return GL_TRUE;
163 }
164 else if (mode == GL_BACK_LEFT)
165 {
166 GGICTX->active_buffer = 0;
167 return GL_TRUE;
168 }
169 else
170 {
171 return GL_FALSE;
172 }
173 }
174
175
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)
179 {
180 GGIMESADPRINT_CORE("gl_ggiSetReadBuffer() called\n");
181
182 if (mode == GL_FRONT_LEFT)
183 {
184 GGICTX->active_buffer = 1;
185 }
186 else if (mode == GL_BACK_LEFT)
187 {
188 GGICTX->active_buffer = 0;
189 }
190 }
191
192
193 static const GLubyte * gl_ggiGetString(GLcontext *ctx, GLenum name)
194 {
195 GGIMESADPRINT_CORE("gl_ggiGetString() called\n");
196
197 if (name == GL_RENDERER)
198 return (GLubyte *) "Mesa GGI";
199 else
200 return NULL;
201 }
202
203 static void gl_ggiFlush(GLcontext *ctx)
204 {
205 GGIMESADPRINT_CORE("gl_ggiFlush() called\n");
206
207 ggiFlush(VIS);
208 }
209
210 static void gl_ggiIndexMask(GLcontext *ctx, GLuint mask)
211 {
212 GGIMESADPRINT_CORE("gl_ggiIndexMask() called\n");
213 }
214
215 static void gl_ggiColorMask(GLcontext *ctx, GLboolean rmask, GLboolean gmask, GLboolean bmask, GLboolean amask)
216 {
217 GGIMESADPRINT_CORE("gl_ggiColorMask() called\n");
218 }
219
220 static void gl_ggiEnable(GLcontext *ctx, GLenum pname, GLboolean state)
221 {
222 GGIMESADPRINT_CORE("gl_ggiEnable() called\n");
223 }
224
225 static void gl_ggiSetupPointers(GLcontext *ctx)
226 {
227 GGIMESADPRINT_CORE("gl_ggiSetupPointers() called\n");
228
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! */
231
232 ctx->Driver.GetString = gl_ggiGetString;
233 ctx->Driver.UpdateState = gl_ggiUpdateState;
234
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;
241
242 ctx->Driver.SetDrawBuffer = gl_ggiSetDrawBuffer;
243 ctx->Driver.SetReadBuffer = gl_ggiSetReadBuffer;
244
245 ctx->Driver.GetBufferSize = gl_ggiGetSize;
246
247 ctx->Driver.Finish = gl_ggiFlush;
248 ctx->Driver.Flush = gl_ggiFlush;
249
250 ctx->Driver.RenderStart = 0;
251 ctx->Driver.RenderFinish = _swrast_flush;
252
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;
260 }
261
262 static int gl_ggiInitInfo(GGIMesaContext ctx, struct ggi_mesa_info *info)
263 {
264 ggi_mode mode;
265
266 GGIMESADPRINT_CORE("gl_ggiInitInfo() called\n");
267
268 ggiGetMode(ctx->ggi_vis, &mode);
269
270 info->depth_bits = DEFAULT_SOFTWARE_DEPTH_BITS;
271 info->stencil_bits = STENCIL_BITS;
272 info->accum_bits = ACCUM_BITS;
273
274 if (info->rgb_flag)
275 {
276 info->rgb_flag = GL_TRUE;
277 info->alpha_flag = GL_FALSE;
278 info->index_bits = 0;
279
280 info->red_bits = 8;
281 info->green_bits = 8;
282 info->blue_bits = 8;
283
284 info->alpha_bits = 0;
285 }
286 else
287 {
288 info->alpha_flag = GL_FALSE;
289
290 info->index_bits = GT_SIZE(mode.graphtype);
291 info->red_bits = info->green_bits =
292 info->blue_bits = info->alpha_bits = 0;
293 }
294
295 return 0;
296 }
297
298 int ggiMesaInit()
299 {
300 int err;
301 char *str;
302
303 GGIMESADPRINT_CORE("ggiMesaInit() called\n");
304
305 str = getenv("GGIMESA_DEBUG");
306 if (str != NULL) {
307 _ggimesaDebugState = atoi(str);
308 GGIMESADPRINT_CORE("Debugging=%d\n", _ggimesaDebugState);
309 }
310
311 str = getenv("GGIMESA_DEBUGSYNC");
312 if (str != NULL) {
313 _ggimesaDebugSync = 1;
314 }
315
316 GGIMESADPRINT_CORE("ggiMesaInit()\n");
317
318 _ggimesaLibIsUp++;
319 if (_ggimesaLibIsUp > 1)
320 return 0; /* Initialize only at first call */
321
322 err = ggLoadConfig(ggimesaconffile, &_ggimesaConfigHandle);
323 if (err != GGI_OK)
324 {
325 GGIMESADPRINT_CORE("GGIMesa: Couldn't open %s\n", ggimesaconffile);
326 _ggimesaLibIsUp--;
327 return err;
328 }
329
330 ggiMesaID = ggiExtensionRegister("GGIMesa", sizeof(struct mesa_ext), changed);
331
332 if (ggiMesaID < 0)
333 {
334 GGIMESADPRINT_CORE("GGIMesa: failed to register as extension\n");
335 _ggimesaLibIsUp--;
336 ggFreeConfig(_ggimesaConfigHandle);
337 return ggiMesaID;
338 }
339
340 return 0;
341 }
342
343
344 GGIMesaContext GGIMesaCreateContext(void)
345 {
346 GGIMesaContext ctx;
347 char *str;
348
349 GGIMESADPRINT_CORE("ggiMesaCreateContext() called\n");
350
351 if (ggiMesaInit() < 0) /* register extensions*/
352 {
353 return NULL;
354 }
355
356 ctx = (GGIMesaContext)calloc(1, sizeof(struct ggi_mesa_context));
357 if (!ctx)
358 return NULL;
359
360 ctx->gl_vis = (GLvisual *)calloc(1, sizeof(GLvisual));
361 if (!ctx->gl_vis)
362 return NULL;
363
364 ctx->viewport_init = GL_FALSE;
365 ctx->gl_vis->DBflag = GL_FALSE;
366
367 ctx->gl_ctx = _mesa_create_context(ctx->gl_vis, NULL, (void *)ctx, GL_TRUE);
368 if (!ctx->gl_ctx)
369 return NULL;
370
371 _mesa_enable_sw_extensions(ctx->gl_ctx);
372
373 _swrast_CreateContext(ctx->gl_ctx);
374 _swsetup_CreateContext(ctx->gl_ctx);
375 _tnl_CreateContext(ctx->gl_ctx);
376
377 return ctx;
378 }
379
380 void GGIMesaDestroyContext(GGIMesaContext ctx)
381 {
382 GGIMESADPRINT_CORE("ggiMesaDestroyContext() called\n");
383
384 if (ctx)
385 {
386 _mesa_destroy_visual(ctx->gl_vis);
387 _mesa_destroy_context(ctx->gl_ctx);
388 _mesa_destroy_framebuffer(ctx->gl_buffer);
389 if (ctx == GGIMesa)
390 GGIMesa = NULL;
391 if (ctx->ggi_vis)
392 ggiExtensionDetach(ctx->ggi_vis, ggiMesaID);
393 ggiExtensionUnregister(ggiMesaID);
394 free(ctx);
395 }
396 }
397
398 int GGIMesaSetVisual(GGIMesaContext ctx, ggi_visual_t vis,
399 GLboolean rgb_flag, GLboolean db_flag)
400 {
401 struct ggi_mesa_info info;
402 int err;
403 uint16 r,g,b;
404 ggi_color pal[256];
405 int i;
406 void *func;
407 ggi_mode mode;
408 int num_buf;
409
410 GGIMESADPRINT_CORE("ggiMesaSetVisual() called\n");
411
412 if (!ctx) return -1;
413 if (!vis) return -1;
414
415 if (ctx->ggi_vis)
416 ggiExtensionDetach(ctx->ggi_vis, ggiMesaID);
417
418 ctx->ggi_vis=vis;
419
420 err = ggiExtensionAttach(vis, ggiMesaID);
421 if (err < 0)
422 return -1;
423 if (err == 0)
424 changed(vis, GGI_CHG_APILIST);
425
426 if (ctx->gl_vis)
427 _mesa_destroy_visual(ctx->gl_vis);
428
429 if (ctx->gl_buffer)
430 _mesa_destroy_framebuffer(ctx->gl_buffer);
431
432 info.rgb_flag = rgb_flag;
433 info.db_flag = db_flag;
434
435 err = gl_ggiInitInfo(ctx, &info);
436 if (err)
437 return -1;
438
439 gl_ggiSetupPointers(ctx->gl_ctx);
440
441 func = (void *)LIBGGI_MESAEXT(ctx->ggi_vis)->setup_driver;
442
443 if (!func)
444 {
445 GGIMESADPRINT_CORE("setup_driver==NULL!\n");
446 GGIMESADPRINT_CORE("Please check your config files!\n");
447 return -1;
448 }
449
450 err = LIBGGI_MESAEXT(ctx->ggi_vis)->setup_driver(ctx, &info);
451 if (err)
452 return -1;
453
454 ctx->gl_vis = _mesa_create_visual(info.rgb_flag,
455 info.db_flag,
456 GL_FALSE, /*stereo*/
457 info.red_bits, info.green_bits,
458 info.blue_bits, info.alpha_bits,
459 info.index_bits,
460 info.depth_bits,
461 info.stencil_bits,
462 info.accum_bits,
463 info.accum_bits,
464 info.accum_bits,
465 info.accum_bits,
466 1);
467 if (!ctx->gl_vis)
468 {
469 GGIMESADPRINT_CORE("Can't create gl_visual!\n");
470 return -1;
471 }
472
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);
478
479
480 if (!ctx->gl_buffer)
481 {
482 GGIMESADPRINT_CORE("Can't create gl_buffer!\n");
483 return -1;
484 }
485
486 ggiGetMode(ctx->ggi_vis, &mode);
487 ctx->width = mode.visible.x;
488 ctx->height = mode.visible.y;
489 ctx->stride = mode.virt.x;
490 ctx->origin.x = 0;
491 ctx->origin.y = 0;
492 ctx->flip_y = ctx->origin.y + ctx->height - 1;
493
494 ctx->color = 0;
495
496 ctx->lfb[0] = ctx->lfb[1] = NULL;
497 num_buf = ggiDBGetNumBuffers(ctx->ggi_vis);
498
499 for (i = 0; i < num_buf; i++)
500 {
501 if (ggiDBGetBuffer(ctx->ggi_vis,i)->layout == blPixelLinearBuffer)
502 {
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;
506 }
507 }
508
509 if (ctx->lfb[0] == NULL)
510 {
511 GGIMESADPRINT_CORE("No linear frame buffer!\n");
512 return -1;
513 }
514
515 /* FIXME: Use separate buffers */
516 ctx->lfb[1] = malloc(ctx->stride * ctx->height);
517 ctx->bufsize = (ctx->stride * ctx->height);
518
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;
522
523 if (GGIMesa == ctx)
524 _mesa_make_current(ctx->gl_ctx, ctx->gl_buffer);
525
526 if (rgb_flag && mode.graphtype==GT_8BIT)
527 {
528 for (i = r = 0; r < 8; r++)
529 for (g = 0; g < 8; g++)
530 for (b = 0; b < 4; b++, i++)
531 {
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);
535 }
536 ggiSetPalette(ctx->ggi_vis, 0, 256, pal);
537 }
538
539 return 0;
540 }
541
542 void GGIMesaMakeCurrent(GGIMesaContext ctx)
543 {
544 GGIMESADPRINT_CORE("ggiMesaMakeCurrent(ctx = %p) called\n", ctx);
545
546 if (!ctx->ggi_vis)
547 return;
548
549 GGIMesa = ctx;
550 _mesa_make_current(ctx->gl_ctx, ctx->gl_buffer);
551
552 if (!ctx->viewport_init)
553 {
554 gl_Viewport(ctx->gl_ctx, 0, 0, ctx->width, ctx->height);
555 ctx->viewport_init = GL_TRUE;
556 }
557 }
558
559
560 GGIMesaContext GGIMesaGetCurrentContext(void)
561 {
562 GGIMESADPRINT_CORE("ggiMesaGetCurrentContext() called\n");
563
564 return GGIMesa;
565 }
566
567 /*
568 * Swap front/back buffers for current context if double buffered.
569 */
570 void GGIMesaSwapBuffers(void)
571 {
572 GGIMESADPRINT_CORE("ggiMesaSwapBuffers() called\n");
573
574 _mesa_swapbuffers( GGIMesa->gl_ctx );
575 gl_ggiFlush(GGIMesa->gl_ctx);
576
577 if (GGIMesa->gl_vis->DBflag)
578 {
579 memcpy(GGIMesa->lfb[0], GGIMesa->lfb[1], GGIMesa->bufsize);
580 }
581 }
582
583 static void gl_ggiUpdateState(GLcontext *ctx, GLuint new_state)
584 {
585 void *func;
586
587 GGIMESADPRINT_CORE("gl_ggiUpdateState() called\n");
588
589 /* Propogate statechange information to swrast and swrast_setup
590 * modules. The GGI driver has no internal GL-dependent state.
591 */
592 _swrast_InvalidateState(ctx, new_state);
593 _swsetup_InvalidateState(ctx, new_state);
594 _tnl_InvalidateState(ctx, new_state);
595
596 func = (void *)CTX_OPMESA(ctx)->update_state;
597
598 if (!func) {
599 GGIMESADPRINT_CORE("update_state == NULL!\n");
600 GGIMESADPRINT_CORE("Please check your config files!\n");
601 ggiPanic("");
602 }
603
604 CTX_OPMESA(ctx)->update_state(ctx);
605 }
606
607 static int changed(ggi_visual_t vis, int whatchanged)
608 {
609 GGIMESADPRINT_CORE("changed() called\n");
610
611 switch (whatchanged)
612 {
613 case GGI_CHG_APILIST:
614 {
615 char api[256];
616 char args[256];
617 int i;
618 const char *fname;
619 ggi_dlhandle *lib;
620
621 for (i = 0; ggiGetAPI(vis, i, api, args) == 0; i++)
622 {
623 strcat(api, "-mesa");
624 fname = ggMatchConfig(_ggimesaConfigHandle, api, NULL);
625 if (fname == NULL)
626 {
627 /* No special implementation for this sublib */
628 continue;
629 }
630 lib = ggiExtensionLoadDL(vis, fname, args, NULL, GGI_SYMNAME_PREFIX);
631 }
632 }
633 break;
634 }
635 return 0;
636 }
637
638
639 int ggiMesaExit(void)
640 {
641 int rc;
642
643 GGIMESADPRINT_CORE("ggiMesaExit() called\n");
644
645 if (!_ggimesaLibIsUp)
646 return -1;
647
648 if (_ggimesaLibIsUp > 1)
649 {
650 /* Exit only at last call */
651 _ggimesaLibIsUp--;
652 return 0;
653 }
654
655 rc = ggiExtensionUnregister(ggiMesaID);
656 ggFreeConfig(_ggimesaConfigHandle);
657
658 _ggimesaLibIsUp = 0;
659
660 return rc;
661 }
662
663 static int _ggi_error(void)
664 {
665 GGIMESADPRINT_CORE("_ggi_error() called\n");
666
667 return -1;
668 }
669
670 int ggiMesaAttach(ggi_visual_t vis)
671 {
672 int rc;
673
674 GGIMESADPRINT_CORE("ggiMesaAttach() called\n");
675
676 rc = ggiExtensionAttach(vis, ggiMesaID);
677 if (rc == 0)
678 {
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;
683
684 /* Now fake an "API change" so the right libs get loaded */
685 changed(vis, GGI_CHG_APILIST);
686 }
687
688 return rc;
689 }
690
691 int ggiMesaDetach(ggi_visual_t vis)
692 {
693 GGIMESADPRINT_CORE("ggiMesaDetach() called\n");
694
695 return ggiExtensionDetach(vis, ggiMesaID);
696 }