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