wmesa.c revision 24d55a1145d52d221c7aa7066e033ca34e3ddef5
1/* 2 * Windows (Win32) 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 // TEMP - 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), 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 885/** 886 * Called by ctx->Driver.ResizeBuffers() 887 * Resize the front/back colorbuffers to match the latest window size. 888 */ 889static void 890wmesa_resize_buffers(GLcontext *ctx, GLframebuffer *buffer, 891 GLuint width, GLuint height) 892{ 893 RECT CR; 894 if (Current->width != width || Current->height != height) { 895 Current->width = width; 896 Current->height = height; 897 /* Realloc back buffer */ 898 if (Current->db_flag) { 899 wmDeleteBackingStore(Current); 900 wmCreateBackingStore(Current, width, height); 901 } 902 GetClientRect(Current->Window, &CR); 903 Current->width = CR.right; 904 Current->height = CR.bottom; 905 } 906 _mesa_resize_framebuffer(ctx, buffer, width, height); 907} 908 909 910/** 911 * Called by glViewport. 912 * This is a good time for us to poll the current window size and adjust 913 * our renderbuffers to match the current window size. 914 * Remember, we have no opportunity to respond to conventional 915 * resize events since the driver has no event loop. 916 * Thus, we poll. 917 * Note that this trick isn't fool-proof. If the application never calls 918 * glViewport, our notion of the current window size may be incorrect. 919 */ 920static void wmesa_viewport(GLcontext *ctx, 921 GLint x, GLint y, 922 GLsizei width, GLsizei height) 923{ 924 if (Current->width != width || Current->height != height) { 925 wmesa_resize_buffers(ctx, ctx->WinSysDrawBuffer, width, height); 926 ctx->NewState |= _NEW_BUFFERS; /* to update scissor / window bounds */ 927 } 928} 929 930 931 932 933/** 934 * Called when the driver should update it's state, based on the new_state 935 * flags. 936 */ 937static void wmesa_update_state(GLcontext *ctx, GLuint new_state) 938{ 939 _swrast_InvalidateState(ctx, new_state); 940 _swsetup_InvalidateState(ctx, new_state); 941 _ac_InvalidateState(ctx, new_state); 942 _tnl_InvalidateState(ctx, new_state); 943 944 /* TODO - need code to update the span functions in case the 945 * renderer changes the target buffer (like a DB app writing to 946 * the front buffer). */ 947} 948 949 950 951 952 953/**********************************************************************/ 954/***** WMESA Functions *****/ 955/**********************************************************************/ 956 957WMesaContext WMesaCreateContext(HWND hWnd, 958 HPALETTE* Pal, 959 GLboolean rgb_flag, 960 GLboolean db_flag, 961 GLboolean alpha_flag) 962{ 963 RECT CR; 964 WMesaContext c; 965 struct dd_function_table functions; 966 struct gl_renderbuffer *rb; 967 968 (void) Pal; 969 970 /* Indexed mode not supported */ 971 if (!rgb_flag) 972 return NULL; 973 974 c = CALLOC_STRUCT(wmesa_context); 975 if (!c) 976 return NULL; 977 978 c->Window = hWnd; 979 c->hDC = GetDC(hWnd); 980 GetClientRect(c->Window, &CR); 981 c->width = CR.right; 982 c->height = CR.bottom; 983 984 c->clearPen = CreatePen(PS_SOLID, 1, 0); 985 c->clearBrush = CreateSolidBrush(0); 986 987 /* Create back buffer if double buffered */ 988 if (db_flag) { 989 c->db_flag = 1; 990 wmCreateBackingStore(c, c->width, c->height); 991 992 } 993 994 c->gl_visual = _mesa_create_visual(rgb_flag, 995 db_flag, /* db_flag */ 996 GL_FALSE, /* stereo */ 997 8,8,8, /* color RGB */ 998 alpha_flag ? 8 : 0, /* color A */ 999 0, /* index bits */ 1000 16, /* depth_bits */ 1001 8, /* stencil_bits */ 1002 16,16,16, /* accum RGB */ 1003 alpha_flag ? 16 : 0, /* accum A */ 1004 1); 1005 1006 if (!c->gl_visual) { 1007 _mesa_free(c); 1008 return NULL; 1009 } 1010 1011 /* Set up driver functions */ 1012 _mesa_init_driver_functions(&functions); 1013 /* Fill in required functions */ 1014 functions.GetString = wmesa_get_string; 1015 functions.UpdateState = wmesa_update_state; 1016 functions.GetBufferSize = wmesa_get_buffer_size; 1017 functions.Flush = wmesa_flush; 1018 1019 functions.Clear = clear; 1020 functions.ClearIndex = clear_index; 1021 functions.ClearColor = clear_color; 1022 1023 functions.ResizeBuffers = wmesa_resize_buffers; 1024 functions.Viewport = wmesa_viewport; 1025 1026 /* allocate a new Mesa context */ 1027 c->gl_ctx = _mesa_create_context(c->gl_visual, NULL, 1028 &functions, (void *)c); 1029 if (!c->gl_ctx) { 1030 _mesa_destroy_visual( c->gl_visual ); 1031 _mesa_free(c); 1032 return NULL; 1033 } 1034 1035 _mesa_enable_sw_extensions(c->gl_ctx); 1036 _mesa_enable_1_3_extensions(c->gl_ctx); 1037 _mesa_enable_1_4_extensions(c->gl_ctx); 1038 _mesa_enable_1_5_extensions(c->gl_ctx); 1039 _mesa_enable_2_0_extensions(c->gl_ctx); 1040 1041 c->gl_buffer = _mesa_create_framebuffer(c->gl_visual); 1042 if (!c->gl_buffer) { 1043 _mesa_destroy_visual(c->gl_visual); 1044 _mesa_free_context_data(c->gl_ctx); 1045 _mesa_free(c); 1046 return NULL; 1047 } 1048 1049 rb = CALLOC_STRUCT(gl_renderbuffer); 1050 1051 if (!rb) { 1052 _mesa_destroy_visual(c->gl_visual); 1053 _mesa_destroy_framebuffer(c->gl_buffer); 1054 _mesa_free_context_data(c->gl_ctx); 1055 _mesa_free(c); 1056 return NULL; 1057 } 1058 1059 _mesa_init_renderbuffer(rb, (GLuint)0); 1060 1061 rb->_BaseFormat = GL_RGBA; 1062 rb->InternalFormat = GL_RGBA; 1063 rb->DataType = CHAN_TYPE; 1064 rb->Delete = wmesa_delete_renderbuffer; 1065 rb->AllocStorage = wmesa_renderbuffer_storage; 1066 1067 if (db_flag) { 1068 switch(c->cColorBits) { 1069 case 16: 1070 rb->PutRow = write_rgba_span_16; 1071 rb->PutRowRGB = write_rgb_span_16; 1072 rb->PutMonoRow = write_mono_rgba_span_16; 1073 rb->PutValues = write_rgba_pixels_16; 1074 rb->PutMonoValues = write_mono_rgba_pixels_16; 1075 rb->GetRow = read_rgba_span_16; 1076 rb->GetValues = read_rgba_pixels_16; 1077 break; 1078 case 32: 1079 rb->PutRow = write_rgba_span_32; 1080 rb->PutRowRGB = write_rgb_span_32; 1081 rb->PutMonoRow = write_mono_rgba_span_32; 1082 rb->PutValues = write_rgba_pixels_32; 1083 rb->PutMonoValues = write_mono_rgba_pixels_32; 1084 rb->GetRow = read_rgba_span_32; 1085 rb->GetValues = read_rgba_pixels_32; 1086 break; 1087 default: 1088 break; 1089 } 1090 _mesa_add_renderbuffer(c->gl_buffer, BUFFER_BACK_LEFT, rb); 1091 } 1092 else { /* single buffer */ 1093 rb->PutRow = write_rgba_span_single; 1094 rb->PutRowRGB = write_rgb_span_single; 1095 rb->PutMonoRow = write_mono_rgba_span_single; 1096 rb->PutValues = write_rgba_pixels_single; 1097 rb->PutMonoValues = write_mono_rgba_pixels_single; 1098 rb->GetRow = read_rgba_span_single; 1099 rb->GetValues = read_rgba_pixels_single; 1100 _mesa_add_renderbuffer(c->gl_buffer, BUFFER_FRONT_LEFT, rb); 1101 } 1102 1103 _mesa_add_soft_renderbuffers(c->gl_buffer, 1104 GL_FALSE, /* color */ 1105 c->gl_visual->depthBits > 0, 1106 c->gl_visual->stencilBits > 0, 1107 c->gl_visual->accumRedBits > 0, 1108 alpha_flag, 1109 GL_FALSE); 1110 1111 /* Initialize the software rasterizer and helper modules. */ 1112 if (!_swrast_CreateContext(c->gl_ctx) || 1113 !_ac_CreateContext(c->gl_ctx) || 1114 !_tnl_CreateContext(c->gl_ctx) || 1115 !_swsetup_CreateContext(c->gl_ctx)) { 1116 _mesa_destroy_visual(c->gl_visual); 1117 _mesa_destroy_framebuffer(c->gl_buffer); 1118 _mesa_free_context_data(c->gl_ctx); 1119 _mesa_free(c); 1120 return NULL; 1121 } 1122 1123 _swsetup_Wakeup(c->gl_ctx); 1124 1125 TNL_CONTEXT(c->gl_ctx)->Driver.RunPipeline = _tnl_run_pipeline; 1126 1127 return c; 1128} 1129 1130void WMesaDestroyContext( void ) 1131{ 1132 WMesaContext c = Current; 1133 1134 WMesaMakeCurrent(NULL); 1135 1136 ReleaseDC(c->Window, c->hDC); 1137 DeleteObject(c->clearPen); 1138 DeleteObject(c->clearBrush); 1139 1140 if (c->db_flag) 1141 wmDeleteBackingStore(c); 1142 1143 _swsetup_DestroyContext(c->gl_ctx); 1144 _tnl_DestroyContext(c->gl_ctx); 1145 _ac_DestroyContext(c->gl_ctx); 1146 _swrast_DestroyContext(c->gl_ctx); 1147 1148 _mesa_destroy_visual(c->gl_visual); 1149 _mesa_destroy_framebuffer(c->gl_buffer); 1150 _mesa_free_context_data(c->gl_ctx); 1151 _mesa_free(c->gl_ctx); 1152 _mesa_free(c); 1153} 1154 1155 1156void WMesaMakeCurrent(WMesaContext c) 1157{ 1158 /* return if already current */ 1159 if (Current == c) 1160 return; 1161 1162 if (Current = c) 1163 _mesa_make_current(c->gl_ctx, c->gl_buffer, c->gl_buffer); 1164} 1165 1166 1167void WMesaSwapBuffers( void ) 1168{ 1169 GET_CURRENT_CONTEXT(ctx); 1170 1171 /* If we're swapping the buffer associated with the current context 1172 * we have to flush any pending rendering commands first. 1173 */ 1174 if (Current && Current->gl_ctx == ctx) 1175 _mesa_notifySwapBuffers(ctx); 1176 1177 if (Current->db_flag) 1178 wmesa_flush(ctx); 1179} 1180 1181/**********************************************************************/ 1182/***** END *****/ 1183/**********************************************************************/ 1184