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