r300: add occlusion queries support
[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 for Mesa
27 *
28 * Author: Daniel Borca
29 * Email : dborca@users.sourceforge.net
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 "null.h"
42 #include "video.h"
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 void (*vl_flip) (void);
57
58
59 /* FakeColor data */
60 #define R_CNT 6
61 #define G_CNT 6
62 #define B_CNT 6
63
64 #define R_BIAS 7
65 #define G_BIAS 7
66 #define B_BIAS 7
67
68 static word32 VGAPalette[256];
69 word8 array_r[256];
70 word8 array_g[256];
71 word8 array_b[256];
72 word8 tab_16_8[0x10000];
73
74
75 /* lookup table for scaling 5 bit colors up to 8 bits */
76 static int _rgb_scale_5[32] = {
77 0, 8, 16, 25, 33, 41, 49, 58,
78 66, 74, 82, 90, 99, 107, 115, 123,
79 132, 140, 148, 156, 165, 173, 181, 189,
80 197, 206, 214, 222, 230, 239, 247, 255
81 };
82
83 /* lookup table for scaling 6 bit colors up to 8 bits */
84 static int _rgb_scale_6[64] = {
85 0, 4, 8, 12, 16, 20, 24, 28,
86 32, 36, 40, 45, 49, 53, 57, 61,
87 65, 69, 73, 77, 81, 85, 89, 93,
88 97, 101, 105, 109, 113, 117, 121, 125,
89 130, 134, 138, 142, 146, 150, 154, 158,
90 162, 166, 170, 174, 178, 182, 186, 190,
91 194, 198, 202, 206, 210, 215, 219, 223,
92 227, 231, 235, 239, 243, 247, 251, 255
93 };
94
95
96 /* Desc: color composition (w/o ALPHA)
97 *
98 * In : array of integers (R, G, B)
99 * Out : color
100 *
101 * Note: -
102 */
103 static int
104 v_mixrgb8fake (const unsigned char rgb[])
105 {
106 return array_b[rgb[2]]*G_CNT*R_CNT
107 + array_g[rgb[1]]*R_CNT
108 + array_r[rgb[0]];
109 }
110
111
112 /* Desc: color decomposition
113 *
114 * In : pixel offset, array of integers to hold color components (R, G, B, A)
115 * Out : -
116 *
117 * Note: uses current read buffer
118 */
119 static void
120 v_getrgb8fake6 (unsigned int offset, unsigned char rgb[])
121 {
122 word32 c = VGAPalette[((word8 *)vl_current_read_buffer)[offset]];
123 rgb[0] = _rgb_scale_6[(c >> 16) & 0x3F];
124 rgb[1] = _rgb_scale_6[(c >> 8) & 0x3F];
125 rgb[2] = _rgb_scale_6[ c & 0x3F];
126 }
127 static void
128 v_getrgb8fake8 (unsigned int offset, unsigned char rgb[])
129 {
130 word32 c = VGAPalette[((word8 *)vl_current_read_buffer)[offset]];
131 rgb[0] = c >> 16;
132 rgb[1] = c >> 8;
133 rgb[2] = c;
134 }
135
136
137 /* Desc: create R5G6B5 to FakeColor table lookup
138 *
139 * In : -
140 * Out : -
141 *
142 * Note: -
143 */
144 static void
145 init_tab_16_8 (void)
146 {
147 int i;
148 for (i = 0; i < 0x10000; i++) {
149 unsigned char rgb[3];
150 rgb[0] = _rgb_scale_5[(i >> 11) & 0x1F];
151 rgb[1] = _rgb_scale_6[(i >> 5) & 0x3F];
152 rgb[2] = _rgb_scale_5[ i & 0x1F];
153 tab_16_8[i] = v_mixrgb8fake(rgb);
154 }
155 (void)v_getrgb8fake6;
156 (void)v_getrgb8fake8;
157 }
158
159
160 /* Desc: set one palette entry
161 *
162 * In : index, R, G, B
163 * Out : -
164 *
165 * Note: color components are in range [0.0 .. 1.0]
166 */
167 void
168 vl_setCI (int index, float red, float green, float blue)
169 {
170 drv->setCI_f(index, red, green, blue);
171 }
172
173
174 /* Desc: set one palette entry
175 *
176 * In : color, R, G, B
177 * Out : -
178 *
179 * Note: -
180 */
181 static void
182 fake_setcolor (int c, int r, int g, int b)
183 {
184 VGAPalette[c] = 0xff000000 | (r<<16) | (g<<8) | b;
185
186 drv->setCI_i(c, r, g, b);
187 }
188
189
190 /* Desc: build FakeColor palette
191 *
192 * In : CI precision in bits
193 * Out : -
194 *
195 * Note: -
196 */
197 static void
198 fake_buildpalette (int bits)
199 {
200 double c_r, c_g, c_b;
201 int r, g, b, color = 0;
202
203 double max = (1 << bits) - 1;
204
205 for (b = 0; b < B_CNT; ++b) {
206 for (g = 0; g < G_CNT; ++g) {
207 for (r = 0; r < R_CNT; ++r) {
208 c_r = 0.5 + (double)r * (max-R_BIAS) / (R_CNT-1.) + R_BIAS;
209 c_g = 0.5 + (double)g * (max-G_BIAS) / (G_CNT-1.) + G_BIAS;
210 c_b = 0.5 + (double)b * (max-B_BIAS) / (B_CNT-1.) + B_BIAS;
211 fake_setcolor(color++, (int)c_r, (int)c_g, (int)c_b);
212 }
213 }
214 }
215
216 for (color = 0; color < 256; color++) {
217 c_r = (double)color * R_CNT / 256.;
218 c_g = (double)color * G_CNT / 256.;
219 c_b = (double)color * B_CNT / 256.;
220 array_r[color] = (int)c_r;
221 array_g[color] = (int)c_g;
222 array_b[color] = (int)c_b;
223 }
224 }
225
226
227 /* Desc: initialize hardware
228 *
229 * In : -
230 * Out : list of available modes
231 *
232 * Note: when returning non-NULL, global variable `drv' is guaranteed to be ok
233 */
234 static vl_mode *
235 v_init_hw (void)
236 {
237 static vl_mode *q = NULL;
238
239 if (q == NULL) {
240 /* are we forced to NUL driver? */
241 if (getenv("DMESA_NULDRV")) {
242 if ((q = NUL.init()) != NULL) {
243 drv = &NUL;
244 }
245 return q;
246 }
247 /* initialize hardware */
248 if ((q = VESA.init()) != NULL) {
249 drv = &VESA;
250 } else if ((q = VGA.init()) != NULL) {
251 drv = &VGA;
252 } else {
253 drv = NULL;
254 }
255 }
256
257 return q;
258 }
259
260
261 /* Desc: sync buffer with video hardware
262 *
263 * In : ptr to old buffer, position, size
264 * Out : 0 if success
265 *
266 * Note: -
267 */
268 int
269 vl_sync_buffer (void **buffer, int x, int y, int width, int height)
270 {
271 if ((/*XXX*/width & 7) || (x < 0) || (y < 0) || (x+width > video_mode->xres) || (y+height > video_mode->yres)) {
272 return -1;
273 } else {
274 void *newbuf = *buffer;
275
276 if ((newbuf == NULL) || (vl_current_width != width) || (vl_current_height != height)) {
277 newbuf = realloc(newbuf, width * height * video_bypp);
278 }
279
280 if (newbuf == NULL) {
281 return -2;
282 }
283
284 vl_current_width = width;
285 vl_current_height = height;
286 vl_current_stride = vl_current_width * video_bypp;
287 vl_current_bytes = vl_current_stride * height;
288
289 vl_current_offset = video_scanlen * y + video_bypp * x;
290 vl_current_delta = video_scanlen - vl_current_stride;
291
292 vl_current_draw_buffer = vl_current_read_buffer = *buffer = newbuf;
293 return 0;
294 }
295 }
296
297
298 /* Desc: state retrieval
299 *
300 * In : name, storage
301 * Out : -1 for an error
302 *
303 * Note: -
304 */
305 int
306 vl_get (int pname, int *params)
307 {
308 switch (pname) {
309 case VL_GET_SCREEN_SIZE:
310 params[0] = video_mode->xres;
311 params[1] = video_mode->yres;
312 break;
313 case VL_GET_VIDEO_MODES: {
314 int n;
315 vl_mode *q;
316 if ((q = v_init_hw()) == NULL) {
317 return -1;
318 }
319 /* count available visuals */
320 for (n = 0; q->mode != 0xffff; q++) {
321 if ((q + 1)->mode == (q->mode | 0x4000)) {
322 /* same mode, but linear */
323 q++;
324 }
325 if (params) {
326 params[n] = (int)q;
327 }
328 n++;
329 }
330 return n;
331 }
332 default:
333 return (drv != NULL) ? drv->get(pname, params) : -1;
334 }
335 return 0;
336 }
337
338
339 /* Desc: setup mode
340 *
341 * In : ptr to mode definition
342 * Out : 0 if success
343 *
344 * Note: -
345 */
346 static int
347 vl_setup_mode (vl_mode *p)
348 {
349 if (p == NULL) {
350 return -1;
351 }
352
353 switch (p->bpp) {
354 case 8:
355 break;
356 case 15:
357 break;
358 case 16:
359 break;
360 case 24:
361 break;
362 case 32:
363 break;
364 default:
365 return -1;
366 }
367
368 video_mode = p;
369 video_bypp = (p->bpp+7)/8;
370 video_scanlen = p->scanlen;
371 vl_video_selector = p->sel;
372
373 return 0;
374 }
375
376
377 /* Desc: restore to the mode prior to first call to `vl_video_init'.
378 *
379 * In : -
380 * Out : -
381 *
382 * Note: -
383 */
384 void
385 vl_video_exit (void)
386 {
387 drv->restore();
388 drv->fini();
389 video_mode = NULL;
390 }
391
392
393 /* Desc: enter mode
394 *
395 * In : xres, yres, bits/pixel, RGB, refresh rate
396 * Out : pixel width in bits if success
397 *
398 * Note: -
399 */
400 int
401 vl_video_init (int width, int height, int bpp, int rgb, int refresh, int fbbits)
402 {
403 int fake;
404 vl_mode *p, *q;
405 unsigned int min;
406
407 fake = 0;
408 if (!rgb) {
409 bpp = 8;
410 } else if (bpp == 8) {
411 fake = 1;
412 }
413
414 /* initialize hardware */
415 if ((q = v_init_hw()) == NULL) {
416 return 0;
417 }
418
419 /* search for a mode that fits our request */
420 for (min = -1, p = NULL; q->mode != 0xffff; q++) {
421 if ((q->xres >= width) && (q->yres >= height) && (q->bpp == bpp)) {
422 if (min >= (unsigned)(q->xres * q->yres)) {
423 min = q->xres * q->yres;
424 p = q;
425 }
426 }
427 }
428
429 /* setup and enter mode */
430 if ((vl_setup_mode(p) == 0) && (drv->entermode(p, refresh, fbbits) == 0)) {
431 vl_flip = drv->blit;
432 if (fake) {
433 drv->get(VL_GET_CI_PREC, (int *)(&min));
434 fake_buildpalette(min);
435 init_tab_16_8();
436 }
437 return bpp;
438 }
439
440 /* abort */
441 return 0;
442 }