Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Windows (Win32/Win64) device driver for Mesa
  3.  *
  4.  */
  5.  
  6. #include "wmesadef.h"
  7. #include "colors.h"
  8. #include "GL/wmesa.h"
  9. #include <winuser.h>
  10. #include "main/context.h"
  11. #include "main/api_exec.h"
  12. #include "main/extensions.h"
  13. #include "main/framebuffer.h"
  14. #include "main/renderbuffer.h"
  15. #include "main/macros.h"
  16. #include "main/version.h"
  17. #include "main/vtxfmt.h"
  18. #include "drivers/common/driverfuncs.h"
  19. #include "drivers/common/meta.h"
  20. #include "vbo/vbo.h"
  21. #include "swrast/swrast.h"
  22. #include "swrast/s_renderbuffer.h"
  23. #include "swrast_setup/swrast_setup.h"
  24. #include "tnl/tnl.h"
  25. #include "tnl/t_context.h"
  26. #include "tnl/t_pipeline.h"
  27.  
  28.  
  29. /* linked list of our Framebuffers (windows) */
  30. static WMesaFramebuffer FirstFramebuffer = NULL;
  31.  
  32.  
  33. /**
  34.  * Create a new WMesaFramebuffer object which will correspond to the
  35.  * given HDC (Window handle).
  36.  */
  37. static WMesaFramebuffer
  38. wmesa_new_framebuffer(HDC hdc, struct gl_config *visual)
  39. {
  40.     WMesaFramebuffer pwfb
  41.         = malloc(sizeof(struct wmesa_framebuffer));
  42.     if (pwfb) {
  43.         _mesa_initialize_window_framebuffer(&pwfb->Base, visual);
  44.         pwfb->hDC = hdc;
  45.         /* insert at head of list */
  46.         pwfb->next = FirstFramebuffer;
  47.         FirstFramebuffer = pwfb;
  48.     }
  49.     return pwfb;
  50. }
  51.  
  52. /**
  53.  * Given an hdc, free the corresponding WMesaFramebuffer
  54.  */
  55. static void
  56. wmesa_free_framebuffer(HDC hdc)
  57. {
  58.     WMesaFramebuffer pwfb, prev;
  59.     for (pwfb = FirstFramebuffer; pwfb; pwfb = pwfb->next) {
  60.         if (pwfb->hDC == hdc)
  61.             break;
  62.         prev = pwfb;
  63.     }
  64.     if (pwfb) {
  65.         struct gl_framebuffer *fb;
  66.         if (pwfb == FirstFramebuffer)
  67.             FirstFramebuffer = pwfb->next;
  68.         else
  69.             prev->next = pwfb->next;
  70.         fb = &pwfb->Base;
  71.         _mesa_reference_framebuffer(&fb, NULL);
  72.     }
  73. }
  74.  
  75. /**
  76.  * Given an hdc, return the corresponding WMesaFramebuffer
  77.  */
  78. static WMesaFramebuffer
  79. wmesa_lookup_framebuffer(HDC hdc)
  80. {
  81.     WMesaFramebuffer pwfb;
  82.     for (pwfb = FirstFramebuffer; pwfb; pwfb = pwfb->next) {
  83.         if (pwfb->hDC == hdc)
  84.             return pwfb;
  85.     }
  86.     return NULL;
  87. }
  88.  
  89.  
  90. /**
  91.  * Given a struct gl_framebuffer, return the corresponding WMesaFramebuffer.
  92.  */
  93. static WMesaFramebuffer wmesa_framebuffer(struct gl_framebuffer *fb)
  94. {
  95.     return (WMesaFramebuffer) fb;
  96. }
  97.  
  98.  
  99. /**
  100.  * Given a struct gl_context, return the corresponding WMesaContext.
  101.  */
  102. static WMesaContext wmesa_context(const struct gl_context *ctx)
  103. {
  104.     return (WMesaContext) ctx;
  105. }
  106.  
  107.  
  108. /*
  109.  * Every driver should implement a GetString function in order to
  110.  * return a meaningful GL_RENDERER string.
  111.  */
  112. static const GLubyte *wmesa_get_string(struct gl_context *ctx, GLenum name)
  113. {
  114.     return (name == GL_RENDERER) ?
  115.         (GLubyte *) "Mesa Windows GDI Driver" : NULL;
  116. }
  117.  
  118.  
  119. /*
  120.  * Determine the pixel format based on the pixel size.
  121.  */
  122. static void wmSetPixelFormat(WMesaFramebuffer pwfb, HDC hDC)
  123. {
  124.     pwfb->cColorBits = GetDeviceCaps(hDC, BITSPIXEL);
  125.  
  126.     /* Only 16 and 32 bit targets are supported now */
  127.     assert(pwfb->cColorBits == 0 ||
  128.            pwfb->cColorBits == 16 ||
  129.            pwfb->cColorBits == 24 ||
  130.            pwfb->cColorBits == 32);
  131.  
  132.     switch(pwfb->cColorBits){
  133.     case 8:
  134.         pwfb->pixelformat = PF_INDEX8;
  135.         break;
  136.     case 16:
  137.         pwfb->pixelformat = PF_5R6G5B;
  138.         break;
  139.     case 24:
  140.     case 32:
  141.         pwfb->pixelformat = PF_8R8G8B;
  142.         break;
  143.     default:
  144.         pwfb->pixelformat = PF_BADFORMAT;
  145.     }
  146. }
  147.  
  148.  
  149. /**
  150.  * Create DIB for back buffer.
  151.  * We write into this memory with the span routines and then blit it
  152.  * to the window on a buffer swap.
  153.  */
  154. static BOOL wmCreateBackingStore(WMesaFramebuffer pwfb, long lxSize, long lySize)
  155. {
  156.     LPBITMAPINFO pbmi = &(pwfb->bmi);
  157.     HDC          hic;
  158.  
  159.     pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  160.     pbmi->bmiHeader.biWidth = lxSize;
  161.     pbmi->bmiHeader.biHeight= -lySize;
  162.     pbmi->bmiHeader.biPlanes = 1;
  163.     pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwfb->hDC, BITSPIXEL);
  164.     pbmi->bmiHeader.biCompression = BI_RGB;
  165.     pbmi->bmiHeader.biSizeImage = 0;
  166.     pbmi->bmiHeader.biXPelsPerMeter = 0;
  167.     pbmi->bmiHeader.biYPelsPerMeter = 0;
  168.     pbmi->bmiHeader.biClrUsed = 0;
  169.     pbmi->bmiHeader.biClrImportant = 0;
  170.    
  171.     pwfb->cColorBits = pbmi->bmiHeader.biBitCount;
  172.     pwfb->ScanWidth = (lxSize * (pwfb->cColorBits / 8) + 3) & ~3;
  173.    
  174.     hic = CreateIC("display", NULL, NULL, NULL);
  175.     pwfb->dib_hDC = CreateCompatibleDC(hic);
  176.    
  177.     pwfb->hbmDIB = CreateDIBSection(hic,
  178.                                    &pwfb->bmi,
  179.                                    DIB_RGB_COLORS,
  180.                                    (void **)&(pwfb->pbPixels),
  181.                                    0,
  182.                                    0);
  183.     pwfb->hOldBitmap = SelectObject(pwfb->dib_hDC, pwfb->hbmDIB);
  184.    
  185.     DeleteDC(hic);
  186.  
  187.     wmSetPixelFormat(pwfb, pwfb->hDC);
  188.     return TRUE;
  189. }
  190.  
  191.  
  192. static void wmDeleteBackingStore(WMesaFramebuffer pwfb)
  193. {
  194.     if (pwfb->hbmDIB) {
  195.         SelectObject(pwfb->dib_hDC, pwfb->hOldBitmap);
  196.         DeleteDC(pwfb->dib_hDC);
  197.         DeleteObject(pwfb->hbmDIB);
  198.     }
  199. }
  200.  
  201.  
  202. /**
  203.  * Find the width and height of the window named by hdc.
  204.  */
  205. static void
  206. get_window_size(HDC hdc, GLuint *width, GLuint *height)
  207. {
  208.     if (WindowFromDC(hdc)) {
  209.         RECT rect;
  210.         GetClientRect(WindowFromDC(hdc), &rect);
  211.         *width = rect.right - rect.left;
  212.         *height = rect.bottom - rect.top;
  213.     }
  214.     else { /* Memory context */
  215.         /* From contributed code - use the size of the desktop
  216.          * for the size of a memory context (?) */
  217.         *width = GetDeviceCaps(hdc, HORZRES);
  218.         *height = GetDeviceCaps(hdc, VERTRES);
  219.     }
  220. }
  221.  
  222.  
  223. static void
  224. wmesa_get_buffer_size(struct gl_framebuffer *buffer, GLuint *width, GLuint *height)
  225. {
  226.     WMesaFramebuffer pwfb = wmesa_framebuffer(buffer);
  227.     get_window_size(pwfb->hDC, width, height);
  228. }
  229.  
  230.  
  231. static void wmesa_flush(struct gl_context *ctx)
  232. {
  233.     WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->WinSysDrawBuffer);
  234.  
  235.     if (ctx->Visual.doubleBufferMode == 1) {
  236.         BitBlt(pwfb->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height,
  237.                pwfb->dib_hDC, 0, 0, SRCCOPY);
  238.     }
  239.     else {
  240.         /* Do nothing for single buffer */
  241.     }
  242. }
  243.  
  244.  
  245. /**********************************************************************/
  246. /*****                   CLEAR Functions                          *****/
  247. /**********************************************************************/
  248.  
  249. /*
  250.  * Clear the color/depth/stencil buffers.
  251.  */
  252. static void clear(struct gl_context *ctx, GLbitfield mask)
  253. {
  254. #define FLIP(Y)  (ctx->DrawBuffer->Height - (Y) - 1)
  255.     const GLint x = ctx->DrawBuffer->_Xmin;
  256.     const GLint y = ctx->DrawBuffer->_Ymin;
  257.     const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
  258.     const GLint width  = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
  259.  
  260.     WMesaContext pwc = wmesa_context(ctx);
  261.     WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer);
  262.     int done = 0;
  263.  
  264.     /* Let swrast do all the work if the masks are not set to
  265.      * clear all channels. */
  266.     if (!ctx->Color.ColorMask[0][0] ||
  267.         !ctx->Color.ColorMask[0][1] ||
  268.         !ctx->Color.ColorMask[0][2] ||
  269.         !ctx->Color.ColorMask[0][3]) {
  270.         _swrast_Clear(ctx, mask);
  271.         return;
  272.     }
  273.  
  274.     if (mask & BUFFER_BITS_COLOR) {
  275.        /* setup the clearing color */
  276.        const union gl_color_union color = ctx->Color.ClearColor;
  277.        GLubyte col[3];
  278.        UNCLAMPED_FLOAT_TO_UBYTE(col[0], color.f[0]);
  279.        UNCLAMPED_FLOAT_TO_UBYTE(col[1], color.f[1]);
  280.        UNCLAMPED_FLOAT_TO_UBYTE(col[2], color.f[2]);
  281.        pwc->clearColorRef = RGB(col[0], col[1], col[2]);
  282.        DeleteObject(pwc->clearPen);
  283.        DeleteObject(pwc->clearBrush);
  284.        pwc->clearPen = CreatePen(PS_SOLID, 1, pwc->clearColorRef);
  285.        pwc->clearBrush = CreateSolidBrush(pwc->clearColorRef);
  286.     }
  287.  
  288.     /* Back buffer */
  289.     if (mask & BUFFER_BIT_BACK_LEFT) {
  290.        
  291.         int     i, rowSize;
  292.         UINT    bytesPerPixel = pwfb->cColorBits / 8;
  293.         LPBYTE  lpb, clearRow;
  294.         LPWORD  lpw;
  295.         BYTE    bColor;
  296.         WORD    wColor;
  297.         BYTE    r, g, b;
  298.         DWORD   dwColor;
  299.         LPDWORD lpdw;
  300.        
  301.         /* Try for a fast clear - clearing entire buffer with a single
  302.          * byte value. */
  303.         if (width == ctx->DrawBuffer->Width &&
  304.             height == ctx->DrawBuffer->Height) { /* entire buffer */
  305.             /* Now check for an easy clear value */
  306.             switch (bytesPerPixel) {
  307.             case 1:
  308.                 bColor = BGR8(GetRValue(pwc->clearColorRef),
  309.                               GetGValue(pwc->clearColorRef),
  310.                               GetBValue(pwc->clearColorRef));
  311.                 memset(pwfb->pbPixels, bColor,
  312.                        pwfb->ScanWidth * height);
  313.                 done = 1;
  314.                 break;
  315.             case 2:
  316.                 wColor = BGR16(GetRValue(pwc->clearColorRef),
  317.                                GetGValue(pwc->clearColorRef),
  318.                                GetBValue(pwc->clearColorRef));
  319.                 if (((wColor >> 8) & 0xff) == (wColor & 0xff)) {
  320.                     memset(pwfb->pbPixels, wColor & 0xff,
  321.                            pwfb->ScanWidth * height);
  322.                     done = 1;
  323.                 }
  324.                 break;
  325.             case 3:
  326.                 /* fall through */
  327.             case 4:
  328.                 if (GetRValue(pwc->clearColorRef) ==
  329.                     GetGValue(pwc->clearColorRef) &&
  330.                     GetRValue(pwc->clearColorRef) ==
  331.                     GetBValue(pwc->clearColorRef)) {
  332.                     memset(pwfb->pbPixels,
  333.                            GetRValue(pwc->clearColorRef),
  334.                            pwfb->ScanWidth * height);
  335.                     done = 1;
  336.                 }
  337.                 break;
  338.             default:
  339.                 break;
  340.             }
  341.         } /* all */
  342.  
  343.         if (!done) {
  344.             /* Need to clear a row at a time.  Begin by setting the first
  345.              * row in the area to be cleared to the clear color. */
  346.            
  347.             clearRow = pwfb->pbPixels +
  348.                 pwfb->ScanWidth * FLIP(y) +
  349.                 bytesPerPixel * x;
  350.             switch (bytesPerPixel) {
  351.             case 1:
  352.                 lpb = clearRow;
  353.                 bColor = BGR8(GetRValue(pwc->clearColorRef),
  354.                               GetGValue(pwc->clearColorRef),
  355.                               GetBValue(pwc->clearColorRef));
  356.                 memset(lpb, bColor, width);
  357.                 break;
  358.             case 2:
  359.                 lpw = (LPWORD)clearRow;
  360.                 wColor = BGR16(GetRValue(pwc->clearColorRef),
  361.                                GetGValue(pwc->clearColorRef),
  362.                                GetBValue(pwc->clearColorRef));
  363.                 for (i=0; i<width; i++)
  364.                     *lpw++ = wColor;
  365.                 break;
  366.             case 3:
  367.                 lpb = clearRow;
  368.                 r = GetRValue(pwc->clearColorRef);
  369.                 g = GetGValue(pwc->clearColorRef);
  370.                 b = GetBValue(pwc->clearColorRef);
  371.                 for (i=0; i<width; i++) {
  372.                     *lpb++ = b;
  373.                     *lpb++ = g;
  374.                     *lpb++ = r;
  375.                 }
  376.                 break;
  377.             case 4:
  378.                 lpdw = (LPDWORD)clearRow;
  379.                 dwColor = BGR32(GetRValue(pwc->clearColorRef),
  380.                                 GetGValue(pwc->clearColorRef),
  381.                                 GetBValue(pwc->clearColorRef));
  382.                 for (i=0; i<width; i++)
  383.                     *lpdw++ = dwColor;
  384.                 break;
  385.             default:
  386.                 break;
  387.             } /* switch */
  388.            
  389.             /* copy cleared row to other rows in buffer */
  390.             lpb = clearRow - pwfb->ScanWidth;
  391.             rowSize = width * bytesPerPixel;
  392.             for (i=1; i<height; i++) {
  393.                 memcpy(lpb, clearRow, rowSize);
  394.                 lpb -= pwfb->ScanWidth;
  395.             }
  396.         } /* not done */
  397.         mask &= ~BUFFER_BIT_BACK_LEFT;
  398.     } /* back buffer */
  399.  
  400.     /* front buffer */
  401.     if (mask & BUFFER_BIT_FRONT_LEFT) {
  402.         HDC DC = pwc->hDC;
  403.         HPEN Old_Pen = SelectObject(DC, pwc->clearPen);
  404.         HBRUSH Old_Brush = SelectObject(DC, pwc->clearBrush);
  405.         Rectangle(DC,
  406.                   x,
  407.                   FLIP(y) + 1,
  408.                   x + width + 1,
  409.                   FLIP(y) - height + 1);
  410.         SelectObject(DC, Old_Pen);
  411.         SelectObject(DC, Old_Brush);
  412.         mask &= ~BUFFER_BIT_FRONT_LEFT;
  413.     } /* front buffer */
  414.    
  415.     /* Call swrast if there is anything left to clear (like DEPTH) */
  416.     if (mask)
  417.         _swrast_Clear(ctx, mask);
  418.  
  419. #undef FLIP
  420. }
  421.  
  422.  
  423.  
  424. /**********************************************************************/
  425. /*****                   BUFFER Functions                         *****/
  426. /**********************************************************************/
  427.  
  428.  
  429.  
  430.  
  431. static void
  432. wmesa_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
  433. {
  434.     _mesa_delete_renderbuffer(ctx, rb);
  435. }
  436.  
  437.  
  438. /**
  439.  * This is called by Mesa whenever it determines that the window size
  440.  * has changed.  Do whatever's needed to cope with that.
  441.  */
  442. static GLboolean
  443. wmesa_renderbuffer_storage(struct gl_context *ctx,
  444.                            struct gl_renderbuffer *rb,
  445.                            GLenum internalFormat,
  446.                            GLuint width,
  447.                            GLuint height)
  448. {
  449.     rb->Width = width;
  450.     rb->Height = height;
  451.     return GL_TRUE;
  452. }
  453.  
  454.  
  455. /**
  456.  * Called by ctx->Driver.ResizeBuffers()
  457.  * Resize the front/back colorbuffers to match the latest window size.
  458.  */
  459. static void
  460. wmesa_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *buffer,
  461.                      GLuint width, GLuint height)
  462. {
  463.     WMesaFramebuffer pwfb = wmesa_framebuffer(buffer);
  464.  
  465.     if (pwfb->Base.Width != width || pwfb->Base.Height != height) {
  466.         /* Realloc back buffer */
  467.         if (ctx->Visual.doubleBufferMode == 1) {
  468.             wmDeleteBackingStore(pwfb);
  469.             wmCreateBackingStore(pwfb, width, height);
  470.         }
  471.     }
  472.     _mesa_resize_framebuffer(ctx, buffer, width, height);
  473. }
  474.  
  475.  
  476. /**
  477.  * Called by glViewport.
  478.  * This is a good time for us to poll the current window size and adjust
  479.  * our renderbuffers to match the current window size.
  480.  * Remember, we have no opportunity to respond to conventional
  481.  * resize events since the driver has no event loop.
  482.  * Thus, we poll.
  483.  * MakeCurrent also ends up making a call here, so that ensures
  484.  * we get the viewport set correctly, even if the app does not call
  485.  * glViewport and relies on the defaults.
  486.  */
  487. static void wmesa_viewport(struct gl_context *ctx,
  488.                            GLint x, GLint y,
  489.                            GLsizei width, GLsizei height)
  490. {
  491.     GLuint new_width, new_height;
  492.  
  493.     wmesa_get_buffer_size(ctx->WinSysDrawBuffer, &new_width, &new_height);
  494.  
  495.     /**
  496.      * Resize buffers if the window size changed.
  497.      */
  498.     wmesa_resize_buffers(ctx, ctx->WinSysDrawBuffer, new_width, new_height);
  499.     ctx->NewState |= _NEW_BUFFERS;  /* to update scissor / window bounds */
  500. }
  501.  
  502.  
  503.  
  504.  
  505. /**
  506.  * Called when the driver should update it's state, based on the new_state
  507.  * flags.
  508.  */
  509. static void wmesa_update_state(struct gl_context *ctx, GLuint new_state)
  510. {
  511.     _swrast_InvalidateState(ctx, new_state);
  512.     _swsetup_InvalidateState(ctx, new_state);
  513.     _vbo_InvalidateState(ctx, new_state);
  514.     _tnl_InvalidateState(ctx, new_state);
  515.  
  516.     /* TODO - This code is not complete yet because I
  517.      * don't know what to do for all state updates.
  518.      */
  519.  
  520.     if (new_state & _NEW_BUFFERS) {
  521.     }
  522. }
  523.  
  524.  
  525.  
  526.  
  527.  
  528. /**********************************************************************/
  529. /*****                   WMESA Functions                          *****/
  530. /**********************************************************************/
  531.  
  532. WMesaContext WMesaCreateContext(HDC hDC,
  533.                                 HPALETTE* Pal,
  534.                                 GLboolean rgb_flag,
  535.                                 GLboolean db_flag,
  536.                                 GLboolean alpha_flag)
  537. {
  538.     WMesaContext c;
  539.     struct dd_function_table functions;
  540.     GLint red_bits, green_bits, blue_bits, alpha_bits;
  541.     struct gl_context *ctx;
  542.     struct gl_config *visual;
  543.  
  544.     (void) Pal;
  545.    
  546.     /* Indexed mode not supported */
  547.     if (!rgb_flag)
  548.         return NULL;
  549.  
  550.     /* Allocate wmesa context */
  551.     c = CALLOC_STRUCT(wmesa_context);
  552.     if (!c)
  553.         return NULL;
  554.  
  555. #if 0
  556.     /* I do not understand this contributed code */
  557.     /* Support memory and device contexts */
  558.     if(WindowFromDC(hDC) != NULL) {
  559.         c->hDC = GetDC(WindowFromDC(hDC)); /* huh ???? */
  560.     }
  561.     else {
  562.         c->hDC = hDC;
  563.     }
  564. #else
  565.     c->hDC = hDC;
  566. #endif
  567.  
  568.     /* Get data for visual */
  569.     /* Dealing with this is actually a bit of overkill because Mesa will end
  570.      * up treating all color component size requests less than 8 by using
  571.      * a single byte per channel.  In addition, the interface to the span
  572.      * routines passes colors as an entire byte per channel anyway, so there
  573.      * is nothing to be saved by telling the visual to be 16 bits if the device
  574.      * is 16 bits.  That is, Mesa is going to compute colors down to 8 bits per
  575.      * channel anyway.
  576.      * But we go through the motions here anyway.
  577.      */
  578.     switch (GetDeviceCaps(c->hDC, BITSPIXEL)) {
  579.     case 16:
  580.         red_bits = green_bits = blue_bits = 5;
  581.         alpha_bits = 0;
  582.         break;
  583.     default:
  584.         red_bits = green_bits = blue_bits = 8;
  585.         alpha_bits = 8;
  586.         break;
  587.     }
  588.     /* Create visual based on flags */
  589.     visual = _mesa_create_visual(db_flag,    /* db_flag */
  590.                                  GL_FALSE,   /* stereo */
  591.                                  red_bits, green_bits, blue_bits, /* color RGB */
  592.                                  alpha_flag ? alpha_bits : 0, /* color A */
  593.                                  DEFAULT_SOFTWARE_DEPTH_BITS, /* depth_bits */
  594.                                  8,          /* stencil_bits */
  595.                                  16,16,16,   /* accum RGB */
  596.                                  alpha_flag ? 16 : 0, /* accum A */
  597.                                  1);         /* num samples */
  598.    
  599.     if (!visual) {
  600.         free(c);
  601.         return NULL;
  602.     }
  603.  
  604.     /* Set up driver functions */
  605.     _mesa_init_driver_functions(&functions);
  606.     functions.GetString = wmesa_get_string;
  607.     functions.UpdateState = wmesa_update_state;
  608.     functions.Flush = wmesa_flush;
  609.     functions.Clear = clear;
  610.     functions.ResizeBuffers = wmesa_resize_buffers;
  611.     functions.Viewport = wmesa_viewport;
  612.  
  613.     /* initialize the Mesa context data */
  614.     ctx = &c->gl_ctx;
  615.     _mesa_initialize_context(ctx, API_OPENGL_COMPAT, visual,
  616.                              NULL, &functions);
  617.  
  618.     /* visual no longer needed - it was copied by _mesa_initialize_context() */
  619.     _mesa_destroy_visual(visual);
  620.  
  621.     _mesa_enable_sw_extensions(ctx);
  622.  
  623.     _mesa_meta_init(ctx);
  624.  
  625.     /* Initialize the software rasterizer and helper modules. */
  626.     if (!_swrast_CreateContext(ctx) ||
  627.         !_vbo_CreateContext(ctx) ||
  628.         !_tnl_CreateContext(ctx) ||
  629.         !_swsetup_CreateContext(ctx)) {
  630.         _mesa_free_context_data(ctx);
  631.         free(c);
  632.         return NULL;
  633.     }
  634.     _swsetup_Wakeup(ctx);
  635.     TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
  636.  
  637.     _mesa_compute_version(ctx);
  638.  
  639.     /* Exec table initialization requires the version to be computed */
  640.     _mesa_initialize_dispatch_tables(ctx);
  641.     _mesa_initialize_vbo_vtxfmt(ctx);
  642.  
  643.     return c;
  644. }
  645.  
  646.  
  647. void WMesaDestroyContext( WMesaContext pwc )
  648. {
  649.     struct gl_context *ctx = &pwc->gl_ctx;
  650.     WMesaFramebuffer pwfb;
  651.     GET_CURRENT_CONTEXT(cur_ctx);
  652.  
  653.     if (cur_ctx == ctx) {
  654.         /* unbind current if deleting current context */
  655.         WMesaMakeCurrent(NULL, NULL);
  656.     }
  657.  
  658.     /* clean up frame buffer resources */
  659.     pwfb = wmesa_lookup_framebuffer(pwc->hDC);
  660.     if (pwfb) {
  661.         if (ctx->Visual.doubleBufferMode == 1)
  662.             wmDeleteBackingStore(pwfb);
  663.         wmesa_free_framebuffer(pwc->hDC);
  664.     }
  665.  
  666.     /* Release for device, not memory contexts */
  667.     if (WindowFromDC(pwc->hDC) != NULL)
  668.     {
  669.       ReleaseDC(WindowFromDC(pwc->hDC), pwc->hDC);
  670.     }
  671.     DeleteObject(pwc->clearPen);
  672.     DeleteObject(pwc->clearBrush);
  673.    
  674.     _mesa_meta_free(ctx);
  675.  
  676.     _swsetup_DestroyContext(ctx);
  677.     _tnl_DestroyContext(ctx);
  678.     _vbo_DestroyContext(ctx);
  679.     _swrast_DestroyContext(ctx);
  680.    
  681.     _mesa_free_context_data(ctx);
  682.     free(pwc);
  683. }
  684.  
  685.  
  686. /**
  687.  * Create a new color renderbuffer.
  688.  */
  689. static struct gl_renderbuffer *
  690. wmesa_new_renderbuffer(void)
  691. {
  692.     struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
  693.     if (!rb)
  694.         return NULL;
  695.  
  696.     _mesa_init_renderbuffer(rb, (GLuint)0);
  697.    
  698.     rb->_BaseFormat = GL_RGBA;
  699.     rb->InternalFormat = GL_RGBA;
  700.     rb->Delete = wmesa_delete_renderbuffer;
  701.     rb->AllocStorage = wmesa_renderbuffer_storage;
  702.     return rb;
  703. }
  704.  
  705.  
  706. void WMesaMakeCurrent(WMesaContext c, HDC hdc)
  707. {
  708.     WMesaFramebuffer pwfb;
  709.  
  710.     {
  711.         /* return if already current */
  712.         GET_CURRENT_CONTEXT(ctx);
  713.         WMesaContext pwc = wmesa_context(ctx);
  714.         if (pwc && c == pwc && pwc->hDC == hdc)
  715.             return;
  716.     }
  717.  
  718.     pwfb = wmesa_lookup_framebuffer(hdc);
  719.  
  720.     /* Lazy creation of framebuffers */
  721.     if (c && !pwfb && hdc) {
  722.         struct gl_renderbuffer *rb;
  723.         struct gl_config *visual = &c->gl_ctx.Visual;
  724.         GLuint width, height;
  725.  
  726.         get_window_size(hdc, &width, &height);
  727.  
  728.         c->clearPen = CreatePen(PS_SOLID, 1, 0);
  729.         c->clearBrush = CreateSolidBrush(0);
  730.  
  731.         pwfb = wmesa_new_framebuffer(hdc, visual);
  732.  
  733.         /* Create back buffer if double buffered */
  734.         if (visual->doubleBufferMode == 1) {
  735.             wmCreateBackingStore(pwfb, width, height);
  736.         }
  737.        
  738.         /* make render buffers */
  739.         if (visual->doubleBufferMode == 1) {
  740.             rb = wmesa_new_renderbuffer();
  741.             _mesa_add_renderbuffer(&pwfb->Base, BUFFER_BACK_LEFT, rb);
  742.         }
  743.         rb = wmesa_new_renderbuffer();
  744.         _mesa_add_renderbuffer(&pwfb->Base, BUFFER_FRONT_LEFT, rb);
  745.  
  746.         /* Let Mesa own the Depth, Stencil, and Accum buffers */
  747.         _swrast_add_soft_renderbuffers(&pwfb->Base,
  748.                                        GL_FALSE, /* color */
  749.                                        visual->depthBits > 0,
  750.                                        visual->stencilBits > 0,
  751.                                        visual->accumRedBits > 0,
  752.                                        visual->alphaBits >0,
  753.                                        GL_FALSE);
  754.     }
  755.  
  756.     if (c && pwfb)
  757.         _mesa_make_current(&c->gl_ctx, &pwfb->Base, &pwfb->Base);
  758.     else
  759.         _mesa_make_current(NULL, NULL, NULL);
  760. }
  761.  
  762.  
  763. void WMesaSwapBuffers( HDC hdc )
  764. {
  765.     GET_CURRENT_CONTEXT(ctx);
  766.     WMesaContext pwc = wmesa_context(ctx);
  767.     WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(hdc);
  768.  
  769.     if (!pwfb) {
  770.         _mesa_problem(NULL, "wmesa: swapbuffers on unknown hdc");
  771.         return;
  772.     }
  773.  
  774.     /* If we're swapping the buffer associated with the current context
  775.      * we have to flush any pending rendering commands first.
  776.      */
  777.     if (pwc->hDC == hdc) {
  778.         _mesa_notifySwapBuffers(ctx);
  779.  
  780.         BitBlt(pwfb->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height,
  781.                pwfb->dib_hDC, 0, 0, SRCCOPY);
  782.     }
  783.     else {
  784.         /* XXX for now only allow swapping current window */
  785.         _mesa_problem(NULL, "wmesa: can't swap non-current window");
  786.     }
  787. }
  788.  
  789. void WMesaShareLists(WMesaContext ctx_to_share, WMesaContext ctx)
  790. {
  791.         _mesa_share_state(&ctx->gl_ctx, &ctx_to_share->gl_ctx);
  792. }
  793.  
  794.