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/* 247 * Clear the color/depth/stencil buffers. 248 */ 249static void clear(struct gl_context *ctx, GLbitfield mask) 250{ 251#define FLIP(Y) (ctx->DrawBuffer->Height - (Y) - 1) 252 const GLint x = ctx->DrawBuffer->_Xmin; 253 const GLint y = ctx->DrawBuffer->_Ymin; 254 const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; 255 const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; 256 257 WMesaContext pwc = wmesa_context(ctx); 258 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 259 int done = 0; 260 261 /* Let swrast do all the work if the masks are not set to 262 * clear all channels. */ 263 if (!ctx->Color.ColorMask[0][0] || 264 !ctx->Color.ColorMask[0][1] || 265 !ctx->Color.ColorMask[0][2] || 266 !ctx->Color.ColorMask[0][3]) { 267 _swrast_Clear(ctx, mask); 268 return; 269 } 270 271 if (mask & BUFFER_BITS_COLOR) { 272 /* setup the clearing color */ 273 const union gl_color_union color = ctx->Color.ClearColor; 274 GLubyte col[3]; 275 UNCLAMPED_FLOAT_TO_UBYTE(col[0], color.f[0]); 276 UNCLAMPED_FLOAT_TO_UBYTE(col[1], color.f[1]); 277 UNCLAMPED_FLOAT_TO_UBYTE(col[2], color.f[2]); 278 pwc->clearColorRef = RGB(col[0], col[1], col[2]); 279 DeleteObject(pwc->clearPen); 280 DeleteObject(pwc->clearBrush); 281 pwc->clearPen = CreatePen(PS_SOLID, 1, pwc->clearColorRef); 282 pwc->clearBrush = CreateSolidBrush(pwc->clearColorRef); 283 } 284 285 /* Back buffer */ 286 if (mask & BUFFER_BIT_BACK_LEFT) { 287 288 int i, rowSize; 289 UINT bytesPerPixel = pwfb->cColorBits / 8; 290 LPBYTE lpb, clearRow; 291 LPWORD lpw; 292 BYTE bColor; 293 WORD wColor; 294 BYTE r, g, b; 295 DWORD dwColor; 296 LPDWORD lpdw; 297 298 /* Try for a fast clear - clearing entire buffer with a single 299 * byte value. */ 300 if (width == ctx->DrawBuffer->Width && 301 height == ctx->DrawBuffer->Height) { /* entire buffer */ 302 /* Now check for an easy clear value */ 303 switch (bytesPerPixel) { 304 case 1: 305 bColor = BGR8(GetRValue(pwc->clearColorRef), 306 GetGValue(pwc->clearColorRef), 307 GetBValue(pwc->clearColorRef)); 308 memset(pwfb->pbPixels, bColor, 309 pwfb->ScanWidth * height); 310 done = 1; 311 break; 312 case 2: 313 wColor = BGR16(GetRValue(pwc->clearColorRef), 314 GetGValue(pwc->clearColorRef), 315 GetBValue(pwc->clearColorRef)); 316 if (((wColor >> 8) & 0xff) == (wColor & 0xff)) { 317 memset(pwfb->pbPixels, wColor & 0xff, 318 pwfb->ScanWidth * height); 319 done = 1; 320 } 321 break; 322 case 3: 323 /* fall through */ 324 case 4: 325 if (GetRValue(pwc->clearColorRef) == 326 GetGValue(pwc->clearColorRef) && 327 GetRValue(pwc->clearColorRef) == 328 GetBValue(pwc->clearColorRef)) { 329 memset(pwfb->pbPixels, 330 GetRValue(pwc->clearColorRef), 331 pwfb->ScanWidth * height); 332 done = 1; 333 } 334 break; 335 default: 336 break; 337 } 338 } /* all */ 339 340 if (!done) { 341 /* Need to clear a row at a time. Begin by setting the first 342 * row in the area to be cleared to the clear color. */ 343 344 clearRow = pwfb->pbPixels + 345 pwfb->ScanWidth * FLIP(y) + 346 bytesPerPixel * x; 347 switch (bytesPerPixel) { 348 case 1: 349 lpb = clearRow; 350 bColor = BGR8(GetRValue(pwc->clearColorRef), 351 GetGValue(pwc->clearColorRef), 352 GetBValue(pwc->clearColorRef)); 353 memset(lpb, bColor, width); 354 break; 355 case 2: 356 lpw = (LPWORD)clearRow; 357 wColor = BGR16(GetRValue(pwc->clearColorRef), 358 GetGValue(pwc->clearColorRef), 359 GetBValue(pwc->clearColorRef)); 360 for (i=0; i<width; i++) 361 *lpw++ = wColor; 362 break; 363 case 3: 364 lpb = clearRow; 365 r = GetRValue(pwc->clearColorRef); 366 g = GetGValue(pwc->clearColorRef); 367 b = GetBValue(pwc->clearColorRef); 368 for (i=0; i<width; i++) { 369 *lpb++ = b; 370 *lpb++ = g; 371 *lpb++ = r; 372 } 373 break; 374 case 4: 375 lpdw = (LPDWORD)clearRow; 376 dwColor = BGR32(GetRValue(pwc->clearColorRef), 377 GetGValue(pwc->clearColorRef), 378 GetBValue(pwc->clearColorRef)); 379 for (i=0; i<width; i++) 380 *lpdw++ = dwColor; 381 break; 382 default: 383 break; 384 } /* switch */ 385 386 /* copy cleared row to other rows in buffer */ 387 lpb = clearRow - pwfb->ScanWidth; 388 rowSize = width * bytesPerPixel; 389 for (i=1; i<height; i++) { 390 memcpy(lpb, clearRow, rowSize); 391 lpb -= pwfb->ScanWidth; 392 } 393 } /* not done */ 394 mask &= ~BUFFER_BIT_BACK_LEFT; 395 } /* back buffer */ 396 397 /* front buffer */ 398 if (mask & BUFFER_BIT_FRONT_LEFT) { 399 HDC DC = pwc->hDC; 400 HPEN Old_Pen = SelectObject(DC, pwc->clearPen); 401 HBRUSH Old_Brush = SelectObject(DC, pwc->clearBrush); 402 Rectangle(DC, 403 x, 404 FLIP(y) + 1, 405 x + width + 1, 406 FLIP(y) - height + 1); 407 SelectObject(DC, Old_Pen); 408 SelectObject(DC, Old_Brush); 409 mask &= ~BUFFER_BIT_FRONT_LEFT; 410 } /* front buffer */ 411 412 /* Call swrast if there is anything left to clear (like DEPTH) */ 413 if (mask) 414 _swrast_Clear(ctx, mask); 415 416#undef FLIP 417} 418 419 420/**********************************************************************/ 421/***** PIXEL Functions *****/ 422/**********************************************************************/ 423 424#define FLIP(Y) (rb->Height - (Y) - 1) 425 426 427/** 428 ** Front Buffer reading/writing 429 ** These are slow, but work with all non-indexed visual types. 430 **/ 431 432/* Write a horizontal span of RGBA color pixels with a boolean mask. */ 433static void write_rgba_span_front(struct gl_context *ctx, 434 struct gl_renderbuffer *rb, 435 GLuint n, GLint x, GLint y, 436 const void *values, 437 const GLubyte *mask) 438{ 439 const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values; 440 WMesaContext pwc = wmesa_context(ctx); 441 WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(pwc->hDC); 442 HBITMAP bmp=0; 443 HDC mdc=0; 444 typedef union 445 { 446 unsigned i; 447 struct { 448 unsigned b:8, g:8, r:8, a:8; 449 }; 450 } BGRA; 451 BGRA *bgra, c; 452 GLuint i; 453 454 if (n < 16) { // the value 16 is just guessed 455 y=FLIP(y); 456 if (mask) { 457 for (i=0; i<n; i++) 458 if (mask[i]) 459 SetPixel(pwc->hDC, x+i, y, 460 RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP])); 461 } 462 else { 463 for (i=0; i<n; i++) 464 SetPixel(pwc->hDC, x+i, y, 465 RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP])); 466 } 467 } 468 else { 469 if (!pwfb) { 470 _mesa_problem(NULL, "wmesa: write_rgba_span_front on unknown hdc"); 471 return; 472 } 473 bgra=malloc(n*sizeof(BGRA)); 474 if (!bgra) { 475 _mesa_problem(NULL, "wmesa: write_rgba_span_front: out of memory"); 476 return; 477 } 478 c.a=0; 479 if (mask) { 480 for (i=0; i<n; i++) { 481 if (mask[i]) { 482 c.r=rgba[i][RCOMP]; 483 c.g=rgba[i][GCOMP]; 484 c.b=rgba[i][BCOMP]; 485 c.a=rgba[i][ACOMP]; 486 bgra[i]=c; 487 } 488 else 489 bgra[i].i=0; 490 } 491 } 492 else { 493 for (i=0; i<n; i++) { 494 c.r=rgba[i][RCOMP]; 495 c.g=rgba[i][GCOMP]; 496 c.b=rgba[i][BCOMP]; 497 c.a=rgba[i][ACOMP]; 498 bgra[i]=c; 499 } 500 } 501 bmp=CreateBitmap(n, 1, 1, 32, bgra); 502 mdc=CreateCompatibleDC(pwfb->hDC); 503 SelectObject(mdc, bmp); 504 y=FLIP(y); 505 BitBlt(pwfb->hDC, x, y, n, 1, mdc, 0, 0, SRCCOPY); 506 SelectObject(mdc, 0); 507 DeleteObject(bmp); 508 DeleteDC(mdc); 509 free(bgra); 510 } 511} 512 513 514/* Write an array of RGBA pixels with a boolean mask. */ 515static void write_rgba_pixels_front(struct gl_context *ctx, 516 struct gl_renderbuffer *rb, 517 GLuint n, 518 const GLint x[], const GLint y[], 519 const void *values, 520 const GLubyte *mask) 521{ 522 const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values; 523 GLuint i; 524 WMesaContext pwc = wmesa_context(ctx); 525 (void) ctx; 526 for (i=0; i<n; i++) 527 if (mask[i]) 528 SetPixel(pwc->hDC, x[i], FLIP(y[i]), 529 RGB(rgba[i][RCOMP], rgba[i][GCOMP], 530 rgba[i][BCOMP])); 531} 532 533 534 535/* Read a horizontal span of color pixels. */ 536static void read_rgba_span_front(struct gl_context *ctx, 537 struct gl_renderbuffer *rb, 538 GLuint n, GLint x, GLint y, 539 void *values) 540{ 541 GLubyte (*rgba)[4] = (GLubyte (*)[4])values; 542 WMesaContext pwc = wmesa_context(ctx); 543 GLuint i; 544 COLORREF Color; 545 y = FLIP(y); 546 for (i=0; i<n; i++) { 547 Color = GetPixel(pwc->hDC, x+i, y); 548 rgba[i][RCOMP] = GetRValue(Color); 549 rgba[i][GCOMP] = GetGValue(Color); 550 rgba[i][BCOMP] = GetBValue(Color); 551 rgba[i][ACOMP] = 255; 552 } 553} 554 555 556/* Read an array of color pixels. */ 557static void read_rgba_pixels_front(struct gl_context *ctx, 558 struct gl_renderbuffer *rb, 559 GLuint n, const GLint x[], const GLint y[], 560 void *values) 561{ 562 GLubyte (*rgba)[4] = (GLubyte (*)[4])values; 563 WMesaContext pwc = wmesa_context(ctx); 564 GLuint i; 565 COLORREF Color; 566 for (i=0; i<n; i++) { 567 GLint y2 = FLIP(y[i]); 568 Color = GetPixel(pwc->hDC, x[i], y2); 569 rgba[i][RCOMP] = GetRValue(Color); 570 rgba[i][GCOMP] = GetGValue(Color); 571 rgba[i][BCOMP] = GetBValue(Color); 572 rgba[i][ACOMP] = 255; 573 } 574} 575 576/*********************************************************************/ 577 578/* DOUBLE BUFFER 32-bit */ 579 580#define WMSETPIXEL32(pwc, y, x, r, g, b) { \ 581LPDWORD lpdw = ((LPDWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \ 582*lpdw = BGR32((r),(g),(b)); } 583 584 585 586/* Write a horizontal span of RGBA color pixels with a boolean mask. */ 587static void write_rgba_span_32(struct gl_context *ctx, 588 struct gl_renderbuffer *rb, 589 GLuint n, GLint x, GLint y, 590 const void *values, 591 const GLubyte *mask) 592{ 593 const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values; 594 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 595 GLuint i; 596 LPDWORD lpdw; 597 598 (void) ctx; 599 600 y=FLIP(y); 601 lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x; 602 if (mask) { 603 for (i=0; i<n; i++) 604 if (mask[i]) 605 lpdw[i] = BGR32(rgba[i][RCOMP], rgba[i][GCOMP], 606 rgba[i][BCOMP]); 607 } 608 else { 609 for (i=0; i<n; i++) 610 *lpdw++ = BGR32(rgba[i][RCOMP], rgba[i][GCOMP], 611 rgba[i][BCOMP]); 612 } 613} 614 615 616/* Write an array of RGBA pixels with a boolean mask. */ 617static void write_rgba_pixels_32(struct gl_context *ctx, 618 struct gl_renderbuffer *rb, 619 GLuint n, const GLint x[], const GLint y[], 620 const void *values, 621 const GLubyte *mask) 622{ 623 const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values; 624 GLuint i; 625 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 626 for (i=0; i<n; i++) 627 if (mask[i]) 628 WMSETPIXEL32(pwfb, FLIP(y[i]), x[i], 629 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); 630} 631 632 633/* Read a horizontal span of color pixels. */ 634static void read_rgba_span_32(struct gl_context *ctx, 635 struct gl_renderbuffer *rb, 636 GLuint n, GLint x, GLint y, 637 void *values) 638{ 639 GLubyte (*rgba)[4] = (GLubyte (*)[4])values; 640 GLuint i; 641 DWORD pixel; 642 LPDWORD lpdw; 643 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 644 645 y = FLIP(y); 646 lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x; 647 for (i=0; i<n; i++) { 648 pixel = lpdw[i]; 649 rgba[i][RCOMP] = (GLubyte)((pixel & 0x00ff0000) >> 16); 650 rgba[i][GCOMP] = (GLubyte)((pixel & 0x0000ff00) >> 8); 651 rgba[i][BCOMP] = (GLubyte)(pixel & 0x000000ff); 652 rgba[i][ACOMP] = 255; 653 } 654} 655 656 657/* Read an array of color pixels. */ 658static void read_rgba_pixels_32(struct gl_context *ctx, 659 struct gl_renderbuffer *rb, 660 GLuint n, const GLint x[], const GLint y[], 661 void *values) 662{ 663 GLubyte (*rgba)[4] = (GLubyte (*)[4])values; 664 GLuint i; 665 DWORD pixel; 666 LPDWORD lpdw; 667 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 668 669 for (i=0; i<n; i++) { 670 GLint y2 = FLIP(y[i]); 671 lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i]; 672 pixel = *lpdw; 673 rgba[i][RCOMP] = (GLubyte)((pixel & 0x00ff0000) >> 16); 674 rgba[i][GCOMP] = (GLubyte)((pixel & 0x0000ff00) >> 8); 675 rgba[i][BCOMP] = (GLubyte)(pixel & 0x000000ff); 676 rgba[i][ACOMP] = 255; 677 } 678} 679 680 681/*********************************************************************/ 682 683/* DOUBLE BUFFER 24-bit */ 684 685#define WMSETPIXEL24(pwc, y, x, r, g, b) { \ 686LPBYTE lpb = ((LPBYTE)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (3 * x)); \ 687lpb[0] = (b); \ 688lpb[1] = (g); \ 689lpb[2] = (r); } 690 691/* Write a horizontal span of RGBA color pixels with a boolean mask. */ 692static void write_rgba_span_24(struct gl_context *ctx, 693 struct gl_renderbuffer *rb, 694 GLuint n, GLint x, GLint y, 695 const void *values, 696 const GLubyte *mask) 697{ 698 const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values; 699 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 700 GLuint i; 701 LPBYTE lpb; 702 703 (void) ctx; 704 705 y=FLIP(y); 706 lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x); 707 if (mask) { 708 for (i=0; i<n; i++) 709 if (mask[i]) { 710 lpb[3*i] = rgba[i][BCOMP]; 711 lpb[3*i+1] = rgba[i][GCOMP]; 712 lpb[3*i+2] = rgba[i][RCOMP]; 713 } 714 } 715 else { 716 for (i=0; i<n; i++) { 717 *lpb++ = rgba[i][BCOMP]; 718 *lpb++ = rgba[i][GCOMP]; 719 *lpb++ = rgba[i][RCOMP]; 720 } 721 } 722} 723 724 725/* Write an array of RGBA pixels with a boolean mask. */ 726static void write_rgba_pixels_24(struct gl_context *ctx, 727 struct gl_renderbuffer *rb, 728 GLuint n, const GLint x[], const GLint y[], 729 const void *values, 730 const GLubyte *mask) 731{ 732 const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values; 733 GLuint i; 734 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 735 for (i=0; i<n; i++) 736 if (mask[i]) 737 WMSETPIXEL24(pwfb, FLIP(y[i]), x[i], 738 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); 739} 740 741 742/* Read a horizontal span of color pixels. */ 743static void read_rgba_span_24(struct gl_context *ctx, 744 struct gl_renderbuffer *rb, 745 GLuint n, GLint x, GLint y, 746 void *values) 747{ 748 GLubyte (*rgba)[4] = (GLubyte (*)[4])values; 749 GLuint i; 750 LPBYTE lpb; 751 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 752 753 y = FLIP(y); 754 lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y)) + (3 * x); 755 for (i=0; i<n; i++) { 756 rgba[i][RCOMP] = lpb[3*i+2]; 757 rgba[i][GCOMP] = lpb[3*i+1]; 758 rgba[i][BCOMP] = lpb[3*i]; 759 rgba[i][ACOMP] = 255; 760 } 761} 762 763 764/* Read an array of color pixels. */ 765static void read_rgba_pixels_24(struct gl_context *ctx, 766 struct gl_renderbuffer *rb, 767 GLuint n, const GLint x[], const GLint y[], 768 void *values) 769{ 770 GLubyte (*rgba)[4] = (GLubyte (*)[4])values; 771 GLuint i; 772 LPBYTE lpb; 773 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 774 775 for (i=0; i<n; i++) { 776 GLint y2 = FLIP(y[i]); 777 lpb = ((LPBYTE)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + (3 * x[i]); 778 rgba[i][RCOMP] = lpb[3*i+2]; 779 rgba[i][GCOMP] = lpb[3*i+1]; 780 rgba[i][BCOMP] = lpb[3*i]; 781 rgba[i][ACOMP] = 255; 782 } 783} 784 785 786/*********************************************************************/ 787 788/* DOUBLE BUFFER 16-bit */ 789 790#define WMSETPIXEL16(pwc, y, x, r, g, b) { \ 791LPWORD lpw = ((LPWORD)((pwc)->pbPixels + (pwc)->ScanWidth * (y)) + (x)); \ 792*lpw = BGR16((r),(g),(b)); } 793 794 795 796/* Write a horizontal span of RGBA color pixels with a boolean mask. */ 797static void write_rgba_span_16(struct gl_context *ctx, 798 struct gl_renderbuffer *rb, 799 GLuint n, GLint x, GLint y, 800 const void *values, 801 const GLubyte *mask) 802{ 803 const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values; 804 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 805 GLuint i; 806 LPWORD lpw; 807 808 (void) ctx; 809 810 y=FLIP(y); 811 lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x; 812 if (mask) { 813 for (i=0; i<n; i++) 814 if (mask[i]) 815 lpw[i] = BGR16(rgba[i][RCOMP], rgba[i][GCOMP], 816 rgba[i][BCOMP]); 817 } 818 else { 819 for (i=0; i<n; i++) 820 *lpw++ = BGR16(rgba[i][RCOMP], rgba[i][GCOMP], 821 rgba[i][BCOMP]); 822 } 823} 824 825 826 827/* Write an array of RGBA pixels with a boolean mask. */ 828static void write_rgba_pixels_16(struct gl_context *ctx, 829 struct gl_renderbuffer *rb, 830 GLuint n, const GLint x[], const GLint y[], 831 const void *values, 832 const GLubyte *mask) 833{ 834 const GLubyte (*rgba)[4] = (const GLubyte (*)[4])values; 835 GLuint i; 836 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 837 (void) ctx; 838 for (i=0; i<n; i++) 839 if (mask[i]) 840 WMSETPIXEL16(pwfb, FLIP(y[i]), x[i], 841 rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]); 842} 843 844 845/* Read a horizontal span of color pixels. */ 846static void read_rgba_span_16(struct gl_context *ctx, 847 struct gl_renderbuffer *rb, 848 GLuint n, GLint x, GLint y, 849 void *values) 850{ 851 GLubyte (*rgba)[4] = (GLubyte (*)[4])values; 852 GLuint i, pixel; 853 LPWORD lpw; 854 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 855 856 y = FLIP(y); 857 lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y)) + x; 858 for (i=0; i<n; i++) { 859 pixel = lpw[i]; 860 /* Windows uses 5,5,5 for 16-bit */ 861 rgba[i][RCOMP] = (pixel & 0x7c00) >> 7; 862 rgba[i][GCOMP] = (pixel & 0x03e0) >> 2; 863 rgba[i][BCOMP] = (pixel & 0x001f) << 3; 864 rgba[i][ACOMP] = 255; 865 } 866} 867 868 869/* Read an array of color pixels. */ 870static void read_rgba_pixels_16(struct gl_context *ctx, 871 struct gl_renderbuffer *rb, 872 GLuint n, const GLint x[], const GLint y[], 873 void *values) 874{ 875 GLubyte (*rgba)[4] = (GLubyte (*)[4])values; 876 GLuint i, pixel; 877 LPWORD lpw; 878 WMesaFramebuffer pwfb = wmesa_framebuffer(ctx->DrawBuffer); 879 880 for (i=0; i<n; i++) { 881 GLint y2 = FLIP(y[i]); 882 lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i]; 883 pixel = *lpw; 884 /* Windows uses 5,5,5 for 16-bit */ 885 rgba[i][RCOMP] = (pixel & 0x7c00) >> 7; 886 rgba[i][GCOMP] = (pixel & 0x03e0) >> 2; 887 rgba[i][BCOMP] = (pixel & 0x001f) << 3; 888 rgba[i][ACOMP] = 255; 889 } 890} 891 892 893 894 895/**********************************************************************/ 896/***** BUFFER Functions *****/ 897/**********************************************************************/ 898 899 900 901 902static void 903wmesa_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb) 904{ 905 _mesa_delete_renderbuffer(ctx, rb); 906} 907 908 909/** 910 * This is called by Mesa whenever it determines that the window size 911 * has changed. Do whatever's needed to cope with that. 912 */ 913static GLboolean 914wmesa_renderbuffer_storage(struct gl_context *ctx, 915 struct gl_renderbuffer *rb, 916 GLenum internalFormat, 917 GLuint width, 918 GLuint height) 919{ 920 rb->Width = width; 921 rb->Height = height; 922 return GL_TRUE; 923} 924 925 926/** 927 * Called by ctx->Driver.ResizeBuffers() 928 * Resize the front/back colorbuffers to match the latest window size. 929 */ 930static void 931wmesa_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *buffer, 932 GLuint width, GLuint height) 933{ 934 WMesaFramebuffer pwfb = wmesa_framebuffer(buffer); 935 936 if (pwfb->Base.Width != width || pwfb->Base.Height != height) { 937 /* Realloc back buffer */ 938 if (ctx->Visual.doubleBufferMode == 1) { 939 wmDeleteBackingStore(pwfb); 940 wmCreateBackingStore(pwfb, width, height); 941 } 942 } 943 _mesa_resize_framebuffer(ctx, buffer, width, height); 944} 945 946 947/** 948 * Called by glViewport. 949 * This is a good time for us to poll the current window size and adjust 950 * our renderbuffers to match the current window size. 951 * Remember, we have no opportunity to respond to conventional 952 * resize events since the driver has no event loop. 953 * Thus, we poll. 954 * MakeCurrent also ends up making a call here, so that ensures 955 * we get the viewport set correctly, even if the app does not call 956 * glViewport and relies on the defaults. 957 */ 958static void wmesa_viewport(struct gl_context *ctx, 959 GLint x, GLint y, 960 GLsizei width, GLsizei height) 961{ 962 GLuint new_width, new_height; 963 964 wmesa_get_buffer_size(ctx->WinSysDrawBuffer, &new_width, &new_height); 965 966 /** 967 * Resize buffers if the window size changed. 968 */ 969 wmesa_resize_buffers(ctx, ctx->WinSysDrawBuffer, new_width, new_height); 970 ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */ 971} 972 973 974 975 976/** 977 * Called when the driver should update it's state, based on the new_state 978 * flags. 979 */ 980static void wmesa_update_state(struct gl_context *ctx, GLuint new_state) 981{ 982 _swrast_InvalidateState(ctx, new_state); 983 _swsetup_InvalidateState(ctx, new_state); 984 _vbo_InvalidateState(ctx, new_state); 985 _tnl_InvalidateState(ctx, new_state); 986 987 /* TODO - This code is not complete yet because I 988 * don't know what to do for all state updates. 989 */ 990 991 if (new_state & _NEW_BUFFERS) { 992 } 993} 994 995 996 997 998 999/**********************************************************************/ 1000/***** WMESA Functions *****/ 1001/**********************************************************************/ 1002 1003WMesaContext WMesaCreateContext(HDC hDC, 1004 HPALETTE* Pal, 1005 GLboolean rgb_flag, 1006 GLboolean db_flag, 1007 GLboolean alpha_flag) 1008{ 1009 WMesaContext c; 1010 struct dd_function_table functions; 1011 GLint red_bits, green_bits, blue_bits, alpha_bits; 1012 struct gl_context *ctx; 1013 struct gl_config *visual; 1014 1015 (void) Pal; 1016 1017 /* Indexed mode not supported */ 1018 if (!rgb_flag) 1019 return NULL; 1020 1021 /* Allocate wmesa context */ 1022 c = CALLOC_STRUCT(wmesa_context); 1023 if (!c) 1024 return NULL; 1025 1026#if 0 1027 /* I do not understand this contributed code */ 1028 /* Support memory and device contexts */ 1029 if(WindowFromDC(hDC) != NULL) { 1030 c->hDC = GetDC(WindowFromDC(hDC)); /* huh ???? */ 1031 } 1032 else { 1033 c->hDC = hDC; 1034 } 1035#else 1036 c->hDC = hDC; 1037#endif 1038 1039 /* Get data for visual */ 1040 /* Dealing with this is actually a bit of overkill because Mesa will end 1041 * up treating all color component size requests less than 8 by using 1042 * a single byte per channel. In addition, the interface to the span 1043 * routines passes colors as an entire byte per channel anyway, so there 1044 * is nothing to be saved by telling the visual to be 16 bits if the device 1045 * is 16 bits. That is, Mesa is going to compute colors down to 8 bits per 1046 * channel anyway. 1047 * But we go through the motions here anyway. 1048 */ 1049 switch (GetDeviceCaps(c->hDC, BITSPIXEL)) { 1050 case 16: 1051 red_bits = green_bits = blue_bits = 5; 1052 alpha_bits = 0; 1053 break; 1054 default: 1055 red_bits = green_bits = blue_bits = 8; 1056 alpha_bits = 8; 1057 break; 1058 } 1059 /* Create visual based on flags */ 1060 visual = _mesa_create_visual(db_flag, /* db_flag */ 1061 GL_FALSE, /* stereo */ 1062 red_bits, green_bits, blue_bits, /* color RGB */ 1063 alpha_flag ? alpha_bits : 0, /* color A */ 1064 DEFAULT_SOFTWARE_DEPTH_BITS, /* depth_bits */ 1065 8, /* stencil_bits */ 1066 16,16,16, /* accum RGB */ 1067 alpha_flag ? 16 : 0, /* accum A */ 1068 1); /* num samples */ 1069 1070 if (!visual) { 1071 free(c); 1072 return NULL; 1073 } 1074 1075 /* Set up driver functions */ 1076 _mesa_init_driver_functions(&functions); 1077 functions.GetString = wmesa_get_string; 1078 functions.UpdateState = wmesa_update_state; 1079 functions.GetBufferSize = wmesa_get_buffer_size; 1080 functions.Flush = wmesa_flush; 1081 functions.Clear = clear; 1082 functions.ResizeBuffers = wmesa_resize_buffers; 1083 functions.Viewport = wmesa_viewport; 1084 1085 /* initialize the Mesa context data */ 1086 ctx = &c->gl_ctx; 1087 _mesa_initialize_context(ctx, API_OPENGL, visual, 1088 NULL, &functions, (void *)c); 1089 1090 /* visual no longer needed - it was copied by _mesa_initialize_context() */ 1091 _mesa_destroy_visual(visual); 1092 1093 _mesa_enable_sw_extensions(ctx); 1094 _mesa_enable_1_3_extensions(ctx); 1095 _mesa_enable_1_4_extensions(ctx); 1096 _mesa_enable_1_5_extensions(ctx); 1097 _mesa_enable_2_0_extensions(ctx); 1098 _mesa_enable_2_1_extensions(ctx); 1099 1100 _mesa_meta_init(ctx); 1101 1102 /* Initialize the software rasterizer and helper modules. */ 1103 if (!_swrast_CreateContext(ctx) || 1104 !_vbo_CreateContext(ctx) || 1105 !_tnl_CreateContext(ctx) || 1106 !_swsetup_CreateContext(ctx)) { 1107 _mesa_free_context_data(ctx); 1108 free(c); 1109 return NULL; 1110 } 1111 _swsetup_Wakeup(ctx); 1112 TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline; 1113 1114 return c; 1115} 1116 1117 1118void WMesaDestroyContext( WMesaContext pwc ) 1119{ 1120 struct gl_context *ctx = &pwc->gl_ctx; 1121 WMesaFramebuffer pwfb; 1122 GET_CURRENT_CONTEXT(cur_ctx); 1123 1124 if (cur_ctx == ctx) { 1125 /* unbind current if deleting current context */ 1126 WMesaMakeCurrent(NULL, NULL); 1127 } 1128 1129 /* clean up frame buffer resources */ 1130 pwfb = wmesa_lookup_framebuffer(pwc->hDC); 1131 if (pwfb) { 1132 if (ctx->Visual.doubleBufferMode == 1) 1133 wmDeleteBackingStore(pwfb); 1134 wmesa_free_framebuffer(pwc->hDC); 1135 } 1136 1137 /* Release for device, not memory contexts */ 1138 if (WindowFromDC(pwc->hDC) != NULL) 1139 { 1140 ReleaseDC(WindowFromDC(pwc->hDC), pwc->hDC); 1141 } 1142 DeleteObject(pwc->clearPen); 1143 DeleteObject(pwc->clearBrush); 1144 1145 _mesa_meta_free(ctx); 1146 1147 _swsetup_DestroyContext(ctx); 1148 _tnl_DestroyContext(ctx); 1149 _vbo_DestroyContext(ctx); 1150 _swrast_DestroyContext(ctx); 1151 1152 _mesa_free_context_data(ctx); 1153 free(pwc); 1154} 1155 1156 1157/** 1158 * Create a new color renderbuffer. 1159 */ 1160static struct gl_renderbuffer * 1161wmesa_new_renderbuffer(void) 1162{ 1163 struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer); 1164 if (!rb) 1165 return NULL; 1166 1167 _mesa_init_renderbuffer(rb, (GLuint)0); 1168 1169 rb->_BaseFormat = GL_RGBA; 1170 rb->InternalFormat = GL_RGBA; 1171 rb->Delete = wmesa_delete_renderbuffer; 1172 rb->AllocStorage = wmesa_renderbuffer_storage; 1173 return rb; 1174} 1175 1176 1177void WMesaMakeCurrent(WMesaContext c, HDC hdc) 1178{ 1179 WMesaFramebuffer pwfb; 1180 1181 { 1182 /* return if already current */ 1183 GET_CURRENT_CONTEXT(ctx); 1184 WMesaContext pwc = wmesa_context(ctx); 1185 if (pwc && c == pwc && pwc->hDC == hdc) 1186 return; 1187 } 1188 1189 pwfb = wmesa_lookup_framebuffer(hdc); 1190 1191 /* Lazy creation of framebuffers */ 1192 if (c && !pwfb && hdc) { 1193 struct gl_renderbuffer *rb; 1194 struct gl_config *visual = &c->gl_ctx.Visual; 1195 GLuint width, height; 1196 1197 get_window_size(hdc, &width, &height); 1198 1199 c->clearPen = CreatePen(PS_SOLID, 1, 0); 1200 c->clearBrush = CreateSolidBrush(0); 1201 1202 pwfb = wmesa_new_framebuffer(hdc, visual); 1203 1204 /* Create back buffer if double buffered */ 1205 if (visual->doubleBufferMode == 1) { 1206 wmCreateBackingStore(pwfb, width, height); 1207 } 1208 1209 /* make render buffers */ 1210 if (visual->doubleBufferMode == 1) { 1211 rb = wmesa_new_renderbuffer(); 1212 _mesa_add_renderbuffer(&pwfb->Base, BUFFER_BACK_LEFT, rb); 1213 } 1214 rb = wmesa_new_renderbuffer(); 1215 _mesa_add_renderbuffer(&pwfb->Base, BUFFER_FRONT_LEFT, rb); 1216 1217 /* Let Mesa own the Depth, Stencil, and Accum buffers */ 1218 _swrast_add_soft_renderbuffers(&pwfb->Base, 1219 GL_FALSE, /* color */ 1220 visual->depthBits > 0, 1221 visual->stencilBits > 0, 1222 visual->accumRedBits > 0, 1223 visual->alphaBits >0, 1224 GL_FALSE); 1225 } 1226 1227 if (c && pwfb) 1228 _mesa_make_current(&c->gl_ctx, &pwfb->Base, &pwfb->Base); 1229 else 1230 _mesa_make_current(NULL, NULL, NULL); 1231} 1232 1233 1234void WMesaSwapBuffers( HDC hdc ) 1235{ 1236 GET_CURRENT_CONTEXT(ctx); 1237 WMesaContext pwc = wmesa_context(ctx); 1238 WMesaFramebuffer pwfb = wmesa_lookup_framebuffer(hdc); 1239 1240 if (!pwfb) { 1241 _mesa_problem(NULL, "wmesa: swapbuffers on unknown hdc"); 1242 return; 1243 } 1244 1245 /* If we're swapping the buffer associated with the current context 1246 * we have to flush any pending rendering commands first. 1247 */ 1248 if (pwc->hDC == hdc) { 1249 _mesa_notifySwapBuffers(ctx); 1250 1251 BitBlt(pwfb->hDC, 0, 0, pwfb->Base.Width, pwfb->Base.Height, 1252 pwfb->dib_hDC, 0, 0, SRCCOPY); 1253 } 1254 else { 1255 /* XXX for now only allow swapping current window */ 1256 _mesa_problem(NULL, "wmesa: can't swap non-current window"); 1257 } 1258} 1259 1260void WMesaShareLists(WMesaContext ctx_to_share, WMesaContext ctx) 1261{ 1262 _mesa_share_state(&ctx->gl_ctx, &ctx_to_share->gl_ctx); 1263} 1264 1265