From db41d2ea8c8b6ceddf54f87268085a83d8f342ba Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Tue, 12 Feb 2002 03:24:56 +0000 Subject: Daniel Borca's new DOS/DJGPP driver. --- src/mesa/drivers/dos/dmesa.c | 592 ++++++++++++++++++++++++++++++++++++++++ src/mesa/drivers/dos/dmesaint.h | 231 ++++++++++++++++ src/mesa/drivers/dos/dvesa.c | 549 +++++++++++++++++++++++++++++++++++++ src/mesa/drivers/dos/dvesa.h | 127 +++++++++ 4 files changed, 1499 insertions(+) create mode 100644 src/mesa/drivers/dos/dmesa.c create mode 100644 src/mesa/drivers/dos/dmesaint.h create mode 100644 src/mesa/drivers/dos/dvesa.c create mode 100644 src/mesa/drivers/dos/dvesa.h (limited to 'src/mesa/drivers') diff --git a/src/mesa/drivers/dos/dmesa.c b/src/mesa/drivers/dos/dmesa.c new file mode 100644 index 0000000000..01be301224 --- /dev/null +++ b/src/mesa/drivers/dos/dmesa.c @@ -0,0 +1,592 @@ +/* + * 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 v0.1 for Mesa 4.0 + * + * Copyright (C) 2002 - Borca Daniel + * Email : dborca@yahoo.com + * Web : http://www.geocities.com/dborca + */ + + +#ifdef PC_HEADER +#include "all.h" +#else +#include "glheader.h" +#include "context.h" +#include "GL/dmesa.h" +#include "matrix.h" +#include "texformat.h" +#include "texstore.h" +#include "array_cache/acache.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" +#endif + +#include "dvesa.h" +#include "dmesaint.h" + + + +/* + * In C++ terms, this class derives from the GLvisual class. + * Add system-specific fields to it. + */ +struct dmesa_visual { + GLvisual *gl_visual; + GLboolean db_flag; /* double buffered? */ + GLboolean rgb_flag; /* RGB mode? */ + GLuint depth; /* bits per pixel (1, 8, 24, etc) */ +}; + +/* + * In C++ terms, this class derives from the GLframebuffer class. + * Add system-specific fields to it. + */ +struct dmesa_buffer { + GLframebuffer *gl_buffer; /* The depth, stencil, accum, etc buffers */ + void *the_window; /* your window handle, etc */ + + int width, height; /* size in pixels */ + int xpos, ypos; /* buffer position */ + int xsize, len; /* number of bytes in a line, then total */ + int delta; /* used to wrap around */ + int offset; /* offset in video */ + struct dvmode *video; +}; + +/* + * In C++ terms, this class derives from the GLcontext class. + * Add system-specific fields to it. + */ +struct dmesa_context { + GLcontext *gl_ctx; /* the core library context */ + DMesaVisual visual; + DMesaBuffer Buffer; + GLuint ClearColor; + /* etc... */ +}; + + + +static void dmesa_update_state (GLcontext *ctx, GLuint new_state); + + + +/**********************************************************************/ +/***** Read/Write pixels *****/ +/**********************************************************************/ + + + +WRITE_RGBA_SPAN(15) +WRITE_RGBA_SPAN(16) +WRITE_RGBA_SPAN(24) +WRITE_RGBA_SPAN(32) + +WRITE_RGB_SPAN(15) +WRITE_RGB_SPAN(16) +WRITE_RGB_SPAN(24) +WRITE_RGB_SPAN(32) + +WRITE_MONO_RGBA_SPAN(15) +WRITE_MONO_RGBA_SPAN(16) +WRITE_MONO_RGBA_SPAN(24) +WRITE_MONO_RGBA_SPAN(32) + +READ_RGBA_SPAN(15) +READ_RGBA_SPAN(16) +READ_RGBA_SPAN(24) +READ_RGBA_SPAN(32) + +WRITE_RGBA_PIXELS(15) +WRITE_RGBA_PIXELS(16) +WRITE_RGBA_PIXELS(24) +WRITE_RGBA_PIXELS(32) + +WRITE_MONO_RGBA_PIXELS(15) +WRITE_MONO_RGBA_PIXELS(16) +WRITE_MONO_RGBA_PIXELS(24) +WRITE_MONO_RGBA_PIXELS(32) + +READ_RGBA_PIXELS(15) +READ_RGBA_PIXELS(16) +READ_RGBA_PIXELS(24) +READ_RGBA_PIXELS(32) + + + +/**********************************************************************/ +/***** Miscellaneous device driver funcs *****/ +/**********************************************************************/ + + + +static void clear_color (GLcontext *ctx, const GLchan color[4]) +{ + DMesaContext c = (DMesaContext)ctx->DriverCtx; + c->ClearColor = dv_color(color); +} + + + +static void clear (GLcontext *ctx, GLbitfield mask, GLboolean all, + GLint x, GLint y, GLint width, GLint height) +{ + DMesaContext c = (DMesaContext)ctx->DriverCtx; + const GLuint *colorMask = (GLuint *)&ctx->Color.ColorMask; + DMesaBuffer b = c->Buffer; + +/* + * Clear the specified region of the buffers indicated by 'mask' + * using the clear color or index as specified by one of the two + * functions above. + * If all==GL_TRUE, clear whole buffer, else just clear region defined + * by x,y,width,height + */ + + /* we can't handle color or index masking */ + if (*colorMask==0xffffffff && ctx->Color.IndexMask==0xffffffff) { + if (mask&DD_BACK_LEFT_BIT) { + if (all) { + dv_clear_virtual(b->the_window, b->len, c->ClearColor); + } else { + dv_fillrect(b->the_window, b->width, x, y, width, height, c->ClearColor); + } + mask &= ~DD_BACK_LEFT_BIT; + } + } + + if (mask) { + _swrast_Clear(ctx, mask, all, x, y, width, height); + } +} + + + +/* + * Set the current reading buffer. + */ +static void set_read_buffer (GLcontext *ctx, GLframebuffer *buffer, + GLenum mode) +{ +/* + DMesaContext c = (DMesaContext)ctx->DriverCtx; + dmesa_update_state(ctx); +*/ +} + + + +/* + * Set the destination/draw buffer. + */ +static GLboolean set_draw_buffer (GLcontext *ctx, GLenum mode) +{ + if (mode==GL_BACK_LEFT) { + return GL_TRUE; + } else { + return GL_FALSE; + } +} + + + +/* + * Return the width and height of the current buffer. + * If anything special has to been done when the buffer/window is + * resized, do it now. + */ +static void get_buffer_size (GLcontext *ctx, GLuint *width, GLuint *height) +{ + DMesaContext c = (DMesaContext)ctx->DriverCtx; + + *width = c->Buffer->width; + *height = c->Buffer->height; +} + + + +static const GLubyte* get_string (GLcontext *ctx, GLenum name) +{ + switch (name) { + case GL_RENDERER: + return (const GLubyte *)"DOS Mesa"; + default: + return NULL; + } +} + + + +/**********************************************************************/ +/***** Miscellaneous device driver funcs *****/ +/***** Note that these functions are mandatory *****/ +/**********************************************************************/ + + + +/* OPTIONAL FUNCTION: implements glFinish if possible */ +static void finish (GLcontext *ctx) +{ +/* + DMesaContext c = (DMesaContext)ctx->DriverCtx; +*/ +} + + + +/* OPTIONAL FUNCTION: implements glFlush if possible */ +static void flush (GLcontext *ctx) +{ +/* + DMesaContext c = (DMesaContext)ctx->DriverCtx; +*/ +} + + + +/**********************************************************************/ +/**********************************************************************/ + + + +/* Setup pointers and other driver state that is constant for the life + * of a context. + */ +void dmesa_init_pointers (GLcontext *ctx) +{ + TNLcontext *tnl; + + ctx->Driver.UpdateState = dmesa_update_state; + + ctx->Driver.GetString = get_string; + ctx->Driver.GetBufferSize = get_buffer_size; + ctx->Driver.Flush = flush; + ctx->Driver.Finish = finish; + + /* Software rasterizer pixel paths: + */ + ctx->Driver.Accum = _swrast_Accum; + ctx->Driver.Bitmap = _swrast_Bitmap; + ctx->Driver.Clear = clear; + ctx->Driver.ResizeBuffersMESA = _swrast_alloc_buffers; + ctx->Driver.CopyPixels = _swrast_CopyPixels; + ctx->Driver.DrawPixels = _swrast_DrawPixels; + ctx->Driver.ReadPixels = _swrast_ReadPixels; + + /* Software texture functions: + */ + ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format; + ctx->Driver.TexImage1D = _mesa_store_teximage1d; + ctx->Driver.TexImage2D = _mesa_store_teximage2d; + ctx->Driver.TexImage3D = _mesa_store_teximage3d; + ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d; + ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d; + ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d; + ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage; + + ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d; + ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d; + ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d; + ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d; + ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d; + + ctx->Driver.BaseCompressedTexFormat = _mesa_base_compressed_texformat; + ctx->Driver.CompressedTextureSize = _mesa_compressed_texture_size; + ctx->Driver.GetCompressedTexImage = _mesa_get_compressed_teximage; + + /* Swrast hooks for imaging extensions: + */ + ctx->Driver.CopyColorTable = _swrast_CopyColorTable; + ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable; + ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D; + ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D; + + /* Statechange callbacks: + */ + ctx->Driver.SetDrawBuffer = set_draw_buffer; + ctx->Driver.ClearColor = clear_color; + + /* Initialize the TNL driver interface: + */ + tnl = TNL_CONTEXT(ctx); + tnl->Driver.RunPipeline = _tnl_run_pipeline; + + /* Install swsetup for tnl->Driver.Render.*: + */ + _swsetup_Wakeup(ctx); +} + + + +static void dmesa_update_state (GLcontext *ctx, GLuint new_state) +{ + DMesaContext c = (DMesaContext)ctx->DriverCtx; + struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx); + + /* Initialize all the pointers in the DD struct. Do this whenever */ + /* a new context is made current or we change buffers via set_buffer! */ + + _swrast_InvalidateState(ctx, new_state); + _swsetup_InvalidateState(ctx, new_state); + _ac_InvalidateState(ctx, new_state); + _tnl_InvalidateState(ctx, new_state); + + swdd->SetReadBuffer = set_read_buffer; + + /* RGB(A) span/pixel functions */ + switch (c->visual->depth) { + case 15: + swdd->WriteRGBASpan = write_rgba_span_15; + swdd->WriteRGBSpan = write_rgb_span_15; + swdd->WriteMonoRGBASpan = write_mono_rgba_span_15; + swdd->WriteRGBAPixels = write_rgba_pixels_15; + swdd->WriteMonoRGBAPixels = write_mono_rgba_pixels_15; + swdd->ReadRGBASpan = read_rgba_span_15; + swdd->ReadRGBAPixels = read_rgba_pixels_15; + break; + case 16: + swdd->WriteRGBASpan = write_rgba_span_16; + swdd->WriteRGBSpan = write_rgb_span_16; + swdd->WriteMonoRGBASpan = write_mono_rgba_span_16; + swdd->WriteRGBAPixels = write_rgba_pixels_16; + swdd->WriteMonoRGBAPixels = write_mono_rgba_pixels_16; + swdd->ReadRGBASpan = read_rgba_span_16; + swdd->ReadRGBAPixels = read_rgba_pixels_16; + break; + case 24: + swdd->WriteRGBASpan = write_rgba_span_24; + swdd->WriteRGBSpan = write_rgb_span_24; + swdd->WriteMonoRGBASpan = write_mono_rgba_span_24; + swdd->WriteRGBAPixels = write_rgba_pixels_24; + swdd->WriteMonoRGBAPixels = write_mono_rgba_pixels_24; + swdd->ReadRGBASpan = read_rgba_span_24; + swdd->ReadRGBAPixels = read_rgba_pixels_24; + break; + case 32: + swdd->WriteRGBASpan = write_rgba_span_32; + swdd->WriteRGBSpan = write_rgb_span_32; + swdd->WriteMonoRGBASpan = write_mono_rgba_span_32; + swdd->WriteRGBAPixels = write_rgba_pixels_32; + swdd->WriteMonoRGBAPixels = write_mono_rgba_pixels_32; + swdd->ReadRGBASpan = read_rgba_span_32; + swdd->ReadRGBAPixels = read_rgba_pixels_32; + break; + } +} + + + +/**********************************************************************/ +/***** DMesa Public API Functions *****/ +/**********************************************************************/ + + + +/* + * The exact arguments to this function will depend on your window system + */ +DMesaVisual DMesaCreateVisual (GLint colDepth, GLboolean dbFlag, + GLint depthSize, GLint stencilSize, + GLint accumSize) +{ + DMesaVisual v; + GLint redBits, greenBits, blueBits, alphaBits; + + if (!dbFlag) { + return NULL; + } + switch (colDepth) { + case 15: + redBits = 5; + greenBits = 5; + blueBits = 5; + break; + case 16: + redBits = 5; + greenBits = 6; + blueBits = 5; + break; + case 24: + case 32: + redBits = 8; + greenBits = 8; + blueBits = 8; + break; + default: + return NULL; + } + alphaBits = 8; + + if ((v=(DMesaVisual)calloc(1, sizeof(struct dmesa_visual)))!=NULL) { + /* Create core visual */ + v->gl_visual = _mesa_create_visual(colDepth>8, /* rgb */ + dbFlag, + GL_FALSE, /* stereo */ + redBits, + greenBits, + blueBits, + alphaBits, + 0, /* indexBits */ + depthSize, + stencilSize, + accumSize, /* accumRed */ + accumSize, /* accumGreen */ + accumSize, /* accumBlue */ + alphaBits?accumSize:0, /* accumAlpha */ + 1); /* numSamples */ + + v->depth = colDepth; + v->db_flag = dbFlag; + } + + return v; +} + + + +void DMesaDestroyVisual (DMesaVisual v) +{ + _mesa_destroy_visual(v->gl_visual); + free(v); +} + + + +DMesaBuffer DMesaCreateBuffer (DMesaVisual visual, + GLint width, GLint height, + GLint xpos, GLint ypos) +{ + DMesaBuffer b; + + if ((b=(DMesaBuffer)calloc(1, sizeof(struct dmesa_buffer)))!=NULL) { + if (visual->db_flag) { + if ((b->the_window=calloc(1, width*height*((visual->depth+7)/8)))==NULL) { + return NULL; + } + } + + b->gl_buffer = _mesa_create_framebuffer(visual->gl_visual, + visual->gl_visual->depthBits > 0, + visual->gl_visual->stencilBits > 0, + visual->gl_visual->accumRedBits > 0, + visual->gl_visual->alphaBits > 0); + b->width = width; + b->height = height; + b->xpos = xpos; + b->ypos = ypos; + } + + return b; +} + + + +void DMesaDestroyBuffer (DMesaBuffer b) +{ + free(b->the_window); + _mesa_destroy_framebuffer(b->gl_buffer); + free(b); +} + + + +DMesaContext DMesaCreateContext (DMesaVisual visual, + DMesaContext share) +{ + DMesaContext c; + GLboolean direct = GL_FALSE; + + if ((c=(DMesaContext)calloc(1, sizeof(struct dmesa_context)))!=NULL) { + c->gl_ctx = _mesa_create_context(visual->gl_visual, + share ? share->gl_ctx : NULL, + (void *)c, direct); + + /* you probably have to do a bunch of other initializations here. */ + c->visual = visual; + + /* Initialize the software rasterizer and helper modules. + */ + _swrast_CreateContext(c->gl_ctx); + _ac_CreateContext(c->gl_ctx); + _tnl_CreateContext(c->gl_ctx); + _swsetup_CreateContext(c->gl_ctx); + dmesa_init_pointers(c->gl_ctx); + } + + return c; +} + + + +void DMesaDestroyContext (DMesaContext c) +{ + _mesa_destroy_context(c->gl_ctx); + free(c); +} + + + +/* + * Make the specified context and buffer the current one. + */ +GLboolean DMesaMakeCurrent (DMesaContext c, DMesaBuffer b) +{ + if (c&&b) { + c->Buffer = b; + if ((b->video=dv_select_mode(b->xpos, b->ypos, b->width, b->height, c->visual->depth, &b->delta, &b->offset))==NULL) { + return GL_FALSE; + } + + b->xsize = b->width*((c->visual->depth+7)/8); + b->len = b->xsize*b->height; + + dmesa_update_state(c->gl_ctx, 0); + _mesa_make_current(c->gl_ctx, b->gl_buffer); + if (c->gl_ctx->Viewport.Width==0) { + /* initialize viewport to window size */ + _mesa_Viewport(0, 0, c->Buffer->width, c->Buffer->height); + } + } else { + /* Detach */ + _mesa_make_current(NULL, NULL); + } + + return GL_TRUE; +} + + + +void DMesaSwapBuffers (DMesaBuffer b) +{ + /* copy/swap back buffer to front if applicable */ + if (b->the_window) { + dv_dump_virtual(b->the_window, b->xsize, b->height, b->offset, b->delta); + } +} diff --git a/src/mesa/drivers/dos/dmesaint.h b/src/mesa/drivers/dos/dmesaint.h new file mode 100644 index 0000000000..b8aa7064d5 --- /dev/null +++ b/src/mesa/drivers/dos/dmesaint.h @@ -0,0 +1,231 @@ +/* + * 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 v0.1 for Mesa 4.0 + * + * Copyright (C) 2002 - Borca Daniel + * Email : dborca@yahoo.com + * Web : http://www.geocities.com/dborca + */ + + +#ifndef DMESAINT_H_included +#define DMESAINT_H_included + + + +#define FLIP(y) (c->Buffer->height - (y) - 1) +#define FLIP2(y) (h - (y) - 1) + + + +/**********************************************************************/ +/***** Write spans of pixels *****/ +/**********************************************************************/ +#define WRITE_RGBA_SPAN(bpp) \ +static void write_rgba_span_##bpp (const GLcontext *ctx, GLuint n, GLint x, GLint y, \ + const GLubyte rgba[][4], const GLubyte mask[]) \ +{ \ + DMesaContext c = (DMesaContext)ctx->DriverCtx; \ + void *b = c->Buffer->the_window; \ + GLuint i, offset; \ + \ + offset = c->Buffer->width * FLIP(y) + x; \ + if (mask) { \ + /* draw some pixels */ \ + for (i=0; iDriverCtx; \ + void *b = c->Buffer->the_window; \ + GLuint i, offset; \ + \ + offset = c->Buffer->width * FLIP(y) + x; \ + if (mask) { \ + /* draw some pixels */ \ + for (i=0; iDriverCtx; \ + void *b = c->Buffer->the_window; \ + GLuint i, offset, rgba = dv_color##bpp(color); \ + \ + offset = c->Buffer->width * FLIP(y) + x; \ + if (mask) { \ + /* draw some pixels */ \ + for (i=0; iDriverCtx; \ + void *b = c->Buffer->the_window; \ + GLuint i, offset; \ + \ + offset = c->Buffer->width * FLIP(y) + x; \ + /* read all pixels */ \ + for (i=0; iDriverCtx; \ + void *b = c->Buffer->the_window; \ + GLuint i, w = c->Buffer->width, h = c->Buffer->height; \ + \ + if (mask) { \ + /* draw some pixels */ \ + for (i=0; iDriverCtx; \ + void *b = c->Buffer->the_window; \ + GLuint i, w = c->Buffer->width, h = c->Buffer->height, rgba = dv_color##bpp(color); \ + \ + if (mask) { \ + /* draw some pixels */ \ + for (i=0; iDriverCtx; \ + void *b = c->Buffer->the_window; \ + GLuint i, w = c->Buffer->width, h = c->Buffer->height; \ + \ + if (mask) { \ + /* read some pixels */ \ + for (i=0; i +#include +#include +#include +#include +#include + +#include "dvesa.h" + + + +typedef struct dvmode { + int mode; + int xres, yres; + int scanlen; + int bpp; + word32 opaque; +} dvmode; + +#define _16_ *(word16 *)& +#define _32_ *(word32 *)& + +static int init; +static int selector = -1; +static int granularity; +static dvmode modes[128]; +static void (*dv_putpixel) (void *buffer, int offset, int color); +int (*dv_color) (const unsigned char rgba[]); +void (*dv_dump_virtual) (void *buffer, int width, int height, int offset, int delta); +void (*dv_clear_virtual) (void *buffer, int len, int color); + +extern void dv_dump_virtual_linear (void *buffer, int width, int height, int offset, int delta); +extern void dv_dump_virtual_banked (void *buffer, int width, int height, int offset, int delta); + +extern void dv_clear_virtual16 (void *buffer, int len, int color); +extern void dv_clear_virtual24 (void *buffer, int len, int color); +extern void dv_clear_virtual32 (void *buffer, int len, int color); + +/* lookup table for scaling 5 bit colors up to 8 bits */ +int _rgb_scale_5[32] = +{ + 0, 8, 16, 24, 32, 41, 49, 57, + 65, 74, 82, 90, 98, 106, 115, 123, + 131, 139, 148, 156, 164, 172, 180, 189, + 197, 205, 213, 222, 230, 238, 246, 255 +}; + +/* lookup table for scaling 6 bit colors up to 8 bits */ +int _rgb_scale_6[64] = +{ + 0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 44, 48, 52, 56, 60, + 64, 68, 72, 76, 80, 85, 89, 93, + 97, 101, 105, 109, 113, 117, 121, 125, + 129, 133, 137, 141, 145, 149, 153, 157, + 161, 165, 170, 174, 178, 182, 186, 190, + 194, 198, 202, 206, 210, 214, 218, 222, + 226, 230, 234, 238, 242, 246, 250, 255 +}; + + + +/* + * colors + */ +int dv_color15 (const unsigned char rgba[]) +{ + return ((rgba[0]>>3)<<10)|((rgba[1]>>3)<<5)|(rgba[2]>>3); +} +int dv_color16 (const unsigned char rgba[]) +{ + return ((rgba[0]>>3)<<11)|((rgba[1]>>2)<<5)|(rgba[2]>>3); +} +int dv_color32 (const unsigned char rgba[]) +{ + return (rgba[0]<<16)|(rgba[1]<<8)|(rgba[2]); +} + + + +/* + * getpixel + decompose + */ +void dv_getrgba15 (void *buffer, int offset, unsigned char rgba[4]) +{ + int c = ((word16 *)buffer)[offset]; + rgba[0] = _rgb_scale_5[(c >> 10) & 0x1F]; + rgba[1] = _rgb_scale_5[(c >> 5) & 0x1F]; + rgba[2] = _rgb_scale_5[c & 0x1F]; + rgba[3] = 255; +} +void dv_getrgba16 (void *buffer, int offset, unsigned char rgba[4]) +{ + int c = ((word16 *)buffer)[offset]; + rgba[0] = _rgb_scale_5[(c >> 11) & 0x1F]; + rgba[1] = _rgb_scale_6[(c >> 5) & 0x3F]; + rgba[2] = _rgb_scale_5[c & 0x1F]; + rgba[3] = 255; +} +void dv_getrgba24 (void *buffer, int offset, unsigned char rgba[4]) +{ + int c = *(word32 *)(buffer+offset*3); + rgba[0] = c >> 16; + rgba[1] = c >> 8; + rgba[2] = c; + rgba[3] = 255; +} +void dv_getrgba32 (void *buffer, int offset, unsigned char rgba[4]) +{ + int c = ((word32 *)buffer)[offset]; + rgba[0] = c >> 16; + rgba[1] = c >> 8; + rgba[2] = c; + rgba[3] = 255; +} + + + +/* + * request mapping from DPMI + */ +static word32 _map_linear (word32 phys, word32 len) +{ + __dpmi_meminfo meminfo; + + if (phys >= 0x100000) { + /* map into linear memory */ + meminfo.address = (long)phys; + meminfo.size = len; + if (__dpmi_physical_address_mapping(&meminfo)) { + return 0; + } + return meminfo.address; + } else { + /* exploit 1 -> 1 physical to linear mapping in low megabyte */ + return phys; + } +} + + + +/* + * attempts to detect VESA and video modes + */ +static word16 dv_get_vesa (void) +{ + __dpmi_regs r; + unsigned short *p; + dvmode *q; + char vesa_info[512], tmp[512]; + + _farpokel(_stubinfo->ds_selector, 0, 0x32454256); + r.x.ax = 0x4f00; + r.x.di = 0; + r.x.es = _stubinfo->ds_segment; + __dpmi_int(0x10, &r); + if (r.x.ax==0x004f) { + movedata(_stubinfo->ds_selector, 0, _my_ds(), (unsigned)vesa_info, 512); + if ((_32_ vesa_info[0])==0x41534556) { + p = (unsigned short *)(((_16_ vesa_info[0x10])<<4) + (_16_ vesa_info[0x0e])); + q = modes; + do { + if ((q->mode=_farpeekw(__djgpp_dos_sel, (unsigned long)(p++)))==0xffff) { + break; + } + + r.x.ax = 0x4f01; + r.x.cx = q->mode; + r.x.di = 512; + r.x.es = _stubinfo->ds_segment; + __dpmi_int(0x10, &r); + movedata(_stubinfo->ds_selector, 512, _my_ds(), (unsigned)tmp, 256); + switch (tmp[0x19]) { + case 16: + q->bpp = tmp[0x1f] + tmp[0x21] + tmp[0x23]; + break; + case 15: + case 24: + case 32: + q->bpp = tmp[0x19]; + break; + default: + q->bpp = 0; + } + if ((r.x.ax==0x004f)&&((tmp[0]&0x11)==0x11)&&q->bpp) { + q->xres = _16_ tmp[0x12]; + q->yres = _16_ tmp[0x14]; + q->scanlen = _16_ tmp[0x10]; + q->opaque = (_16_ tmp[4])<<10; + if (tmp[0]&0x80) { + *(q+1) = *q++; + q->opaque = _32_ tmp[0x28]; + q->mode |= 0x4000; + } + q++; + } + } while (!0); + + return _16_ vesa_info[4]; + } + } + + return 0; +} + + + +/* + * select a mode + */ +dvmode *dv_select_mode (int x, int y, int width, int height, int depth, int *delta, int *offset) +{ + dvmode *p, *q; + unsigned int min; + + if ((width&3)||(height&3)||(depth<=8)) { + return NULL; + } + + if (!init) { + init = !init; + if (!dv_get_vesa()) { + return NULL; + } + } + + for (min=-1, p=NULL, q=modes; q->mode!=0xffff; q++) { + if ((q->xres>=(x+width))&&(q->yres>=(y+height))&&(q->bpp==depth)) { + if (min>(unsigned)(q->xres*q->yres)) { + min = q->xres*q->yres; + p = q; + } + } + } + + if (p) { + int sel = -1; + unsigned base, limit; + + if ((p->mode|0x4000)==(p+1)->mode) { + p++; + } + + if (selector==-1) { + if ((selector=sel=__dpmi_allocate_ldt_descriptors(1))==-1) { + return NULL; + } + } + if (p->mode&0x4000) { + limit = ((p->scanlen*p->yres+0xfffUL)&~0xfffUL) - 1; + if ((base=_map_linear(p->opaque, limit))==NULL) { + if (sel!=-1) { + selector = -1; + __dpmi_free_ldt_descriptor(sel); + } + return NULL; + } + dv_dump_virtual = dv_dump_virtual_linear; + } else { + limit = granularity = p->opaque; + base = 0xa0000; + dv_dump_virtual = dv_dump_virtual_banked; + } + __dpmi_set_segment_base_address(selector, base); + __dpmi_set_descriptor_access_rights(selector, ((_my_ds()&3)<<5)|0x4092); + __dpmi_set_segment_limit(selector, limit); + + switch (p->bpp) { + case 15: + dv_clear_virtual = dv_clear_virtual16; + dv_putpixel = dv_putpixel16; + dv_color = dv_color15; + break; + case 16: + dv_clear_virtual = dv_clear_virtual16; + dv_putpixel = dv_putpixel16; + dv_color = dv_color16; + break; + case 24: + dv_clear_virtual = dv_clear_virtual24; + dv_putpixel = dv_putpixel24; + dv_color = dv_color32; + break; + case 32: + dv_clear_virtual = dv_clear_virtual32; + dv_putpixel = dv_putpixel32; + dv_color = dv_color32; + break; + default: + dv_clear_virtual = NULL; + dv_putpixel = NULL; + } + + *delta = p->scanlen - ((depth+7)/8) * width; + *offset = p->scanlen*y + ((depth+7)/8) * x; + + __asm__("movw $0x4f02, %%ax; int $0x10"::"b"(p->mode):"%eax"); + } + + return p; +} + + + +/* + * fill rectangle + */ +void dv_fillrect (void *buffer, int bwidth, int x, int y, int width, int height, int color) +{ + int i, offset; + + offset = y*bwidth + x; + bwidth -= width; + for (height+=y; y>16); +} +extern __inline__ void dv_putpixel32 (void *buffer, int offset, int color) +{ + ((word32 *)buffer)[offset] = color; +} + +/* + * dv_color inlines + */ +extern __inline__ int dv_color15 (const unsigned char rgba[]) +{ + return ((rgba[0]>>3)<<10)|((rgba[1]>>3)<<5)|(rgba[2]>>3); +} +extern __inline__ int dv_color16 (const unsigned char rgba[]) +{ + return ((rgba[0]>>3)<<11)|((rgba[1]>>2)<<5)|(rgba[2]>>3); +} +#define dv_color24 dv_color32 +extern __inline__ int dv_color32 (const unsigned char rgba[]) +{ + return (rgba[0]<<16)|(rgba[1]<<8)|(rgba[2]); +} + +/* + * dv_getrgba inlines + */ +extern __inline__ void dv_getrgba15 (void *buffer, int offset, unsigned char rgba[4]) +{ + int c = ((word16 *)buffer)[offset]; + rgba[0] = _rgb_scale_5[(c >> 10) & 0x1F]; + rgba[1] = _rgb_scale_5[(c >> 5) & 0x1F]; + rgba[2] = _rgb_scale_5[c & 0x1F]; + rgba[3] = 255; +} +extern __inline__ void dv_getrgba16 (void *buffer, int offset, unsigned char rgba[4]) +{ + int c = ((word16 *)buffer)[offset]; + rgba[0] = _rgb_scale_5[(c >> 11) & 0x1F]; + rgba[1] = _rgb_scale_6[(c >> 5) & 0x3F]; + rgba[2] = _rgb_scale_5[c & 0x1F]; + rgba[3] = 255; +} +extern __inline__ void dv_getrgba24 (void *buffer, int offset, unsigned char rgba[4]) +{ + int c = *(word32 *)(buffer+offset*3); + rgba[0] = c >> 16; + rgba[1] = c >> 8; + rgba[2] = c; + rgba[3] = 255; +} +extern __inline__ void dv_getrgba32 (void *buffer, int offset, unsigned char rgba[4]) +{ + int c = ((word32 *)buffer)[offset]; + rgba[0] = c >> 16; + rgba[1] = c >> 8; + rgba[2] = c; + rgba[3] = 255; +} + +#endif -- cgit v1.2.3