1 /* $Id: logic.c,v 1.7 1997/07/24 01:24:11 brianp Exp $ */ 2 3 /* 4 * Mesa 3-D graphics library 5 * Version: 2.4 6 * Copyright (C) 1995-1997 Brian Paul 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Library General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Library General Public License for more details. 17 * 18 * You should have received a copy of the GNU Library General Public 19 * License along with this library; if not, write to the Free 20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 */ 22 23 24 /* 25 * $Log: logic.c,v $ 26 * Revision 1.7 1997/07/24 01:24:11 brianp 27 * changed precompiled header symbol from PCH to PC_HEADER 28 * 29 * Revision 1.6 1997/05/28 03:25:26 brianp 30 * added precompiled header (PCH) support 31 * 32 * Revision 1.5 1997/04/20 20:28:49 brianp 33 * replaced abort() with gl_problem() 34 * 35 * Revision 1.4 1997/03/04 18:56:57 brianp 36 * added #include <stdlib.h> for abort() 37 * 38 * Revision 1.3 1997/01/28 22:16:31 brianp 39 * added gl_logicop_rgba_span() and gl_logicop_rgba_pixels() 40 * 41 * Revision 1.2 1997/01/04 00:13:11 brianp 42 * was using ! instead of ~ to invert pixel bits (ugh!) 43 * 44 * Revision 1.1 1996/09/13 01:38:16 brianp 45 * Initial revision 46 * 47 */ 48 49 50 #ifdef PC_HEADER 51 #include "all.h" 52 #else 53 #include <stdlib.h> 54 #include "alphabuf.h" 55 #include "context.h" 56 #include "dlist.h" 57 #include "logic.h" 58 #include "macros.h" 59 #include "pb.h" 60 #include "span.h" 61 #include "types.h" 62 #endif 63 64 65 66 void gl_LogicOp( GLcontext *ctx, GLenum opcode ) 67 { 68 if (INSIDE_BEGIN_END(ctx)) { 69 gl_error( ctx, GL_INVALID_OPERATION, "glLogicOp" ); 70 return; 71 } 72 switch (opcode) { 73 case GL_CLEAR: 74 case GL_SET: 75 case GL_COPY: 76 case GL_COPY_INVERTED: 77 case GL_NOOP: 78 case GL_INVERT: 79 case GL_AND: 80 case GL_NAND: 81 case GL_OR: 82 case GL_NOR: 83 case GL_XOR: 84 case GL_EQUIV: 85 case GL_AND_REVERSE: 86 case GL_AND_INVERTED: 87 case GL_OR_REVERSE: 88 case GL_OR_INVERTED: 89 ctx->Color.LogicOp = opcode; 90 ctx->NewState |= NEW_RASTER_OPS; 91 return; 92 default: 93 gl_error( ctx, GL_INVALID_ENUM, "glLogicOp" ); 94 return; 95 } 96 } 97 98 99 100 101 /* 102 * Apply the current logic operator to a span of CI pixels. This is only 103 * used if the device driver can't do logic ops. 104 */ 105 void gl_logicop_ci_span( GLcontext *ctx, GLuint n, GLint x, GLint y, 106 GLuint index[], GLubyte mask[] ) 107 { 108 GLuint dest[MAX_WIDTH]; 109 GLuint i; 110 111 /* Read dest values from frame buffer */ 112 (*ctx->Driver.ReadIndexSpan)( ctx, n, x, y, dest ); 113 114 switch (ctx->Color.LogicOp) { 115 case GL_CLEAR: 116 for (i=0;i<n;i++) { 117 if (mask[i]) { 118 index[i] = 0; 119 } 120 } 121 break; 122 case GL_SET: 123 for (i=0;i<n;i++) { 124 if (mask[i]) { 125 index[i] = 1; 126 } 127 } 128 break; 129 case GL_COPY: 130 /* do nothing */ 131 break; 132 case GL_COPY_INVERTED: 133 for (i=0;i<n;i++) { 134 if (mask[i]) { 135 index[i] = ~index[i]; 136 } 137 } 138 break; 139 case GL_NOOP: 140 for (i=0;i<n;i++) { 141 if (mask[i]) { 142 index[i] = dest[i]; 143 } 144 } 145 break; 146 case GL_INVERT: 147 for (i=0;i<n;i++) { 148 if (mask[i]) { 149 index[i] = ~dest[i]; 150 } 151 } 152 break; 153 case GL_AND: 154 for (i=0;i<n;i++) { 155 if (mask[i]) { 156 index[i] &= dest[i]; 157 } 158 } 159 break; 160 case GL_NAND: 161 for (i=0;i<n;i++) { 162 if (mask[i]) { 163 index[i] = ~(index[i] & dest[i]); 164 } 165 } 166 break; 167 case GL_OR: 168 for (i=0;i<n;i++) { 169 if (mask[i]) { 170 index[i] |= dest[i]; 171 } 172 } 173 break; 174 case GL_NOR: 175 for (i=0;i<n;i++) { 176 if (mask[i]) { 177 index[i] = ~(index[i] | dest[i]); 178 } 179 } 180 break; 181 case GL_XOR: 182 for (i=0;i<n;i++) { 183 if (mask[i]) { 184 index[i] ^= dest[i]; 185 } 186 } 187 break; 188 case GL_EQUIV: 189 for (i=0;i<n;i++) { 190 if (mask[i]) { 191 index[i] = ~(index[i] ^ dest[i]); 192 } 193 } 194 break; 195 case GL_AND_REVERSE: 196 for (i=0;i<n;i++) { 197 if (mask[i]) { 198 index[i] = index[i] & ~dest[i]; 199 } 200 } 201 break; 202 case GL_AND_INVERTED: 203 for (i=0;i<n;i++) { 204 if (mask[i]) { 205 index[i] = ~index[i] & dest[i]; 206 } 207 } 208 break; 209 case GL_OR_REVERSE: 210 for (i=0;i<n;i++) { 211 if (mask[i]) { 212 index[i] = index[i] | ~dest[i]; 213 } 214 } 215 break; 216 case GL_OR_INVERTED: 217 for (i=0;i<n;i++) { 218 if (mask[i]) { 219 index[i] = ~index[i] | dest[i]; 220 } 221 } 222 break; 223 default: 224 gl_error( ctx, GL_INVALID_ENUM, "gl_logic error" ); 225 } 226 } 227 228 229 230 /* 231 * Apply the current logic operator to an array of CI pixels. This is only 232 * used if the device driver can't do logic ops. 233 */ 234 void gl_logicop_ci_pixels( GLcontext *ctx, 235 GLuint n, const GLint x[], const GLint y[], 236 GLuint index[], GLubyte mask[] ) 237 { 238 GLuint dest[PB_SIZE]; 239 GLuint i; 240 241 /* Read dest values from frame buffer */ 242 (*ctx->Driver.ReadIndexPixels)( ctx, n, x, y, dest, mask ); 243 244 switch (ctx->Color.LogicOp) { 245 case GL_CLEAR: 246 for (i=0;i<n;i++) { 247 if (mask[i]) { 248 index[i] = 0; 249 } 250 } 251 break; 252 case GL_SET: 253 for (i=0;i<n;i++) { 254 if (mask[i]) { 255 index[i] = 1; 256 } 257 } 258 break; 259 case GL_COPY: 260 /* do nothing */ 261 break; 262 case GL_COPY_INVERTED: 263 for (i=0;i<n;i++) { 264 if (mask[i]) { 265 index[i] = ~index[i]; 266 } 267 } 268 break; 269 case GL_NOOP: 270 for (i=0;i<n;i++) { 271 if (mask[i]) { 272 index[i] = dest[i]; 273 } 274 } 275 break; 276 case GL_INVERT: 277 for (i=0;i<n;i++) { 278 if (mask[i]) { 279 index[i] = ~dest[i]; 280 } 281 } 282 break; 283 case GL_AND: 284 for (i=0;i<n;i++) { 285 if (mask[i]) { 286 index[i] &= dest[i]; 287 } 288 } 289 break; 290 case GL_NAND: 291 for (i=0;i<n;i++) { 292 if (mask[i]) { 293 index[i] = ~(index[i] & dest[i]); 294 } 295 } 296 break; 297 case GL_OR: 298 for (i=0;i<n;i++) { 299 if (mask[i]) { 300 index[i] |= dest[i]; 301 } 302 } 303 break; 304 case GL_NOR: 305 for (i=0;i<n;i++) { 306 if (mask[i]) { 307 index[i] = ~(index[i] | dest[i]); 308 } 309 } 310 break; 311 case GL_XOR: 312 for (i=0;i<n;i++) { 313 if (mask[i]) { 314 index[i] ^= dest[i]; 315 } 316 } 317 break; 318 case GL_EQUIV: 319 for (i=0;i<n;i++) { 320 if (mask[i]) { 321 index[i] = ~(index[i] ^ dest[i]); 322 } 323 } 324 break; 325 case GL_AND_REVERSE: 326 for (i=0;i<n;i++) { 327 if (mask[i]) { 328 index[i] = index[i] & ~dest[i]; 329 } 330 } 331 break; 332 case GL_AND_INVERTED: 333 for (i=0;i<n;i++) { 334 if (mask[i]) { 335 index[i] = ~index[i] & dest[i]; 336 } 337 } 338 break; 339 case GL_OR_REVERSE: 340 for (i=0;i<n;i++) { 341 if (mask[i]) { 342 index[i] = index[i] | ~dest[i]; 343 } 344 } 345 break; 346 case GL_OR_INVERTED: 347 for (i=0;i<n;i++) { 348 if (mask[i]) { 349 index[i] = ~index[i] | dest[i]; 350 } 351 } 352 break; 353 default: 354 gl_error( ctx, GL_INVALID_ENUM, "gl_logic_pixels error" ); 355 } 356 } 357 358 359 360 /* 361 * Apply the current logic operator to a span of RGBA pixels. This is only 362 * used if the device driver can't do logic ops. 363 */ 364 void gl_logicop_rgba_span( GLcontext *ctx, 365 GLuint n, GLint x, GLint y, 366 GLubyte red[], GLubyte green[], 367 GLubyte blue[], GLubyte alpha[], 368 GLubyte mask[] ) 369 { 370 GLubyte rdest[MAX_WIDTH], gdest[MAX_WIDTH]; 371 GLubyte bdest[MAX_WIDTH], adest[MAX_WIDTH]; 372 GLuint i; 373 374 /* Read span of current frame buffer pixels */ 375 gl_read_color_span( ctx, n, x, y, rdest, gdest, bdest, adest ); 376 377 /* apply logic op */ 378 switch (ctx->Color.LogicOp) { 379 case GL_CLEAR: 380 for (i=0;i<n;i++) { 381 if (mask[i]) { 382 red[i] = green[i] = blue[i] = alpha[i] = 0; 383 } 384 } 385 break; 386 case GL_SET: 387 { 388 GLubyte r = (GLint) ctx->Visual->RedScale; 389 GLubyte g = (GLint) ctx->Visual->GreenScale; 390 GLubyte b = (GLint) ctx->Visual->BlueScale; 391 GLubyte a = (GLint) ctx->Visual->AlphaScale; 392 for (i=0;i<n;i++) { 393 if (mask[i]) { 394 red[i] = r; 395 green[i] = g; 396 blue[i] = b; 397 alpha[i] = a; 398 } 399 } 400 } 401 break; 402 case GL_COPY: 403 /* do nothing */ 404 break; 405 case GL_COPY_INVERTED: 406 for (i=0;i<n;i++) { 407 if (mask[i]) { 408 red[i] = ~red[i]; 409 green[i] = ~green[i]; 410 blue[i] = ~blue[i]; 411 alpha[i] = ~alpha[i]; 412 } 413 } 414 break; 415 case GL_NOOP: 416 for (i=0;i<n;i++) { 417 if (mask[i]) { 418 red[i] = rdest[i]; 419 green[i] = gdest[i]; 420 blue[i] = bdest[i]; 421 alpha[i] = adest[i]; 422 } 423 } 424 break; 425 case GL_INVERT: 426 for (i=0;i<n;i++) { 427 if (mask[i]) { 428 red[i] = ~rdest[i]; 429 green[i] = ~gdest[i]; 430 blue[i] = ~bdest[i]; 431 alpha[i] = ~adest[i]; 432 } 433 } 434 break; 435 case GL_AND: 436 for (i=0;i<n;i++) { 437 if (mask[i]) { 438 red[i] &= rdest[i]; 439 green[i] &= gdest[i]; 440 blue[i] &= bdest[i]; 441 alpha[i] &= adest[i]; 442 } 443 } 444 break; 445 case GL_NAND: 446 for (i=0;i<n;i++) { 447 if (mask[i]) { 448 red[i] = ~(red[i] & rdest[i]); 449 green[i] = ~(green[i] & gdest[i]); 450 blue[i] = ~(blue[i] & bdest[i]); 451 alpha[i] = ~(alpha[i] & adest[i]); 452 } 453 } 454 break; 455 case GL_OR: 456 for (i=0;i<n;i++) { 457 if (mask[i]) { 458 red[i] |= rdest[i]; 459 green[i] |= gdest[i]; 460 blue[i] |= bdest[i]; 461 alpha[i] |= adest[i]; 462 } 463 } 464 break; 465 case GL_NOR: 466 for (i=0;i<n;i++) { 467 if (mask[i]) { 468 red[i] = ~(red[i] | rdest[i]); 469 green[i] = ~(green[i] | gdest[i]); 470 blue[i] = ~(blue[i] | bdest[i]); 471 alpha[i] = ~(alpha[i] | adest[i]); 472 } 473 } 474 break; 475 case GL_XOR: 476 for (i=0;i<n;i++) { 477 if (mask[i]) { 478 red[i] ^= rdest[i]; 479 green[i] ^= gdest[i]; 480 blue[i] ^= bdest[i]; 481 alpha[i] ^= adest[i]; 482 } 483 } 484 break; 485 case GL_EQUIV: 486 for (i=0;i<n;i++) { 487 if (mask[i]) { 488 red[i] = ~(red[i] ^ rdest[i]); 489 green[i] = ~(green[i] ^ gdest[i]); 490 blue[i] = ~(blue[i] ^ bdest[i]); 491 alpha[i] = ~(alpha[i] ^ adest[i]); 492 } 493 } 494 break; 495 case GL_AND_REVERSE: 496 for (i=0;i<n;i++) { 497 if (mask[i]) { 498 red[i] = red[i] & ~rdest[i]; 499 green[i] = green[i] & ~gdest[i]; 500 blue[i] = blue[i] & ~bdest[i]; 501 alpha[i] = alpha[i] & ~adest[i]; 502 } 503 } 504 break; 505 case GL_AND_INVERTED: 506 for (i=0;i<n;i++) { 507 if (mask[i]) { 508 red[i] = ~red[i] & rdest[i]; 509 green[i] = ~green[i] & gdest[i]; 510 blue[i] = ~blue[i] & bdest[i]; 511 alpha[i] = ~alpha[i] & adest[i]; 512 } 513 } 514 break; 515 case GL_OR_REVERSE: 516 for (i=0;i<n;i++) { 517 if (mask[i]) { 518 red[i] = red[i] | ~rdest[i]; 519 green[i] = green[i] | ~gdest[i]; 520 blue[i] = blue[i] | ~bdest[i]; 521 alpha[i] = alpha[i] | ~adest[i]; 522 } 523 } 524 break; 525 case GL_OR_INVERTED: 526 for (i=0;i<n;i++) { 527 if (mask[i]) { 528 red[i] = ~red[i] | rdest[i]; 529 green[i] = ~green[i] | gdest[i]; 530 blue[i] = ~blue[i] | bdest[i]; 531 alpha[i] = ~alpha[i] | adest[i]; 532 } 533 } 534 break; 535 default: 536 /* should never happen */ 537 gl_problem(ctx, "Bad function in gl_logicop_rgba_span"); 538 return; 539 } 540 } 541 542 543 544 /* 545 * Apply the current logic operator to an array of RGBA pixels. This is only 546 * used if the device driver can't do logic ops. 547 */ 548 void gl_logicop_rgba_pixels( GLcontext *ctx, 549 GLuint n, const GLint x[], const GLint y[], 550 GLubyte red[], GLubyte green[], 551 GLubyte blue[], GLubyte alpha[], 552 GLubyte mask[] ) 553 { 554 GLubyte rdest[PB_SIZE], gdest[PB_SIZE], bdest[PB_SIZE], adest[PB_SIZE]; 555 GLuint i; 556 557 /* Read pixels from current color buffer */ 558 (*ctx->Driver.ReadColorPixels)( ctx, n, x, y, rdest, gdest, bdest, adest, mask ); 559 if (ctx->RasterMask & ALPHABUF_BIT) { 560 gl_read_alpha_pixels( ctx, n, x, y, adest, mask ); 561 } 562 563 /* apply logic op */ 564 switch (ctx->Color.LogicOp) { 565 case GL_CLEAR: 566 for (i=0;i<n;i++) { 567 if (mask[i]) { 568 red[i] = green[i] = blue[i] = alpha[i] = 0; 569 } 570 } 571 break; 572 case GL_SET: 573 { 574 GLubyte r = (GLint) ctx->Visual->RedScale; 575 GLubyte g = (GLint) ctx->Visual->GreenScale; 576 GLubyte b = (GLint) ctx->Visual->BlueScale; 577 GLubyte a = (GLint) ctx->Visual->AlphaScale; 578 for (i=0;i<n;i++) { 579 if (mask[i]) { 580 red[i] = r; 581 green[i] = g; 582 blue[i] = b; 583 alpha[i] = a; 584 } 585 } 586 } 587 break; 588 case GL_COPY: 589 /* do nothing */ 590 break; 591 case GL_COPY_INVERTED: 592 for (i=0;i<n;i++) { 593 if (mask[i]) { 594 red[i] = ~red[i]; 595 green[i] = ~green[i]; 596 blue[i] = ~blue[i]; 597 alpha[i] = ~alpha[i]; 598 } 599 } 600 break; 601 case GL_NOOP: 602 for (i=0;i<n;i++) { 603 if (mask[i]) { 604 red[i] = rdest[i]; 605 green[i] = gdest[i]; 606 blue[i] = bdest[i]; 607 alpha[i] = adest[i]; 608 } 609 } 610 break; 611 case GL_INVERT: 612 for (i=0;i<n;i++) { 613 if (mask[i]) { 614 red[i] = ~rdest[i]; 615 green[i] = ~gdest[i]; 616 blue[i] = ~bdest[i]; 617 alpha[i] = ~adest[i]; 618 } 619 } 620 break; 621 case GL_AND: 622 for (i=0;i<n;i++) { 623 if (mask[i]) { 624 red[i] &= rdest[i]; 625 green[i] &= gdest[i]; 626 blue[i] &= bdest[i]; 627 alpha[i] &= adest[i]; 628 } 629 } 630 break; 631 case GL_NAND: 632 for (i=0;i<n;i++) { 633 if (mask[i]) { 634 red[i] = ~(red[i] & rdest[i]); 635 green[i] = ~(green[i] & gdest[i]); 636 blue[i] = ~(blue[i] & bdest[i]); 637 alpha[i] = ~(alpha[i] & adest[i]); 638 } 639 } 640 break; 641 case GL_OR: 642 for (i=0;i<n;i++) { 643 if (mask[i]) { 644 red[i] |= rdest[i]; 645 green[i] |= gdest[i]; 646 blue[i] |= bdest[i]; 647 alpha[i] |= adest[i]; 648 } 649 } 650 break; 651 case GL_NOR: 652 for (i=0;i<n;i++) { 653 if (mask[i]) { 654 red[i] = ~(red[i] | rdest[i]); 655 green[i] = ~(green[i] | gdest[i]); 656 blue[i] = ~(blue[i] | bdest[i]); 657 alpha[i] = ~(alpha[i] | adest[i]); 658 } 659 } 660 break; 661 case GL_XOR: 662 for (i=0;i<n;i++) { 663 if (mask[i]) { 664 red[i] ^= rdest[i]; 665 green[i] ^= gdest[i]; 666 blue[i] ^= bdest[i]; 667 alpha[i] ^= adest[i]; 668 } 669 } 670 break; 671 case GL_EQUIV: 672 for (i=0;i<n;i++) { 673 if (mask[i]) { 674 red[i] = ~(red[i] ^ rdest[i]); 675 green[i] = ~(green[i] ^ gdest[i]); 676 blue[i] = ~(blue[i] ^ bdest[i]); 677 alpha[i] = ~(alpha[i] ^ adest[i]); 678 } 679 } 680 break; 681 case GL_AND_REVERSE: 682 for (i=0;i<n;i++) { 683 if (mask[i]) { 684 red[i] = red[i] & ~rdest[i]; 685 green[i] = green[i] & ~gdest[i]; 686 blue[i] = blue[i] & ~bdest[i]; 687 alpha[i] = alpha[i] & ~adest[i]; 688 } 689 } 690 break; 691 case GL_AND_INVERTED: 692 for (i=0;i<n;i++) { 693 if (mask[i]) { 694 red[i] = ~red[i] & rdest[i]; 695 green[i] = ~green[i] & gdest[i]; 696 blue[i] = ~blue[i] & bdest[i]; 697 alpha[i] = ~alpha[i] & adest[i]; 698 } 699 } 700 break; 701 case GL_OR_REVERSE: 702 for (i=0;i<n;i++) { 703 if (mask[i]) { 704 red[i] = red[i] | ~rdest[i]; 705 green[i] = green[i] | ~gdest[i]; 706 blue[i] = blue[i] | ~bdest[i]; 707 alpha[i] = alpha[i] | ~adest[i]; 708 } 709 } 710 break; 711 case GL_OR_INVERTED: 712 for (i=0;i<n;i++) { 713 if (mask[i]) { 714 red[i] = ~red[i] | rdest[i]; 715 green[i] = ~green[i] | gdest[i]; 716 blue[i] = ~blue[i] | bdest[i]; 717 alpha[i] = ~alpha[i] | adest[i]; 718 } 719 } 720 break; 721 default: 722 /* should never happen */ 723 gl_problem(ctx, "Bad function in gl_logicop_rgba_pixels"); 724 return; 725 } 726 } 727