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