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