OSDN Git Service

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