updated FX wrapper
[mesa.git] / src / mesa / drivers / dos / dmesa.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 5.1
4 *
5 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /*
26 * DOS/DJGPP device driver v1.5 for Mesa
27 *
28 * Copyright (c) 2003 - Borca Daniel
29 * Email : dborca@users.sourceforge.net
30 * Web : http://www.geocities.com/dborca
31 */
32
33
34 #include "glheader.h"
35 #include "context.h"
36 #ifndef FX
37 #include "bufferobj.h"
38 #include "extensions.h"
39 #include "macros.h"
40 #include "matrix.h"
41 #include "mtypes.h"
42 #include "texformat.h"
43 #include "teximage.h"
44 #include "texstore.h"
45 #include "imports.h"
46 #include "array_cache/acache.h"
47 #include "swrast/s_context.h"
48 #include "swrast/s_depth.h"
49 #include "swrast/s_lines.h"
50 #include "swrast/s_triangle.h"
51 #include "swrast/swrast.h"
52 #include "swrast_setup/swrast_setup.h"
53 #include "tnl/tnl.h"
54 #include "tnl/t_context.h"
55 #include "tnl/t_pipeline.h"
56 #include "video.h"
57 #else /* FX */
58 #include "GL/fxmesa.h"
59 #endif /* FX */
60
61 #include "GL/dmesa.h"
62
63
64
65 /*
66 * In C++ terms, this class derives from the GLvisual class.
67 * Add system-specific fields to it.
68 */
69 struct dmesa_visual {
70 GLvisual gl_visual;
71 GLboolean db_flag; /* double buffered? */
72 GLboolean rgb_flag; /* RGB mode? */
73 GLboolean sw_alpha; /* use Mesa's alpha buffer? */
74 GLuint depth; /* bits per pixel (1, 8, 24, etc) */
75 int zbuffer; /* Z=buffer: 0=no, 1=SW, -1=HW */
76 };
77
78 /*
79 * In C++ terms, this class derives from the GLframebuffer class.
80 * Add system-specific fields to it.
81 */
82 struct dmesa_buffer {
83 GLframebuffer gl_buffer; /* The depth, stencil, accum, etc buffers */
84 void *the_window; /* your window handle, etc */
85
86 int xpos, ypos; /* position */
87 int width, height; /* size in pixels */
88 };
89
90 /*
91 * In C++ terms, this class derives from the GLcontext class.
92 * Add system-specific fields to it.
93 */
94 struct dmesa_context {
95 GLcontext gl_ctx; /* the core library context */
96 DMesaVisual visual;
97 DMesaBuffer Buffer;
98 GLuint ClearColor;
99 GLuint ClearIndex;
100 /* etc... */
101 };
102
103
104
105 #ifndef FX
106 /****************************************************************************
107 * Read/Write pixels
108 ***************************************************************************/
109 #define FLIP(y) (dmesa->Buffer->height - (y) - 1)
110 #define FLIP2(y) (_b_ - (y))
111
112 #define DSTRIDE dmesa->Buffer->width
113
114 /****************************************************************************
115 * RGB[A]
116 ***************************************************************************/
117 static void write_rgba_span (const GLcontext *ctx, GLuint n, GLint x, GLint y,
118 const GLubyte rgba[][4], const GLubyte mask[])
119 {
120 const DMesaContext dmesa = (DMesaContext)ctx;
121 GLuint i, offset;
122
123 offset = DSTRIDE * FLIP(y) + x;
124 if (mask) {
125 /* draw some pixels */
126 for (i=0; i<n; i++, offset++) {
127 if (mask[i]) {
128 vl_putpixel(offset, vl_mixrgba(rgba[i]));
129 }
130 }
131 } else {
132 /* draw all pixels */
133 for (i=0; i<n; i++, offset++) {
134 vl_putpixel(offset, vl_mixrgba(rgba[i]));
135 }
136 }
137 }
138
139
140
141 static void write_rgb_span (const GLcontext *ctx, GLuint n, GLint x, GLint y,
142 const GLubyte rgb[][3], const GLubyte mask[])
143 {
144 const DMesaContext dmesa = (DMesaContext)ctx;
145 GLuint i, offset;
146
147 offset = DSTRIDE * FLIP(y) + x;
148 if (mask) {
149 /* draw some pixels */
150 for (i=0; i<n; i++, offset++) {
151 if (mask[i]) {
152 vl_putpixel(offset, vl_mixrgb(rgb[i]));
153 }
154 }
155 } else {
156 /* draw all pixels */
157 for (i=0; i<n; i++, offset++) {
158 vl_putpixel(offset, vl_mixrgb(rgb[i]));
159 }
160 }
161 }
162
163
164
165 static void write_mono_rgba_span (const GLcontext *ctx,
166 GLuint n, GLint x, GLint y,
167 const GLchan color[4], const GLubyte mask[])
168 {
169 const DMesaContext dmesa = (DMesaContext)ctx;
170 GLuint i, offset, rgba = vl_mixrgba(color);
171
172 offset = DSTRIDE * FLIP(y) + x;
173 if (mask) {
174 /* draw some pixels */
175 for (i=0; i<n; i++, offset++) {
176 if (mask[i]) {
177 vl_putpixel(offset, rgba);
178 }
179 }
180 } else {
181 /* draw all pixels */
182 for (i=0; i<n; i++, offset++) {
183 vl_putpixel(offset, rgba);
184 }
185 }
186 }
187
188
189
190 static void read_rgba_span (const GLcontext *ctx, GLuint n, GLint x, GLint y,
191 GLubyte rgba[][4])
192 {
193 const DMesaContext dmesa = (DMesaContext)ctx;
194 GLuint i, offset;
195
196 offset = DSTRIDE * FLIP(y) + x;
197 /* read all pixels */
198 for (i=0; i<n; i++, offset++) {
199 vl_getrgba(offset, rgba[i]);
200 }
201 }
202
203
204
205 static void write_rgba_pixels (const GLcontext *ctx,
206 GLuint n, const GLint x[], const GLint y[],
207 const GLubyte rgba[][4], const GLubyte mask[])
208 {
209 const DMesaContext dmesa = (DMesaContext)ctx;
210 GLuint i, _w_ = DSTRIDE, _b_ = dmesa->Buffer->height - 1;
211
212 if (mask) {
213 /* draw some pixels */
214 for (i=0; i<n; i++) {
215 if (mask[i]) {
216 vl_putpixel(FLIP2(y[i])*_w_ + x[i], vl_mixrgba(rgba[i]));
217 }
218 }
219 } else {
220 /* draw all pixels */
221 for (i=0; i<n; i++) {
222 vl_putpixel(FLIP2(y[i])*_w_ + x[i], vl_mixrgba(rgba[i]));
223 }
224 }
225 }
226
227
228
229 static void write_mono_rgba_pixels (const GLcontext *ctx,
230 GLuint n, const GLint x[], const GLint y[],
231 const GLchan color[4], const GLubyte mask[])
232 {
233 const DMesaContext dmesa = (DMesaContext)ctx;
234 GLuint i, _w_ = DSTRIDE, _b_ = dmesa->Buffer->height - 1, rgba = vl_mixrgba(color);
235
236 if (mask) {
237 /* draw some pixels */
238 for (i=0; i<n; i++) {
239 if (mask[i]) {
240 vl_putpixel(FLIP2(y[i])*_w_ + x[i], rgba);
241 }
242 }
243 } else {
244 /* draw all pixels */
245 for (i=0; i<n; i++) {
246 vl_putpixel(FLIP2(y[i])*_w_ + x[i], rgba);
247 }
248 }
249 }
250
251
252
253 static void read_rgba_pixels (const GLcontext *ctx,
254 GLuint n, const GLint x[], const GLint y[],
255 GLubyte rgba[][4], const GLubyte mask[])
256 {
257 const DMesaContext dmesa = (DMesaContext)ctx;
258 GLuint i, _w_ = DSTRIDE, _b_ = dmesa->Buffer->height - 1;
259
260 if (mask) {
261 /* read some pixels */
262 for (i=0; i<n; i++) {
263 if (mask[i]) {
264 vl_getrgba(FLIP2(y[i])*_w_ + x[i], rgba[i]);
265 }
266 }
267 } else {
268 /* read all pixels */
269 for (i=0; i<n; i++) {
270 vl_getrgba(FLIP2(y[i])*_w_ + x[i], rgba[i]);
271 }
272 }
273 }
274
275
276
277 /****************************************************************************
278 * Index
279 ***************************************************************************/
280 static void write_index_span (const GLcontext *ctx, GLuint n, GLint x, GLint y,
281 const GLuint index[], const GLubyte mask[])
282 {
283 const DMesaContext dmesa = (DMesaContext)ctx;
284 GLuint i, offset;
285
286 offset = DSTRIDE * FLIP(y) + x;
287 if (mask) {
288 /* draw some pixels */
289 for (i=0; i<n; i++, offset++) {
290 if (mask[i]) {
291 vl_putpixel(offset, index[i]);
292 }
293 }
294 } else {
295 /* draw all pixels */
296 for (i=0; i<n; i++, offset++) {
297 vl_putpixel(offset, index[i]);
298 }
299 }
300 }
301
302
303
304 static void write_index8_span (const GLcontext *ctx, GLuint n, GLint x, GLint y,
305 const GLubyte index[], const GLubyte mask[])
306 {
307 const DMesaContext dmesa = (DMesaContext)ctx;
308 GLuint i, offset;
309
310 offset = DSTRIDE * FLIP(y) + x;
311 if (mask) {
312 /* draw some pixels */
313 for (i=0; i<n; i++, offset++) {
314 if (mask[i]) {
315 vl_putpixel(offset, index[i]);
316 }
317 }
318 } else {
319 /* draw all pixels */
320 for (i=0; i<n; i++, offset++) {
321 vl_putpixel(offset, index[i]);
322 }
323 }
324 }
325
326
327
328 static void write_mono_index_span (const GLcontext *ctx,
329 GLuint n, GLint x, GLint y,
330 GLuint colorIndex, const GLubyte mask[])
331 {
332 const DMesaContext dmesa = (DMesaContext)ctx;
333 GLuint i, offset;
334
335 offset = DSTRIDE * FLIP(y) + x;
336 if (mask) {
337 /* draw some pixels */
338 for (i=0; i<n; i++, offset++) {
339 if (mask[i]) {
340 vl_putpixel(offset, colorIndex);
341 }
342 }
343 } else {
344 /* draw all pixels */
345 for (i=0; i<n; i++, offset++) {
346 vl_putpixel(offset, colorIndex);
347 }
348 }
349 }
350
351
352
353 static void read_index_span (const GLcontext *ctx, GLuint n, GLint x, GLint y,
354 GLuint index[])
355 {
356 const DMesaContext dmesa = (DMesaContext)ctx;
357 GLuint i, offset;
358
359 offset = DSTRIDE * FLIP(y) + x;
360 /* read all pixels */
361 for (i=0; i<n; i++, offset++) {
362 index[i] = vl_getpixel(offset);
363 }
364 }
365
366
367
368 static void write_index_pixels (const GLcontext *ctx,
369 GLuint n, const GLint x[], const GLint y[],
370 const GLuint index[], const GLubyte mask[])
371 {
372 const DMesaContext dmesa = (DMesaContext)ctx;
373 GLuint i, _w_ = DSTRIDE, _b_ = dmesa->Buffer->height - 1;
374
375 if (mask) {
376 /* draw some pixels */
377 for (i=0; i<n; i++) {
378 if (mask[i]) {
379 vl_putpixel(FLIP2(y[i])*_w_ + x[i], index[i]);
380 }
381 }
382 } else {
383 /* draw all pixels */
384 for (i=0; i<n; i++) {
385 vl_putpixel(FLIP2(y[i])*_w_ + x[i], index[i]);
386 }
387 }
388 }
389
390
391
392 static void write_mono_index_pixels (const GLcontext *ctx,
393 GLuint n, const GLint x[], const GLint y[],
394 GLuint colorIndex, const GLubyte mask[])
395 {
396 const DMesaContext dmesa = (DMesaContext)ctx;
397 GLuint i, _w_ = DSTRIDE, _b_ = dmesa->Buffer->height - 1;
398
399 if (mask) {
400 /* draw some pixels */
401 for (i=0; i<n; i++) {
402 if (mask[i]) {
403 vl_putpixel(FLIP2(y[i])*_w_ + x[i], colorIndex);
404 }
405 }
406 } else {
407 /* draw all pixels */
408 for (i=0; i<n; i++) {
409 vl_putpixel(FLIP2(y[i])*_w_ + x[i], colorIndex);
410 }
411 }
412 }
413
414
415
416 static void read_index_pixels (const GLcontext *ctx,
417 GLuint n, const GLint x[], const GLint y[],
418 GLuint index[], const GLubyte mask[])
419 {
420 const DMesaContext dmesa = (DMesaContext)ctx;
421 GLuint i, _w_ = DSTRIDE, _b_ = dmesa->Buffer->height - 1;
422
423 if (mask) {
424 /* read some pixels */
425 for (i=0; i<n; i++) {
426 if (mask[i]) {
427 index[i] = vl_getpixel(FLIP2(y[i])*_w_ + x[i]);
428 }
429 }
430 } else {
431 /* read all pixels */
432 for (i=0; i<n; i++) {
433 index[i] = vl_getpixel(FLIP2(y[i])*_w_ + x[i]);
434 }
435 }
436 }
437
438
439
440 /****************************************************************************
441 * Z-buffer
442 ***************************************************************************/
443
444
445
446 /****************************************************************************
447 * Optimized triangle rendering
448 ***************************************************************************/
449
450 /*
451 * NON-depth-buffered flat triangle.
452 */
453 #define NAME tri_rgb_flat
454
455 #define SETUP_CODE \
456 const DMesaContext dmesa = (DMesaContext)ctx; \
457 GLuint _b_ = dmesa->Buffer->height - 1; \
458 GLuint _w_ = dmesa->Buffer->width; \
459 GLuint rgb = vl_mixrgb(v2->color);
460
461 #define RENDER_SPAN(span) \
462 GLuint i, offset = FLIP2(span.y)*_w_ + span.x; \
463 for (i = 0; i < span.end; i++, offset++) { \
464 vl_putpixel(offset, rgb); \
465 }
466
467 #include "swrast/s_tritemp.h"
468
469
470
471 /*
472 * Z-less flat triangle.
473 */
474 #define NAME tri_rgb_flat_zless
475
476 #define INTERP_Z 1
477 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
478
479 #define SETUP_CODE \
480 const DMesaContext dmesa = (DMesaContext)ctx; \
481 GLuint _b_ = dmesa->Buffer->height - 1; \
482 GLuint _w_ = dmesa->Buffer->width; \
483 GLuint rgb = vl_mixrgb(v2->color);
484
485 #define RENDER_SPAN(span) \
486 GLuint i, offset = FLIP2(span.y)*_w_ + span.x; \
487 for (i = 0; i < span.end; i++, offset++) { \
488 const DEPTH_TYPE z = FixedToDepth(span.z); \
489 if (z < zRow[i]) { \
490 vl_putpixel(offset, rgb); \
491 zRow[i] = z; \
492 } \
493 span.z += span.zStep; \
494 }
495
496 #include "swrast/s_tritemp.h"
497
498
499
500 /*
501 * NON-depth-buffered iterated triangle.
502 */
503 #define NAME tri_rgb_iter
504
505 #define INTERP_RGB 1
506
507 #define SETUP_CODE \
508 const DMesaContext dmesa = (DMesaContext)ctx; \
509 GLuint _b_ = dmesa->Buffer->height - 1; \
510 GLuint _w_ = dmesa->Buffer->width;
511
512 #define RENDER_SPAN(span) \
513 GLuint i, offset = FLIP2(span.y)*_w_ + span.x; \
514 for (i = 0; i < span.end; i++, offset++) { \
515 vl_putpixel(offset, vl_mixfix(span.red, span.green, span.blue)); \
516 span.red += span.redStep; \
517 span.green += span.greenStep; \
518 span.blue += span.blueStep; \
519 }
520
521 #include "swrast/s_tritemp.h"
522
523
524
525 /*
526 * Z-less iterated triangle.
527 */
528 #define NAME tri_rgb_iter_zless
529
530 #define INTERP_Z 1
531 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
532 #define INTERP_RGB 1
533
534 #define SETUP_CODE \
535 const DMesaContext dmesa = (DMesaContext)ctx; \
536 GLuint _b_ = dmesa->Buffer->height - 1; \
537 GLuint _w_ = dmesa->Buffer->width;
538
539 #define RENDER_SPAN(span) \
540 GLuint i, offset = FLIP2(span.y)*_w_ + span.x; \
541 for (i = 0; i < span.end; i++, offset++) { \
542 const DEPTH_TYPE z = FixedToDepth(span.z); \
543 if (z < zRow[i]) { \
544 vl_putpixel(offset, vl_mixfix(span.red, span.green, span.blue));\
545 zRow[i] = z; \
546 } \
547 span.red += span.redStep; \
548 span.green += span.greenStep; \
549 span.blue += span.blueStep; \
550 span.z += span.zStep; \
551 }
552
553 #include "swrast/s_tritemp.h"
554
555
556
557 /*
558 * Analyze context state to see if we can provide a fast triangle function
559 * Otherwise, return NULL.
560 */
561 static swrast_tri_func dmesa_choose_tri_function (GLcontext *ctx)
562 {
563 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
564
565 if ((ctx->RenderMode != GL_RENDER)
566 || (ctx->Polygon.SmoothFlag)
567 || (ctx->Polygon.StippleFlag)
568 || (ctx->Texture._EnabledUnits)
569 || (swrast->_RasterMask & MULTI_DRAW_BIT)
570 || (ctx->Polygon.CullFlag && ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)) {
571 return (swrast_tri_func)NULL;
572 }
573
574 if (swrast->_RasterMask==DEPTH_BIT
575 && ctx->Depth.Func==GL_LESS
576 && ctx->Depth.Mask==GL_TRUE
577 && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
578 return (ctx->Light.ShadeModel==GL_SMOOTH) ? tri_rgb_iter_zless : tri_rgb_flat_zless;
579 }
580
581 if (swrast->_RasterMask==0) { /* no depth test */
582 return (ctx->Light.ShadeModel==GL_SMOOTH) ? tri_rgb_iter : tri_rgb_flat;
583 }
584
585 return (swrast_tri_func)NULL;
586 }
587
588
589
590 /* Override for the swrast triangle-selection function. Try to use one
591 * of our internal triangle functions, otherwise fall back to the
592 * standard swrast functions.
593 */
594 static void dmesa_choose_tri (GLcontext *ctx)
595 {
596 SWcontext *swrast = SWRAST_CONTEXT(ctx);
597
598 if (!(swrast->Triangle=dmesa_choose_tri_function(ctx)))
599 _swrast_choose_triangle(ctx);
600 }
601
602
603
604 /****************************************************************************
605 * Optimized line rendering
606 ***************************************************************************/
607
608 /*
609 * NON-depth-buffered flat line.
610 */
611 #define NAME line_rgb_flat
612
613 #define INTERP_XY 1
614 #define CLIP_HACK 1
615
616 #define SETUP_CODE \
617 const DMesaContext dmesa = (DMesaContext)ctx; \
618 GLuint _b_ = dmesa->Buffer->height - 1; \
619 GLuint _w_ = dmesa->Buffer->width; \
620 GLuint rgb = vl_mixrgb(vert1->color);
621
622 #define PLOT(X,Y) vl_putpixel(FLIP2(Y) * _w_ + X, rgb);
623
624 #include "swrast/s_linetemp.h"
625
626
627
628 /*
629 * Z-less flat line.
630 */
631 #define NAME line_rgb_flat_zless
632
633 #define INTERP_XY 1
634 #define INTERP_Z 1
635 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
636 #define CLIP_HACK 1
637
638 #define SETUP_CODE \
639 const DMesaContext dmesa = (DMesaContext)ctx; \
640 GLuint _b_ = dmesa->Buffer->height - 1; \
641 GLuint _w_ = dmesa->Buffer->width; \
642 GLuint rgb = vl_mixrgb(vert1->color);
643
644 #define PLOT(X,Y) \
645 if (Z < *zPtr) { \
646 *zPtr = Z; \
647 vl_putpixel(FLIP2(Y) * _w_ + X, rgb); \
648 }
649
650 #include "swrast/s_linetemp.h"
651
652
653
654 /*
655 * NON-depth-buffered iterated line.
656 */
657 #define line_rgb_iter NULL
658
659
660
661 /*
662 * Z-less iterated line.
663 */
664 #define line_rgb_iter_zless NULL
665
666
667
668 /*
669 * Analyze context state to see if we can provide a fast line function
670 * Otherwise, return NULL.
671 */
672 static swrast_line_func dmesa_choose_line_function (GLcontext *ctx)
673 {
674 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
675
676 if ((ctx->RenderMode != GL_RENDER)
677 || (ctx->Line.SmoothFlag)
678 || (ctx->Texture._EnabledUnits)
679 || (ctx->Line.StippleFlag)
680 || (swrast->_RasterMask & MULTI_DRAW_BIT)
681 || (ctx->Line.Width!=1.0F)) {
682 return (swrast_line_func)NULL;
683 }
684
685 if (swrast->_RasterMask==DEPTH_BIT
686 && ctx->Depth.Func==GL_LESS
687 && ctx->Depth.Mask==GL_TRUE
688 && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
689 return (ctx->Light.ShadeModel==GL_SMOOTH) ? line_rgb_iter_zless : line_rgb_flat_zless;
690 }
691
692 if (swrast->_RasterMask==0) { /* no depth test */
693 return (ctx->Light.ShadeModel==GL_SMOOTH) ? line_rgb_iter : line_rgb_flat;
694 }
695
696 return (swrast_line_func)NULL;
697 }
698
699
700
701 /* Override for the swrast line-selection function. Try to use one
702 * of our internal line functions, otherwise fall back to the
703 * standard swrast functions.
704 */
705 static void dmesa_choose_line (GLcontext *ctx)
706 {
707 SWcontext *swrast = SWRAST_CONTEXT(ctx);
708
709 if (!(swrast->Line=dmesa_choose_line_function(ctx)))
710 _swrast_choose_line(ctx);
711 }
712
713
714
715 /****************************************************************************
716 * Miscellaneous device driver funcs
717 ***************************************************************************/
718
719 static void clear_index (GLcontext *ctx, GLuint index)
720 {
721 ((DMesaContext)ctx)->ClearIndex = index;
722 }
723
724 static void clear_color (GLcontext *ctx, const GLfloat color[4])
725 {
726 GLubyte col[4];
727 CLAMPED_FLOAT_TO_UBYTE(col[0], color[0]);
728 CLAMPED_FLOAT_TO_UBYTE(col[1], color[1]);
729 CLAMPED_FLOAT_TO_UBYTE(col[2], color[2]);
730 CLAMPED_FLOAT_TO_UBYTE(col[3], color[3]);
731 ((DMesaContext)ctx)->ClearColor = vl_mixrgba(col);
732 }
733
734
735
736 static void clear (GLcontext *ctx, GLbitfield mask, GLboolean all,
737 GLint x, GLint y, GLint width, GLint height)
738 {
739 const DMesaContext c = (DMesaContext)ctx;
740 const GLuint *colorMask = (GLuint *)&ctx->Color.ColorMask;
741
742 /*
743 * Clear the specified region of the buffers indicated by 'mask'
744 * using the clear color or index as specified by one of the two
745 * functions above.
746 * If all==GL_TRUE, clear whole buffer, else just clear region defined
747 * by x,y,width,height
748 */
749
750 /* we can't handle color or index masking */
751 if ((*colorMask == 0xffffffff) && (ctx->Color.IndexMask == 0xffffffff)) {
752 if (mask & DD_BACK_LEFT_BIT) {
753 int color = c->visual->rgb_flag ? c->ClearColor : c->ClearIndex;
754
755 if (all) {
756 vl_clear(color);
757 } else {
758 vl_rect(x, y, width, height, color);
759 }
760
761 mask &= ~DD_BACK_LEFT_BIT;
762 }
763 }
764
765 if (mask) {
766 _swrast_Clear(ctx, mask, all, x, y, width, height);
767 }
768 }
769
770
771
772 /*
773 * This function is called to specify which buffer to read and write
774 * for software rasterization (swrast) fallbacks. This doesn't necessarily
775 * correspond to glDrawBuffer() or glReadBuffer() calls.
776 */
777 static void set_buffer (GLcontext *ctx, GLframebuffer *colorBuffer, GLuint bufferBit)
778 {
779 /*
780 * XXX todo - examine bufferBit and set read/write pointers
781 */
782 /* Normally, we would have
783 * ctx->Driver.ReadBuffer == set_read_buffer
784 * ctx->Driver.DrawBuffer == set_draw_buffer
785 * and make sure set_draw_buffer calls _swrast_DrawBuffer,
786 * which in turn will call this routine via dd->SetBuffer.
787 */
788 }
789
790
791
792 /*
793 * Return the width and height of the current buffer.
794 * If anything special has to been done when the buffer/window is
795 * resized, do it now.
796 */
797 static void get_buffer_size (GLframebuffer *buffer, GLuint *width, GLuint *height)
798 {
799 DMesaBuffer b = (DMesaBuffer)buffer;
800
801 *width = b->width;
802 *height = b->height;
803 }
804
805
806
807 static const GLubyte* get_string (GLcontext *ctx, GLenum name)
808 {
809 switch (name) {
810 case GL_RENDERER:
811 return (const GLubyte *)"Mesa DJGPP"
812 "\0port (c) Borca Daniel dec-2003";
813 default:
814 return NULL;
815 }
816 }
817
818
819
820 static void finish (GLcontext *ctx)
821 {
822 /*
823 * XXX todo - OPTIONAL FUNCTION: implements glFinish if possible
824 */
825 }
826
827
828
829 static void flush (GLcontext *ctx)
830 {
831 /*
832 * XXX todo - OPTIONAL FUNCTION: implements glFlush if possible
833 */
834 }
835
836
837
838 /****************************************************************************
839 * State
840 ***************************************************************************/
841 #define DMESA_NEW_LINE (_NEW_LINE | \
842 _NEW_TEXTURE | \
843 _NEW_LIGHT | \
844 _NEW_DEPTH | \
845 _NEW_RENDERMODE | \
846 _SWRAST_NEW_RASTERMASK)
847
848 #define DMESA_NEW_TRIANGLE (_NEW_POLYGON | \
849 _NEW_TEXTURE | \
850 _NEW_LIGHT | \
851 _NEW_DEPTH | \
852 _NEW_RENDERMODE | \
853 _SWRAST_NEW_RASTERMASK)
854
855 /* Extend the software rasterizer with our line and triangle
856 * functions.
857 */
858 static void dmesa_register_swrast_functions (GLcontext *ctx)
859 {
860 SWcontext *swrast = SWRAST_CONTEXT(ctx);
861
862 swrast->choose_line = dmesa_choose_line;
863 swrast->choose_triangle = dmesa_choose_tri;
864
865 swrast->invalidate_line |= DMESA_NEW_LINE;
866 swrast->invalidate_triangle |= DMESA_NEW_TRIANGLE;
867 }
868
869
870
871 /* Setup pointers and other driver state that is constant for the life
872 * of a context.
873 */
874 static void dmesa_init_pointers (GLcontext *ctx)
875 {
876 TNLcontext *tnl;
877 struct swrast_device_driver *dd = _swrast_GetDeviceDriverReference(ctx);
878
879 ctx->Driver.GetString = get_string;
880 ctx->Driver.GetBufferSize = get_buffer_size;
881 ctx->Driver.Flush = flush;
882 ctx->Driver.Finish = finish;
883
884 /* Software rasterizer pixel paths:
885 */
886 ctx->Driver.Accum = _swrast_Accum;
887 ctx->Driver.Bitmap = _swrast_Bitmap;
888 ctx->Driver.Clear = clear;
889 ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
890 ctx->Driver.CopyPixels = _swrast_CopyPixels;
891 ctx->Driver.DrawPixels = _swrast_DrawPixels;
892 ctx->Driver.ReadPixels = _swrast_ReadPixels;
893 ctx->Driver.DrawBuffer = _swrast_DrawBuffer;
894
895 /* Software texture functions:
896 */
897 ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format;
898 ctx->Driver.TexImage1D = _mesa_store_teximage1d;
899 ctx->Driver.TexImage2D = _mesa_store_teximage2d;
900 ctx->Driver.TexImage3D = _mesa_store_teximage3d;
901 ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
902 ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d;
903 ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
904 ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
905
906 ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
907 ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
908 ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
909 ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
910 ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
911
912 ctx->Driver.CompressedTexImage1D = _mesa_store_compressed_teximage1d;
913 ctx->Driver.CompressedTexImage2D = _mesa_store_compressed_teximage2d;
914 ctx->Driver.CompressedTexImage3D = _mesa_store_compressed_teximage3d;
915 ctx->Driver.CompressedTexSubImage1D = _mesa_store_compressed_texsubimage1d;
916 ctx->Driver.CompressedTexSubImage2D = _mesa_store_compressed_texsubimage2d;
917 ctx->Driver.CompressedTexSubImage3D = _mesa_store_compressed_texsubimage3d;
918
919 /* Swrast hooks for imaging extensions:
920 */
921 ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
922 ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
923 ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
924 ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
925
926 /* Statechange callbacks:
927 */
928 ctx->Driver.ClearColor = clear_color;
929 ctx->Driver.ClearIndex = clear_index;
930
931 /* Initialize the TNL driver interface:
932 */
933 tnl = TNL_CONTEXT(ctx);
934 tnl->Driver.RunPipeline = _tnl_run_pipeline;
935
936 dd->SetBuffer = set_buffer;
937
938 /* Install swsetup for tnl->Driver.Render.*:
939 */
940 _swsetup_Wakeup(ctx);
941
942 /* The span functions should be in `dmesa_update_state', but I'm
943 * pretty sure they will never change during the life of the Visual
944 */
945
946 /* Index span/pixel functions */
947 dd->WriteCI32Span = write_index_span;
948 dd->WriteCI8Span = write_index8_span;
949 dd->WriteMonoCISpan = write_mono_index_span;
950 dd->WriteCI32Pixels = write_index_pixels;
951 dd->WriteMonoCIPixels = write_mono_index_pixels;
952 dd->ReadCI32Span = read_index_span;
953 dd->ReadCI32Pixels = read_index_pixels;
954
955 /* RGB(A) span/pixel functions */
956 dd->WriteRGBASpan = write_rgba_span;
957 dd->WriteRGBSpan = write_rgb_span;
958 dd->WriteMonoRGBASpan = write_mono_rgba_span;
959 dd->WriteRGBAPixels = write_rgba_pixels;
960 dd->WriteMonoRGBAPixels = write_mono_rgba_pixels;
961 dd->ReadRGBASpan = read_rgba_span;
962 dd->ReadRGBAPixels = read_rgba_pixels;
963 }
964
965
966
967 static void dmesa_update_state (GLcontext *ctx, GLuint new_state)
968 {
969 /* Propagate statechange information to swrast and swrast_setup
970 * modules. The DMesa driver has no internal GL-dependent state.
971 */
972 _swrast_InvalidateState( ctx, new_state );
973 _ac_InvalidateState( ctx, new_state );
974 _tnl_InvalidateState( ctx, new_state );
975 _swsetup_InvalidateState( ctx, new_state );
976 }
977 #endif /* FX */
978
979
980
981 /****************************************************************************
982 * DMesa Public API Functions
983 ***************************************************************************/
984
985 /*
986 * The exact arguments to this function will depend on your window system
987 */
988 DMesaVisual DMesaCreateVisual (GLint width,
989 GLint height,
990 GLint colDepth,
991 GLint refresh,
992 GLboolean dbFlag,
993 GLboolean rgbFlag,
994 GLint alphaSize,
995 GLint depthSize,
996 GLint stencilSize,
997 GLint accumSize)
998 {
999 #ifndef FX
1000 DMesaVisual v;
1001 GLint redBits, greenBits, blueBits, alphaBits, indexBits;
1002 GLboolean sw_alpha;
1003
1004 if (!dbFlag) {
1005 return NULL;
1006 }
1007
1008 alphaBits = 0;
1009
1010 if (!rgbFlag) {
1011 indexBits = 8;
1012 redBits = 0;
1013 greenBits = 0;
1014 blueBits = 0;
1015 } else {
1016 indexBits = 0;
1017 switch (colDepth) {
1018 case 8:
1019 redBits = 8;
1020 greenBits = 8;
1021 blueBits = 8;
1022 break;
1023 case 15:
1024 alphaBits = 1;
1025 redBits = 5;
1026 greenBits = 5;
1027 blueBits = 5;
1028 break;
1029 case 16:
1030 redBits = 5;
1031 greenBits = 6;
1032 blueBits = 5;
1033 break;
1034 case 32:
1035 alphaBits = 8;
1036 case 24:
1037 redBits = 8;
1038 greenBits = 8;
1039 blueBits = 8;
1040 break;
1041 default:
1042 return NULL;
1043 }
1044 }
1045
1046 /* Okay,
1047 * `alphaBits' is what we can provide
1048 * `alphaSize' is what app requests
1049 *
1050 * Note that alpha buffering is required only if destination alpha is used
1051 * in alpha blending; alpha blending modes that do not use destination alpha
1052 * can be used w/o alpha buffer.
1053 *
1054 * We will use whatever ALPHA app requests. Later, in `CreateBuffer' we'll
1055 * instruct Mesa to use its own ALPHA buffer, by passing a non-FALSE value
1056 * for ALPHA to `_mesa_initialize_framebuffer'.
1057 *
1058 * Basically, 32bit modes provide ALPHA storage, but can we rely on this?
1059 */
1060 alphaBits = alphaSize;
1061 sw_alpha = (alphaBits > 0);
1062
1063 if ((colDepth=vl_video_init(width, height, colDepth, rgbFlag, refresh)) <= 0) {
1064 return NULL;
1065 }
1066
1067 if ((v=(DMesaVisual)CALLOC_STRUCT(dmesa_visual)) != NULL) {
1068 /* Create core visual */
1069 _mesa_initialize_visual((GLvisual *)v,
1070 rgbFlag, /* rgb */
1071 dbFlag,
1072 GL_FALSE, /* stereo */
1073 redBits,
1074 greenBits,
1075 blueBits,
1076 alphaBits,
1077 indexBits, /* indexBits */
1078 depthSize,
1079 stencilSize,
1080 accumSize, /* accumRed */
1081 accumSize, /* accumGreen */
1082 accumSize, /* accumBlue */
1083 alphaBits?accumSize:0, /* accumAlpha */
1084 1); /* numSamples */
1085
1086 v->depth = colDepth;
1087 v->db_flag = dbFlag;
1088 v->rgb_flag = rgbFlag;
1089 v->sw_alpha = sw_alpha;
1090
1091 v->zbuffer = (depthSize > 0) ? 1 : 0;
1092 }
1093
1094 return v;
1095
1096 #else /* FX */
1097
1098 char *env;
1099 int i = 0, fx_attrib[32];
1100
1101 if (!rgbFlag) {
1102 return NULL;
1103 }
1104
1105 if (dbFlag) fx_attrib[i++] = FXMESA_DOUBLEBUFFER;
1106 if (depthSize > 0) { fx_attrib[i++] = FXMESA_DEPTH_SIZE; fx_attrib[i++] = depthSize; }
1107 if (stencilSize > 0) { fx_attrib[i++] = FXMESA_STENCIL_SIZE; fx_attrib[i++] = stencilSize; }
1108 if (accumSize > 0) { fx_attrib[i++] = FXMESA_ACCUM_SIZE; fx_attrib[i++] = accumSize; }
1109 if (alphaSize) { fx_attrib[i++] = FXMESA_ALPHA_SIZE; fx_attrib[i++] = alphaSize; }
1110 fx_attrib[i++] = FXMESA_COLORDEPTH;
1111 fx_attrib[i++] = colDepth;
1112 fx_attrib[i] = FXMESA_NONE;
1113
1114 if ((env = getenv("MESA_FX_INFO")) && (env[0] == 'r')) {
1115 freopen("MESA.LOG", "w", stderr);
1116 }
1117
1118 return (DMesaVisual)fxMesaCreateBestContext(-1, width, height, fx_attrib);
1119 #endif /* FX */
1120 }
1121
1122
1123
1124 void DMesaDestroyVisual (DMesaVisual v)
1125 {
1126 #ifndef FX
1127 _mesa_destroy_visual((GLvisual *)v);
1128
1129 vl_video_exit();
1130
1131 #else
1132 fxMesaDestroyContext((fxMesaContext)v);
1133 #endif
1134 }
1135
1136
1137
1138 DMesaBuffer DMesaCreateBuffer (DMesaVisual visual,
1139 GLint xpos, GLint ypos,
1140 GLint width, GLint height)
1141 {
1142 #ifndef FX
1143 DMesaBuffer b;
1144
1145 if ((b=(DMesaBuffer)CALLOC_STRUCT(dmesa_buffer)) != NULL) {
1146 _mesa_initialize_framebuffer((GLframebuffer *)b,
1147 (GLvisual *)visual,
1148 visual->zbuffer == 1,
1149 ((GLvisual *)visual)->stencilBits > 0,
1150 ((GLvisual *)visual)->accumRedBits > 0,
1151 visual->sw_alpha);
1152 b->xpos = xpos;
1153 b->ypos = ypos;
1154 b->width = width;
1155 b->height = height;
1156 }
1157
1158 return b;
1159 #else
1160 return (DMesaBuffer)visual;
1161 #endif
1162 }
1163
1164
1165
1166 void DMesaDestroyBuffer (DMesaBuffer b)
1167 {
1168 #ifndef FX
1169 free(b->the_window);
1170 _mesa_destroy_framebuffer((GLframebuffer *)b);
1171 #endif
1172 }
1173
1174
1175
1176 DMesaContext DMesaCreateContext (DMesaVisual visual,
1177 DMesaContext share)
1178 {
1179 #ifndef FX
1180 DMesaContext c;
1181 GLboolean direct = GL_FALSE;
1182
1183 if ((c=(DMesaContext)CALLOC_STRUCT(dmesa_context)) != NULL) {
1184 _mesa_initialize_context((GLcontext *)c,
1185 (GLvisual *)visual,
1186 (GLcontext *)share,
1187 (void *)c, direct);
1188
1189 _mesa_enable_sw_extensions((GLcontext *)c);
1190 _mesa_enable_1_3_extensions((GLcontext *)c);
1191 _mesa_enable_1_4_extensions((GLcontext *)c);
1192 _mesa_enable_1_5_extensions((GLcontext *)c);
1193
1194 /* you probably have to do a bunch of other initializations here. */
1195 c->visual = visual;
1196
1197 ((GLcontext *)c)->Driver.UpdateState = dmesa_update_state;
1198
1199 /* Initialize the software rasterizer and helper modules.
1200 */
1201 _swrast_CreateContext((GLcontext *)c);
1202 _ac_CreateContext((GLcontext *)c);
1203 _tnl_CreateContext((GLcontext *)c);
1204 _swsetup_CreateContext((GLcontext *)c);
1205 if (visual->rgb_flag) dmesa_register_swrast_functions((GLcontext *)c);
1206 dmesa_init_pointers((GLcontext *)c);
1207 }
1208
1209 return c;
1210
1211 #else /* FX */
1212 return (DMesaContext)visual;
1213 #endif /* FX */
1214 }
1215
1216
1217
1218 void DMesaDestroyContext (DMesaContext c)
1219 {
1220 #ifndef FX
1221 if (c) {
1222 _swsetup_DestroyContext((GLcontext *)c);
1223 _swrast_DestroyContext((GLcontext *)c);
1224 _tnl_DestroyContext((GLcontext *)c);
1225 _ac_DestroyContext((GLcontext *)c);
1226 _mesa_destroy_context((GLcontext *)c);
1227 }
1228 #endif
1229 }
1230
1231
1232
1233 GLboolean DMesaMoveBuffer (GLint xpos, GLint ypos)
1234 {
1235 #ifndef FX
1236 GET_CURRENT_CONTEXT(ctx);
1237 DMesaBuffer b = ((DMesaContext)ctx)->Buffer;
1238
1239 if (vl_sync_buffer(&b->the_window, xpos, ypos, b->width, b->height) != 0) {
1240 return GL_FALSE;
1241 } else {
1242 b->xpos = xpos;
1243 b->ypos = ypos;
1244 return GL_TRUE;
1245 }
1246
1247 #else
1248 return GL_FALSE;
1249 #endif
1250 }
1251
1252
1253
1254 GLboolean DMesaResizeBuffer (GLint width, GLint height)
1255 {
1256 #ifndef FX
1257 GET_CURRENT_CONTEXT(ctx);
1258 DMesaBuffer b = ((DMesaContext)ctx)->Buffer;
1259
1260 if (vl_sync_buffer(&b->the_window, b->xpos, b->ypos, width, height) != 0) {
1261 return GL_FALSE;
1262 } else {
1263 b->width = width;
1264 b->height = height;
1265 return GL_TRUE;
1266 }
1267
1268 #else
1269 return GL_FALSE;
1270 #endif
1271 }
1272
1273
1274
1275 /*
1276 * Make the specified context and buffer the current one.
1277 */
1278 GLboolean DMesaMakeCurrent (DMesaContext c, DMesaBuffer b)
1279 {
1280 #ifndef FX
1281 if ((c != NULL) && (b != NULL)) {
1282 if (vl_sync_buffer(&b->the_window, b->xpos, b->ypos, b->width, b->height) != 0) {
1283 return GL_FALSE;
1284 }
1285
1286 c->Buffer = b;
1287
1288 _mesa_make_current((GLcontext *)c, (GLframebuffer *)b);
1289 if (((GLcontext *)c)->Viewport.Width == 0) {
1290 /* initialize viewport to window size */
1291 _mesa_Viewport(0, 0, b->width, b->height);
1292 }
1293 } else {
1294 /* Detach */
1295 _mesa_make_current(NULL, NULL);
1296 }
1297
1298 #else
1299 fxMesaMakeCurrent((fxMesaContext)c);
1300 #endif
1301
1302 return GL_TRUE;
1303 }
1304
1305
1306
1307 void DMesaSwapBuffers (DMesaBuffer b)
1308 {
1309 /* copy/swap back buffer to front if applicable */
1310 #ifndef FX
1311 GET_CURRENT_CONTEXT(ctx);
1312 _mesa_notifySwapBuffers(ctx);
1313 vl_flip();
1314 #else
1315 fxMesaSwapBuffers();
1316 #endif
1317 }
1318
1319
1320
1321 void DMesaSetCI (int ndx, GLfloat red, GLfloat green, GLfloat blue)
1322 {
1323 #ifndef FX
1324 vl_setCI(ndx, red, green, blue);
1325 #endif
1326 }
1327
1328
1329
1330 void *DMesaGetCurrentContext (void)
1331 {
1332 #ifndef FX
1333 GET_CURRENT_CONTEXT(ctx);
1334 return ctx;
1335 #else
1336 return fxMesaGetCurrentContext();
1337 #endif
1338 }
1339
1340
1341
1342 int DMesaGetIntegerv (GLenum pname, GLint *params)
1343 {
1344 switch (pname) {
1345 case DMESA_GET_SCREEN_SIZE:
1346 #ifndef FX
1347 vl_get(VL_GET_SCREEN_SIZE, params);
1348 #else
1349 fxGetScreenGeometry(&params[0], &params[1]);
1350 #endif
1351 break;
1352 case DMESA_GET_DRIVER_CAPS:
1353 #ifndef FX
1354 params[0] = DMESA_DRIVER_SWDB_BIT;
1355 #else
1356 params[0] = DMESA_DRIVER_LLWO_BIT;
1357 #endif
1358 break;
1359 case DMESA_GET_VIDEO_MODES:
1360 #ifndef FX
1361 return vl_get(VL_GET_VIDEO_MODES, params);
1362 #else
1363 {
1364 /* `vmode' struct must be sync'ed with `internal.h' (vl_mode)
1365 * `vmode' list must be sync'ed with `fxapi.c'
1366 * `hw >= 6' means Napalm and can do 32bit rendering
1367 * TODO: we should take an envvar for `fxMesaSelectCurrentBoard'
1368 */
1369 static struct {
1370 int width, height;
1371 int bpp;
1372 } vmode[] = {
1373 { 320, 200, 16 },
1374 { 320, 240, 16 },
1375 { 512, 384, 16 },
1376 { 640, 400, 16 },
1377 { 640, 480, 16 },
1378 { 800, 600, 16 },
1379 {1024, 768, 16 },
1380
1381 { 320, 200, 32 },
1382 { 320, 240, 32 },
1383 { 512, 384, 32 },
1384 { 640, 400, 32 },
1385 { 640, 480, 32 },
1386 { 800, 600, 32 },
1387 {1024, 768, 32 }
1388 };
1389 int hw = fxMesaSelectCurrentBoard(0);
1390 int i, n = sizeof(vmode) / sizeof(vmode[0]);
1391 if (hw < 6) {
1392 n /= 2;
1393 }
1394 if (params) {
1395 for (i = 0; i < n; i++) {
1396 params[i] = (GLint)(&vmode[i]);
1397 }
1398 }
1399 return n;
1400 }
1401 #endif
1402 default:
1403 return -1;
1404 }
1405
1406 return 0;
1407 }