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