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