home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / mesa-1.2.8 / src / wmesa.c < prev    next >
C/C++ Source or Header  |  1996-05-27  |  24KB  |  963 lines

  1. /* wmesa.c */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995  Brian Paul  (brianp@ssec.wisc.edu)
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  *
  22.  * Windows driver by: Mark E. Peterson (markp@ic.mankato.mn.us)
  23.  */
  24.  
  25. /*
  26. $Id: wmesa.c,v 1.11 1995/12/19 22:18:41 brianp Exp $
  27.  
  28. $Log: wmesa.c,v $
  29.  * Revision 1.11  1995/12/19  22:18:41  brianp
  30.  * removed 0.5 window coordinate offsets thanks to CC.RasterOffsetX/Y
  31.  *
  32.  * Revision 1.10  1995/11/20  20:11:08  brianp
  33.  * incorporated Mark's November 17th updates
  34.  *
  35.  * Revision 1.9  1995/10/30  15:30:00  brianp
  36.  * pass mask array to read_[index|color]_pixels()
  37.  *
  38.  * Revision 1.8  1995/10/19  15:44:42  brianp
  39.  * updated arguments to set_color, clear_color and gl_new_context
  40.  *
  41.  * Revision 1.7  1995/10/17  21:28:01  brianp
  42.  * updated for new device driver structure in Mesa 1.2.4
  43.  *
  44.  * Revision 1.6  1995/09/15  18:52:55  brianp
  45.  * cleaned up some code
  46.  * modified write_color_span to take NULL mask
  47.  *
  48.  * Revision 1.5  1995/07/24  18:56:00  brianp
  49.  * added dd_finish()
  50.  *
  51.  * Revision 1.4  1995/06/21  15:39:26  brianp
  52.  * removed #include "wmesaP.h"
  53.  *
  54.  * Revision 1.3  1995/06/21  15:38:10  brianp
  55.  * added struct_wmesa_context, don't need wmesaP.h anymore
  56.  *
  57.  * Revision 1.2  1995/06/09  18:53:39  brianp
  58.  * removed compute_mult_and_shift()
  59.  * dd_read/write_color_span/pixels() take GLubyte arrays instead of GLints
  60.  *
  61.  * Revision 1.1  1995/06/09  18:52:29  brianp
  62.  * Initial revision
  63.  *
  64.  */
  65.  
  66.  
  67. #include <stdlib.h>
  68. #include <windows.h>
  69. #include "gl\wmesa.h"
  70. #include "context.h"
  71. #include "dd.h"
  72. #include "xform.h"
  73. #include "vb.h"
  74. #include "wing.h"
  75.  
  76.  
  77. /* Bit's used for dest: */
  78. #define FRONT_PIXMAP    1
  79. #define BACK_PIXMAP    2
  80. #define BACK_XIMAGE    4
  81.  
  82. struct wmesa_context
  83. {
  84.   struct gl_context *gl_ctx;    /* the main library context */
  85.   HWND Window;
  86.   HDC Compat_DC;                /* Display context for double buffering. */
  87.   HBITMAP Old_Compat_BM,Compat_BM;            /* Bitmap for double buffering */
  88.   GLuint width, height,ScanWidth;
  89.   GLboolean db_flag;    /* double buffered? */
  90.   GLboolean rgb_flag;    /* RGB mode? */
  91.   GLuint depth;        /* bits per pixel (1, 8, 24, etc) */
  92.   unsigned long pixel;    /* current color index or RGBA pixel value */
  93.   unsigned long clearpixel; /* pixel for clearing the color buffers */
  94.   char *ScreenMem; // WinG memory
  95.   BITMAPINFO *IndexFormat;
  96.   HPALETTE hPal; // Current Palette
  97. };
  98.  
  99.  
  100. #ifdef NDEBUG
  101.   #define assert(ignore)    ((void) 0)
  102. #else
  103.   void Mesa_Assert(void *Cond,void *File,unsigned Line)
  104.   {
  105.     char Msg[512];
  106.     sprintf(Msg,"%s %s %d",Cond,File,Line);
  107.     MessageBox(NULL,Msg,"Assertion failed.",MB_OK);
  108.     exit(1);
  109.   }
  110.   #define assert(e)    if (!e) Mesa_Assert(#e,__FILE__,__LINE__);
  111. #endif
  112. #define DD_GETDC ((Current->db_flag) ? Current->Compat_DC : GetDC(Current->Window))
  113. #define DD_RELEASEDC if (!Current->db_flag) ReleaseDC(Current->Window,DC)
  114. static WMesaContext Current = NULL;
  115. #ifdef __SYMANTEC_BUGS
  116.   struct dd_function_table DD;
  117. #endif
  118. #define FLIP(Y)  (Current->height-(Y)-1)
  119.  
  120.  
  121.  
  122.  
  123.  
  124. /* Finish all pending operations and synchronize. */
  125. static void finish(void)
  126. {
  127.    /* no op */
  128. }
  129.  
  130.  
  131.  
  132. static void flush(void)
  133. {
  134.    /* no op */
  135. }
  136.  
  137.  
  138.  
  139. /*
  140.  * Set the color index used to clear the color buffer.
  141.  */
  142. static void clear_index(GLuint index)
  143. {
  144.   Current->clearpixel = index;
  145. }
  146.  
  147.  
  148.  
  149. /*
  150.  * Set the color used to clear the color buffer.
  151.  */
  152. static void clear_color( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
  153. {
  154.   Current->clearpixel=RGB(r, g, b );
  155. }
  156.  
  157.  
  158.  
  159. /*
  160.  * Clear the specified region of the color buffer using the clear color
  161.  * or index as specified by one of the two functions above.
  162.  */
  163. static void clear(GLboolean all,GLint x, GLint y, GLint width, GLint height )
  164. {
  165.   if (all)
  166.   {
  167.     x=y=0;
  168.     width=Current->width;
  169.     height=Current->height;
  170.   }
  171.   if (Current->rgb_flag==GL_TRUE)
  172.   {
  173.     HDC DC=DD_GETDC;
  174.     HPEN Pen=CreatePen(PS_SOLID,1,Current->clearpixel);
  175.     HBRUSH Brush=CreateSolidBrush(Current->clearpixel);
  176.     HPEN Old_Pen=SelectObject(DC,Pen);
  177.     HBRUSH Old_Brush=SelectObject(DC,Brush);
  178.     Rectangle(DC,x,y,x+width,y+height);
  179.     SelectObject(DC,Old_Pen);
  180.     SelectObject(DC,Old_Brush);
  181.     DeleteObject(Pen);
  182.     DeleteObject(Brush);
  183.     DD_RELEASEDC;
  184.   }
  185.   else
  186.   {
  187.     int i;
  188.     char *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
  189.     for (i=0; i<height; i++)
  190.     {
  191.       memset(Mem,Current->clearpixel,width);
  192.       Mem+=width;
  193.     }
  194.   }
  195. }
  196.  
  197.  
  198.  
  199. /* Set the current color index. */
  200. static void set_index(GLuint index)
  201. {
  202.   Current->pixel=index;
  203. }
  204.  
  205.  
  206.  
  207. /* Set the current RGBA color. */
  208. static void set_color( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
  209. {
  210.   Current->pixel = RGB( r, g, b );
  211. }
  212.  
  213.  
  214.  
  215. /* Set the index mode bitplane mask. */
  216. static GLboolean index_mask(GLuint mask)
  217. {
  218.    /* can't implement */
  219.    return GL_FALSE;
  220. }
  221.  
  222.  
  223.  
  224. /* Set the RGBA drawing mask. */
  225. static GLboolean color_mask( GLboolean rmask, GLboolean gmask,
  226.                              GLboolean bmask, GLboolean amask)
  227. {
  228.    /* can't implement */
  229.    return GL_FALSE;
  230. }
  231.  
  232.  
  233.  
  234. /*
  235.  * Set the pixel logic operation.  Return GL_TRUE if the device driver
  236.  * can perform the operation, otherwise return GL_FALSE.  If GL_FALSE
  237.  * is returned, the logic op will be done in software by Mesa.
  238.  */
  239. GLboolean logicop( GLenum op )
  240. {
  241.    /* can't implement */
  242.    return GL_FALSE;
  243. }
  244.  
  245.  
  246. static void dither( GLboolean enable )
  247. {
  248.    /* No op */
  249. }
  250.  
  251.  
  252.  
  253. static GLboolean set_buffer( GLenum mode )
  254. {
  255.    /* TODO: this could be better */
  256.    if (mode==GL_FRONT || mode==GL_BACK) {
  257.       return GL_TRUE;
  258.    }
  259.    else {
  260.       return GL_FALSE;
  261.    }
  262. }
  263.  
  264.  
  265.  
  266. /* Return characteristics of the output buffer. */
  267. static void buffer_size( GLuint *width, GLuint *height, GLuint *depth )
  268. {
  269.   int New_Size;
  270.   RECT CR;
  271.   GetClientRect(Current->Window,&CR);
  272.   *width=CR.right;
  273.   *height=CR.bottom;
  274.   *depth = Current->depth;
  275.   New_Size=((*width)!=Current->width) || ((*height)!=Current->height);
  276.   if (New_Size)
  277.   {
  278.     Current->width=*width;
  279.     Current->ScanWidth=Current->width;
  280.     if ((Current->ScanWidth%sizeof(long))!=0)
  281.       Current->ScanWidth+=(sizeof(long)-(Current->ScanWidth%sizeof(long)));
  282.     Current->height=*height;
  283.     if (Current->db_flag)
  284.     {
  285.       if (Current->rgb_flag==GL_TRUE)
  286.         Current->Compat_BM=CreateCompatibleBitmap(Current->Compat_DC,Current->width,Current->height);
  287.       else
  288.       {
  289.         Current->IndexFormat->bmiHeader.biWidth=Current->width;
  290.         if (Current->IndexFormat->bmiHeader.biHeight<0)
  291.           Current->IndexFormat->bmiHeader.biHeight=-Current->height;
  292.         else
  293.           Current->IndexFormat->bmiHeader.biHeight=Current->height;
  294.         Current->Compat_BM=WinGCreateBitmap(Current->Compat_DC,Current->IndexFormat,&((void *) Current->ScreenMem));
  295.       }
  296.       DeleteObject(SelectObject(Current->Compat_DC,Current->Compat_BM));
  297.     }
  298.   }
  299. }
  300.  
  301.  
  302.  
  303. /**********************************************************************/
  304. /*****           Accelerated point, line, polygon rendering       *****/
  305. /**********************************************************************/
  306.  
  307.  
  308. static void fast_rgb_points( GLuint first, GLuint last )
  309. {
  310.    int i;
  311.    HDC DC=DD_GETDC;
  312.    if (VB.MonoColor) {
  313.       /* all drawn with current color */
  314.       for (i=first;i<=last;i++) {
  315.          if (VB.Unclipped[i]) {
  316.             int x, y;
  317.             x =       (GLint) VB.Win[i][0];
  318.             y = FLIP( (GLint) VB.Win[i][1] );
  319.             SetPixel(DC,x,y,Current->pixel);
  320.          }
  321.       }
  322.    }
  323.    else {
  324.       /* draw points of different colors */
  325.       HPEN Pen=CreatePen(PS_SOLID,1,Current->pixel);
  326.       HPEN Old_Pen=SelectObject(DC,Pen);
  327.       for (i=first;i<=last;i++) {
  328.          if (VB.Unclipped[i]) {
  329.             int x, y;
  330.             unsigned long pixel=RGB(VB.Color[i][0]*255.0,
  331.                                     VB.Color[i][1]*255.0,
  332.                                     VB.Color[i][2]*255.0);
  333.             x =       (GLint) VB.Win[i][0];
  334.             y = FLIP( (GLint) VB.Win[i][1] );
  335.             SetPixel(DC,x,y,pixel);
  336.          }
  337.       }
  338.       SelectObject(DC,Old_Pen);
  339.       DeleteObject(Pen);
  340.    }
  341.    DD_RELEASEDC;
  342. }
  343.  
  344.  
  345.  
  346. /* Return pointer to accerated points function */
  347. static points_func choose_points_function( void )
  348. {
  349.    if (CC.Point.Size==1.0 && !CC.Point.SmoothFlag && CC.RasterMask==0
  350.        && !CC.Texture.Enabled  && Current->rgb_flag) {
  351.       return fast_rgb_points;
  352.    }
  353.    else {
  354.       return NULL;
  355.    }
  356. }
  357.  
  358.  
  359.  
  360. /* Draw a line using the color specified by VB.Color[pv] */
  361. static void fast_flat_rgb_line( GLuint v0, GLuint v1, GLuint pv )
  362. {
  363.    int x0, y0, x1, y1;
  364.    unsigned long pixel;
  365.    HDC DC=DD_GETDC;
  366.    HPEN Pen;
  367.    HPEN Old_Pen;
  368.  
  369.    if (VB.MonoColor) {
  370.       pixel = Current->pixel;  /* use current color */
  371.    }
  372.    else {
  373.       pixel = RGB(VB.Color[pv][0]*255.0, VB.Color[pv][1]*255.0, VB.Color[pv][2]*255.0);
  374.    }
  375.  
  376.    x0 =       (int) VB.Win[v0][0];
  377.    y0 = FLIP( (int) VB.Win[v0][1] );
  378.    x1 =       (int) VB.Win[v1][0];
  379.    y1 = FLIP( (int) VB.Win[v1][1] );
  380.  
  381.    Pen=CreatePen(PS_SOLID,1,pixel);
  382.    Old_Pen=SelectObject(DC,Pen);
  383.    MoveToEx(DC,x0,y0,NULL);
  384.    LineTo(DC,x1,y1);
  385.    SelectObject(DC,Old_Pen);
  386.    DeleteObject(Pen);
  387.    DD_RELEASEDC;
  388. }
  389.  
  390.  
  391.  
  392. /* Return pointer to accerated line function */
  393. static line_func choose_line_function( void )
  394. {
  395.    if (CC.Line.Width==1.0 && !CC.Line.SmoothFlag && !CC.Line.StippleFlag
  396.        && CC.Light.ShadeModel==GL_FLAT && CC.RasterMask==0
  397.        && !CC.Texture.Enabled && Current->rgb_flag) {
  398.       return fast_flat_rgb_line;
  399.    }
  400.    else {
  401.       return NULL;
  402.    }
  403. }
  404.  
  405.  
  406. /* Draw a convex polygon using color VB.Color[pv] */
  407. static void fast_flat_rgb_polygon( GLuint n, GLuint vlist[], GLuint pv )
  408. {
  409.    POINT *Pts=(POINT *) malloc(n*sizeof(POINT));
  410.    HDC DC=DD_GETDC;
  411.    HPEN Pen;
  412.    HBRUSH Brush;
  413.    HPEN Old_Pen;
  414.    HBRUSH Old_Brush;
  415.    GLint pixel;
  416.    int i;
  417.  
  418.    if (VB.MonoColor) {
  419.       pixel = Current->pixel;  /* use current color */
  420.    }
  421.    else {
  422.       pixel = RGB(VB.Color[pv][0]*255.0, VB.Color[pv][1]*255.0, VB.Color[pv][2]*255.0);
  423.    }
  424.  
  425.    Pen=CreatePen(PS_SOLID,1,pixel);
  426.    Brush=CreateSolidBrush(pixel);
  427.    Old_Pen=SelectObject(DC,Pen);
  428.    Old_Brush=SelectObject(DC,Brush);
  429.  
  430.    for (i=0; i<n; i++) {
  431.       int j = vlist[i];
  432.       Pts[i].x =       (int) VB.Win[j][0];
  433.       Pts[i].y = FLIP( (int) VB.Win[j][1] );
  434.    }
  435.    Polygon(DC,Pts,n);
  436.    SelectObject(DC,Old_Pen);
  437.    SelectObject(DC,Old_Brush);
  438.    DeleteObject(Pen);
  439.    DeleteObject(Brush);
  440.    DD_RELEASEDC;
  441.    free(Pts);
  442. }
  443.  
  444.  
  445.  
  446. /* Return pointer to accerated polygon function */
  447. static polygon_func choose_polygon_function( void )
  448. {
  449.    if (!CC.Polygon.SmoothFlag && !CC.Polygon.StippleFlag
  450.        && CC.Light.ShadeModel==GL_FLAT && CC.RasterMask==0
  451.        && !CC.Texture.Enabled && Current->rgb_flag==GL_TRUE) {
  452.       return fast_flat_rgb_polygon;
  453.    }
  454.    else {
  455.       return NULL;
  456.    }
  457. }
  458.  
  459.  
  460.  
  461. /**********************************************************************/
  462. /*****                 Span-based pixel drawing                   *****/
  463. /**********************************************************************/
  464.  
  465.  
  466. /* Write a horizontal span of color-index pixels with a boolean mask. */
  467. static void write_index_span( GLuint n, GLint x, GLint y,
  468.                               const GLuint index[],
  469.                               const GLubyte mask[] )
  470. {
  471.   int i;
  472.   char *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
  473.   assert(Current->rgb_flag==GL_FALSE);
  474.   for (i=0; i<n; i++)
  475.     if (mask[i])
  476.       Mem[i]=index[i];
  477. }
  478.  
  479.  
  480.  
  481. /*
  482.  * Write a horizontal span of pixels with a boolean mask.  The current
  483.  * color index is used for all pixels.
  484.  */
  485. static void write_monoindex_span(GLuint n,GLint x,GLint y,const GLubyte mask[])
  486. {
  487.   int i;
  488.   char *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
  489.   assert(Current->rgb_flag==GL_FALSE);
  490.   for (i=0; i<n; i++)
  491.     if (mask[i])
  492.       Mem[i]=Current->pixel;
  493. }
  494.  
  495.  
  496.  
  497. /* Write a horizontal span of color pixels with a boolean mask. */
  498. static void write_color_span( GLuint n, GLint x, GLint y,
  499.               const GLubyte red[], const GLubyte green[],
  500.               const GLubyte blue[], const GLubyte alpha[],
  501.               const GLubyte mask[] )
  502. {
  503.   if (Current->rgb_flag==GL_TRUE)
  504.   {
  505.     int i;
  506.     HDC DC=DD_GETDC;
  507.     y=FLIP(y);
  508.     if (mask) {
  509.        for (i=0; i<n; i++)
  510.          if (mask[i])
  511.            SetPixel(DC,x+i,y,RGB(red[i],green[i],blue[i]));
  512.     }
  513.     else {
  514.        for (i=0; i<n; i++)
  515.          SetPixel(DC,x+i,y,RGB(red[i],green[i],blue[i]));
  516.     }
  517.     DD_RELEASEDC;
  518.   }
  519.   else
  520.   {
  521.     int i;
  522.     char *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
  523.     if (mask) {
  524.        for (i=0; i<n; i++)
  525.          if (mask[i])
  526.            Mem[i]=GetNearestPaletteIndex(Current->hPal,RGB(red[i],green[i],blue[i]));
  527.     }
  528.     else {
  529.        for (i=0; i<n; i++)
  530.          Mem[i]=GetNearestPaletteIndex(Current->hPal,RGB(red[i],green[i],blue[i]));
  531.     }
  532.   }
  533. }
  534.  
  535.  
  536.  
  537. /*
  538.  * Write a horizontal span of pixels with a boolean mask.  The current color
  539.  * is used for all pixels.
  540.  */
  541. static void write_monocolor_span( GLuint n, GLint x, GLint y,const GLubyte mask[])
  542. {
  543.   int i;
  544.   HDC DC=DD_GETDC;
  545.   assert(Current->rgb_flag==GL_TRUE);
  546.   y=FLIP(y);
  547.   for (i=0; i<n; i++)
  548.     if (mask[i])
  549.       SetPixel(DC,x+i,y,Current->pixel);
  550.   DD_RELEASEDC;
  551. }
  552.  
  553.  
  554.  
  555. /**********************************************************************/
  556. /*****                   Array-based pixel drawing                *****/
  557. /**********************************************************************/
  558.  
  559.  
  560. /* Write an array of pixels with a boolean mask. */
  561. static void write_index_pixels( GLuint n, const GLint x[], const GLint y[],
  562.                                 const GLuint index[], const GLubyte mask[] )
  563. {
  564.    int i;
  565.    assert(Current->rgb_flag==GL_FALSE);
  566.    for (i=0; i<n; i++) {
  567.       if (mask[i]) {
  568.          char *Mem=Current->ScreenMem+y[i]*Current->ScanWidth+x[i];
  569.          *Mem = index[i];
  570.       }
  571.    }
  572. }
  573.  
  574.  
  575.  
  576. /*
  577.  * Write an array of pixels with a boolean mask.  The current color
  578.  * index is used for all pixels.
  579.  */
  580. static void write_monoindex_pixels( GLuint n,
  581.                                     const GLint x[], const GLint y[],
  582.                                     const GLubyte mask[] )
  583. {
  584.    int i;
  585.    assert(Current->rgb_flag==GL_FALSE);
  586.    for (i=0; i<n; i++) {
  587.       if (mask[i]) {
  588.          char *Mem=Current->ScreenMem+y[i]*Current->ScanWidth+x[i];
  589.          *Mem = Current->pixel;
  590.       }
  591.    }
  592. }
  593.  
  594.  
  595.  
  596. /* Write an array of pixels with a boolean mask. */
  597. static void write_color_pixels( GLuint n, const GLint x[], const GLint y[],
  598.                                 const GLubyte r[], const GLubyte g[],
  599.                                 const GLubyte b[], const GLubyte a[],
  600.                                 const GLubyte mask[] )
  601. {
  602.   int i;
  603.   HDC DC=DD_GETDC;
  604.   assert(Current->rgb_flag==GL_TRUE);
  605.   for (i=0; i<n; i++)
  606.     if (mask[i])
  607.       SetPixel(DC,x[i],FLIP(y[i]),RGB(r[i],g[i],b[i]));
  608.   DD_RELEASEDC;
  609. }
  610.  
  611.  
  612.  
  613. /*
  614.  * Write an array of pixels with a boolean mask.  The current color
  615.  * is used for all pixels.
  616.  */
  617. static void write_monocolor_pixels( GLuint n,
  618.                                     const GLint x[], const GLint y[],
  619.                                     const GLubyte mask[] )
  620. {
  621.   int i;
  622.   HDC DC=DD_GETDC;
  623.   assert(Current->rgb_flag==GL_TRUE);
  624.   for (i=0; i<n; i++)
  625.     if (mask[i])
  626.       SetPixel(DC,x[i],FLIP(y[i]),Current->pixel);
  627.   DD_RELEASEDC;
  628. }
  629.  
  630.  
  631.  
  632. /**********************************************************************/
  633. /*****            Read spans/arrays of pixels                     *****/
  634. /**********************************************************************/
  635.  
  636.  
  637. /* Read a horizontal span of color-index pixels. */
  638. static void read_index_span( GLuint n, GLint x, GLint y, GLuint index[])
  639. {
  640.   int i;
  641.   char *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
  642.   assert(Current->rgb_flag==GL_FALSE);
  643.   for (i=0; i<n; i++)
  644.     index[i]=Mem[i];
  645. }
  646.  
  647.  
  648.  
  649.  
  650. /* Read an array of color index pixels. */
  651. static void read_index_pixels( GLuint n, const GLint x[], const GLint y[],
  652.                                GLuint indx[], const GLubyte mask[] )
  653. {
  654.   int i;
  655.   assert(Current->rgb_flag==GL_FALSE);
  656.   for (i=0; i<n; i++) {
  657.      if (mask[i]) {
  658.         indx[i]=*(Current->ScreenMem+y[i]*Current->ScanWidth+x[i]);
  659.      }
  660.   }
  661. }
  662.  
  663.  
  664.  
  665. /* Read a horizontal span of color pixels. */
  666. static void read_color_span( GLuint n, GLint x, GLint y,
  667.                              GLubyte red[], GLubyte green[],
  668.                              GLubyte blue[], GLubyte alpha[] )
  669. {
  670.   int i;
  671.   COLORREF Color;
  672.   HDC DC=DD_GETDC;
  673.   assert(Current->rgb_flag==GL_TRUE);
  674.   y=FLIP(y);
  675.   for (i=0; i<n; i++)
  676.   {
  677.     Color=GetPixel(DC,x+i,y);
  678.     red[i]=GetRValue(Color);
  679.     green[i]=GetGValue(Color);
  680.     blue[i]=GetBValue(Color);
  681.     alpha[i]=255;
  682.   }
  683.   DD_RELEASEDC;
  684.   memset(alpha,0,n*sizeof(GLint));
  685. }
  686.  
  687.  
  688. /* Read an array of color pixels. */
  689. static void read_color_pixels( GLuint n, const GLint x[], const GLint y[],
  690.                                GLubyte red[], GLubyte green[],
  691.                                GLubyte blue[], GLubyte alpha[],
  692.                                const GLubyte mask[] )
  693. {
  694.   int i;
  695.   COLORREF Color;
  696.   HDC DC=DD_GETDC;
  697.   assert(Current->rgb_flag==GL_TRUE);
  698.   for (i=0; i<n; i++) {
  699.      if (mask[i]) {
  700.         Color=GetPixel(DC,x[i],FLIP(y[i]));
  701.         red[i]=GetRValue(Color);
  702.         green[i]=GetGValue(Color);
  703.         blue[i]=GetBValue(Color);
  704.         alpha[i]=255;
  705.      }
  706.   }
  707.   DD_RELEASEDC;
  708.   memset(alpha,0,n*sizeof(GLint));
  709. }
  710.  
  711.  
  712.  
  713. /**********************************************************************/
  714. /**********************************************************************/
  715.  
  716.  
  717.  
  718. static void setup_DD_pointers( void )
  719. {
  720.    DD.finish = finish;
  721.    DD.flush = flush;
  722.  
  723.    DD.clear_index = clear_index;
  724.    DD.clear_color = clear_color;
  725.    DD.clear = clear;
  726.  
  727.    DD.index = set_index;
  728.    DD.color = set_color;
  729.    DD.index_mask = index_mask;
  730.    DD.color_mask = color_mask;
  731.  
  732.    DD.logicop = logicop;
  733.    DD.dither = dither;
  734.  
  735.    DD.set_buffer = set_buffer;
  736.    DD.buffer_size = buffer_size;
  737.  
  738.    DD.get_points_func = choose_points_function;
  739.    DD.get_line_func = choose_line_function;
  740.    DD.get_polygon_func = choose_polygon_function;
  741.  
  742.    /* Pixel/span writing functions: */
  743.    DD.write_color_span       = write_color_span;
  744.    DD.write_monocolor_span   = write_monocolor_span;
  745.    DD.write_color_pixels     = write_color_pixels;
  746.    DD.write_monocolor_pixels = write_monocolor_pixels;
  747.    DD.write_index_span       = write_index_span;
  748.    DD.write_monoindex_span   = write_monoindex_span;
  749.    DD.write_index_pixels     = write_index_pixels;
  750.    DD.write_monoindex_pixels = write_monoindex_pixels;
  751.  
  752.    /* Pixel/span reading functions: */
  753.    DD.read_index_span = read_index_span;
  754.    DD.read_color_span = read_color_span;
  755.    DD.read_index_pixels = read_index_pixels;
  756.    DD.read_color_pixels = read_color_pixels;
  757. }
  758.  
  759.  
  760.  
  761. /**********************************************************************/
  762. /*****                  WMesa API Functions                       *****/
  763. /**********************************************************************/
  764.  
  765.  
  766.  
  767. #define PAL_SIZE 256
  768. static void GetPalette(HPALETTE Pal,RGBQUAD *aRGB)
  769. {
  770.     int i;
  771.     HDC hdc;
  772.     struct
  773.     {
  774.         WORD Version;
  775.         WORD NumberOfEntries;
  776.         PALETTEENTRY aEntries[PAL_SIZE];
  777.     } Palette =
  778.     {
  779.         0x300,
  780.         PAL_SIZE
  781.     };
  782.     hdc=GetDC(NULL);
  783.     if (Pal!=NULL)
  784.     GetPaletteEntries(Pal,0,PAL_SIZE,Palette.aEntries);
  785.   else
  786.     GetSystemPaletteEntries(hdc,0,PAL_SIZE,Palette.aEntries);
  787.     if (GetSystemPaletteUse(hdc) == SYSPAL_NOSTATIC)
  788.     {
  789.         for(i = 0; i <PAL_SIZE; i++)
  790.             Palette.aEntries[i].peFlags = PC_RESERVED;
  791.         Palette.aEntries[255].peRed = 255;
  792.         Palette.aEntries[255].peGreen = 255;
  793.         Palette.aEntries[255].peBlue = 255;
  794.         Palette.aEntries[255].peFlags = 0;
  795.         Palette.aEntries[0].peRed = 0;
  796.         Palette.aEntries[0].peGreen = 0;
  797.         Palette.aEntries[0].peBlue = 0;
  798.         Palette.aEntries[0].peFlags = 0;
  799.     }
  800.     else
  801.     {
  802.         int nStaticColors;
  803.         int nUsableColors;
  804.         nStaticColors = GetDeviceCaps(hdc, NUMCOLORS)/2;
  805.         for (i=0; i<nStaticColors; i++)
  806.             Palette.aEntries[i].peFlags = 0;
  807.         nUsableColors = PAL_SIZE-nStaticColors;
  808.         for (; i<nUsableColors; i++)
  809.             Palette.aEntries[i].peFlags = PC_RESERVED;
  810.         for (; i<PAL_SIZE-nStaticColors; i++)
  811.             Palette.aEntries[i].peFlags = PC_RESERVED;
  812.         for (i=PAL_SIZE-nStaticColors; i<PAL_SIZE; i++)
  813.             Palette.aEntries[i].peFlags = 0;
  814.     }
  815.     ReleaseDC(NULL,hdc);
  816.   for (i=0; i<PAL_SIZE; i++)
  817.   {
  818.     aRGB[i].rgbRed=Palette.aEntries[i].peRed;
  819.     aRGB[i].rgbGreen=Palette.aEntries[i].peGreen;
  820.     aRGB[i].rgbBlue=Palette.aEntries[i].peBlue;
  821.     aRGB[i].rgbReserved=Palette.aEntries[i].peFlags;
  822.   }
  823. }
  824.  
  825.  
  826.  
  827. WMesaContext WMesaCreateContext( HWND hWnd, HPALETTE Pal, GLboolean rgb_flag,
  828.                                  GLboolean db_flag )
  829. {
  830.   BITMAPINFO *Rec;
  831.   HDC DC;
  832.   RECT CR;
  833.   WMesaContext c;
  834.  
  835.   c = (struct wmesa_context *) calloc(1,sizeof(struct wmesa_context));
  836.   if (!c)
  837.     return NULL;
  838.  
  839.   c->Window=hWnd;
  840.   if (rgb_flag==GL_FALSE)
  841.   {
  842.     c->rgb_flag = GL_FALSE;
  843.     c->pixel = 1;
  844.     db_flag=GL_TRUE; // WinG requires double buffering
  845.     //c->gl_ctx->BufferDepth = windepth;
  846.   }
  847.   else
  848.   {
  849.     c->rgb_flag = GL_TRUE;
  850.     c->pixel = 0;
  851.   }
  852.   GetClientRect(c->Window,&CR);
  853.   c->width=CR.right;
  854.   c->height=CR.bottom;
  855.   if (db_flag)
  856.   {
  857.     c->db_flag = 1;
  858.     /* Double buffered */
  859.     if (c->rgb_flag==GL_TRUE)
  860.     {
  861.       DC=GetDC(c->Window);
  862.       c->Compat_DC=CreateCompatibleDC(DC);
  863.       c->Compat_BM=CreateCompatibleBitmap(DC,c->width,c->height);
  864.       ReleaseDC(c->Window,DC);
  865.       c->Old_Compat_BM=SelectObject(c->Compat_DC,c->Compat_BM);
  866.     }
  867.     else
  868.     {
  869.       c->Compat_DC=WinGCreateDC();
  870.       Rec=(BITMAPINFO *) malloc(sizeof(BITMAPINFO)+(PAL_SIZE-1)*sizeof(RGBQUAD));
  871.       c->hPal=Pal;
  872.       GetPalette(Pal,Rec->bmiColors);
  873.       WinGRecommendDIBFormat(Rec);
  874.       Rec->bmiHeader.biWidth=c->width;
  875.       Rec->bmiHeader.biHeight*=c->height;
  876.       Rec->bmiHeader.biClrUsed=PAL_SIZE;
  877.       if (Rec->bmiHeader.biPlanes!=1 || Rec->bmiHeader.biBitCount!=8)
  878.       {
  879.         MessageBox(NULL,"Error.","This code presumes a 256 color, single plane, WinG Device.\n",MB_OK);
  880.         exit(1);
  881.       }
  882.       c->Compat_BM=WinGCreateBitmap(c->Compat_DC,Rec,&((void *) c->ScreenMem));
  883.       c->Old_Compat_BM=SelectObject(c->Compat_DC,c->Compat_BM);
  884.       WinGSetDIBColorTable(c->Compat_DC,0,PAL_SIZE,Rec->bmiColors);
  885.       c->IndexFormat=Rec;
  886.       c->ScanWidth=c->width;
  887.       if ((c->ScanWidth%sizeof(long))!=0)
  888.         c->ScanWidth+=(sizeof(long)-(c->ScanWidth%sizeof(long)));
  889.     }
  890.   }
  891.   else
  892.   {
  893.     /* Single Buffered */
  894.     c->db_flag = 0;
  895.   }
  896.  
  897.   /* allocate a new Mesa context */
  898.   c->gl_ctx = gl_new_context( rgb_flag,
  899.                               255.0, 255.0, 255.0, 255.0,
  900.                               db_flag, NULL);
  901.  
  902.   setup_DD_pointers();
  903.  
  904.   return c;
  905. }
  906.  
  907.  
  908.  
  909. void WMesaDestroyContext( WMesaContext c )
  910. {
  911.    gl_destroy_context( c->gl_ctx );
  912.    if (c->db_flag)
  913.    {
  914.      SelectObject(c->Compat_DC,c->Old_Compat_BM);
  915.      DeleteDC(c->Compat_DC);
  916.      DeleteObject(c->Compat_BM);
  917.    }
  918.    free( (void *) c );
  919. }
  920.  
  921.  
  922.  
  923. void WMesaMakeCurrent( WMesaContext c )
  924. {
  925.    gl_set_context( c->gl_ctx );
  926.    Current = c;
  927.    setup_DD_pointers();
  928.    if (Current->gl_ctx->Viewport.Width==0) {
  929.       /* initialize viewport to window size */
  930.       gl_viewport( 0, 0, Current->width, Current->height );
  931.    }
  932. }
  933.  
  934.  
  935.  
  936. void WMesaSwapBuffers( void )
  937. {
  938.   // *** Perhaps the DC should be saved in WMesaContext?
  939.   HDC DC;
  940.   if (Current->db_flag)
  941.   {
  942.     DC=GetDC(Current->Window);
  943.     if (Current->rgb_flag)
  944.       BitBlt(DC,0,0,Current->width,Current->height,Current->Compat_DC,0,0,SRCCOPY);
  945.     else
  946.       WinGBitBlt(DC,0,0,Current->width,Current->height,Current->Compat_DC,0,0);
  947.     ReleaseDC(Current->Window,DC);
  948.   }
  949. }
  950.  
  951.  
  952.  
  953. void WMesaPaletteChange(HPALETTE Pal)
  954. {
  955.   if (Current && Current->rgb_flag==GL_FALSE)
  956.   {
  957.     Current->hPal=Pal;
  958.     GetPalette(Pal,Current->IndexFormat->bmiColors);
  959.     WinGSetDIBColorTable(Current->Compat_DC,0,PAL_SIZE,Current->IndexFormat->bmiColors);
  960.   }
  961. }
  962.  
  963.