wmesa.c revision 4a1c66059957f8650afb73f9c0f982e4ae7b8200
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 530/* Write an array of RGBA pixels with a boolean mask. */ 531static void write_rgba_pixels_front(struct gl_context *ctx, 532 struct gl_renderbuffer *rb, 533 GLuint n, 534 const GLint x[], const GLint y[], 535 const void *values, 536 const GLubyte *mask) 537{ 538 const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values; 539 GLuint i; 540 WMesaContext pwc = wmesa_context(ctx); 541 (void) ctx; 542 for (i=0; i<n; i++) 543 if (mask[i]) 544 SetPixel(pwc->hDC, x[i], FLIP(y[i]), 545 RGB(rgba[i][RCOMP], rgba[i][GCOMP], 546 rgba[i][BCOMP])); 547} 548 549 550 551/* Read a horizontal span of color pixels. */ 552static void read_rgba_span_front(struct gl_context *ctx, 553 struct gl_renderbuffer *rb, 554 GLuint n, GLint x, GLint y, 555 void *values) 556{ 557 GLubyte (*rgba)[4] = (GLubyte (*)[4])values; 558 WMesaContext pwc = wmesa_context(ctx); 559 GLuint i; 560 COLORREF Color; 561 y = FLIP(y); 562 for (i=0; i<n; i++) { 563 Color = GetPixel(pwc->hDC, x+i, y); 564 rgba[i][RCOMP] = GetRValue(Color); 565 rgba[i][GCOMP] = GetGValue(Color); 566 rgba[i][BCOMP] = GetBValue(Color); 567 rgba[i][ACOMP] = 255; 568 } 569} 570 571 572/* Read an array of color pixels. */ 573static void read_rgba_pixels_front(struct gl_context *ctx, 574 struct gl_renderbuffer *rb, 575 GLuint n, const GLint x[], const GLint y[], 576 void *values) 577{ 578 GLubyte (*rgba)[4] = (GLubyte (*)[4])values; 579 WMesaContext pwc = wmesa_context(ctx); 580 GLuint i; 581 COLORREF Color; 582 for (i=0; i<n; i++) { 583 GLint y2 = FLIP(y[i]); 584 Color = GetPixel(pwc->hDC, x[i], y2); 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 594/* DOUBLE BUFFER 32-bit */ 595 596#define WMSETPIXEL32(pwc, y, x, r, g, b) { \ 597LPDWORD lpdw = ((LPDWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \ 598*lpdw = BGR32((r),(g),(b)); } 599 600 601 602/* Write a horizontal span of RGBA color pixels with a boolean mask. */ 603static void write_rgba_span_32(struct gl_context *ctx, 604 struct gl_renderbuffer *rb, 605 GLuint n, GLint x, GLint y, 606 const void *values, 607 const GLubyte *mask) 608{ 609 const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values; 610 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 611 GLuint i; 612 LPDWORD lpdw; 613 614 (void) ctx; 615 616 y=FLIP(y); 617 lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x; 618 if (mask) { 619 for (i=0; i<n; i++) 620 if (mask[i]) 621 lpdw[i] = BGR32(rgba[i][RCOMP], rgba[i][GCOMP], 622 rgba[i][BCOMP]); 623 } 624 else { 625 for (i=0; i<n; i++) 626 *lpdw++ = BGR32(rgba[i][RCOMP], rgba[i][GCOMP], 627 rgba[i][BCOMP]); 628 } 629} 630 631 632/* Write an array of RGBA pixels with a boolean mask. */ 633static void write_rgba_pixels_32(struct gl_context *ctx, 634 struct gl_renderbuffer *rb, 635 GLuint n, const GLint x[], const GLint y[], 636 const void *values, 637 const GLubyte *mask) 638{ 639 const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values; 640 GLuint i; 641 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 642 for (i=0; i<n; i++) 643 if (mask[i]) 644 WMSETPIXEL32(pwfb, FLIP(y[i]), x[i], 645 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); 646} 647 648 649/* Read a horizontal span of color pixels. */ 650static void read_rgba_span_32(struct gl_context *ctx, 651 struct gl_renderbuffer *rb, 652 GLuint n, GLint x, GLint y, 653 void *values) 654{ 655 GLubyte (*rgba)[4] = (GLubyte (*)[4])values; 656 GLuint i; 657 DWORD pixel; 658 LPDWORD lpdw; 659 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 660 661 y = FLIP(y); 662 lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x; 663 for (i=0; i<n; i++) { 664 pixel = lpdw[i]; 665 rgba[i][RCOMP] = (GLubyte)((pixel & 0x00ff0000) >> 16); 666 rgba[i][GCOMP] = (GLubyte)((pixel & 0x0000ff00) >> 8); 667 rgba[i][BCOMP] = (GLubyte)(pixel & 0x000000ff); 668 rgba[i][ACOMP] = 255; 669 } 670} 671 672 673/* Read an array of color pixels. */ 674static void read_rgba_pixels_32(struct gl_context *ctx, 675 struct gl_renderbuffer *rb, 676 GLuint n, const GLint x[], const GLint y[], 677 void *values) 678{ 679 GLubyte (*rgba)[4] = (GLubyte (*)[4])values; 680 GLuint i; 681 DWORD pixel; 682 LPDWORD lpdw; 683 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 684 685 for (i=0; i<n; i++) { 686 GLint y2 = FLIP(y[i]); 687 lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i]; 688 pixel = *lpdw; 689 rgba[i][RCOMP] = (GLubyte)((pixel & 0x00ff0000) >> 16); 690 rgba[i][GCOMP] = (GLubyte)((pixel & 0x0000ff00) >> 8); 691 rgba[i][BCOMP] = (GLubyte)(pixel & 0x000000ff); 692 rgba[i][ACOMP] = 255; 693 } 694} 695 696 697/*********************************************************************/ 698 699/* DOUBLE BUFFER 24-bit */ 700 701#define WMSETPIXEL24(pwc, y, x, r, g, b) { \ 702LPBYTE lpb = ((LPBYTE)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (3 * x)); \ 703lpb[0] = (b); \ 704lpb[1] = (g); \ 705lpb[2] = (r); } 706 707/* Write a horizontal span of RGBA color pixels with a boolean mask. */ 708static void write_rgba_span_24(struct gl_context *ctx, 709 struct gl_renderbuffer *rb, 710 GLuint n, GLint x, GLint y, 711 const void *values, 712 const GLubyte *mask) 713{ 714 const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values; 715 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 716 GLuint i; 717 LPBYTE lpb; 718 719 (void) ctx; 720 721 y=FLIP(y); 722 lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x); 723 if (mask) { 724 for (i=0; i<n; i++) 725 if (mask[i]) { 726 lpb[3*i] = rgba[i][BCOMP]; 727 lpb[3*i+1] = rgba[i][GCOMP]; 728 lpb[3*i+2] = rgba[i][RCOMP]; 729 } 730 } 731 else { 732 for (i=0; i<n; i++) { 733 *lpb++ = rgba[i][BCOMP]; 734 *lpb++ = rgba[i][GCOMP]; 735 *lpb++ = rgba[i][RCOMP]; 736 } 737 } 738} 739 740 741/* Write an array of RGBA pixels with a boolean mask. */ 742static void write_rgba_pixels_24(struct gl_context *ctx, 743 struct gl_renderbuffer *rb, 744 GLuint n, const GLint x[], const GLint y[], 745 const void *values, 746 const GLubyte *mask) 747{ 748 const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values; 749 GLuint i; 750 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 751 for (i=0; i<n; i++) 752 if (mask[i]) 753 WMSETPIXEL24(pwfb, FLIP(y[i]), x[i], 754 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); 755} 756 757 758/* Read a horizontal span of color pixels. */ 759static void read_rgba_span_24(struct gl_context *ctx, 760 struct gl_renderbuffer *rb, 761 GLuint n, GLint x, GLint y, 762 void *values) 763{ 764 GLubyte (*rgba)[4] = (GLubyte (*)[4])values; 765 GLuint i; 766 LPBYTE lpb; 767 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 768 769 y = FLIP(y); 770 lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x); 771 for (i=0; i<n; i++) { 772 rgba[i][RCOMP] = lpb[3*i+2]; 773 rgba[i][GCOMP] = lpb[3*i+1]; 774 rgba[i][BCOMP] = lpb[3*i]; 775 rgba[i][ACOMP] = 255; 776 } 777} 778 779 780/* Read an array of color pixels. */ 781static void read_rgba_pixels_24(struct gl_context *ctx, 782 struct gl_renderbuffer *rb, 783 GLuint n, const GLint x[], const GLint y[], 784 void *values) 785{ 786 GLubyte (*rgba)[4] = (GLubyte (*)[4])values; 787 GLuint i; 788 LPBYTE lpb; 789 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 790 791 for (i=0; i<n; i++) { 792 GLint y2 = FLIP(y[i]); 793 lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + (3 * x[i]); 794 rgba[i][RCOMP] = lpb[3*i+2]; 795 rgba[i][GCOMP] = lpb[3*i+1]; 796 rgba[i][BCOMP] = lpb[3*i]; 797 rgba[i][ACOMP] = 255; 798 } 799} 800 801 802/*********************************************************************/ 803 804/* DOUBLE BUFFER 16-bit */ 805 806#define WMSETPIXEL16(pwc, y, x, r, g, b) { \ 807LPWORD lpw = ((LPWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \ 808*lpw = BGR16((r),(g),(b)); } 809 810 811 812/* Write a horizontal span of RGBA color pixels with a boolean mask. */ 813static void write_rgba_span_16(struct gl_context *ctx, 814 struct gl_renderbuffer *rb, 815 GLuint n, GLint x, GLint y, 816 const void *values, 817 const GLubyte *mask) 818{ 819 const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values; 820 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 821 GLuint i; 822 LPWORD lpw; 823 824 (void) ctx; 825 826 y=FLIP(y); 827 lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x; 828 if (mask) { 829 for (i=0; i<n; i++) 830 if (mask[i]) 831 lpw[i] = BGR16(rgba[i][RCOMP], rgba[i][GCOMP], 832 rgba[i][BCOMP]); 833 } 834 else { 835 for (i=0; i<n; i++) 836 *lpw++ = BGR16(rgba[i][RCOMP], rgba[i][GCOMP], 837 rgba[i][BCOMP]); 838 } 839} 840 841 842 843/* Write an array of RGBA pixels with a boolean mask. */ 844static void write_rgba_pixels_16(struct gl_context *ctx, 845 struct gl_renderbuffer *rb, 846 GLuint n, const GLint x[], const GLint y[], 847 const void *values, 848 const GLubyte *mask) 849{ 850 const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values; 851 GLuint i; 852 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 853 (void) ctx; 854 for (i=0; i<n; i++) 855 if (mask[i]) 856 WMSETPIXEL16(pwfb, FLIP(y[i]), x[i], 857 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); 858} 859 860 861/* Read a horizontal span of color pixels. */ 862static void read_rgba_span_16(struct gl_context *ctx, 863 struct gl_renderbuffer *rb, 864 GLuint n, GLint x, GLint y, 865 void *values) 866{ 867 GLubyte (*rgba)[4] = (GLubyte (*)[4])values; 868 GLuint i, pixel; 869 LPWORD lpw; 870 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 871 872 y = FLIP(y); 873 lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x; 874 for (i=0; i<n; i++) { 875 pixel = lpw[i]; 876 /* Windows uses 5,5,5 for 16-bit */ 877 rgba[i][RCOMP] = (pixel & 0x7c00) >> 7; 878 rgba[i][GCOMP] = (pixel & 0x03e0) >> 2; 879 rgba[i][BCOMP] = (pixel & 0x001f) << 3; 880 rgba[i][ACOMP] = 255; 881 } 882} 883 884 885/* Read an array of color pixels. */ 886static void read_rgba_pixels_16(struct gl_context *ctx, 887 struct gl_renderbuffer *rb, 888 GLuint n, const GLint x[], const GLint y[], 889 void *values) 890{ 891 GLubyte (*rgba)[4] = (GLubyte (*)[4])values; 892 GLuint i, pixel; 893 LPWORD lpw; 894 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 895 896 for (i=0; i<n; i++) { 897 GLint y2 = FLIP(y[i]); 898 lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i]; 899 pixel = *lpw; 900 /* Windows uses 5,5,5 for 16-bit */ 901 rgba[i][RCOMP] = (pixel & 0x7c00) >> 7; 902 rgba[i][GCOMP] = (pixel & 0x03e0) >> 2; 903 rgba[i][BCOMP] = (pixel & 0x001f) << 3; 904 rgba[i][ACOMP] = 255; 905 } 906} 907 908 909 910 911/**********************************************************************/ 912/***** BUFFER Functions *****/ 913/**********************************************************************/ 914 915 916 917 918static void 919wmesa_delete_renderbuffer(struct gl_renderbuffer *rb) 920{ 921 free(rb); 922} 923 924 925/** 926 * This is called by Mesa whenever it determines that the window size 927 * has changed. Do whatever's needed to cope with that. 928 */ 929static GLboolean 930wmesa_renderbuffer_storage(struct gl_context *ctx, 931 struct gl_renderbuffer *rb, 932 GLenum internalFormat, 933 GLuint width, 934 GLuint height) 935{ 936 rb->Width = width; 937 rb->Height = height; 938 return GL_TRUE; 939} 940 941 942/** 943 * Called by ctx->Driver.ResizeBuffers() 944 * Resize the front/back colorbuffers to match the latest window size. 945 */ 946static void 947wmesa_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *buffer, 948 GLuint width, GLuint height) 949{ 950 WMesaFramebuffer pwfb = wmesa_framebuffer(buffer); 951 952 if (pwfb->Base.Width != width || pwfb->Base.Height != height) { 953 /* Realloc back buffer */ 954 if (ctx->Visual.doubleBufferMode == 1) { 955 wmDeleteBackingStore(pwfb); 956 wmCreateBackingStore(pwfb, width, height); 957 } 958 } 959 _mesa_resize_framebuffer(ctx, buffer, width, height); 960} 961 962 963/** 964 * Called by glViewport. 965 * This is a good time for us to poll the current window size and adjust 966 * our renderbuffers to match the current window size. 967 * Remember, we have no opportunity to respond to conventional 968 * resize events since the driver has no event loop. 969 * Thus, we poll. 970 * MakeCurrent also ends up making a call here, so that ensures 971 * we get the viewport set correctly, even if the app does not call 972 * glViewport and relies on the defaults. 973 */ 974static void wmesa_viewport(struct gl_context *ctx, 975 GLint x, GLint y, 976 GLsizei width, GLsizei height) 977{ 978 GLuint new_width, new_height; 979 980 wmesa_get_buffer_size(ctx->WinSysDrawBuffer, &new_width, &new_height); 981 982 /** 983 * Resize buffers if the window size changed. 984 */ 985 wmesa_resize_buffers(ctx, ctx->WinSysDrawBuffer, new_width, new_height); 986 ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */ 987} 988 989 990 991 992/** 993 * Called when the driver should update it's state, based on the new_state 994 * flags. 995 */ 996static void wmesa_update_state(struct gl_context *ctx, GLuint new_state) 997{ 998 _swrast_InvalidateState(ctx, new_state); 999 _swsetup_InvalidateState(ctx, new_state); 1000 _vbo_InvalidateState(ctx, new_state); 1001 _tnl_InvalidateState(ctx, new_state); 1002 1003 /* TODO - This code is not complete yet because I 1004 * don't know what to do for all state updates. 1005 */ 1006 1007 if (new_state & _NEW_BUFFERS) { 1008 } 1009} 1010 1011 1012 1013 1014 1015/**********************************************************************/ 1016/***** WMESA Functions *****/ 1017/**********************************************************************/ 1018 1019WMesaContext WMesaCreateContext(HDC hDC, 1020 HPALETTE* Pal, 1021 GLboolean rgb_flag, 1022 GLboolean db_flag, 1023 GLboolean alpha_flag) 1024{ 1025 WMesaContext c; 1026 struct dd_function_table functions; 1027 GLint red_bits, green_bits, blue_bits, alpha_bits; 1028 struct gl_context *ctx; 1029 struct gl_config *visual; 1030 1031 (void) Pal; 1032 1033 /* Indexed mode not supported */ 1034 if (!rgb_flag) 1035 return NULL; 1036 1037 /* Allocate wmesa context */ 1038 c = CALLOC_STRUCT(wmesa_context); 1039 if (!c) 1040 return NULL; 1041 1042#if 0 1043 /* I do not understand this contributed code */ 1044 /* Support memory and device contexts */ 1045 if(WindowFromDC(hDC) != NULL) { 1046 c->hDC = GetDC(WindowFromDC(hDC)); /* huh ???? */ 1047 } 1048 else { 1049 c->hDC = hDC; 1050 } 1051#else 1052 c->hDC = hDC; 1053#endif 1054 1055 /* Get data for visual */ 1056 /* Dealing with this is actually a bit of overkill because Mesa will end 1057 * up treating all color component size requests less than 8 by using 1058 * a single byte per channel. In addition, the interface to the span 1059 * routines passes colors as an entire byte per channel anyway, so there 1060 * is nothing to be saved by telling the visual to be 16 bits if the device 1061 * is 16 bits. That is, Mesa is going to compute colors down to 8 bits per 1062 * channel anyway. 1063 * But we go through the motions here anyway. 1064 */ 1065 switch (GetDeviceCaps(c->hDC, BITSPIXEL)) { 1066 case 16: 1067 red_bits = green_bits = blue_bits = 5; 1068 alpha_bits = 0; 1069 break; 1070 default: 1071 red_bits = green_bits = blue_bits = 8; 1072 alpha_bits = 8; 1073 break; 1074 } 1075 /* Create visual based on flags */ 1076 visual = _mesa_create_visual(db_flag, /* db_flag */ 1077 GL_FALSE, /* stereo */ 1078 red_bits, green_bits, blue_bits, /* color RGB */ 1079 alpha_flag ? alpha_bits : 0, /* color A */ 1080 DEFAULT_SOFTWARE_DEPTH_BITS, /* depth_bits */ 1081 8, /* stencil_bits */ 1082 16,16,16, /* accum RGB */ 1083 alpha_flag ? 16 : 0, /* accum A */ 1084 1); /* num samples */ 1085 1086 if (!visual) { 1087 free(c); 1088 return NULL; 1089 } 1090 1091 /* Set up driver functions */ 1092 _mesa_init_driver_functions(&functions); 1093 functions.GetString = wmesa_get_string; 1094 functions.UpdateState = wmesa_update_state; 1095 functions.GetBufferSize = wmesa_get_buffer_size; 1096 functions.Flush = wmesa_flush; 1097 functions.Clear = clear; 1098 functions.ClearColor = clear_color; 1099 functions.ResizeBuffers = wmesa_resize_buffers; 1100 functions.Viewport = wmesa_viewport; 1101 1102 /* initialize the Mesa context data */ 1103 ctx = &c->gl_ctx; 1104 _mesa_initialize_context(ctx, API_OPENGL, visual, 1105 NULL, &functions, (void *)c); 1106 1107 /* visual no longer needed - it was copied by _mesa_initialize_context() */ 1108 _mesa_destroy_visual(visual); 1109 1110 _mesa_enable_sw_extensions(ctx); 1111 _mesa_enable_1_3_extensions(ctx); 1112 _mesa_enable_1_4_extensions(ctx); 1113 _mesa_enable_1_5_extensions(ctx); 1114 _mesa_enable_2_0_extensions(ctx); 1115 _mesa_enable_2_1_extensions(ctx); 1116 1117 _mesa_meta_init(ctx); 1118 1119 /* Initialize the software rasterizer and helper modules. */ 1120 if (!_swrast_CreateContext(ctx) || 1121 !_vbo_CreateContext(ctx) || 1122 !_tnl_CreateContext(ctx) || 1123 !_swsetup_CreateContext(ctx)) { 1124 _mesa_free_context_data(ctx); 1125 free(c); 1126 return NULL; 1127 } 1128 _swsetup_Wakeup(ctx); 1129 TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline; 1130 1131 return c; 1132} 1133 1134 1135void WMesaDestroyContext( WMesaContext pwc ) 1136{ 1137 struct gl_context *ctx = &pwc->gl_ctx; 1138 WMesaFramebuffer pwfb; 1139 GET_CURRENT_CONTEXT(cur_ctx); 1140 1141 if (cur_ctx == ctx) { 1142 /* unbind current if deleting current context */ 1143 WMesaMakeCurrent(NULL, NULL); 1144 } 1145 1146 /* clean up frame buffer resources */ 1147 pwfb = wmesa_lookup_framebuffer(pwc->hDC); 1148 if (pwfb) { 1149 if (ctx->Visual.doubleBufferMode == 1) 1150 wmDeleteBackingStore(pwfb); 1151 wmesa_free_framebuffer(pwc->hDC); 1152 } 1153 1154 /* Release for device, not memory contexts */ 1155 if (WindowFromDC(pwc->hDC) != NULL) 1156 { 1157 ReleaseDC(WindowFromDC(pwc->hDC), pwc->hDC); 1158 } 1159 DeleteObject(pwc->clearPen); 1160 DeleteObject(pwc->clearBrush); 1161 1162 _mesa_meta_free(ctx); 1163 1164 _swsetup_DestroyContext(ctx); 1165 _tnl_DestroyContext(ctx); 1166 _vbo_DestroyContext(ctx); 1167 _swrast_DestroyContext(ctx); 1168 1169 _mesa_free_context_data(ctx); 1170 free(pwc); 1171} 1172 1173 1174/** 1175 * Create a new color renderbuffer. 1176 */ 1177static struct gl_renderbuffer * 1178wmesa_new_renderbuffer(void) 1179{ 1180 struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer); 1181 if (!rb) 1182 return NULL; 1183 1184 _mesa_init_renderbuffer(rb, (GLuint)0); 1185 1186 rb->_BaseFormat = GL_RGBA; 1187 rb->InternalFormat = GL_RGBA; 1188 rb->Delete = wmesa_delete_renderbuffer; 1189 rb->AllocStorage = wmesa_renderbuffer_storage; 1190 return rb; 1191} 1192 1193 1194void WMesaMakeCurrent(WMesaContext c, HDC hdc) 1195{ 1196 WMesaFramebuffer pwfb; 1197 1198 { 1199 /* return if already current */ 1200 GET_CURRENT_CONTEXT(ctx); 1201 WMesaContext pwc = wmesa_context(ctx); 1202 if (pwc && c == pwc && pwc->hDC == hdc) 1203 return; 1204 } 1205 1206 pwfb = wmesa_lookup_framebuffer(hdc); 1207 1208 /* Lazy creation of framebuffers */ 1209 if (c && !pwfb && hdc) { 1210 struct gl_renderbuffer *rb; 1211 struct gl_config *visual = &c->gl_ctx.Visual; 1212 GLuint width, height; 1213 1214 get_window_size(hdc, &width, &height); 1215 1216 c->clearPen = CreatePen(PS_SOLID, 1, 0); 1217 c->clearBrush = CreateSolidBrush(0); 1218 1219 pwfb = wmesa_new_framebuffer(hdc, visual); 1220 1221 /* Create back buffer if double buffered */ 1222 if (visual->doubleBufferMode == 1) { 1223 wmCreateBackingStore(pwfb, width, height); 1224 } 1225 1226 /* make render buffers */ 1227 if (visual->doubleBufferMode == 1) { 1228 rb = wmesa_new_renderbuffer(); 1229 _mesa_add_renderbuffer(&pwfb->Base, BUFFER_BACK_LEFT, rb); 1230 } 1231 rb = wmesa_new_renderbuffer(); 1232 _mesa_add_renderbuffer(&pwfb->Base, BUFFER_FRONT_LEFT, rb); 1233 1234 /* Let Mesa own the Depth, Stencil, and Accum buffers */ 1235 _swrast_add_soft_renderbuffers(&pwfb->Base, 1236 GL_FALSE, /* color */ 1237 visual->depthBits > 0, 1238 visual->stencilBits > 0, 1239 visual->accumRedBits > 0, 1240 visual->alphaBits >0, 1241 GL_FALSE); 1242 } 1243 1244 if (c && pwfb) 1245 _mesa_make_current(&c->gl_ctx, &pwfb->Base, &pwfb->Base); 1246 else 1247 _mesa_make_current(NULL, NULL, NULL); 1248} 1249 1250 1251void WMesaSwapBuffers( HDC hdc ) 1252{ 1253 GET_CURRENT_CONTEXT(ctx); 1254 WMesaContext pwc = wmesa_context(ctx); 1255 WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(hdc); 1256 1257 if (!pwfb) { 1258 _mesa_problem(NULL, "wmesa: swapbuffers on unknown hdc"); 1259 return; 1260 } 1261 1262 /* If we're swapping the buffer associated with the current context 1263 * we have to flush any pending rendering commands first. 1264 */ 1265 if (pwc->hDC == hdc) { 1266 _mesa_notifySwapBuffers(ctx); 1267 1268 BitBlt(pwfb->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height, 1269 pwfb->dib_hDC, 0, 0, SRCCOPY); 1270 } 1271 else { 1272 /* XXX for now only allow swapping current window */ 1273 _mesa_problem(NULL, "wmesa: can't swap non-current window"); 1274 } 1275} 1276 1277void WMesaShareLists(WMesaContext ctx_to_share, WMesaContext ctx) 1278{ 1279 _mesa_share_state(&ctx->gl_ctx, &ctx_to_share->gl_ctx); 1280} 1281 1282