Home | History | Annotate | Download | only in swrast
      1 /*
      2  * Mesa 3-D graphics library
      3  * Version:  6.5.2
      4  *
      5  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the "Software"),
      9  * to deal in the Software without restriction, including without limitation
     10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     11  * and/or sell copies of the Software, and to permit persons to whom the
     12  * Software is furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included
     15  * in all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     21  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 
     25 
     26 #include "main/glheader.h"
     27 #include "main/context.h"
     28 #include "main/imports.h"
     29 #include "main/macros.h"
     30 
     31 #include "s_context.h"
     32 #include "s_logic.h"
     33 #include "s_span.h"
     34 
     35 
     36 /**
     37  * We do all logic ops on 4-byte GLuints.
     38  * Depending on bytes per pixel, the mask array elements correspond to
     39  * 1, 2 or 4 GLuints.
     40  */
     41 #define LOGIC_OP_LOOP(MODE, MASKSTRIDE)		\
     42 do {						\
     43    GLuint i;					\
     44    switch (MODE) {				\
     45       case GL_CLEAR:				\
     46          for (i = 0; i < n; i++) {		\
     47 	    if (mask[i / MASKSTRIDE]) {		\
     48 	       src[i] = 0;			\
     49 	    }					\
     50 	 }					\
     51 	 break;					\
     52       case GL_SET:				\
     53          for (i = 0; i < n; i++) {		\
     54 	    if (mask[i / MASKSTRIDE]) {		\
     55 	       src[i] = ~0;			\
     56 	    }					\
     57 	 }					\
     58 	 break;					\
     59       case GL_COPY:				\
     60 	 /* do nothing */			\
     61 	 break;					\
     62       case GL_COPY_INVERTED:			\
     63          for (i = 0; i < n; i++) {		\
     64 	    if (mask[i / MASKSTRIDE]) {		\
     65 	       src[i] = ~src[i];		\
     66 	    }					\
     67 	 }					\
     68 	 break;					\
     69       case GL_NOOP:				\
     70          for (i = 0; i < n; i++) {		\
     71 	    if (mask[i / MASKSTRIDE]) {		\
     72 	       src[i] = dest[i];		\
     73 	    }					\
     74 	 }					\
     75 	 break;					\
     76       case GL_INVERT:				\
     77          for (i = 0; i < n; i++) {		\
     78 	    if (mask[i / MASKSTRIDE]) {		\
     79 	       src[i] = ~dest[i];		\
     80 	    }					\
     81 	 }					\
     82 	 break;					\
     83       case GL_AND:				\
     84          for (i = 0; i < n; i++) {		\
     85 	    if (mask[i / MASKSTRIDE]) {		\
     86 	       src[i] &= dest[i];		\
     87 	    }					\
     88 	 }					\
     89 	 break;					\
     90       case GL_NAND:				\
     91          for (i = 0; i < n; i++) {		\
     92 	    if (mask[i / MASKSTRIDE]) {		\
     93 	       src[i] = ~(src[i] & dest[i]);	\
     94 	    }					\
     95 	 }					\
     96 	 break;					\
     97       case GL_OR:				\
     98          for (i = 0; i < n; i++) {		\
     99 	    if (mask[i / MASKSTRIDE]) {		\
    100 	       src[i] |= dest[i];		\
    101 	    }					\
    102 	 }					\
    103 	 break;					\
    104       case GL_NOR:				\
    105          for (i = 0; i < n; i++) {		\
    106 	    if (mask[i / MASKSTRIDE]) {		\
    107 	       src[i] = ~(src[i] | dest[i]);	\
    108 	    }					\
    109 	 }					\
    110 	 break;					\
    111       case GL_XOR:				\
    112          for (i = 0; i < n; i++) {		\
    113 	    if (mask[i / MASKSTRIDE]) {		\
    114 	       src[i] ^= dest[i];		\
    115 	    }					\
    116 	 }					\
    117 	 break;					\
    118       case GL_EQUIV:				\
    119          for (i = 0; i < n; i++) {		\
    120 	    if (mask[i / MASKSTRIDE]) {		\
    121 	       src[i] = ~(src[i] ^ dest[i]);	\
    122 	    }					\
    123 	 }					\
    124 	 break;					\
    125       case GL_AND_REVERSE:			\
    126          for (i = 0; i < n; i++) {		\
    127 	    if (mask[i / MASKSTRIDE]) {		\
    128 	       src[i] = src[i] & ~dest[i];	\
    129 	    }					\
    130 	 }					\
    131 	 break;					\
    132       case GL_AND_INVERTED:			\
    133          for (i = 0; i < n; i++) {		\
    134 	    if (mask[i / MASKSTRIDE]) {		\
    135 	       src[i] = ~src[i] & dest[i];	\
    136 	    }					\
    137 	 }					\
    138 	 break;					\
    139       case GL_OR_REVERSE:			\
    140          for (i = 0; i < n; i++) {		\
    141 	    if (mask[i / MASKSTRIDE]) {		\
    142 	       src[i] = src[i] | ~dest[i];	\
    143 	    }					\
    144 	 }					\
    145 	 break;					\
    146       case GL_OR_INVERTED:			\
    147          for (i = 0; i < n; i++) {		\
    148 	    if (mask[i / MASKSTRIDE]) {		\
    149 	       src[i] = ~src[i] | dest[i];	\
    150 	    }					\
    151 	 }					\
    152 	 break;					\
    153       default:					\
    154 	 _mesa_problem(ctx, "bad logicop mode");\
    155    }						\
    156 } while (0)
    157 
    158 
    159 
    160 static inline void
    161 logicop_uint1(struct gl_context *ctx, GLuint n, GLuint src[], const GLuint dest[],
    162               const GLubyte mask[])
    163 {
    164    LOGIC_OP_LOOP(ctx->Color.LogicOp, 1);
    165 }
    166 
    167 
    168 static inline void
    169 logicop_uint2(struct gl_context *ctx, GLuint n, GLuint src[], const GLuint dest[],
    170               const GLubyte mask[])
    171 {
    172    LOGIC_OP_LOOP(ctx->Color.LogicOp, 2);
    173 }
    174 
    175 
    176 static inline void
    177 logicop_uint4(struct gl_context *ctx, GLuint n, GLuint src[], const GLuint dest[],
    178               const GLubyte mask[])
    179 {
    180    LOGIC_OP_LOOP(ctx->Color.LogicOp, 4);
    181 }
    182 
    183 
    184 
    185 /**
    186  * Apply the current logic operator to a span of RGBA pixels.
    187  * We can handle horizontal runs of pixels (spans) or arrays of x/y
    188  * pixel coordinates.
    189  */
    190 void
    191 _swrast_logicop_rgba_span(struct gl_context *ctx, struct gl_renderbuffer *rb,
    192                           SWspan *span)
    193 {
    194    void *rbPixels;
    195 
    196    ASSERT(span->end < SWRAST_MAX_WIDTH);
    197    ASSERT(span->arrayMask & SPAN_RGBA);
    198 
    199    rbPixels = _swrast_get_dest_rgba(ctx, rb, span);
    200 
    201    if (span->array->ChanType == GL_UNSIGNED_BYTE) {
    202       /* treat 4*GLubyte as GLuint */
    203       logicop_uint1(ctx, span->end,
    204                     (GLuint *) span->array->rgba8,
    205                     (const GLuint *) rbPixels, span->array->mask);
    206    }
    207    else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
    208       /* treat 2*GLushort as GLuint */
    209       logicop_uint2(ctx, 2 * span->end,
    210                     (GLuint *) span->array->rgba16,
    211                     (const GLuint *) rbPixels, span->array->mask);
    212    }
    213    else {
    214       logicop_uint4(ctx, 4 * span->end,
    215                     (GLuint *) span->array->attribs[FRAG_ATTRIB_COL0],
    216                     (const GLuint *) rbPixels, span->array->mask);
    217    }
    218 }
    219