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