DOS updates from Daniel Borca.
[mesa.git] / src / mesa / drivers / dos / video.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.3 for Mesa 5.0
27 *
28 * Copyright (C) 2002 - Borca Daniel
29 * Email : dborca@yahoo.com
30 * Web : http://www.geocities.com/dborca
31 *
32 * Thanks to CrazyPyro (Neil Funk) for FakeColor
33 */
34
35
36 #include <stdlib.h>
37
38 #include "video.h"
39 #include "internal.h"
40 #include "vesa/vesa.h"
41 #include "vga/vga.h"
42
43
44
45 static vl_driver *drv;
46 /* based upon mode specific data: valid entire session */
47 int vl_video_selector;
48 static int video_scanlen, video_bypp;
49 /* valid until next buffer */
50 void *vl_current_draw_buffer, *vl_current_read_buffer;
51 int vl_current_stride, vl_current_width, vl_current_height, vl_current_bytes;
52 int vl_current_offset, vl_current_delta;
53
54
55
56 /* lookup table for scaling 5 bit colors up to 8 bits */
57 static int _rgb_scale_5[32] = {
58 0, 8, 16, 24, 32, 41, 49, 57,
59 65, 74, 82, 90, 98, 106, 115, 123,
60 131, 139, 148, 156, 164, 172, 180, 189,
61 197, 205, 213, 222, 230, 238, 246, 255
62 };
63
64 /* lookup table for scaling 6 bit colors up to 8 bits */
65 static int _rgb_scale_6[64] = {
66 0, 4, 8, 12, 16, 20, 24, 28,
67 32, 36, 40, 44, 48, 52, 56, 60,
68 64, 68, 72, 76, 80, 85, 89, 93,
69 97, 101, 105, 109, 113, 117, 121, 125,
70 129, 133, 137, 141, 145, 149, 153, 157,
71 161, 165, 170, 174, 178, 182, 186, 190,
72 194, 198, 202, 206, 210, 214, 218, 222,
73 226, 230, 234, 238, 242, 246, 250, 255
74 };
75
76 /* FakeColor data */
77 #define R_CNT 6
78 #define G_CNT 6
79 #define B_CNT 6
80
81 #define R_BIAS 7
82 #define G_BIAS 7
83 #define B_BIAS 7
84
85 static word32 VGAPalette[256];
86 static word8 array_r[256];
87 static word8 array_g[256];
88 static word8 array_b[256];
89
90
91
92 int (*vl_mixfix) (fixed r, fixed g, fixed b);
93 int (*vl_mixrgb) (const unsigned char rgb[]);
94 int (*vl_mixrgba) (const unsigned char rgba[]);
95 void (*vl_getrgba) (unsigned int offset, unsigned char rgba[4]);
96 void (*vl_clear) (int color);
97 void (*vl_rect) (int x, int y, int width, int height, int color);
98 void (*vl_flip) (void);
99 void (*vl_putpixel) (unsigned int offset, int color);
100
101
102
103 /* Desc: color composition (w/o ALPHA)
104 *
105 * In : R, G, B
106 * Out : color
107 *
108 * Note: -
109 */
110 static int vl_mixfix8fake (fixed r, fixed g, fixed b)
111 {
112 return array_b[b>>FIXED_SHIFT]*G_CNT*R_CNT
113 + array_g[g>>FIXED_SHIFT]*R_CNT
114 + array_r[r>>FIXED_SHIFT];
115 }
116 #define vl_mixfix8 vl_mixfix8fake
117 static int vl_mixfix15 (fixed r, fixed g, fixed b)
118 {
119 return ((r>>(3+FIXED_SHIFT))<<10)
120 |((g>>(3+FIXED_SHIFT))<<5)
121 |(b>>(3+FIXED_SHIFT));
122 }
123 static int vl_mixfix16 (fixed r, fixed g, fixed b)
124 {
125 return ((r>>(3+FIXED_SHIFT))<<11)
126 |((g>>(2+FIXED_SHIFT))<<5)
127 |(b>>(3+FIXED_SHIFT));
128 }
129 #define vl_mixfix24 vl_mixfix32
130 static int vl_mixfix32 (fixed r, fixed g, fixed b)
131 {
132 return ((r>>FIXED_SHIFT)<<16)
133 |((g>>FIXED_SHIFT)<<8)
134 |(b>>FIXED_SHIFT);
135 }
136
137
138
139 /* Desc: color composition (w/ ALPHA)
140 *
141 * In : array of integers (R, G, B, A)
142 * Out : color
143 *
144 * Note: -
145 */
146 #define vl_mixrgba8 vl_mixrgb8fake
147 #define vl_mixrgba15 vl_mixrgb15
148 #define vl_mixrgba16 vl_mixrgb16
149 #define vl_mixrgba24 vl_mixrgb24
150 static int vl_mixrgba32 (const unsigned char rgba[])
151 {
152 return (rgba[3]<<24)|(rgba[0]<<16)|(rgba[1]<<8)|(rgba[2]);
153 }
154
155
156
157 /* Desc: color composition (w/o ALPHA)
158 *
159 * In : array of integers (R, G, B)
160 * Out : color
161 *
162 * Note: -
163 */
164 static int vl_mixrgb8fake (const unsigned char rgba[])
165 {
166 return array_b[rgba[2]]*G_CNT*R_CNT
167 + array_g[rgba[1]]*R_CNT
168 + array_r[rgba[0]];
169 }
170 #define vl_mixrgb8 vl_mixrgb8fake
171 static int vl_mixrgb15 (const unsigned char rgb[])
172 {
173 return ((rgb[0]>>3)<<10)|((rgb[1]>>3)<<5)|(rgb[2]>>3);
174 }
175 static int vl_mixrgb16 (const unsigned char rgb[])
176 {
177 return ((rgb[0]>>3)<<11)|((rgb[1]>>2)<<5)|(rgb[2]>>3);
178 }
179 #define vl_mixrgb24 vl_mixrgb32
180 static int vl_mixrgb32 (const unsigned char rgb[])
181 {
182 return (rgb[0]<<16)|(rgb[1]<<8)|(rgb[2]);
183 }
184
185
186
187 /* Desc: color decomposition
188 *
189 * In : pixel offset, array of integers to hold color components (R, G, B, A)
190 * Out : -
191 *
192 * Note: uses current read buffer
193 */
194 static void v_getrgba8fake6 (unsigned int offset, unsigned char rgba[])
195 {
196 word32 c = VGAPalette[((word8 *)vl_current_read_buffer)[offset]];
197 rgba[0] = _rgb_scale_6[(c >> 16) & 0x3F];
198 rgba[1] = _rgb_scale_6[(c >> 8) & 0x3F];
199 rgba[2] = _rgb_scale_6[c & 0x3F];
200 rgba[3] = c >> 24;
201 }
202 static void v_getrgba8fake8 (unsigned int offset, unsigned char rgba[])
203 {
204 word32 c = VGAPalette[((word8 *)vl_current_read_buffer)[offset]];
205 rgba[0] = c >> 16;
206 rgba[1] = c >> 8;
207 rgba[2] = c;
208 rgba[3] = c >> 24;
209 }
210 #define v_getrgba8 v_getrgba8fake6
211 static void v_getrgba15 (unsigned int offset, unsigned char rgba[4])
212 {
213 word32 c = ((word16 *)vl_current_read_buffer)[offset];
214 rgba[0] = _rgb_scale_5[(c >> 10) & 0x1F];
215 rgba[1] = _rgb_scale_5[(c >> 5) & 0x1F];
216 rgba[2] = _rgb_scale_5[c & 0x1F];
217 rgba[3] = 255;
218 }
219 static void v_getrgba16 (unsigned int offset, unsigned char rgba[4])
220 {
221 word32 c = ((word16 *)vl_current_read_buffer)[offset];
222 rgba[0] = _rgb_scale_5[(c >> 11) & 0x1F];
223 rgba[1] = _rgb_scale_6[(c >> 5) & 0x3F];
224 rgba[2] = _rgb_scale_5[c & 0x1F];
225 rgba[3] = 255;
226 }
227 static void v_getrgba24 (unsigned int offset, unsigned char rgba[4])
228 {
229 word32 c = *(word32 *)((long)vl_current_read_buffer+offset*3);
230 rgba[0] = c >> 16;
231 rgba[1] = c >> 8;
232 rgba[2] = c;
233 rgba[3] = 255;
234 }
235 static void v_getrgba32 (unsigned int offset, unsigned char rgba[4])
236 {
237 word32 c = ((word32 *)vl_current_read_buffer)[offset];
238 rgba[0] = c >> 16;
239 rgba[1] = c >> 8;
240 rgba[2] = c;
241 rgba[3] = c >> 24;
242 }
243
244
245
246 /* Desc: set one palette entry
247 *
248 * In : index, R, G, B
249 * Out : -
250 *
251 * Note: color components are in range [0.0 .. 1.0]
252 */
253 void vl_setCI (int index, float red, float green, float blue)
254 {
255 drv->setCI_f(index, red, green, blue);
256 }
257
258
259
260 /* Desc: read pixel from 8bit buffer
261 *
262 * In : pixel offset
263 * Out : pixel read
264 *
265 * Note: used only for CI modes
266 */
267 int vl_getCIpixel (unsigned int offset)
268 {
269 return ((word8 *)vl_current_read_buffer)[offset];
270 }
271
272
273
274 /* Desc: set one palette entry
275 *
276 * In : color, R, G, B
277 * Out : -
278 *
279 * Note: color components are in range [0 .. 63]
280 */
281 static void fake_setcolor (int c, int r, int g, int b)
282 {
283 VGAPalette[c] = 0xff000000 | (r<<16) | (g<<8) | b;
284
285 drv->setCI_i(c, r, g, b);
286 }
287
288
289
290 /* Desc: build FakeColor palette
291 *
292 * In : CI precision in bits
293 * Out : -
294 *
295 * Note: -
296 */
297 static void fake_buildpalette (int bits)
298 {
299 double c_r, c_g, c_b;
300 int r, g, b, color = 0;
301
302 double max = (1 << bits) - 1;
303
304 for (b=0; b<B_CNT; ++b) {
305 for (g=0; g<G_CNT; ++g) {
306 for (r=0; r<R_CNT; ++r) {
307 c_r = 0.5 + (double)r*(max-R_BIAS)/(R_CNT-1.) + R_BIAS;
308 c_g = 0.5 + (double)g*(max-G_BIAS)/(G_CNT-1.) + G_BIAS;
309 c_b = 0.5 + (double)b*(max-B_BIAS)/(B_CNT-1.) + B_BIAS;
310 fake_setcolor(color++, (int)c_r, (int)c_g, (int)c_b);
311 }
312 }
313 }
314
315 for (color=0; color<256; color++) {
316 c_r = (double)color*R_CNT/256.;
317 c_g = (double)color*G_CNT/256.;
318 c_b = (double)color*B_CNT/256.;
319 array_r[color] = (int)c_r;
320 array_g[color] = (int)c_g;
321 array_b[color] = (int)c_b;
322 }
323 }
324
325
326
327 /* Desc: sync buffer with video hardware
328 *
329 * In : old buffer, position, size
330 * Out : new buffer
331 *
332 * Note: -
333 */
334 void *vl_sync_buffer (void *buffer, int x, int y, int width, int height)
335 {
336 void *newbuf;
337
338 if (width&7) {
339 return NULL;
340 } else {
341 if ((newbuf=realloc(buffer, width * height * video_bypp)) != NULL) {
342 vl_current_width = width;
343 vl_current_height = height;
344 vl_current_stride = vl_current_width * video_bypp;
345 vl_current_bytes = vl_current_stride * height;
346
347 vl_current_offset = video_scanlen * y + video_bypp * x;
348 vl_current_delta = video_scanlen - vl_current_stride;
349 }
350 return vl_current_draw_buffer = vl_current_read_buffer = newbuf;
351 }
352 }
353
354
355
356 /* Desc: retrieve CPU MMX capability
357 *
358 * In : -
359 * Out : FALSE if CPU cannot do MMX
360 *
361 * Note: -
362 */
363 int vl_can_mmx (void)
364 {
365 #ifdef USE_MMX_ASM
366 extern int _mesa_identify_x86_cpu_features (void);
367 int _mesa_x86_cpu_features = _mesa_identify_x86_cpu_features();
368 return (_mesa_x86_cpu_features & 0x00800000);
369 #else
370 return 0;
371 #endif
372 }
373
374
375
376 /* Desc: setup mode
377 *
378 * In : ptr to mode definition
379 * Out : 0 if success
380 *
381 * Note: -
382 */
383 static int vl_setup_mode (vl_mode *p)
384 {
385 #define INITPTR(bpp) \
386 vl_putpixel = v_putpixel##bpp; \
387 vl_getrgba = v_getrgba##bpp; \
388 vl_rect = v_rect##bpp; \
389 vl_mixfix = vl_mixfix##bpp; \
390 vl_mixrgb = vl_mixrgb##bpp; \
391 vl_mixrgba = vl_mixrgba##bpp; \
392 vl_clear = vl_can_mmx() ? v_clear##bpp##_mmx : v_clear##bpp
393
394 switch (p->bpp) {
395 case 8:
396 INITPTR(8);
397 break;
398 case 15:
399 INITPTR(15);
400 break;
401 case 16:
402 INITPTR(16);
403 break;
404 case 24:
405 INITPTR(24);
406 break;
407 case 32:
408 INITPTR(32);
409 break;
410 default:
411 return -1;
412 }
413
414 #undef INITPTR
415
416 video_bypp = (p->bpp+7)/8;
417 video_scanlen = p->scanlen;
418 vl_video_selector = p->sel;
419
420 return 0;
421 }
422
423
424
425 /* Desc: restore to the mode prior to first call to `vl_video_init'.
426 *
427 * In : -
428 * Out : -
429 *
430 * Note: -
431 */
432 void vl_video_exit (void)
433 {
434 drv->restore();
435 drv->finit();
436 }
437
438
439
440 /* Desc: enter mode
441 *
442 * In : xres, yres, bits/pixel, RGB, refresh rate
443 * Out : pixel width in bits if success
444 *
445 * Note: -
446 */
447 int vl_video_init (int width, int height, int bpp, int rgb, int refresh)
448 {
449 int fake;
450 vl_mode *p, *q;
451 unsigned int min;
452
453 fake = 0;
454 if (!rgb) {
455 bpp = 8;
456 } else if (bpp == 8) {
457 fake = 1;
458 }
459
460 /* initialize hardware */
461 drv = &VESA;
462 if ((q=drv->init()) == NULL) {
463 drv = &VGA;
464 if ((q=drv->init()) == NULL) {
465 return 0;
466 }
467 }
468
469 /* search for a mode that fits our request */
470 for (min=-1, p=NULL; q->mode!=0xffff; q++) {
471 if ((q->xres>=width) && (q->yres>=height) && (q->bpp==bpp)) {
472 if (min>=(unsigned)(q->xres*q->yres)) {
473 min = q->xres*q->yres;
474 p = q;
475 }
476 }
477 }
478
479 /* check, setup and enter mode */
480 if ((p!=NULL) && (vl_setup_mode(p) == 0) && (drv->entermode(p, refresh) == 0)) {
481 vl_flip = drv->blit;
482 if (fake) {
483 min = drv->getCIprec();
484 fake_buildpalette(min);
485 if (min == 8) {
486 vl_getrgba = v_getrgba8fake8;
487 }
488 }
489 return bpp;
490 }
491
492 /* abort */
493 return 0;
494 }