radeons: use dp4 for position invariant vertex programs
[mesa.git] / src / mesa / drivers / dos / video.c
index d31037de616e3e6881ee989105b3f3e44698ffbe..468207fbf6ff45742968543d8422f894867ec9e5 100644 (file)
-/*\r
- * Mesa 3-D graphics library\r
- * Version:  4.0\r
- * \r
- * Copyright (C) 1999  Brian Paul   All Rights Reserved.\r
- * \r
- * Permission is hereby granted, free of charge, to any person obtaining a\r
- * copy of this software and associated documentation files (the "Software"),\r
- * to deal in the Software without restriction, including without limitation\r
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
- * and/or sell copies of the Software, and to permit persons to whom the\r
- * Software is furnished to do so, subject to the following conditions:\r
- * \r
- * The above copyright notice and this permission notice shall be included\r
- * in all copies or substantial portions of the Software.\r
- * \r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\r
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\r
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
- */\r
-\r
-/*\r
- * DOS/DJGPP device driver v1.0 for Mesa 4.0\r
- *\r
- *  Copyright (C) 2002 - Borca Daniel\r
- *  Email : dborca@yahoo.com\r
- *  Web   : http://www.geocities.com/dborca\r
- */\r
-\r
-\r
-#include <dpmi.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <stubinfo.h>\r
-#include <sys/exceptn.h>\r
-#include <sys/segments.h>\r
-#include <sys/farptr.h>\r
-\r
-#include "video.h"\r
-#include "dpmiint.h"\r
-\r
-\r
-\r
-typedef unsigned char word8;\r
-typedef unsigned short word16;\r
-typedef unsigned long word32;\r
-\r
-typedef struct vl_mode {\r
-        int mode;\r
-        int xres, yres;\r
-        int scanlen;\r
-        int bpp;\r
-} vl_mode;\r
-\r
-#define _16_ *(word16 *)&\r
-#define _32_ *(word32 *)&\r
-\r
-static int init;\r
-\r
-static vl_mode modes[64];\r
-\r
-/* card specific: valid forever */\r
-static word16 vesa_ver;\r
-static word32 hw_granularity, hw_linearfb;\r
-static unsigned int gran_shift, gran_mask;\r
-/* based upon mode specific data: valid entire session */\r
-static int video_selector, banked_selector, linear_selector;\r
-static int video_scanlen, video_bypp;\r
-/* valid until next buffer */\r
-static int current_offset, current_delta, current_width;\r
-\r
-\r
-\r
-/* lookup table for scaling 5 bit colors up to 8 bits */\r
-static int _rgb_scale_5[32] =\r
-{\r
-   0,   8,   16,  24,  32,  41,  49,  57,\r
-   65,  74,  82,  90,  98,  106, 115, 123,\r
-   131, 139, 148, 156, 164, 172, 180, 189,\r
-   197, 205, 213, 222, 230, 238, 246, 255\r
-};\r
-\r
-/* lookup table for scaling 6 bit colors up to 8 bits */\r
-static int _rgb_scale_6[64] =\r
-{\r
-   0,   4,   8,   12,  16,  20,  24,  28,\r
-   32,  36,  40,  44,  48,  52,  56,  60,\r
-   64,  68,  72,  76,  80,  85,  89,  93,\r
-   97,  101, 105, 109, 113, 117, 121, 125,\r
-   129, 133, 137, 141, 145, 149, 153, 157,\r
-   161, 165, 170, 174, 178, 182, 186, 190,\r
-   194, 198, 202, 206, 210, 214, 218, 222,\r
-   226, 230, 234, 238, 242, 246, 250, 255\r
-};\r
-\r
-\r
-\r
-/*\r
- * virtual clearing\r
- */\r
-void (*vl_clear) (void *buffer, int len, int color);\r
-\r
-#define v_clear15 v_clear16\r
-extern void v_clear16 (void *buffer, int len, int color);\r
-extern void v_clear32 (void *buffer, int len, int color);\r
-__asm__("\n\\r
-               .text                           \n\\r
-               .balign 4                       \n\\r
-               .global _v_clear16              \n\\r
-_v_clear16:                                    \n\\r
-               movl    12(%esp), %eax          \n\\r
-               pushw   %ax                     \n\\r
-               pushw   %ax                     \n\\r
-               popl    %eax                    \n\\r
-               jmp     _v_clear_common         \n\\r
-               .balign 4                       \n\\r
-               .global _v_clear32              \n\\r
-_v_clear32:                                    \n\\r
-               movl    12(%esp), %eax          \n\\r
-               .balign 4                       \n\\r
-_v_clear_common:                               \n\\r
-               movl    8(%esp), %ecx           \n\\r
-               movl    4(%esp), %edx           \n\\r
-               shrl    $2, %ecx                \n\\r
-       0:                                      \n\\r
-               .balign 4                       \n\\r
-               movl    %eax, (%edx)            \n\\r
-               addl    $4, %edx                \n\\r
-               decl    %ecx                    \n\\r
-               jnz     0b                      \n\\r
-               ret");\r
-extern void v_clear24 (void *buffer, int len, int color);\r
-__asm__("\n\\r
-               .text                           \n\\r
-               .balign 4                       \n\\r
-               .global _v_clear24              \n\\r
-_v_clear24:                                    \n\\r
-               movl    8(%esp), %edx           \n\\r
-               movl    $0xaaaaaaab, %eax       \n\\r
-               mull    %edx                    \n\\r
-               movl    12(%esp), %eax          \n\\r
-               movl    %edx, %ecx              \n\\r
-               movl    4(%esp), %edx           \n\\r
-               pushl   %ebx                    \n\\r
-               shrl    %ecx                    \n\\r
-               movb    18(%esp), %bl           \n\\r
-               .balign 4                       \n\\r
-       0:                                      \n\\r
-               movw    %ax, (%edx)             \n\\r
-               movb    %bl, 2(%edx)            \n\\r
-               addl    $3, %edx                \n\\r
-               decl    %ecx                    \n\\r
-               jnz     0b                      \n\\r
-               popl    %ebx                    \n\\r
-               ret");\r
-\r
-\r
-\r
-/*\r
- * virtual rectangle clearing\r
- */\r
-void vl_rect (void *buffer, int x, int y, int width, int height, int color)\r
-{\r
- int offset = y*current_width + x;\r
- int delta = current_width - width;\r
-\r
- for (y=0; y<height; y++) {\r
-     for (x=0; x<width; x++, offset++) {\r
-         vl_putpixel(buffer, offset, color);\r
-     }\r
-     offset += delta;\r
- }\r
-}\r
-\r
-\r
-\r
-/*\r
- * virtual dumping:\r
- */\r
-void (*vl_flip) (void *buffer, int width, int height);\r
-\r
-extern void b_dump_virtual (void *buffer, int width, int height);\r
-__asm__("\n\\r
-               .text                           \n\\r
-               .balign 4                       \n\\r
-               .global _b_dump_virtual         \n\\r
-_b_dump_virtual:                               \n\\r
-               pushl   %ebx                    \n\\r
-               pushl   %esi                    \n\\r
-               pushl   %edi                    \n\\r
-               pushl   %ebp                    \n\\r
-               movl    _video_selector, %fs    \n\\r
-               movl    4*4+4+0(%esp), %esi     \n\\r
-               movl    _hw_granularity, %ebp   \n\\r
-               xorl    %edx, %edx              \n\\r
-               movl    _current_offset, %eax   \n\\r
-               divl    %ebp                    \n\\r
-               movl    %edx, %edi              \n\\r
-               pushl   %eax                    \n\\r
-               movl    %eax, %edx              \n\\r
-               xorl    %ebx, %ebx              \n\\r
-               movw    $0x4f05, %ax            \n\\r
-               int     $0x10                   \n\\r
-               movl    _current_delta, %ebx    \n\\r
-               movl    5*4+4+4(%esp), %ecx     \n\\r
-               movl    5*4+4+8(%esp), %edx     \n\\r
-               shrl    $2, %ecx                \n\\r
-               .balign 4                       \n\\r
-       0:                                      \n\\r
-               pushl   %ecx                    \n\\r
-               .balign 4                       \n\\r
-       1:                                      \n\\r
-               cmpl    %ebp, %edi              \n\\r
-               jb      2f                      \n\\r
-               pushl   %ebx                    \n\\r
-               pushl   %edx                    \n\\r
-               incl    12(%esp)                \n\\r
-               movw    $0x4f05, %ax            \n\\r
-               movl    12(%esp), %edx          \n\\r
-               xorl    %ebx, %ebx              \n\\r
-               int     $0x10                   \n\\r
-               popl    %edx                    \n\\r
-               popl    %ebx                    \n\\r
-               subl    %ebp, %edi              \n\\r
-       2:                                      \n\\r
-               movl    (%esi), %eax            \n\\r
-               addl    $4, %esi                \n\\r
-               movl    %eax, %fs:(%edi)        \n\\r
-               addl    $4, %edi                \n\\r
-               decl    %ecx                    \n\\r
-               jnz     1b                      \n\\r
-               popl    %ecx                    \n\\r
-               addl    %ebx, %edi              \n\\r
-               decl    %edx                    \n\\r
-               jnz     0b                      \n\\r
-               popl    %eax                    \n\\r
-               popl    %ebp                    \n\\r
-               popl    %edi                    \n\\r
-               popl    %esi                    \n\\r
-               popl    %ebx                    \n\\r
-               ret");\r
-extern void l_dump_virtual (void *buffer, int width, int height);\r
-__asm__("\n\\r
-               .text                           \n\\r
-               .balign 4                       \n\\r
-               .global _l_dump_virtual         \n\\r
-_l_dump_virtual:                               \n\\r
-               pushl   %ebx                    \n\\r
-               pushl   %esi                    \n\\r
-               pushl   %edi                    \n\\r
-               movl    _video_selector, %fs    \n\\r
-               movl    3*4+4+0(%esp), %esi     \n\\r
-               movl    _current_offset, %edi   \n\\r
-               movl    3*4+4+4(%esp), %ecx     \n\\r
-               movl    3*4+4+8(%esp), %edx     \n\\r
-               movl    _current_delta, %ebx    \n\\r
-               shrl    $2, %ecx                \n\\r
-               .balign 4                       \n\\r
-       0:                                      \n\\r
-               pushl   %ecx                    \n\\r
-               .balign 4                       \n\\r
-       1:                                      \n\\r
-               movl    (%esi), %eax            \n\\r
-               addl    $4, %esi                \n\\r
-               movl    %eax, %fs:(%edi)        \n\\r
-               addl    $4, %edi                \n\\r
-               decl    %ecx                    \n\\r
-               jnz     1b                      \n\\r
-               popl    %ecx                    \n\\r
-               addl    %ebx, %edi              \n\\r
-               decl    %edx                    \n\\r
-               jnz     0b                      \n\\r
-               popl    %edi                    \n\\r
-               popl    %esi                    \n\\r
-               popl    %ebx                    \n\\r
-               ret");\r
-\r
-\r
-\r
-/*\r
- * mix RGBA components\r
- */\r
-int (*vl_mixrgba) (const unsigned char rgba[]);\r
\r
-#define vl_mixrgba15 vl_mixrgb15\r
-#define vl_mixrgba16 vl_mixrgb16\r
-#define vl_mixrgba24 vl_mixrgb24\r
-static int vl_mixrgba32 (const unsigned char rgba[])\r
-{\r
- return (rgba[3]<<24)|(rgba[0]<<16)|(rgba[1]<<8)|(rgba[2]);\r
-}\r
-\r
-\r
-\r
-/*\r
- * mix RGB components\r
- */\r
-int (*vl_mixrgb) (const unsigned char rgb[]);\r
\r
-static int vl_mixrgb15 (const unsigned char rgb[])\r
-{\r
- return ((rgb[0]>>3)<<10)|((rgb[1]>>3)<<5)|(rgb[2]>>3);\r
-}\r
-static int vl_mixrgb16 (const unsigned char rgb[])\r
-{\r
- return ((rgb[0]>>3)<<11)|((rgb[1]>>2)<<5)|(rgb[2]>>3);\r
-}\r
-#define vl_mixrgb24 vl_mixrgb32\r
-static int vl_mixrgb32 (const unsigned char rgb[])\r
-{\r
- return (rgb[0]<<16)|(rgb[1]<<8)|(rgb[2]);\r
-}\r
-\r
-\r
-\r
-/*\r
- * vl_putpixel*\r
- */\r
-void (*vl_putpixel) (void *buffer, int offset, int color);\r
\r
-#define v_putpixel15 v_putpixel16\r
-extern void v_putpixel16 (void *buffer, int offset, int color);\r
-__asm__("\n\\r
-               .text                           \n\\r
-               .balign 4                       \n\\r
-               .global _v_putpixel16           \n\\r
-_v_putpixel16:                                 \n\\r
-               movl    8(%esp), %edx           \n\\r
-               shll    %edx                    \n\\r
-               movl    12(%esp), %eax          \n\\r
-               addl    4(%esp), %edx           \n\\r
-               movw    %ax, (%edx)             \n\\r
-               ret");\r
-extern void v_putpixel24 (void *buffer, int offset, int color);\r
-__asm__("\n\\r
-               .text                           \n\\r
-               .balign 4                       \n\\r
-               .global _v_putpixel24           \n\\r
-_v_putpixel24:                                 \n\\r
-               movl    8(%esp), %edx           \n\\r
-               leal    (%edx, %edx, 2), %edx   \n\\r
-               movl    12(%esp), %eax          \n\\r
-               addl    4(%esp), %edx           \n\\r
-               movw    %ax, (%edx)             \n\\r
-               shrl    $16, %eax               \n\\r
-               movb    %al, 2(%edx)            \n\\r
-               ret");\r
-extern void v_putpixel32 (void *buffer, int offset, int color);\r
-__asm__("\n\\r
-               .text                           \n\\r
-               .balign 4                       \n\\r
-               .global _v_putpixel32           \n\\r
-_v_putpixel32:                                 \n\\r
-               movl    8(%esp), %edx           \n\\r
-               shll    $2, %edx                \n\\r
-               movl    12(%esp), %eax          \n\\r
-               addl    4(%esp), %edx           \n\\r
-               movl    %eax, (%edx)            \n\\r
-               ret");\r
-\r
-\r
-\r
-/*\r
- * get pixel and decompose R, G, B, A\r
- */\r
-void (*vl_getrgba) (void *buffer, int offset, unsigned char rgba[4]);\r
-\r
-/*\r
- * v_getrgba*\r
- */\r
-static void v_getrgba15 (void *buffer, int offset, unsigned char rgba[4])\r
-{\r
- int c = ((word16 *)buffer)[offset];\r
- rgba[0] = _rgb_scale_5[(c >> 10) & 0x1F];\r
- rgba[1] = _rgb_scale_5[(c >> 5) & 0x1F];\r
- rgba[2] = _rgb_scale_5[c & 0x1F];\r
- rgba[3] = 255;\r
-}\r
-static void v_getrgba16 (void *buffer, int offset, unsigned char rgba[4])\r
-{\r
- int c = ((word16 *)buffer)[offset];\r
- rgba[0] = _rgb_scale_5[(c >> 11) & 0x1F];\r
- rgba[1] = _rgb_scale_6[(c >> 5) & 0x3F];\r
- rgba[2] = _rgb_scale_5[c & 0x1F];\r
- rgba[3] = 255;\r
-}\r
-static void v_getrgba24 (void *buffer, int offset, unsigned char rgba[4])\r
-{\r
- int c = *(word32 *)((long)buffer+offset*3);\r
- rgba[0] = c >> 16;\r
- rgba[1] = c >> 8;\r
- rgba[2] = c;\r
- rgba[3] = 255;\r
-}\r
-static void v_getrgba32 (void *buffer, int offset, unsigned char rgba[4])\r
-{\r
- int c = ((word32 *)buffer)[offset];\r
- rgba[0] = c >> 16;\r
- rgba[1] = c >> 8;\r
- rgba[2] = c; \r
- rgba[3] = c >> 24;\r
-}\r
-\r
-\r
-\r
-/*\r
- * sync buffer with video hardware\r
- */\r
-void *vl_sync_buffer (void *buffer, int x, int y, int width, int height)\r
-{\r
- void *newbuf;\r
-\r
- if (width&3) {\r
-    return NULL;\r
- } else {\r
-    if ((newbuf=realloc(buffer, width*height*video_bypp))!=NULL) {\r
-       current_offset = video_scanlen * y + video_bypp * x;\r
-       current_width = width;\r
-       current_delta = video_scanlen - video_bypp * width;\r
-    }\r
-    return newbuf;\r
- }\r
-}\r
-\r
-\r
-\r
-/*\r
- * attempts to detect VESA and video modes\r
- */\r
-static word16 vl_vesa_init (void)\r
-{\r
- __dpmi_regs r;\r
- unsigned short *p;\r
- vl_mode *q;\r
- char vesa_info[512], tmp[512];\r
- int maxsize = 0;\r
-\r
- _farpokel(_stubinfo->ds_selector, 0, 0x32454256);\r
- r.x.ax = 0x4f00;\r
- r.x.di = 0;\r
- r.x.es = _stubinfo->ds_segment;\r
- __dpmi_int(0x10, &r);\r
- if (r.x.ax==0x004f) {\r
-    movedata(_stubinfo->ds_selector, 0, _my_ds(), (unsigned)vesa_info, 512);\r
-    if ((_32_ vesa_info[0])==0x41534556) {\r
-       p = (unsigned short *)(((_16_ vesa_info[0x10])<<4) + (_16_ vesa_info[0x0e]));\r
-       q = modes;\r
-       do {\r
-           if ((q->mode=_farpeekw(__djgpp_dos_sel, (unsigned long)(p++)))==0xffff) {\r
-              break;\r
-           }\r
-\r
-           r.x.ax = 0x4f01;\r
-           r.x.cx = q->mode;\r
-           r.x.di = 512;\r
-           r.x.es = _stubinfo->ds_segment;\r
-           __dpmi_int(0x10, &r);\r
-           movedata(_stubinfo->ds_selector, 512, _my_ds(), (unsigned)tmp, 256);\r
-           switch (tmp[0x19]) {\r
-                  case 16:\r
-                       q->bpp = tmp[0x1f] + tmp[0x21] + tmp[0x23];\r
-                       break;\r
-                  case 15:\r
-                  case 24:\r
-                  case 32:\r
-                       q->bpp = tmp[0x19];\r
-                       break;\r
-                  default:\r
-                       q->bpp = 0;\r
-           }\r
-           if ((r.x.ax==0x004f)&&((tmp[0]&0x11)==0x11)&&q->bpp) {\r
-              q->xres = _16_ tmp[0x12];\r
-              q->yres = _16_ tmp[0x14];\r
-              q->scanlen = _16_ tmp[0x10];\r
-              hw_granularity = (_16_ tmp[4])<<10;\r
-              if (tmp[0]&0x80) {\r
-                 *(q+1) = *q++;\r
-                 hw_linearfb = _32_ tmp[0x28];\r
-                 q->mode |= 0x4000;\r
-              }\r
-              if (maxsize<(q->scanlen*q->yres)) {\r
-                 maxsize = q->scanlen*q->yres;\r
-              }\r
-              q++;\r
-           }\r
-       } while (!0);\r
-\r
-       if (hw_linearfb) {\r
-          maxsize = ((maxsize+0xfffUL)&~0xfffUL);\r
-          if (_create_selector(&linear_selector, hw_linearfb, maxsize)) {\r
-             return 0;\r
-          }\r
-       }\r
-       if (_create_selector(&banked_selector, 0xa0000, hw_granularity)) {\r
-          _remove_selector(&linear_selector);\r
-          return 0;\r
-       }\r
-\r
-       return _16_ vesa_info[4];\r
-    }\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-\r
-\r
-/*\r
- * setup mode\r
- */\r
-static int vl_setup_mode (vl_mode *p)\r
-{\r
- if (p->mode&0x4000) {\r
-    video_selector = linear_selector;\r
-    vl_flip = l_dump_virtual;\r
- } else {\r
-    { int n; for (gran_shift=0, n=hw_granularity; n; gran_shift++, n>>=1) ; }\r
-    gran_mask = (1<<(--gran_shift)) - 1;\r
-    if (hw_granularity!=(gran_mask+1)) {\r
-       return -1;\r
-    }\r
-    video_selector = banked_selector;\r
-    vl_flip = b_dump_virtual;\r
- }\r
-\r
-#define INITPTR(bpp) \\r
-        vl_putpixel = v_putpixel##bpp; \\r
-        vl_getrgba = v_getrgba##bpp;   \\r
-        vl_clear = v_clear##bpp;       \\r
-        vl_mixrgb = vl_mixrgb##bpp;    \\r
-        vl_mixrgba = vl_mixrgba##bpp;\r
-\r
- switch (p->bpp) {\r
-        case 15:\r
-             INITPTR(15);\r
-             break;\r
-        case 16:\r
-             INITPTR(16);\r
-             break;\r
-        case 24:\r
-             INITPTR(24);\r
-             break;\r
-        case 32:\r
-             INITPTR(32);\r
-             break;\r
-        default:\r
-             return -1;\r
- }\r
-\r
-#undef INITPTR\r
-\r
- video_bypp = (p->bpp+7)/8;\r
- video_scanlen = p->scanlen;\r
-\r
- return 0;\r
-}\r
-\r
-\r
-\r
-/*\r
- * shutdown the video engine\r
- */\r
-void vl_video_exit (int textmode)\r
-{\r
- if (init) {\r
-    if (textmode) {\r
-       __asm__("movw $0x3, %%ax; int  $0x10":::"%eax");\r
-    }\r
-    \r
-    _remove_selector(&linear_selector);\r
-    _remove_selector(&banked_selector);\r
-   \r
-    init = !init;\r
- }\r
-}\r
-\r
-\r
-\r
-/*\r
- * initialize video engine\r
- *\r
- * success: 0\r
- * failure: -1\r
- */\r
-int vl_video_init (int width, int height, int bpp)\r
-{\r
- vl_mode *p, *q;\r
- unsigned int min;\r
-\r
- /* check for prior initialization */\r
- if (init) {\r
-    return 0;\r
- }\r
-\r
- /* initialize hardware */\r
- if (!(vesa_ver=vl_vesa_init())) {\r
-    return -1;\r
- }\r
- init = !init;\r
-\r
- /* search for a mode that fits our request */\r
- for (min=-1, p=NULL, q=modes; q->mode!=0xffff; q++) {\r
-     if ((q->xres>=width)&&(q->yres>=height)&&(q->bpp==bpp)) {\r
-        if (min>=(unsigned)(q->xres*q->yres)) {\r
-           min = q->xres*q->yres;\r
-           p = q;\r
-        }\r
-     }\r
- }\r
-\r
- if (p) {\r
-    vl_setup_mode(p);\r
-    __asm__("movw $0x4f02, %%ax; int  $0x10"::"b"(p->mode):"%eax");\r
-    return 0;\r
- } else {\r
-    /* no suitable mode found, abort */\r
-    vl_video_exit(0);\r
-    return -1;\r
- }\r
-}\r
+/*
+ * Mesa 3-D graphics library
+ * Version:  4.0
+ * 
+ * Copyright (C) 1999  Brian Paul   All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * DOS/DJGPP device driver for Mesa
+ *
+ *  Author: Daniel Borca
+ *  Email : dborca@users.sourceforge.net
+ *  Web   : http://www.geocities.com/dborca
+ *
+ * Thanks to CrazyPyro (Neil Funk) for FakeColor
+ */
+
+
+#include <stdlib.h>
+
+#include "internal.h"
+#include "vesa.h"
+#include "vga.h"
+#include "null.h"
+#include "video.h"
+
+
+static vl_driver *drv;
+/* based upon mode specific data: valid entire session */
+int vl_video_selector;
+static vl_mode *video_mode;
+static int video_scanlen, video_bypp;
+/* valid until next buffer */
+void *vl_current_draw_buffer, *vl_current_read_buffer;
+int vl_current_stride, vl_current_width, vl_current_height, vl_current_bytes;
+int vl_current_offset, vl_current_delta;
+
+
+void (*vl_flip) (void);
+
+
+/* FakeColor data */
+#define R_CNT 6
+#define G_CNT 6
+#define B_CNT 6
+
+#define R_BIAS 7
+#define G_BIAS 7
+#define B_BIAS 7
+
+static word32 VGAPalette[256];
+word8 array_r[256];
+word8 array_g[256];
+word8 array_b[256];
+word8 tab_16_8[0x10000];
+
+
+/* lookup table for scaling 5 bit colors up to 8 bits */
+static int _rgb_scale_5[32] = {
+   0,   8,   16,  25,  33,  41,  49,  58,
+   66,  74,  82,  90,  99,  107, 115, 123,
+   132, 140, 148, 156, 165, 173, 181, 189,
+   197, 206, 214, 222, 230, 239, 247, 255
+};
+
+/* lookup table for scaling 6 bit colors up to 8 bits */
+static int _rgb_scale_6[64] = {
+   0,   4,   8,   12,  16,  20,  24,  28,
+   32,  36,  40,  45,  49,  53,  57,  61,
+   65,  69,  73,  77,  81,  85,  89,  93,
+   97,  101, 105, 109, 113, 117, 121, 125,
+   130, 134, 138, 142, 146, 150, 154, 158,
+   162, 166, 170, 174, 178, 182, 186, 190,
+   194, 198, 202, 206, 210, 215, 219, 223,
+   227, 231, 235, 239, 243, 247, 251, 255
+};
+
+
+/* Desc: color composition (w/o ALPHA)
+ *
+ * In  : array of integers (R, G, B)
+ * Out : color
+ *
+ * Note: -
+ */
+static int
+v_mixrgb8fake (const unsigned char rgb[])
+{
+   return array_b[rgb[2]]*G_CNT*R_CNT
+        + array_g[rgb[1]]*R_CNT
+        + array_r[rgb[0]];
+}
+
+
+/* Desc: color decomposition
+ *
+ * In  : pixel offset, array of integers to hold color components (R, G, B, A)
+ * Out : -
+ *
+ * Note: uses current read buffer
+ */
+static void
+v_getrgb8fake6 (unsigned int offset, unsigned char rgb[])
+{
+   word32 c = VGAPalette[((word8 *)vl_current_read_buffer)[offset]];
+   rgb[0] = _rgb_scale_6[(c >> 16) & 0x3F];
+   rgb[1] = _rgb_scale_6[(c >> 8)  & 0x3F];
+   rgb[2] = _rgb_scale_6[ c        & 0x3F];
+}
+static void
+v_getrgb8fake8 (unsigned int offset, unsigned char rgb[])
+{
+   word32 c = VGAPalette[((word8 *)vl_current_read_buffer)[offset]];
+   rgb[0] = c >> 16;
+   rgb[1] = c >> 8;
+   rgb[2] = c;
+}
+
+
+/* Desc: create R5G6B5 to FakeColor table lookup
+ *
+ * In  : -
+ * Out : -
+ *
+ * Note: -
+ */
+static void
+init_tab_16_8 (void)
+{
+    int i;
+    for (i = 0; i < 0x10000; i++) {
+       unsigned char rgb[3];
+       rgb[0] = _rgb_scale_5[(i >> 11) & 0x1F];
+       rgb[1] = _rgb_scale_6[(i >>  5) & 0x3F];
+       rgb[2] = _rgb_scale_5[ i        & 0x1F];
+       tab_16_8[i] = v_mixrgb8fake(rgb);
+    }
+    (void)v_getrgb8fake6;
+    (void)v_getrgb8fake8;
+}
+
+
+/* Desc: set one palette entry
+ *
+ * In  : index, R, G, B
+ * Out : -
+ *
+ * Note: color components are in range [0.0 .. 1.0]
+ */
+void
+vl_setCI (int index, float red, float green, float blue)
+{
+   drv->setCI_f(index, red, green, blue);
+}
+
+
+/* Desc: set one palette entry
+ *
+ * In  : color, R, G, B
+ * Out : -
+ *
+ * Note: -
+ */
+static void
+fake_setcolor (int c, int r, int g, int b)
+{
+   VGAPalette[c] = 0xff000000 | (r<<16) | (g<<8) | b;
+
+   drv->setCI_i(c, r, g, b);
+}
+
+
+/* Desc: build FakeColor palette
+ *
+ * In  : CI precision in bits
+ * Out : -
+ *
+ * Note: -
+ */
+static void
+fake_buildpalette (int bits)
+{
+   double c_r, c_g, c_b;
+   int r, g, b, color = 0;
+
+   double max = (1 << bits) - 1;
+
+   for (b = 0; b < B_CNT; ++b) {
+      for (g = 0; g < G_CNT; ++g) {
+         for (r = 0; r < R_CNT; ++r) {
+            c_r = 0.5 + (double)r * (max-R_BIAS) / (R_CNT-1.) + R_BIAS;
+            c_g = 0.5 + (double)g * (max-G_BIAS) / (G_CNT-1.) + G_BIAS;
+            c_b = 0.5 + (double)b * (max-B_BIAS) / (B_CNT-1.) + B_BIAS;
+            fake_setcolor(color++, (int)c_r, (int)c_g, (int)c_b);
+         }
+      }
+   }
+
+   for (color = 0; color < 256; color++) {
+      c_r = (double)color * R_CNT / 256.;
+      c_g = (double)color * G_CNT / 256.;
+      c_b = (double)color * B_CNT / 256.;
+      array_r[color] = (int)c_r;
+      array_g[color] = (int)c_g;
+      array_b[color] = (int)c_b;
+   }
+}
+
+
+/* Desc: initialize hardware
+ *
+ * In  : -
+ * Out : list of available modes
+ *
+ * Note: when returning non-NULL, global variable `drv' is guaranteed to be ok
+ */
+static vl_mode *
+v_init_hw (void)
+{
+   static vl_mode *q = NULL;
+
+   if (q == NULL) {
+      /* are we forced to NUL driver? */
+      if (getenv("DMESA_NULDRV")) {
+         if ((q = NUL.init()) != NULL) {
+            drv = &NUL;
+         }
+         return q;
+      }
+      /* initialize hardware */
+      if ((q = VESA.init()) != NULL) {
+         drv = &VESA;
+      } else if ((q = VGA.init()) != NULL) {
+         drv = &VGA;
+      } else {
+         drv = NULL;
+      }
+   }
+
+   return q;
+}
+
+
+/* Desc: sync buffer with video hardware
+ *
+ * In  : ptr to old buffer, position, size
+ * Out : 0 if success
+ *
+ * Note: -
+ */
+int
+vl_sync_buffer (void **buffer, int x, int y, int width, int height)
+{
+   if ((/*XXX*/width & 7) || (x < 0) || (y < 0) || (x+width > video_mode->xres) || (y+height > video_mode->yres)) {
+      return -1;
+   } else {
+      void *newbuf = *buffer;
+
+      if ((newbuf == NULL) || (vl_current_width != width) || (vl_current_height != height)) {
+         newbuf = realloc(newbuf, width * height * video_bypp);
+      }
+
+      if (newbuf == NULL) {
+         return -2;
+      }
+
+      vl_current_width = width;
+      vl_current_height = height;
+      vl_current_stride = vl_current_width * video_bypp;
+      vl_current_bytes = vl_current_stride * height;
+
+      vl_current_offset = video_scanlen * y + video_bypp * x;
+      vl_current_delta = video_scanlen - vl_current_stride;
+
+      vl_current_draw_buffer = vl_current_read_buffer = *buffer = newbuf;
+      return 0;
+   }
+}
+
+
+/* Desc: state retrieval
+ *
+ * In  : name, storage
+ * Out : -1 for an error
+ *
+ * Note: -
+ */
+int
+vl_get (int pname, int *params)
+{
+   switch (pname) {
+      case VL_GET_SCREEN_SIZE:
+         params[0] = video_mode->xres;
+         params[1] = video_mode->yres;
+         break;
+      case VL_GET_VIDEO_MODES: {
+         int n;
+         vl_mode *q;
+         if ((q = v_init_hw()) == NULL) {
+            return -1;
+         }
+         /* count available visuals */
+         for (n = 0; q->mode != 0xffff; q++) {
+            if ((q + 1)->mode == (q->mode | 0x4000)) {
+               /* same mode, but linear */
+               q++;
+            }
+            if (params) {
+               params[n] = (int)q;
+            }
+            n++;
+         }
+         return n;
+      }
+      default:
+         return (drv != NULL) ? drv->get(pname, params) : -1;
+   }
+   return 0;
+}
+
+
+/* Desc: setup mode
+ *
+ * In  : ptr to mode definition
+ * Out : 0 if success
+ *
+ * Note: -
+ */
+static int
+vl_setup_mode (vl_mode *p)
+{
+   if (p == NULL) {
+      return -1;
+   }
+
+   switch (p->bpp) {
+      case 8:
+         break;
+      case 15:
+         break;
+      case 16:
+         break;
+      case 24:
+         break;
+      case 32:
+         break;
+      default:
+         return -1;
+   }
+
+   video_mode = p;
+   video_bypp = (p->bpp+7)/8;
+   video_scanlen = p->scanlen;
+   vl_video_selector = p->sel;
+
+   return 0;
+}
+
+
+/* Desc: restore to the mode prior to first call to `vl_video_init'.
+ *
+ * In  : -
+ * Out : -
+ *
+ * Note: -
+ */
+void
+vl_video_exit (void)
+{
+   drv->restore();
+   drv->fini();
+   video_mode = NULL;
+}
+
+
+/* Desc: enter mode
+ *
+ * In  : xres, yres, bits/pixel, RGB, refresh rate
+ * Out : pixel width in bits if success
+ *
+ * Note: -
+ */
+int
+vl_video_init (int width, int height, int bpp, int rgb, int refresh, int fbbits)
+{
+   int fake;
+   vl_mode *p, *q;
+   unsigned int min;
+
+   fake = 0;
+   if (!rgb) {
+      bpp = 8;
+   } else if (bpp == 8) {
+      fake = 1;
+   }
+
+   /* initialize hardware */
+   if ((q = v_init_hw()) == NULL) {
+      return 0;
+   }
+
+   /* search for a mode that fits our request */
+   for (min = -1, p = NULL; q->mode != 0xffff; q++) {
+      if ((q->xres >= width) && (q->yres >= height) && (q->bpp == bpp)) {
+         if (min >= (unsigned)(q->xres * q->yres)) {
+            min = q->xres * q->yres;
+            p = q;
+         }
+      }
+   }
+
+    /* setup and enter mode */
+    if ((vl_setup_mode(p) == 0) && (drv->entermode(p, refresh, fbbits) == 0)) {
+       vl_flip = drv->blit;
+       if (fake) {
+           drv->get(VL_GET_CI_PREC, (int *)(&min));
+           fake_buildpalette(min);
+           init_tab_16_8();
+       }
+       return bpp;
+    }
+
+   /* abort */
+   return 0;
+}