DOS updates from Daniel Borca
[mesa.git] / src / mesa / drivers / dos / dmesa.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 4.0
4 *
5 * Copyright (C) 1999 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 v0.2 for Mesa 4.0
27 *
28 * Copyright (C) 2002 - Borca Daniel
29 * Email : dborca@yahoo.com
30 * Web : http://www.geocities.com/dborca
31 */
32
33
34 #ifdef PC_HEADER
35 #include "all.h"
36 #else
37 #include "glheader.h"
38 #include "context.h"
39 #include "GL/dmesa.h"
40 #include "extensions.h"
41 #include "macros.h"
42 #include "matrix.h"
43 #include "mmath.h"
44 #include "texformat.h"
45 #include "texstore.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/s_trispan.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 #endif
58
59 #include "video.h"
60
61
62
63 /*
64 * In C++ terms, this class derives from the GLvisual class.
65 * Add system-specific fields to it.
66 */
67 struct dmesa_visual {
68 GLvisual *gl_visual;
69 GLboolean rgb_flag; /* RGB mode? */
70 GLuint depth; /* bits per pixel (1, 8, 24, etc) */
71
72 GLint caps; /* video mode capabilities */
73 };
74
75 /*
76 * In C++ terms, this class derives from the GLframebuffer class.
77 * Add system-specific fields to it.
78 */
79 struct dmesa_buffer {
80 GLframebuffer *gl_buffer; /* The depth, stencil, accum, etc buffers */
81 void *the_window; /* your window handle, etc */
82
83 int xpos, ypos; /* position */
84 int width, height; /* size in pixels */
85 int pitch, len; /* number of bytes in a line, then total */
86 int cwidth; /* scan width */
87
88 int caps; /* video mode capabilities */
89
90 void (*tri_rgb_flat) ();
91 };
92
93 /*
94 * In C++ terms, this class derives from the GLcontext class.
95 * Add system-specific fields to it.
96 */
97 struct dmesa_context {
98 GLcontext *gl_ctx; /* the core library context */
99 DMesaVisual visual;
100 DMesaBuffer Buffer;
101 GLuint ClearColor;
102 /* etc... */
103 };
104
105
106
107 static void dmesa_update_state (GLcontext *ctx, GLuint new_state);
108
109
110
111 /**********************************************************************/
112 /***** Read/Write pixels *****/
113 /**********************************************************************/
114
115
116
117 #define FLIP(y) (c->Buffer->height - (y) - 1)
118 #define FLIP2(y) (h - (y) - 1)
119
120
121
122 static void write_rgba_span (const GLcontext *ctx, GLuint n, GLint x, GLint y,
123 const GLubyte rgba[][4], const GLubyte mask[])
124 {
125 DMesaContext c = (DMesaContext)ctx->DriverCtx;
126 void *b = c->Buffer->the_window;
127 GLuint i, offset;
128
129 offset = c->Buffer->cwidth * FLIP(y) + x;
130 if (mask) {
131 /* draw some pixels */
132 for (i=0; i<n; i++, offset++) {
133 if (mask[i]) {
134 vl_putpixel(b, offset, vl_mixrgba(rgba[i]));
135 }
136 }
137 } else {
138 /* draw all pixels */
139 for (i=0; i<n; i++, offset++) {
140 vl_putpixel(b, offset, vl_mixrgba(rgba[i]));
141 }
142 }
143 }
144
145 static void write_rgb_span (const GLcontext *ctx, GLuint n, GLint x, GLint y,
146 const GLubyte rgb[][3], const GLubyte mask[])
147 {
148 DMesaContext c = (DMesaContext)ctx->DriverCtx;
149 void *b = c->Buffer->the_window;
150 GLuint i, offset;
151
152 offset = c->Buffer->cwidth * FLIP(y) + x;
153 if (mask) {
154 /* draw some pixels */
155 for (i=0; i<n; i++, offset++) {
156 if (mask[i]) {
157 vl_putpixel(b, offset, vl_mixrgb(rgb[i]));
158 }
159 }
160 } else {
161 /* draw all pixels */
162 for (i=0; i<n; i++, offset++) {
163 vl_putpixel(b, offset, vl_mixrgb(rgb[i]));
164 }
165 }
166 }
167
168 static void write_mono_rgba_span (const GLcontext *ctx,
169 GLuint n, GLint x, GLint y,
170 const GLchan color[4], const GLubyte mask[])
171 {
172 DMesaContext c = (DMesaContext)ctx->DriverCtx;
173 void *b = c->Buffer->the_window;
174 GLuint i, offset, rgba = vl_mixrgba(color);
175
176 offset = c->Buffer->cwidth * FLIP(y) + x;
177 if (mask) {
178 /* draw some pixels */
179 for (i=0; i<n; i++, offset++) {
180 if (mask[i]) {
181 vl_putpixel(b, offset, rgba);
182 }
183 }
184 } else {
185 /* draw all pixels */
186 for (i=0; i<n; i++, offset++) {
187 vl_putpixel(b, offset, rgba);
188 }
189 }
190 }
191
192 static void read_rgba_span (const GLcontext *ctx, GLuint n, GLint x, GLint y,
193 GLubyte rgba[][4])
194 {
195 DMesaContext c = (DMesaContext)ctx->DriverCtx;
196 void *b = c->Buffer->the_window;
197 GLuint i, offset;
198
199 offset = c->Buffer->cwidth * FLIP(y) + x;
200 /* read all pixels */
201 for (i=0; i<n; i++, offset++) {
202 vl_getrgba(b, offset, rgba[i]);
203 }
204 }
205
206 static void 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 DMesaContext c = (DMesaContext)ctx->DriverCtx;
211 void *b = c->Buffer->the_window;
212 GLuint i, w = c->Buffer->cwidth, h = c->Buffer->height;
213
214 if (mask) {
215 /* draw some pixels */
216 for (i=0; i<n; i++) {
217 if (mask[i]) {
218 vl_putpixel(b, FLIP2(y[i])*w + x[i], vl_mixrgba(rgba[i]));
219 }
220 }
221 } else {
222 /* draw all pixels */
223 for (i=0; i<n; i++) {
224 vl_putpixel(b, FLIP2(y[i])*w + x[i], vl_mixrgba(rgba[i]));
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 DMesaContext c = (DMesaContext)ctx->DriverCtx;
234 void *b = c->Buffer->the_window;
235 GLuint i, w = c->Buffer->cwidth, h = c->Buffer->height, 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(b, 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(b, FLIP2(y[i])*w + x[i], rgba);
248 }
249 }
250 }
251
252 static void read_rgba_pixels (const GLcontext *ctx,
253 GLuint n, const GLint x[], const GLint y[],
254 GLubyte rgba[][4], const GLubyte mask[])
255 {
256 DMesaContext c = (DMesaContext)ctx->DriverCtx;
257 void *b = c->Buffer->the_window;
258 GLuint i, w = c->Buffer->cwidth, h = c->Buffer->height;
259
260 if (mask) {
261 /* read some pixels */
262 for (i=0; i<n; i++) {
263 if (mask[i]) {
264 vl_getrgba(b, 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(b, FLIP2(y[i])*w + x[i], rgba[i]);
271 }
272 }
273 }
274
275
276
277 /**********************************************************************/
278 /***** Optimized triangle rendering *****/
279 /**********************************************************************/
280
281
282
283 /*
284 * flat, NON-depth-buffered, triangle.
285 */
286 static void tri_rgb_flat (GLcontext *ctx,
287 const SWvertex *v0,
288 const SWvertex *v1,
289 const SWvertex *v2)
290 {
291 DMesaContext c = (DMesaContext)ctx->DriverCtx;
292 void *b = c->Buffer->the_window;
293 GLuint w = c->Buffer->cwidth, h = c->Buffer->height;
294
295 if (c->Buffer->tri_rgb_flat) {
296 c->Buffer->tri_rgb_flat(IROUND(v0->win[0]), IROUND(FLIP2(v0->win[1])),
297 IROUND(v1->win[0]), IROUND(FLIP2(v1->win[1])),
298 IROUND(v2->win[0]), IROUND(FLIP2(v2->win[1])),
299 vl_mixrgb(v2->color));
300 } else {
301 #define SETUP_CODE GLuint rgb = vl_mixrgb(v2->color);
302
303 #define RENDER_SPAN(span) \
304 GLuint i, offset = FLIP2(span.y)*w + span.x; \
305 for (i = 0; i < span.count; i++, offset++) { \
306 vl_putpixel(b, offset, rgb); \
307 }
308
309 #include "swrast/s_tritemp.h"
310 }
311 }
312
313
314
315 /*
316 * flat, depth-buffered, triangle.
317 */
318 static void tri_rgb_flat_z (GLcontext *ctx,
319 const SWvertex *v0,
320 const SWvertex *v1,
321 const SWvertex *v2)
322 {
323 DMesaContext c = (DMesaContext)ctx->DriverCtx;
324 void *b = c->Buffer->the_window;
325 GLuint w = c->Buffer->cwidth, h = c->Buffer->height;
326
327 #define INTERP_Z 1
328 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
329 #define SETUP_CODE GLuint rgb = vl_mixrgb(v2->color);
330
331 #define RENDER_SPAN(span) \
332 GLuint i, offset = FLIP2(span.y)*w + span.x; \
333 for (i = 0; i < span.count; i++, offset++) { \
334 const DEPTH_TYPE z = FixedToDepth(span.z); \
335 if (z < zRow[i]) { \
336 vl_putpixel(b, offset, rgb); \
337 zRow[i] = z; \
338 } \
339 span.z += span.zStep; \
340 }
341
342 #include "swrast/s_tritemp.h"
343 }
344
345
346
347 /*
348 * smooth, NON-depth-buffered, triangle.
349 */
350 static void tri_rgb_smooth (GLcontext *ctx,
351 const SWvertex *v0,
352 const SWvertex *v1,
353 const SWvertex *v2)
354 {
355 DMesaContext c = (DMesaContext)ctx->DriverCtx;
356 void *b = c->Buffer->the_window;
357 GLuint w = c->Buffer->cwidth, h = c->Buffer->height;
358
359 #define INTERP_RGB 1
360 #define RENDER_SPAN(span) \
361 GLuint i, offset = FLIP2(span.y)*w + span.x; \
362 for (i = 0; i < span.count; i++, offset++) { \
363 unsigned char rgb[3]; \
364 rgb[0] = FixedToInt(span.red); \
365 rgb[1] = FixedToInt(span.green); \
366 rgb[2] = FixedToInt(span.blue); \
367 vl_putpixel(b, offset, vl_mixrgb(rgb)); \
368 span.red += span.redStep; \
369 span.green += span.greenStep; \
370 span.blue += span.blueStep; \
371 }
372
373 #include "swrast/s_tritemp.h"
374 }
375
376
377
378 /*
379 * smooth, depth-buffered, triangle.
380 */
381 static void tri_rgb_smooth_z (GLcontext *ctx,
382 const SWvertex *v0,
383 const SWvertex *v1,
384 const SWvertex *v2)
385 {
386 DMesaContext c = (DMesaContext)ctx->DriverCtx;
387 void *b = c->Buffer->the_window;
388 GLuint w = c->Buffer->cwidth, h = c->Buffer->height;
389
390 #define INTERP_Z 1
391 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
392 #define INTERP_RGB 1
393
394 #define RENDER_SPAN(span) \
395 GLuint i, offset = FLIP2(span.y)*w + span.x; \
396 for (i = 0; i < span.count; i++, offset++) { \
397 const DEPTH_TYPE z = FixedToDepth(span.z); \
398 if (z < zRow[i]) { \
399 unsigned char rgb[3]; \
400 rgb[0] = FixedToInt(span.red); \
401 rgb[1] = FixedToInt(span.green); \
402 rgb[2] = FixedToInt(span.blue); \
403 vl_putpixel(b, offset, vl_mixrgb(rgb)); \
404 zRow[i] = z; \
405 } \
406 span.red += span.redStep; \
407 span.green += span.greenStep; \
408 span.blue += span.blueStep; \
409 span.z += span.zStep; \
410 }
411
412 #include "swrast/s_tritemp.h"
413 }
414
415
416
417 /*
418 * Analyze context state to see if we can provide a fast triangle function
419 * Otherwise, return NULL.
420 */
421 static swrast_tri_func dmesa_choose_tri_function (GLcontext *ctx)
422 {
423 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
424
425 if (ctx->RenderMode != GL_RENDER) return (swrast_tri_func) NULL;
426 if (ctx->Polygon.SmoothFlag) return (swrast_tri_func) NULL;
427 if (ctx->Texture._ReallyEnabled) return (swrast_tri_func) NULL;
428
429 if (ctx->Light.ShadeModel==GL_SMOOTH
430 && swrast->_RasterMask==DEPTH_BIT
431 && ctx->Depth.Func==GL_LESS
432 && ctx->Depth.Mask==GL_TRUE
433 && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS
434 && ctx->Polygon.StippleFlag==GL_FALSE) {
435 return tri_rgb_smooth_z;
436 }
437 if (ctx->Light.ShadeModel==GL_FLAT
438 && swrast->_RasterMask==DEPTH_BIT
439 && ctx->Depth.Func==GL_LESS
440 && ctx->Depth.Mask==GL_TRUE
441 && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS
442 && ctx->Polygon.StippleFlag==GL_FALSE) {
443 return tri_rgb_flat_z;
444 }
445 if (swrast->_RasterMask==0 /* no depth test */
446 && ctx->Light.ShadeModel==GL_SMOOTH
447 && ctx->Polygon.StippleFlag==GL_FALSE) {
448 return tri_rgb_smooth;
449 }
450 if (swrast->_RasterMask==0 /* no depth test */
451 && ctx->Light.ShadeModel==GL_FLAT
452 && ctx->Polygon.StippleFlag==GL_FALSE) {
453 return tri_rgb_flat;
454 }
455
456 return (swrast_tri_func)NULL;
457 }
458
459
460
461 /* Override for the swrast triangle-selection function. Try to use one
462 * of our internal line functions, otherwise fall back to the
463 * standard swrast functions.
464 */
465 static void dmesa_choose_tri (GLcontext *ctx)
466 {
467 SWcontext *swrast = SWRAST_CONTEXT(ctx);
468
469 if (!(swrast->Triangle=dmesa_choose_tri_function(ctx)))
470 _swrast_choose_triangle(ctx);
471 }
472
473
474
475 /**********************************************************************/
476 /***** Miscellaneous device driver funcs *****/
477 /**********************************************************************/
478
479
480
481 static void clear_color (GLcontext *ctx, const GLchan color[4])
482 {
483 DMesaContext c = (DMesaContext)ctx->DriverCtx;
484 c->ClearColor = vl_mixrgba(color);
485 }
486
487
488
489 static void clear (GLcontext *ctx, GLbitfield mask, GLboolean all,
490 GLint x, GLint y, GLint width, GLint height)
491 {
492 DMesaContext c = (DMesaContext)ctx->DriverCtx;
493 const GLuint *colorMask = (GLuint *)&ctx->Color.ColorMask;
494 DMesaBuffer b = c->Buffer;
495
496 /*
497 * Clear the specified region of the buffers indicated by 'mask'
498 * using the clear color or index as specified by one of the two
499 * functions above.
500 * If all==GL_TRUE, clear whole buffer, else just clear region defined
501 * by x,y,width,height
502 */
503
504 /* we can't handle color or index masking */
505 if (*colorMask==0xffffffff) {
506 if (mask & DD_BACK_LEFT_BIT) {
507 if (all) {
508 if CHECK_SOFTDB(b->caps) {
509 vl_clear_virtual(b->the_window, b->len, c->ClearColor);
510 } else {
511 vl_clear(b->the_window, 0, 0, b->width, b->height, c->ClearColor);
512 }
513 } else {
514 vl_clear(b->the_window, x, y, width, height, c->ClearColor);
515 }
516 mask &= ~DD_BACK_LEFT_BIT;
517 }
518 if (mask & DD_FRONT_LEFT_BIT) {
519 if (all) {
520 x = 0;
521 y = 0;
522 width = b->width;
523 height = b->height;
524 }
525 vl_clear(b->the_window, x, y, width, height, c->ClearColor);
526 mask &= ~DD_FRONT_LEFT_BIT;
527 }
528 }
529
530 if (mask) {
531 _swrast_Clear(ctx, mask, all, x, y, width, height);
532 }
533 }
534
535
536
537 /*
538 * Set the current reading buffer.
539 */
540 static void set_read_buffer (GLcontext *ctx, GLframebuffer *buffer,
541 GLenum mode)
542 {
543 /*
544 DMesaContext c = (DMesaContext)ctx->DriverCtx;
545 dmesa_update_state(ctx);
546 */
547 }
548
549
550
551 /*
552 * Set the destination/draw buffer.
553 */
554 static GLboolean set_draw_buffer (GLcontext *ctx, GLenum mode)
555 {
556 if (mode==GL_BACK_LEFT || mode==GL_FRONT_LEFT) {
557 return GL_TRUE;
558 } else {
559 return GL_FALSE;
560 }
561 }
562
563
564
565 /*
566 * Return the width and height of the current buffer.
567 * If anything special has to been done when the buffer/window is
568 * resized, do it now.
569 */
570 static void get_buffer_size (GLcontext *ctx, GLuint *width, GLuint *height)
571 {
572 DMesaContext c = (DMesaContext)ctx->DriverCtx;
573
574 *width = c->Buffer->width;
575 *height = c->Buffer->height;
576 }
577
578
579
580 static const GLubyte* get_string (GLcontext *ctx, GLenum name)
581 {
582 switch (name) {
583 case GL_RENDERER:
584 return (const GLubyte *)"DOS Mesa";
585 default:
586 return NULL;
587 }
588 }
589
590
591
592 /**********************************************************************/
593 /***** Miscellaneous device driver funcs *****/
594 /***** Note that these functions are mandatory *****/
595 /**********************************************************************/
596
597
598
599 /* OPTIONAL FUNCTION: implements glFinish if possible */
600 static void finish (GLcontext *ctx)
601 {
602 /*
603 DMesaContext c = (DMesaContext)ctx->DriverCtx;
604 */
605 }
606
607
608
609 /* OPTIONAL FUNCTION: implements glFlush if possible */
610 static void flush (GLcontext *ctx)
611 {
612 /*
613 DMesaContext c = (DMesaContext)ctx->DriverCtx;
614 */
615 }
616
617
618
619 /**********************************************************************/
620 /**********************************************************************/
621
622
623
624 #define DMESA_NEW_TRIANGLE (_NEW_POLYGON | \
625 _NEW_TEXTURE | \
626 _NEW_LIGHT | \
627 _NEW_DEPTH | \
628 _NEW_RENDERMODE | \
629 _SWRAST_NEW_RASTERMASK)
630
631
632
633 /* Extend the software rasterizer with our line and triangle
634 * functions.
635 */
636 static void dmesa_register_swrast_functions (GLcontext *ctx)
637 {
638 SWcontext *swrast = SWRAST_CONTEXT(ctx);
639
640 swrast->choose_triangle = dmesa_choose_tri;
641
642 swrast->invalidate_triangle |= DMESA_NEW_TRIANGLE;
643 }
644
645
646
647 /* Setup pointers and other driver state that is constant for the life
648 * of a context.
649 */
650 void dmesa_init_pointers (GLcontext *ctx)
651 {
652 TNLcontext *tnl;
653
654 ctx->Driver.UpdateState = dmesa_update_state;
655
656 ctx->Driver.GetString = get_string;
657 ctx->Driver.GetBufferSize = get_buffer_size;
658 ctx->Driver.Flush = flush;
659 ctx->Driver.Finish = finish;
660
661 /* Software rasterizer pixel paths:
662 */
663 ctx->Driver.Accum = _swrast_Accum;
664 ctx->Driver.Bitmap = _swrast_Bitmap;
665 ctx->Driver.Clear = clear;
666 ctx->Driver.ResizeBuffersMESA = _swrast_alloc_buffers;
667 ctx->Driver.CopyPixels = _swrast_CopyPixels;
668 ctx->Driver.DrawPixels = _swrast_DrawPixels;
669 ctx->Driver.ReadPixels = _swrast_ReadPixels;
670
671 /* Software texture functions:
672 */
673 ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format;
674 ctx->Driver.TexImage1D = _mesa_store_teximage1d;
675 ctx->Driver.TexImage2D = _mesa_store_teximage2d;
676 ctx->Driver.TexImage3D = _mesa_store_teximage3d;
677 ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
678 ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d;
679 ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
680 ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
681
682 ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
683 ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
684 ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
685 ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
686 ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
687
688 ctx->Driver.BaseCompressedTexFormat = _mesa_base_compressed_texformat;
689 ctx->Driver.CompressedTextureSize = _mesa_compressed_texture_size;
690 ctx->Driver.GetCompressedTexImage = _mesa_get_compressed_teximage;
691
692 /* Swrast hooks for imaging extensions:
693 */
694 ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
695 ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
696 ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
697 ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
698
699 /* Statechange callbacks:
700 */
701 ctx->Driver.SetDrawBuffer = set_draw_buffer;
702 ctx->Driver.ClearColor = clear_color;
703
704 /* Initialize the TNL driver interface:
705 */
706 tnl = TNL_CONTEXT(ctx);
707 tnl->Driver.RunPipeline = _tnl_run_pipeline;
708
709 /* Install swsetup for tnl->Driver.Render.*:
710 */
711 _swsetup_Wakeup(ctx);
712 }
713
714
715
716 static void dmesa_update_state (GLcontext *ctx, GLuint new_state)
717 {
718 DMesaContext c = (DMesaContext)ctx->DriverCtx;
719 struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
720
721 /* Initialize all the pointers in the DD struct. Do this whenever */
722 /* a new context is made current or we change buffers via set_buffer! */
723
724 _swrast_InvalidateState(ctx, new_state);
725 _swsetup_InvalidateState(ctx, new_state);
726 _ac_InvalidateState(ctx, new_state);
727 _tnl_InvalidateState(ctx, new_state);
728
729 swdd->SetReadBuffer = set_read_buffer;
730
731 /* RGB(A) span/pixel functions */
732 swdd->WriteRGBASpan = write_rgba_span;
733 swdd->WriteRGBSpan = write_rgb_span;
734 swdd->WriteMonoRGBASpan = write_mono_rgba_span;
735 swdd->WriteRGBAPixels = write_rgba_pixels;
736 swdd->WriteMonoRGBAPixels = write_mono_rgba_pixels;
737 swdd->ReadRGBASpan = read_rgba_span;
738 swdd->ReadRGBAPixels = read_rgba_pixels;
739 }
740
741
742
743 /**********************************************************************/
744 /***** DMesa Public API Functions *****/
745 /**********************************************************************/
746
747
748
749 /*
750 * The exact arguments to this function will depend on your window system
751 */
752 DMesaVisual DMesaCreateVisual (GLint width, GLint height, GLint colDepth,
753 GLboolean dbFlag, GLint depthSize,
754 GLint stencilSize,
755 GLint accumSize)
756 {
757 DMesaVisual v;
758 GLint redBits, greenBits, blueBits, alphaBits;
759 GLint caps;
760
761 alphaBits = 0;
762 switch (colDepth) {
763 case 15:
764 redBits = 5;
765 greenBits = 5;
766 blueBits = 5;
767 break;
768 case 16:
769 redBits = 5;
770 greenBits = 6;
771 blueBits = 5;
772 break;
773 case 32:
774 alphaBits = 8;
775 case 24:
776 redBits = 8;
777 greenBits = 8;
778 blueBits = 8;
779 break;
780 default:
781 return NULL;
782 }
783
784 caps = 0;
785 if (!dbFlag) {
786 caps |= VL_SINGLE;
787 }
788 if (vl_video_init(width, height, colDepth, &caps)!=0) {
789 return NULL;
790 }
791
792 if ((v=(DMesaVisual)calloc(1, sizeof(struct dmesa_visual)))!=NULL) {
793 /* Create core visual */
794 v->gl_visual = _mesa_create_visual(colDepth>8, /* rgb */
795 dbFlag,
796 GL_FALSE, /* stereo */
797 redBits,
798 greenBits,
799 blueBits,
800 alphaBits,
801 0, /* indexBits */
802 depthSize,
803 stencilSize,
804 accumSize, /* accumRed */
805 accumSize, /* accumGreen */
806 accumSize, /* accumBlue */
807 alphaBits?accumSize:0, /* accumAlpha */
808 1); /* numSamples */
809
810 v->depth = colDepth;
811 v->caps = caps;
812 }
813
814 return v;
815 }
816
817
818
819 void DMesaDestroyVisual (DMesaVisual v)
820 {
821 vl_video_exit();
822 _mesa_destroy_visual(v->gl_visual);
823 free(v);
824 }
825
826
827
828 DMesaBuffer DMesaCreateBuffer (DMesaVisual visual,
829 GLint xpos, GLint ypos,
830 GLint width, GLint height)
831 {
832 DMesaBuffer b;
833
834 if ((b=(DMesaBuffer)calloc(1, sizeof(struct dmesa_buffer)))!=NULL) {
835
836 b->gl_buffer = _mesa_create_framebuffer(visual->gl_visual,
837 visual->gl_visual->depthBits > 0,
838 visual->gl_visual->stencilBits > 0,
839 visual->gl_visual->accumRedBits > 0,
840 visual->gl_visual->alphaBits > 0);
841 b->xpos = xpos;
842 b->ypos = ypos;
843 b->width = width;
844 b->height = height;
845 b->caps = visual->caps;
846 b->pitch = b->width*((visual->depth+7)/8);
847 b->len = b->pitch*b->height;
848
849 b->tri_rgb_flat = vl_getprim(TRI_RGB_FLAT);
850 }
851
852 return b;
853 }
854
855
856
857 void DMesaDestroyBuffer (DMesaBuffer b)
858 {
859 if CHECK_SOFTDB(b->caps) {
860 free(b->the_window);
861 }
862 _mesa_destroy_framebuffer(b->gl_buffer);
863 free(b);
864 }
865
866
867
868 DMesaContext DMesaCreateContext (DMesaVisual visual,
869 DMesaContext share)
870 {
871 DMesaContext c;
872 GLboolean direct = GL_FALSE;
873
874 if ((c=(DMesaContext)calloc(1, sizeof(struct dmesa_context)))!=NULL) {
875 c->gl_ctx = _mesa_create_context(visual->gl_visual,
876 share ? share->gl_ctx : NULL,
877 (void *)c, direct);
878
879 _mesa_enable_sw_extensions(c->gl_ctx);
880 _mesa_enable_1_3_extensions(c->gl_ctx);
881
882 /* you probably have to do a bunch of other initializations here. */
883 c->visual = visual;
884
885 /* Initialize the software rasterizer and helper modules.
886 */
887 _swrast_CreateContext(c->gl_ctx);
888 _ac_CreateContext(c->gl_ctx);
889 _tnl_CreateContext(c->gl_ctx);
890 _swsetup_CreateContext(c->gl_ctx);
891 dmesa_init_pointers(c->gl_ctx);
892 dmesa_register_swrast_functions(c->gl_ctx);
893 }
894
895 return c;
896 }
897
898
899
900 void DMesaDestroyContext (DMesaContext c)
901 {
902 _mesa_destroy_context(c->gl_ctx);
903 free(c);
904 }
905
906
907
908 /*
909 * Make the specified context and buffer the current one.
910 */
911 GLboolean DMesaMakeCurrent (DMesaContext c, DMesaBuffer b)
912 {
913 if (c&&b) {
914 void *ptr = vl_sync_buffer(b->the_window, b->xpos, b->ypos, b->width, b->height, &b->cwidth);
915
916 if (b->cwidth==-1) {
917 return GL_FALSE;
918 }
919
920 b->the_window = ptr;
921 c->Buffer = b;
922
923 dmesa_update_state(c->gl_ctx, 0);
924 _mesa_make_current(c->gl_ctx, b->gl_buffer);
925 if (c->gl_ctx->Viewport.Width==0) {
926 /* initialize viewport to window size */
927 _mesa_Viewport(0, 0, c->Buffer->width, c->Buffer->height);
928 }
929 } else {
930 /* Detach */
931 _mesa_make_current(NULL, NULL);
932 }
933
934 return GL_TRUE;
935 }
936
937
938
939 void DMesaSwapBuffers (DMesaBuffer b)
940 {
941 /* copy/swap back buffer to front if applicable */
942 b->the_window = vl_flip(b->the_window, b->width, b->height, b->pitch);
943 }