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