wmesa.c revision a9cc078b0e4340d36da2fdef08d45987f8e67145
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 "context.h" 10#include "extensions.h" 11#include "framebuffer.h" 12#include "renderbuffer.h" 13#include "drivers/common/driverfuncs.h" 14#include "array_cache/acache.h" 15#include "swrast/swrast.h" 16#include "swrast_setup/swrast_setup.h" 17#include "tnl/tnl.h" 18#include "tnl/t_context.h" 19#include "tnl/t_pipeline.h" 20 21 22/* linked list of our Framebuffers (windows) */ 23static WMesaFramebuffer FirstFramebuffer = NULL; 24 25 26/** 27 * Create a new WMesaFramebuffer object which will correspond to the 28 * given HDC (Window handle). 29 */ 30WMesaFramebuffer 31wmesa_new_framebuffer(HDC hdc, GLvisual *visual) 32{ 33 WMesaFramebuffer pwfb 34 = (WMesaFramebuffer) malloc(sizeof(struct wmesa_framebuffer)); 35 if (pwfb) { 36 _mesa_initialize_framebuffer(&pwfb->Base, visual); 37 pwfb->hDC = hdc; 38 /* insert at head of list */ 39 pwfb->next = FirstFramebuffer; 40 FirstFramebuffer = pwfb; 41 } 42 return pwfb; 43} 44 45/** 46 * Given an hdc, free the corresponding WMesaFramebuffer 47 */ 48void 49wmesa_free_framebuffer(HDC hdc) 50{ 51 WMesaFramebuffer pwfb, prev; 52 for (pwfb = FirstFramebuffer; pwfb; pwfb = pwfb->next) { 53 if (pwfb->hDC == hdc) 54 break; 55 prev = pwfb; 56 } 57 if (pwfb) { 58 if (pwfb == FirstFramebuffer) 59 FirstFramebuffer = pwfb->next; 60 else 61 prev->next = pwfb->next; 62 free(pwfb); 63 } 64} 65 66/** 67 * Given an hdc, return the corresponding WMesaFramebuffer 68 */ 69WMesaFramebuffer 70wmesa_lookup_framebuffer(HDC hdc) 71{ 72 WMesaFramebuffer pwfb; 73 for (pwfb = FirstFramebuffer; pwfb; pwfb = pwfb->next) { 74 if (pwfb->hDC == hdc) 75 return pwfb; 76 } 77 return NULL; 78} 79 80 81/** 82 * Given a GLframebuffer, return the corresponding WMesaFramebuffer. 83 */ 84static WMesaFramebuffer wmesa_framebuffer(GLframebuffer *fb) 85{ 86 return (WMesaFramebuffer) fb; 87} 88 89 90/** 91 * Given a GLcontext, return the corresponding WMesaContext. 92 */ 93static WMesaContext wmesa_context(const GLcontext *ctx) 94{ 95 return (WMesaContext) ctx; 96} 97 98 99/* 100 * Every driver should implement a GetString function in order to 101 * return a meaningful GL_RENDERER string. 102 */ 103static const GLubyte *wmesa_get_string(GLcontext *ctx, GLenum name) 104{ 105 return (name == GL_RENDERER) ? 106 (GLubyte *) "Mesa Windows GDI Driver" : NULL; 107} 108 109 110/* 111 * Determine the pixel format based on the pixel size. 112 */ 113static void wmSetPixelFormat(WMesaFramebuffer pwfb, HDC hDC) 114{ 115 pwfb->cColorBits = GetDeviceCaps(hDC, BITSPIXEL); 116 117 // Only 16 and 32 bit targets are supported now 118 assert(pwfb->cColorBits == 0 || 119 pwfb->cColorBits == 16 || 120 pwfb->cColorBits == 32); 121 122 switch(pwfb->cColorBits){ 123 case 8: 124 pwfb->pixelformat = PF_INDEX8; 125 break; 126 case 16: 127 pwfb->pixelformat = PF_5R6G5B; 128 break; 129 case 32: 130 pwfb->pixelformat = PF_8R8G8B; 131 break; 132 default: 133 pwfb->pixelformat = PF_BADFORMAT; 134 } 135} 136 137 138/** 139 * Create DIB for back buffer. 140 * We write into this memory with the span routines and then blit it 141 * to the window on a buffer swap. 142 */ 143BOOL wmCreateBackingStore(WMesaFramebuffer pwfb, long lxSize, long lySize) 144{ 145 HDC hdc = pwfb->hDC; 146 LPBITMAPINFO pbmi = &(pwfb->bmi); 147 HDC hic; 148 149 pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 150 pbmi->bmiHeader.biWidth = lxSize; 151 pbmi->bmiHeader.biHeight= -lySize; 152 pbmi->bmiHeader.biPlanes = 1; 153 pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwfb->hDC, BITSPIXEL); 154 pbmi->bmiHeader.biCompression = BI_RGB; 155 pbmi->bmiHeader.biSizeImage = 0; 156 pbmi->bmiHeader.biXPelsPerMeter = 0; 157 pbmi->bmiHeader.biYPelsPerMeter = 0; 158 pbmi->bmiHeader.biClrUsed = 0; 159 pbmi->bmiHeader.biClrImportant = 0; 160 161 pwfb->cColorBits = pbmi->bmiHeader.biBitCount; 162 pwfb->ScanWidth = (lxSize * (pwfb->cColorBits / 8) + 3) & ~3; 163 164 hic = CreateIC("display", NULL, NULL, NULL); 165 pwfb->dib_hDC = CreateCompatibleDC(hic); 166 167 pwfb->hbmDIB = CreateDIBSection(hic, 168 &pwfb->bmi, 169 DIB_RGB_COLORS, 170 (void **)&(pwfb->pbPixels), 171 0, 172 0); 173 pwfb->hOldBitmap = SelectObject(pwfb->dib_hDC, pwfb->hbmDIB); 174 175 DeleteDC(hic); 176 177 wmSetPixelFormat(pwfb, pwfb->hDC); 178 return TRUE; 179} 180 181 182static wmDeleteBackingStore(WMesaFramebuffer pwfb) 183{ 184 if (pwfb->hbmDIB) { 185 SelectObject(pwfb->dib_hDC, pwfb->hOldBitmap); 186 DeleteDC(pwfb->dib_hDC); 187 DeleteObject(pwfb->hbmDIB); 188 } 189} 190 191 192/** 193 * Find the width and height of the window named by hdc. 194 */ 195static void 196get_window_size(HDC hdc, GLuint *width, GLuint *height) 197{ 198 if (WindowFromDC(hdc)) { 199 RECT rect; 200 GetClientRect(WindowFromDC(hdc), &rect); 201 *width = rect.right - rect.left; 202 *height = rect.bottom - rect.top; 203 } 204 else { /* Memory context */ 205 /* From contributed code - use the size of the desktop 206 * for the size of a memory context (?) */ 207 *width = GetDeviceCaps(hdc, HORZRES); 208 *height = GetDeviceCaps(hdc, VERTRES); 209 } 210} 211 212 213static void 214wmesa_get_buffer_size(GLframebuffer *buffer, GLuint *width, GLuint *height) 215{ 216 WMesaFramebuffer pwfb = wmesa_framebuffer(buffer); 217 get_window_size(pwfb->hDC, width, height); 218} 219 220 221static void wmesa_flush(GLcontext *ctx) 222{ 223 WMesaContext pwc = wmesa_context(ctx); 224 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->WinSysDrawBuffer); 225 226 if (ctx->Visual.doubleBufferMode == 1) { 227 BitBlt(pwfb->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height, 228 pwfb->dib_hDC, 0, 0, SRCCOPY); 229 } 230 else { 231 /* Do nothing for single buffer */ 232 } 233} 234 235 236/**********************************************************************/ 237/***** CLEAR Functions *****/ 238/**********************************************************************/ 239 240/* If we do not implement these, Mesa clears the buffers via the pixel 241 * span writing interface, which is very slow for a clear operation. 242 */ 243 244/* 245 * Set the color index used to clear the color buffer. 246 */ 247static void clear_index(GLcontext *ctx, GLuint index) 248{ 249 WMesaContext pwc = wmesa_context(ctx); 250 /* Note that indexed mode is not supported yet */ 251 pwc->clearColorRef = RGB(0,0,0); 252} 253 254/* 255 * Set the color used to clear the color buffer. 256 */ 257static void clear_color(GLcontext *ctx, const GLfloat color[4]) 258{ 259 WMesaContext pwc = wmesa_context(ctx); 260 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 261 GLubyte col[3]; 262 UINT bytesPerPixel = pwfb->cColorBits / 8; 263 264 CLAMPED_FLOAT_TO_UBYTE(col[0], color[0]); 265 CLAMPED_FLOAT_TO_UBYTE(col[1], color[1]); 266 CLAMPED_FLOAT_TO_UBYTE(col[2], color[2]); 267 pwc->clearColorRef = RGB(col[0], col[1], col[2]); 268 DeleteObject(pwc->clearPen); 269 DeleteObject(pwc->clearBrush); 270 pwc->clearPen = CreatePen(PS_SOLID, 1, pwc->clearColorRef); 271 pwc->clearBrush = CreateSolidBrush(pwc->clearColorRef); 272} 273 274 275/* 276 * Clear the specified region of the color buffer using the clear color 277 * or index as specified by one of the two functions above. 278 * 279 * This procedure clears either the front and/or the back COLOR buffers. 280 * Only the "left" buffer is cleared since we are not stereo. 281 * Clearing of the other non-color buffers is left to the swrast. 282 */ 283 284static void clear(GLcontext *ctx, 285 GLbitfield mask, 286 GLboolean all, 287 GLint x, GLint y, 288 GLint width, GLint height) 289{ 290#define FLIP(Y) (ctx->DrawBuffer->Height - (Y) - 1) 291 292 WMesaContext pwc = wmesa_context(ctx); 293 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 294 int done = 0; 295 296 /* Let swrast do all the work if the masks are not set to 297 * clear all channels. */ 298 if (ctx->Color.ColorMask[0] != 0xff || 299 ctx->Color.ColorMask[1] != 0xff || 300 ctx->Color.ColorMask[2] != 0xff || 301 ctx->Color.ColorMask[3] != 0xff) { 302 _swrast_Clear(ctx, mask, all, x, y, width, height); 303 return; 304 } 305 306 /* Back buffer */ 307 if (mask & BUFFER_BIT_BACK_LEFT) { 308 309 int i, rowSize; 310 UINT bytesPerPixel = pwfb->cColorBits / 8; 311 LPBYTE lpb, clearRow; 312 LPWORD lpw; 313 BYTE bColor; 314 WORD wColor; 315 BYTE r, g, b; 316 DWORD dwColor; 317 LPDWORD lpdw; 318 319 /* Try for a fast clear - clearing entire buffer with a single 320 * byte value. */ 321 if (all) { /* entire buffer */ 322 /* Now check for an easy clear value */ 323 switch (bytesPerPixel) { 324 case 1: 325 bColor = BGR8(GetRValue(pwc->clearColorRef), 326 GetGValue(pwc->clearColorRef), 327 GetBValue(pwc->clearColorRef)); 328 memset(pwfb->pbPixels, bColor, 329 pwfb->ScanWidth * height); 330 done = 1; 331 break; 332 case 2: 333 wColor = BGR16(GetRValue(pwc->clearColorRef), 334 GetGValue(pwc->clearColorRef), 335 GetBValue(pwc->clearColorRef)); 336 if (((wColor >> 8) & 0xff) == (wColor & 0xff)) { 337 memset(pwfb->pbPixels, wColor & 0xff, 338 pwfb->ScanWidth * height); 339 done = 1; 340 } 341 break; 342 case 3: 343 /* fall through */ 344 case 4: 345 if (GetRValue(pwc->clearColorRef) == 346 GetGValue(pwc->clearColorRef) && 347 GetRValue(pwc->clearColorRef) == 348 GetBValue(pwc->clearColorRef)) { 349 memset(pwfb->pbPixels, 350 GetRValue(pwc->clearColorRef), 351 pwfb->ScanWidth * height); 352 done = 1; 353 } 354 break; 355 default: 356 break; 357 } 358 } /* all */ 359 360 if (!done) { 361 /* Need to clear a row at a time. Begin by setting the first 362 * row in the area to be cleared to the clear color. */ 363 364 clearRow = pwfb->pbPixels + 365 pwfb->ScanWidth * FLIP(y) + 366 bytesPerPixel * x; 367 switch (bytesPerPixel) { 368 case 1: 369 lpb = clearRow; 370 bColor = BGR8(GetRValue(pwc->clearColorRef), 371 GetGValue(pwc->clearColorRef), 372 GetBValue(pwc->clearColorRef)); 373 memset(lpb, bColor, width); 374 break; 375 case 2: 376 lpw = (LPWORD)clearRow; 377 wColor = BGR16(GetRValue(pwc->clearColorRef), 378 GetGValue(pwc->clearColorRef), 379 GetBValue(pwc->clearColorRef)); 380 for (i=0; i<width; i++) 381 *lpw++ = wColor; 382 break; 383 case 3: 384 lpb = clearRow; 385 r = GetRValue(pwc->clearColorRef); 386 g = GetGValue(pwc->clearColorRef); 387 b = GetBValue(pwc->clearColorRef); 388 for (i=0; i<width; i++) { 389 *lpb++ = b; 390 *lpb++ = g; 391 *lpb++ = r; 392 } 393 break; 394 case 4: 395 lpdw = (LPDWORD)clearRow; 396 dwColor = BGR32(GetRValue(pwc->clearColorRef), 397 GetGValue(pwc->clearColorRef), 398 GetBValue(pwc->clearColorRef)); 399 for (i=0; i<width; i++) 400 *lpdw++ = dwColor; 401 break; 402 default: 403 break; 404 } /* switch */ 405 406 /* copy cleared row to other rows in buffer */ 407 lpb = clearRow - pwfb->ScanWidth; 408 rowSize = width * bytesPerPixel; 409 for (i=1; i<height; i++) { 410 memcpy(lpb, clearRow, rowSize); 411 lpb -= pwfb->ScanWidth; 412 } 413 } /* not done */ 414 mask &= ~BUFFER_BIT_BACK_LEFT; 415 } /* back buffer */ 416 417 /* front buffer */ 418 if (mask & BUFFER_BIT_FRONT_LEFT) { 419 HDC DC = pwc->hDC; 420 HPEN Old_Pen = SelectObject(DC, pwc->clearPen); 421 HBRUSH Old_Brush = SelectObject(DC, pwc->clearBrush); 422 Rectangle(DC, 423 x, 424 FLIP(y) + 1, 425 x + width + 1, 426 FLIP(y) - height + 1); 427 SelectObject(DC, Old_Pen); 428 SelectObject(DC, Old_Brush); 429 mask &= ~BUFFER_BIT_FRONT_LEFT; 430 } /* front buffer */ 431 432 /* Call swrast if there is anything left to clear (like DEPTH) */ 433 if (mask) 434 _swrast_Clear(ctx, mask, all, x, y, width, height); 435 436#undef FLIP 437} 438 439 440/**********************************************************************/ 441/***** PIXEL Functions *****/ 442/**********************************************************************/ 443 444#define FLIP(Y) (rb->Height - (Y) - 1) 445 446 447/** 448 ** Front Buffer reading/writing 449 ** These are slow, but work with all non-indexed visual types. 450 **/ 451 452/* Write a horizontal span of RGBA color pixels with a boolean mask. */ 453static void write_rgba_span_front(const GLcontext *ctx, 454 struct gl_renderbuffer *rb, 455 GLuint n, GLint x, GLint y, 456 const GLubyte rgba[][4], 457 const GLubyte mask[] ) 458{ 459 WMesaContext pwc = wmesa_context(ctx); 460 GLuint i; 461 462 (void) ctx; 463 y=FLIP(y); 464 if (mask) { 465 for (i=0; i<n; i++) 466 if (mask[i]) 467 SetPixel(pwc->hDC, x+i, y, RGB(rgba[i][RCOMP], rgba[i][GCOMP], 468 rgba[i][BCOMP])); 469 } 470 else { 471 for (i=0; i<n; i++) 472 SetPixel(pwc->hDC, x+i, y, RGB(rgba[i][RCOMP], rgba[i][GCOMP], 473 rgba[i][BCOMP])); 474 } 475 476} 477 478/* Write a horizontal span of RGB color pixels with a boolean mask. */ 479static void write_rgb_span_front(const GLcontext *ctx, 480 struct gl_renderbuffer *rb, 481 GLuint n, GLint x, GLint y, 482 const GLubyte rgb[][3], 483 const GLubyte mask[] ) 484{ 485 WMesaContext pwc = wmesa_context(ctx); 486 GLuint i; 487 488 (void) ctx; 489 y=FLIP(y); 490 if (mask) { 491 for (i=0; i<n; i++) 492 if (mask[i]) 493 SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP], 494 rgb[i][BCOMP])); 495 } 496 else { 497 for (i=0; i<n; i++) 498 SetPixel(pwc->hDC, x+i, y, RGB(rgb[i][RCOMP], rgb[i][GCOMP], 499 rgb[i][BCOMP])); 500 } 501 502} 503 504/* 505 * Write a horizontal span of pixels with a boolean mask. The current color 506 * is used for all pixels. 507 */ 508static void write_mono_rgba_span_front(const GLcontext *ctx, 509 struct gl_renderbuffer *rb, 510 GLuint n, GLint x, GLint y, 511 const GLchan color[4], 512 const GLubyte mask[]) 513{ 514 GLuint i; 515 WMesaContext pwc = wmesa_context(ctx); 516 COLORREF colorref; 517 518 (void) ctx; 519 colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]); 520 y=FLIP(y); 521 if (mask) { 522 for (i=0; i<n; i++) 523 if (mask[i]) 524 SetPixel(pwc->hDC, x+i, y, colorref); 525 } 526 else 527 for (i=0; i<n; i++) 528 SetPixel(pwc->hDC, x+i, y, colorref); 529 530} 531 532/* Write an array of RGBA pixels with a boolean mask. */ 533static void write_rgba_pixels_front(const GLcontext *ctx, 534 struct gl_renderbuffer *rb, 535 GLuint n, 536 const GLint x[], const GLint y[], 537 const GLubyte rgba[][4], 538 const GLubyte mask[] ) 539{ 540 GLuint i; 541 WMesaContext pwc = wmesa_context(ctx); 542 (void) ctx; 543 for (i=0; i<n; i++) 544 if (mask[i]) 545 SetPixel(pwc->hDC, x[i], FLIP(y[i]), 546 RGB(rgba[i][RCOMP], rgba[i][GCOMP], 547 rgba[i][BCOMP])); 548} 549 550 551 552/* 553 * Write an array of pixels with a boolean mask. The current color 554 * is used for all pixels. 555 */ 556static void write_mono_rgba_pixels_front(const GLcontext *ctx, 557 struct gl_renderbuffer *rb, 558 GLuint n, 559 const GLint x[], const GLint y[], 560 const GLchan color[4], 561 const GLubyte mask[] ) 562{ 563 GLuint i; 564 WMesaContext pwc = wmesa_context(ctx); 565 COLORREF colorref; 566 (void) ctx; 567 colorref = RGB(color[RCOMP], color[GCOMP], color[BCOMP]); 568 for (i=0; i<n; i++) 569 if (mask[i]) 570 SetPixel(pwc->hDC, x[i], FLIP(y[i]), colorref); 571} 572 573/* Read a horizontal span of color pixels. */ 574static void read_rgba_span_front(const GLcontext *ctx, 575 struct gl_renderbuffer *rb, 576 GLuint n, GLint x, GLint y, 577 GLubyte rgba[][4] ) 578{ 579 WMesaContext pwc = wmesa_context(ctx); 580 GLuint i; 581 COLORREF Color; 582 y = FLIP(y); 583 for (i=0; i<n; i++) { 584 Color = GetPixel(pwc->hDC, x+i, y); 585 rgba[i][RCOMP] = GetRValue(Color); 586 rgba[i][GCOMP] = GetGValue(Color); 587 rgba[i][BCOMP] = GetBValue(Color); 588 rgba[i][ACOMP] = 255; 589 } 590} 591 592 593/* Read an array of color pixels. */ 594static void read_rgba_pixels_front(const GLcontext *ctx, 595 struct gl_renderbuffer *rb, 596 GLuint n, const GLint x[], const GLint y[], 597 GLubyte rgba[][4]) 598{ 599 WMesaContext pwc = wmesa_context(ctx); 600 GLuint i; 601 COLORREF Color; 602 for (i=0; i<n; i++) { 603 GLint y2 = FLIP(y[i]); 604 Color = GetPixel(pwc->hDC, x[i], y2); 605 rgba[i][RCOMP] = GetRValue(Color); 606 rgba[i][GCOMP] = GetGValue(Color); 607 rgba[i][BCOMP] = GetBValue(Color); 608 rgba[i][ACOMP] = 255; 609 } 610} 611 612/*********************************************************************/ 613 614/* DOUBLE BUFFER 32-bit */ 615 616#define WMSETPIXEL32(pwc, y, x, r, g, b) { \ 617LPDWORD lpdw = ((LPDWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \ 618*lpdw = BGR32((r),(g),(b)); } 619 620 621 622/* Write a horizontal span of RGBA color pixels with a boolean mask. */ 623static void write_rgba_span_32(const GLcontext *ctx, 624 struct gl_renderbuffer *rb, 625 GLuint n, GLint x, GLint y, 626 const GLubyte rgba[][4], 627 const GLubyte mask[] ) 628{ 629 WMesaContext pwc = wmesa_context(ctx); 630 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 631 GLuint i; 632 LPDWORD lpdw; 633 634 (void) ctx; 635 636 y=FLIP(y); 637 lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x; 638 if (mask) { 639 for (i=0; i<n; i++) 640 if (mask[i]) 641 lpdw[i] = BGR32(rgba[i][RCOMP], rgba[i][GCOMP], 642 rgba[i][BCOMP]); 643 } 644 else { 645 for (i=0; i<n; i++) 646 *lpdw++ = BGR32(rgba[i][RCOMP], rgba[i][GCOMP], 647 rgba[i][BCOMP]); 648 } 649} 650 651 652/* Write a horizontal span of RGB color pixels with a boolean mask. */ 653static void write_rgb_span_32(const GLcontext *ctx, 654 struct gl_renderbuffer *rb, 655 GLuint n, GLint x, GLint y, 656 const GLubyte rgb[][3], 657 const GLubyte mask[] ) 658{ 659 WMesaContext pwc = wmesa_context(ctx); 660 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 661 GLuint i; 662 LPDWORD lpdw; 663 664 (void) ctx; 665 666 y=FLIP(y); 667 lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x; 668 if (mask) { 669 for (i=0; i<n; i++) 670 if (mask[i]) 671 lpdw[i] = BGR32(rgb[i][RCOMP], rgb[i][GCOMP], 672 rgb[i][BCOMP]); 673 } 674 else { 675 for (i=0; i<n; i++) 676 *lpdw++ = BGR32(rgb[i][RCOMP], rgb[i][GCOMP], 677 rgb[i][BCOMP]); 678 } 679} 680 681/* 682 * Write a horizontal span of pixels with a boolean mask. The current color 683 * is used for all pixels. 684 */ 685static void write_mono_rgba_span_32(const GLcontext *ctx, 686 struct gl_renderbuffer *rb, 687 GLuint n, GLint x, GLint y, 688 const GLchan color[4], 689 const GLubyte mask[]) 690{ 691 LPDWORD lpdw; 692 DWORD pixel; 693 GLuint i; 694 WMesaContext pwc = wmesa_context(ctx); 695 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 696 lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x; 697 y=FLIP(y); 698 pixel = BGR32(color[RCOMP], color[GCOMP], color[BCOMP]); 699 if (mask) { 700 for (i=0; i<n; i++) 701 if (mask[i]) 702 lpdw[i] = pixel; 703 } 704 else 705 for (i=0; i<n; i++) 706 *lpdw++ = pixel; 707 708} 709 710/* Write an array of RGBA pixels with a boolean mask. */ 711static void write_rgba_pixels_32(const GLcontext *ctx, 712 struct gl_renderbuffer *rb, 713 GLuint n, const GLint x[], const GLint y[], 714 const GLubyte rgba[][4], 715 const GLubyte mask[]) 716{ 717 GLuint i; 718 WMesaContext pwc = wmesa_context(ctx); 719 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 720 for (i=0; i<n; i++) 721 if (mask[i]) 722 WMSETPIXEL32(pwfb, FLIP(y[i]), x[i], 723 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); 724} 725 726/* 727 * Write an array of pixels with a boolean mask. The current color 728 * is used for all pixels. 729 */ 730static void write_mono_rgba_pixels_32(const GLcontext *ctx, 731 struct gl_renderbuffer *rb, 732 GLuint n, 733 const GLint x[], const GLint y[], 734 const GLchan color[4], 735 const GLubyte mask[]) 736{ 737 GLuint i; 738 WMesaContext pwc = wmesa_context(ctx); 739 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 740 for (i=0; i<n; i++) 741 if (mask[i]) 742 WMSETPIXEL32(pwfb, FLIP(y[i]),x[i],color[RCOMP], 743 color[GCOMP], color[BCOMP]); 744} 745 746/* Read a horizontal span of color pixels. */ 747static void read_rgba_span_32(const GLcontext *ctx, 748 struct gl_renderbuffer *rb, 749 GLuint n, GLint x, GLint y, 750 GLubyte rgba[][4] ) 751{ 752 GLuint i; 753 DWORD pixel; 754 LPDWORD lpdw; 755 WMesaContext pwc = wmesa_context(ctx); 756 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 757 758 y = FLIP(y); 759 lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x; 760 for (i=0; i<n; i++) { 761 pixel = lpdw[i]; 762 rgba[i][RCOMP] = (pixel & 0x00ff0000) >> 16; 763 rgba[i][GCOMP] = (pixel & 0x0000ff00) >> 8; 764 rgba[i][BCOMP] = (pixel & 0x000000ff); 765 rgba[i][ACOMP] = 255; 766 } 767} 768 769 770/* Read an array of color pixels. */ 771static void read_rgba_pixels_32(const GLcontext *ctx, 772 struct gl_renderbuffer *rb, 773 GLuint n, const GLint x[], const GLint y[], 774 GLubyte rgba[][4]) 775{ 776 GLuint i; 777 DWORD pixel; 778 LPDWORD lpdw; 779 WMesaContext pwc = wmesa_context(ctx); 780 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 781 782 for (i=0; i<n; i++) { 783 GLint y2 = FLIP(y[i]); 784 lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i]; 785 pixel = *lpdw; 786 rgba[i][RCOMP] = (pixel & 0x00ff0000) >> 16; 787 rgba[i][GCOMP] = (pixel & 0x0000ff00) >> 8; 788 rgba[i][BCOMP] = (pixel & 0x000000ff); 789 rgba[i][ACOMP] = 255; 790 } 791} 792 793 794/*********************************************************************/ 795 796/* DOUBLE BUFFER 16-bit */ 797 798#define WMSETPIXEL16(pwc, y, x, r, g, b) { \ 799LPWORD lpw = ((LPWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \ 800*lpw = BGR16((r),(g),(b)); } 801 802 803 804/* Write a horizontal span of RGBA color pixels with a boolean mask. */ 805static void write_rgba_span_16(const GLcontext *ctx, 806 struct gl_renderbuffer *rb, 807 GLuint n, GLint x, GLint y, 808 const GLubyte rgba[][4], 809 const GLubyte mask[] ) 810{ 811 WMesaContext pwc = wmesa_context(ctx); 812 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 813 GLuint i; 814 LPWORD lpw; 815 816 (void) ctx; 817 818 y=FLIP(y); 819 lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x; 820 if (mask) { 821 for (i=0; i<n; i++) 822 if (mask[i]) 823 lpw[i] = BGR16(rgba[i][RCOMP], rgba[i][GCOMP], 824 rgba[i][BCOMP]); 825 } 826 else { 827 for (i=0; i<n; i++) 828 *lpw++ = BGR16(rgba[i][RCOMP], rgba[i][GCOMP], 829 rgba[i][BCOMP]); 830 } 831} 832 833 834/* Write a horizontal span of RGB color pixels with a boolean mask. */ 835static void write_rgb_span_16(const GLcontext *ctx, 836 struct gl_renderbuffer *rb, 837 GLuint n, GLint x, GLint y, 838 const GLubyte rgb[][3], 839 const GLubyte mask[] ) 840{ 841 WMesaContext pwc = wmesa_context(ctx); 842 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 843 GLuint i; 844 LPWORD lpw; 845 846 (void) ctx; 847 848 y=FLIP(y); 849 lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x; 850 if (mask) { 851 for (i=0; i<n; i++) 852 if (mask[i]) 853 lpw[i] = BGR16(rgb[i][RCOMP], rgb[i][GCOMP], 854 rgb[i][BCOMP]); 855 } 856 else { 857 for (i=0; i<n; i++) 858 *lpw++ = BGR16(rgb[i][RCOMP], rgb[i][GCOMP], 859 rgb[i][BCOMP]); 860 } 861} 862 863/* 864 * Write a horizontal span of pixels with a boolean mask. The current color 865 * is used for all pixels. 866 */ 867static void write_mono_rgba_span_16(const GLcontext *ctx, 868 struct gl_renderbuffer *rb, 869 GLuint n, GLint x, GLint y, 870 const GLchan color[4], 871 const GLubyte mask[]) 872{ 873 LPWORD lpw; 874 WORD pixel; 875 GLuint i; 876 WMesaContext pwc = wmesa_context(ctx); 877 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 878 (void) ctx; 879 lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x; 880 y=FLIP(y); 881 pixel = BGR16(color[RCOMP], color[GCOMP], color[BCOMP]); 882 if (mask) { 883 for (i=0; i<n; i++) 884 if (mask[i]) 885 lpw[i] = pixel; 886 } 887 else 888 for (i=0; i<n; i++) 889 *lpw++ = pixel; 890 891} 892 893/* Write an array of RGBA pixels with a boolean mask. */ 894static void write_rgba_pixels_16(const GLcontext *ctx, 895 struct gl_renderbuffer *rb, 896 GLuint n, const GLint x[], const GLint y[], 897 const GLubyte rgba[][4], 898 const GLubyte mask[]) 899{ 900 GLuint i; 901 WMesaContext pwc = wmesa_context(ctx); 902 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 903 (void) ctx; 904 for (i=0; i<n; i++) 905 if (mask[i]) 906 WMSETPIXEL16(pwfb, FLIP(y[i]), x[i], 907 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); 908} 909 910/* 911 * Write an array of pixels with a boolean mask. The current color 912 * is used for all pixels. 913 */ 914static void write_mono_rgba_pixels_16(const GLcontext *ctx, 915 struct gl_renderbuffer *rb, 916 GLuint n, 917 const GLint x[], const GLint y[], 918 const GLchan color[4], 919 const GLubyte mask[]) 920{ 921 GLuint i; 922 WMesaContext pwc = wmesa_context(ctx); 923 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 924 (void) ctx; 925 for (i=0; i<n; i++) 926 if (mask[i]) 927 WMSETPIXEL16(pwfb, FLIP(y[i]),x[i],color[RCOMP], 928 color[GCOMP], color[BCOMP]); 929} 930 931/* Read a horizontal span of color pixels. */ 932static void read_rgba_span_16(const GLcontext *ctx, 933 struct gl_renderbuffer *rb, 934 GLuint n, GLint x, GLint y, 935 GLubyte rgba[][4] ) 936{ 937 GLuint i, pixel; 938 LPWORD lpw; 939 WMesaContext pwc = wmesa_context(ctx); 940 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 941 942 y = FLIP(y); 943 lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x; 944 for (i=0; i<n; i++) { 945 pixel = lpw[i]; 946 /* Windows uses 5,5,5 for 16-bit */ 947 rgba[i][RCOMP] = (pixel & 0x7c00) >> 7; 948 rgba[i][GCOMP] = (pixel & 0x03e0) >> 2; 949 rgba[i][BCOMP] = (pixel & 0x001f) << 3; 950 rgba[i][ACOMP] = 255; 951 } 952} 953 954 955/* Read an array of color pixels. */ 956static void read_rgba_pixels_16(const GLcontext *ctx, 957 struct gl_renderbuffer *rb, 958 GLuint n, const GLint x[], const GLint y[], 959 GLubyte rgba[][4]) 960{ 961 GLuint i, pixel; 962 LPWORD lpw; 963 WMesaContext pwc = wmesa_context(ctx); 964 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 965 966 for (i=0; i<n; i++) { 967 GLint y2 = FLIP(y[i]); 968 lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i]; 969 pixel = *lpw; 970 /* Windows uses 5,5,5 for 16-bit */ 971 rgba[i][RCOMP] = (pixel & 0x7c00) >> 7; 972 rgba[i][GCOMP] = (pixel & 0x03e0) >> 2; 973 rgba[i][BCOMP] = (pixel & 0x001f) << 3; 974 rgba[i][ACOMP] = 255; 975 } 976} 977 978 979 980 981/**********************************************************************/ 982/***** BUFFER Functions *****/ 983/**********************************************************************/ 984 985 986 987 988static void 989wmesa_delete_renderbuffer(struct gl_renderbuffer *rb) 990{ 991 _mesa_free(rb); 992} 993 994 995/** 996 * This is called by Mesa whenever it determines that the window size 997 * has changed. Do whatever's needed to cope with that. 998 */ 999static GLboolean 1000wmesa_renderbuffer_storage(GLcontext *ctx, 1001 struct gl_renderbuffer *rb, 1002 GLenum internalFormat, 1003 GLuint width, 1004 GLuint height) 1005{ 1006 rb->Width = width; 1007 rb->Height = height; 1008 return GL_TRUE; 1009} 1010 1011 1012/** 1013 * Plug in the Get/PutRow/Values functions for a renderbuffer depending 1014 * on if we're drawing to the front or back color buffer. 1015 */ 1016void wmesa_set_renderbuffer_funcs(struct gl_renderbuffer *rb, int pixelformat, 1017 int double_buffer) 1018{ 1019 if (double_buffer) { 1020 /* back buffer */ 1021 /* Picking the correct span functions is important because 1022 * the DIB was allocated with the indicated depth. */ 1023 switch(pixelformat) { 1024 case PF_5R6G5B: 1025 rb->PutRow = write_rgba_span_16; 1026 rb->PutRowRGB = write_rgb_span_16; 1027 rb->PutMonoRow = write_mono_rgba_span_16; 1028 rb->PutValues = write_rgba_pixels_16; 1029 rb->PutMonoValues = write_mono_rgba_pixels_16; 1030 rb->GetRow = read_rgba_span_16; 1031 rb->GetValues = read_rgba_pixels_16; 1032 rb->RedBits = 5; 1033 rb->GreenBits = 6; 1034 rb->BlueBits = 5; 1035 break; 1036 case PF_8R8G8B: 1037 rb->PutRow = write_rgba_span_32; 1038 rb->PutRowRGB = write_rgb_span_32; 1039 rb->PutMonoRow = write_mono_rgba_span_32; 1040 rb->PutValues = write_rgba_pixels_32; 1041 rb->PutMonoValues = write_mono_rgba_pixels_32; 1042 rb->GetRow = read_rgba_span_32; 1043 rb->GetValues = read_rgba_pixels_32; 1044 rb->RedBits = 8; 1045 rb->GreenBits = 8; 1046 rb->BlueBits = 8; 1047 break; 1048 default: 1049 break; 1050 } 1051 } 1052 else { 1053 /* front buffer (actual Windows window) */ 1054 rb->PutRow = write_rgba_span_front; 1055 rb->PutRowRGB = write_rgb_span_front; 1056 rb->PutMonoRow = write_mono_rgba_span_front; 1057 rb->PutValues = write_rgba_pixels_front; 1058 rb->PutMonoValues = write_mono_rgba_pixels_front; 1059 rb->GetRow = read_rgba_span_front; 1060 rb->GetValues = read_rgba_pixels_front; 1061 rb->RedBits = 8; /* XXX fix these (565?) */ 1062 rb->GreenBits = 8; 1063 rb->BlueBits = 8; 1064 } 1065} 1066 1067/** 1068 * Called by ctx->Driver.ResizeBuffers() 1069 * Resize the front/back colorbuffers to match the latest window size. 1070 */ 1071static void 1072wmesa_resize_buffers(GLcontext *ctx, GLframebuffer *buffer, 1073 GLuint width, GLuint height) 1074{ 1075 WMesaContext pwc = wmesa_context(ctx); 1076 WMesaFramebuffer pwfb = wmesa_framebuffer(buffer); 1077 1078 if (pwfb->Base.Width != width || pwfb->Base.Height != height) { 1079 /* Realloc back buffer */ 1080 if (ctx->Visual.doubleBufferMode == 1) { 1081 wmDeleteBackingStore(pwfb); 1082 wmCreateBackingStore(pwfb, width, height); 1083 } 1084 } 1085 _mesa_resize_framebuffer(ctx, buffer, width, height); 1086} 1087 1088 1089/** 1090 * Called by glViewport. 1091 * This is a good time for us to poll the current window size and adjust 1092 * our renderbuffers to match the current window size. 1093 * Remember, we have no opportunity to respond to conventional 1094 * resize events since the driver has no event loop. 1095 * Thus, we poll. 1096 * MakeCurrent also ends up making a call here, so that ensures 1097 * we get the viewport set correctly, even if the app does not call 1098 * glViewport and relies on the defaults. 1099 */ 1100static void wmesa_viewport(GLcontext *ctx, 1101 GLint x, GLint y, 1102 GLsizei width, GLsizei height) 1103{ 1104 WMesaContext pwc = wmesa_context(ctx); 1105 GLuint new_width, new_height; 1106 1107 wmesa_get_buffer_size(ctx->WinSysDrawBuffer, &new_width, &new_height); 1108 1109 /** 1110 * Resize buffers if the window size changed. 1111 */ 1112 wmesa_resize_buffers(ctx, ctx->WinSysDrawBuffer, new_width, new_height); 1113 ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */ 1114} 1115 1116 1117 1118 1119/** 1120 * Called when the driver should update it's state, based on the new_state 1121 * flags. 1122 */ 1123static void wmesa_update_state(GLcontext *ctx, GLuint new_state) 1124{ 1125 _swrast_InvalidateState(ctx, new_state); 1126 _swsetup_InvalidateState(ctx, new_state); 1127 _ac_InvalidateState(ctx, new_state); 1128 _tnl_InvalidateState(ctx, new_state); 1129 1130 /* TODO - This code is not complete yet because I 1131 * don't know what to do for all state updates. 1132 */ 1133 1134 if (new_state & _NEW_BUFFERS) { 1135 } 1136} 1137 1138 1139 1140 1141 1142/**********************************************************************/ 1143/***** WMESA Functions *****/ 1144/**********************************************************************/ 1145 1146WMesaContext WMesaCreateContext(HDC hDC, 1147 HPALETTE* Pal, 1148 GLboolean rgb_flag, 1149 GLboolean db_flag, 1150 GLboolean alpha_flag) 1151{ 1152 WMesaContext c; 1153 struct dd_function_table functions; 1154 GLint red_bits, green_bits, blue_bits, alpha_bits; 1155 GLcontext *ctx; 1156 GLvisual *visual; 1157 1158 (void) Pal; 1159 1160 /* Indexed mode not supported */ 1161 if (!rgb_flag) 1162 return NULL; 1163 1164 /* Allocate wmesa context */ 1165 c = CALLOC_STRUCT(wmesa_context); 1166 if (!c) 1167 return NULL; 1168 1169#if 0 1170 /* I do not understand this contributed code */ 1171 /* Support memory and device contexts */ 1172 if(WindowFromDC(hDC) != NULL) { 1173 c->hDC = GetDC(WindowFromDC(hDC)); // huh ???? 1174 } 1175 else { 1176 c->hDC = hDC; 1177 } 1178#else 1179 c->hDC = hDC; 1180#endif 1181 1182 /* Get data for visual */ 1183 /* Dealing with this is actually a bit of overkill because Mesa will end 1184 * up treating all color component size requests less than 8 by using 1185 * a single byte per channel. In addition, the interface to the span 1186 * routines passes colors as an entire byte per channel anyway, so there 1187 * is nothing to be saved by telling the visual to be 16 bits if the device 1188 * is 16 bits. That is, Mesa is going to compute colors down to 8 bits per 1189 * channel anyway. 1190 * But we go through the motions here anyway. 1191 */ 1192 switch (GetDeviceCaps(c->hDC, BITSPIXEL)) { 1193 case 16: 1194 red_bits = green_bits = blue_bits = 5; 1195 alpha_bits = 0; 1196 break; 1197 default: 1198 red_bits = green_bits = blue_bits = 8; 1199 alpha_bits = 8; 1200 break; 1201 } 1202 /* Create visual based on flags */ 1203 visual = _mesa_create_visual(rgb_flag, 1204 db_flag, /* db_flag */ 1205 GL_FALSE, /* stereo */ 1206 red_bits, green_bits, blue_bits, /* color RGB */ 1207 alpha_flag ? alpha_bits : 0, /* color A */ 1208 0, /* index bits */ 1209 DEFAULT_SOFTWARE_DEPTH_BITS, /* depth_bits */ 1210 8, /* stencil_bits */ 1211 16,16,16, /* accum RGB */ 1212 alpha_flag ? 16 : 0, /* accum A */ 1213 1); /* num samples */ 1214 1215 if (!visual) { 1216 _mesa_free(c); 1217 return NULL; 1218 } 1219 1220 /* Set up driver functions */ 1221 _mesa_init_driver_functions(&functions); 1222 functions.GetString = wmesa_get_string; 1223 functions.UpdateState = wmesa_update_state; 1224 functions.GetBufferSize = wmesa_get_buffer_size; 1225 functions.Flush = wmesa_flush; 1226 functions.Clear = clear; 1227 functions.ClearIndex = clear_index; 1228 functions.ClearColor = clear_color; 1229 functions.ResizeBuffers = wmesa_resize_buffers; 1230 functions.Viewport = wmesa_viewport; 1231 1232 /* initialize the Mesa context data */ 1233 ctx = &c->gl_ctx; 1234 _mesa_initialize_context(ctx, visual, NULL, &functions, (void *)c); 1235 1236 _mesa_enable_sw_extensions(ctx); 1237 _mesa_enable_1_3_extensions(ctx); 1238 _mesa_enable_1_4_extensions(ctx); 1239 _mesa_enable_1_5_extensions(ctx); 1240 _mesa_enable_2_0_extensions(ctx); 1241 1242 /* Initialize the software rasterizer and helper modules. */ 1243 if (!_swrast_CreateContext(ctx) || 1244 !_ac_CreateContext(ctx) || 1245 !_tnl_CreateContext(ctx) || 1246 !_swsetup_CreateContext(ctx)) { 1247 _mesa_free_context_data(ctx); 1248 _mesa_free(c); 1249 return NULL; 1250 } 1251 _swsetup_Wakeup(ctx); 1252 TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline; 1253 1254 return c; 1255} 1256 1257 1258void WMesaDestroyContext( WMesaContext pwc ) 1259{ 1260 GLcontext *ctx = &pwc->gl_ctx; 1261 WMesaFramebuffer pwfb; 1262 GET_CURRENT_CONTEXT(cur_ctx); 1263 1264 if (cur_ctx == ctx) { 1265 /* unbind current if deleting current context */ 1266 WMesaMakeCurrent(NULL, NULL); 1267 } 1268 1269 /* clean up frame buffer resources */ 1270 pwfb = wmesa_lookup_framebuffer(pwc->hDC); 1271 if (pwfb) { 1272 if (ctx->Visual.doubleBufferMode == 1) 1273 wmDeleteBackingStore(pwfb); 1274 wmesa_free_framebuffer(pwc->hDC); 1275 } 1276 1277 /* Release for device, not memory contexts */ 1278 if (WindowFromDC(pwc->hDC) != NULL) 1279 { 1280 ReleaseDC(WindowFromDC(pwc->hDC), pwc->hDC); 1281 } 1282 DeleteObject(pwc->clearPen); 1283 DeleteObject(pwc->clearBrush); 1284 1285 _swsetup_DestroyContext(ctx); 1286 _tnl_DestroyContext(ctx); 1287 _ac_DestroyContext(ctx); 1288 _swrast_DestroyContext(ctx); 1289 1290 _mesa_free_context_data(ctx); 1291 _mesa_free(pwc); 1292} 1293 1294 1295/** 1296 * Create a new color renderbuffer. 1297 */ 1298struct gl_renderbuffer * 1299wmesa_new_renderbuffer(void) 1300{ 1301 struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer); 1302 if (!rb) 1303 return NULL; 1304 1305 _mesa_init_renderbuffer(rb, (GLuint)0); 1306 1307 rb->_BaseFormat = GL_RGBA; 1308 rb->InternalFormat = GL_RGBA; 1309 rb->DataType = CHAN_TYPE; 1310 rb->Delete = wmesa_delete_renderbuffer; 1311 rb->AllocStorage = wmesa_renderbuffer_storage; 1312 return rb; 1313} 1314 1315 1316void WMesaMakeCurrent(WMesaContext c, HDC hdc) 1317{ 1318 WMesaFramebuffer pwfb; 1319 1320 { 1321 /* return if already current */ 1322 GET_CURRENT_CONTEXT(ctx); 1323 WMesaContext pwc = wmesa_context(ctx); 1324 if (c == pwc && pwc->hDC == hdc) 1325 return; 1326 } 1327 1328 pwfb = wmesa_lookup_framebuffer(hdc); 1329 1330 /* Lazy creation of framebuffers */ 1331 if (c && !pwfb && hdc) { 1332 struct gl_renderbuffer *rb; 1333 GLvisual *visual = &c->gl_ctx.Visual; 1334 GLuint width, height; 1335 1336 get_window_size(hdc, &width, &height); 1337 1338 c->clearPen = CreatePen(PS_SOLID, 1, 0); 1339 c->clearBrush = CreateSolidBrush(0); 1340 1341 pwfb = wmesa_new_framebuffer(hdc, visual); 1342 1343 /* Create back buffer if double buffered */ 1344 if (visual->doubleBufferMode == 1) { 1345 wmCreateBackingStore(pwfb, width, height); 1346 } 1347 1348 /* make render buffers */ 1349 if (visual->doubleBufferMode == 1) { 1350 rb = wmesa_new_renderbuffer(); 1351 _mesa_add_renderbuffer(&pwfb->Base, BUFFER_BACK_LEFT, rb); 1352 wmesa_set_renderbuffer_funcs(rb, pwfb->pixelformat, 1); 1353 } 1354 rb = wmesa_new_renderbuffer(); 1355 _mesa_add_renderbuffer(&pwfb->Base, BUFFER_FRONT_LEFT, rb); 1356 wmesa_set_renderbuffer_funcs(rb, pwfb->pixelformat, 0); 1357 1358 /* Let Mesa own the Depth, Stencil, and Accum buffers */ 1359 _mesa_add_soft_renderbuffers(&pwfb->Base, 1360 GL_FALSE, /* color */ 1361 visual->depthBits > 0, 1362 visual->stencilBits > 0, 1363 visual->accumRedBits > 0, 1364 visual->alphaBits >0, 1365 GL_FALSE); 1366 } 1367 1368 if (c && pwfb) 1369 _mesa_make_current(&c->gl_ctx, &pwfb->Base, &pwfb->Base); 1370 else 1371 _mesa_make_current(NULL, NULL, NULL); 1372} 1373 1374 1375void WMesaSwapBuffers( HDC hdc ) 1376{ 1377 GET_CURRENT_CONTEXT(ctx); 1378 WMesaContext pwc = wmesa_context(ctx); 1379 WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(hdc); 1380 1381 if (!pwfb) { 1382 _mesa_problem(NULL, "wmesa: swapbuffers on unknown hdc"); 1383 return; 1384 } 1385 1386 /* If we're swapping the buffer associated with the current context 1387 * we have to flush any pending rendering commands first. 1388 */ 1389 if (pwc->hDC == hdc) { 1390 _mesa_notifySwapBuffers(ctx); 1391 1392 BitBlt(pwfb->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height, 1393 pwfb->dib_hDC, 0, 0, SRCCOPY); 1394 } 1395 else { 1396 /* XXX for now only allow swapping current window */ 1397 _mesa_problem(NULL, "wmesa: can't swap non-current window"); 1398 } 1399} 1400