Home | History | Annotate | Download | only in svga
      1 /**********************************************************
      2  * Copyright 2008-2009 VMware, Inc.  All rights reserved.
      3  *
      4  * Permission is hereby granted, free of charge, to any person
      5  * obtaining a copy of this software and associated documentation
      6  * files (the "Software"), to deal in the Software without
      7  * restriction, including without limitation the rights to use, copy,
      8  * modify, merge, publish, distribute, sublicense, and/or sell copies
      9  * of the Software, and to permit persons to whom the Software is
     10  * furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice shall be
     13  * included in all copies or substantial portions of the Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
     19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     22  * SOFTWARE.
     23  *
     24  **********************************************************/
     25 
     26 #include "util/u_inlines.h"
     27 #include "pipe/p_defines.h"
     28 #include "util/u_math.h"
     29 #include "util/u_memory.h"
     30 
     31 #include "svga_context.h"
     32 
     33 #include "svga_hw_reg.h"
     34 
     35 
     36 static INLINE unsigned
     37 svga_translate_blend_factor(unsigned factor)
     38 {
     39    switch (factor) {
     40    case PIPE_BLENDFACTOR_ZERO:            return SVGA3D_BLENDOP_ZERO;
     41    case PIPE_BLENDFACTOR_SRC_ALPHA:       return SVGA3D_BLENDOP_SRCALPHA;
     42    case PIPE_BLENDFACTOR_ONE:             return SVGA3D_BLENDOP_ONE;
     43    case PIPE_BLENDFACTOR_SRC_COLOR:       return SVGA3D_BLENDOP_SRCCOLOR;
     44    case PIPE_BLENDFACTOR_INV_SRC_COLOR:   return SVGA3D_BLENDOP_INVSRCCOLOR;
     45    case PIPE_BLENDFACTOR_DST_COLOR:       return SVGA3D_BLENDOP_DESTCOLOR;
     46    case PIPE_BLENDFACTOR_INV_DST_COLOR:   return SVGA3D_BLENDOP_INVDESTCOLOR;
     47    case PIPE_BLENDFACTOR_INV_SRC_ALPHA:   return SVGA3D_BLENDOP_INVSRCALPHA;
     48    case PIPE_BLENDFACTOR_DST_ALPHA:       return SVGA3D_BLENDOP_DESTALPHA;
     49    case PIPE_BLENDFACTOR_INV_DST_ALPHA:   return SVGA3D_BLENDOP_INVDESTALPHA;
     50    case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return SVGA3D_BLENDOP_SRCALPHASAT;
     51    case PIPE_BLENDFACTOR_CONST_COLOR:     return SVGA3D_BLENDOP_BLENDFACTOR;
     52    case PIPE_BLENDFACTOR_INV_CONST_COLOR: return SVGA3D_BLENDOP_INVBLENDFACTOR;
     53    case PIPE_BLENDFACTOR_CONST_ALPHA:     return SVGA3D_BLENDOP_BLENDFACTOR; /* ? */
     54    case PIPE_BLENDFACTOR_INV_CONST_ALPHA: return SVGA3D_BLENDOP_INVBLENDFACTOR; /* ? */
     55    default:
     56       assert(0);
     57       return SVGA3D_BLENDOP_ZERO;
     58    }
     59 }
     60 
     61 static INLINE unsigned
     62 svga_translate_blend_func(unsigned mode)
     63 {
     64    switch (mode) {
     65    case PIPE_BLEND_ADD:              return SVGA3D_BLENDEQ_ADD;
     66    case PIPE_BLEND_SUBTRACT:         return SVGA3D_BLENDEQ_SUBTRACT;
     67    case PIPE_BLEND_REVERSE_SUBTRACT: return SVGA3D_BLENDEQ_REVSUBTRACT;
     68    case PIPE_BLEND_MIN:              return SVGA3D_BLENDEQ_MINIMUM;
     69    case PIPE_BLEND_MAX:              return SVGA3D_BLENDEQ_MAXIMUM;
     70    default:
     71       assert(0);
     72       return SVGA3D_BLENDEQ_ADD;
     73    }
     74 }
     75 
     76 
     77 static void *
     78 svga_create_blend_state(struct pipe_context *pipe,
     79                         const struct pipe_blend_state *templ)
     80 {
     81    struct svga_blend_state *blend = CALLOC_STRUCT( svga_blend_state );
     82    unsigned i;
     83 
     84 
     85    /* Fill in the per-rendertarget blend state.  We currently only
     86     * have one rendertarget.
     87     */
     88    for (i = 0; i < 1; i++) {
     89       /* No way to set this in SVGA3D, and no way to correctly implement it on
     90        * top of D3D9 API.  Instead we try to simulate with various blend modes.
     91        */
     92       if (templ->logicop_enable) {
     93          switch (templ->logicop_func) {
     94          case PIPE_LOGICOP_XOR:
     95          case PIPE_LOGICOP_INVERT:
     96             blend->need_white_fragments = TRUE;
     97             blend->rt[i].blend_enable = TRUE;
     98             blend->rt[i].srcblend       = SVGA3D_BLENDOP_ONE;
     99             blend->rt[i].dstblend       = SVGA3D_BLENDOP_ONE;
    100             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_SUBTRACT;
    101             break;
    102          case PIPE_LOGICOP_CLEAR:
    103             blend->rt[i].blend_enable = TRUE;
    104             blend->rt[i].srcblend       = SVGA3D_BLENDOP_ZERO;
    105             blend->rt[i].dstblend       = SVGA3D_BLENDOP_ZERO;
    106             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MINIMUM;
    107             break;
    108          case PIPE_LOGICOP_COPY:
    109             blend->rt[i].blend_enable = FALSE;
    110             break;
    111          case PIPE_LOGICOP_COPY_INVERTED:
    112             blend->rt[i].blend_enable   = TRUE;
    113             blend->rt[i].srcblend       = SVGA3D_BLENDOP_INVSRCCOLOR;
    114             blend->rt[i].dstblend       = SVGA3D_BLENDOP_ZERO;
    115             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_ADD;
    116             break;
    117          case PIPE_LOGICOP_NOOP:
    118             blend->rt[i].blend_enable   = TRUE;
    119             blend->rt[i].srcblend       = SVGA3D_BLENDOP_ZERO;
    120             blend->rt[i].dstblend       = SVGA3D_BLENDOP_DESTCOLOR;
    121             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_ADD;
    122             break;
    123          case PIPE_LOGICOP_SET:
    124             blend->rt[i].blend_enable = TRUE;
    125             blend->rt[i].srcblend       = SVGA3D_BLENDOP_ONE;
    126             blend->rt[i].dstblend       = SVGA3D_BLENDOP_ONE;
    127             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MAXIMUM;
    128             break;
    129          case PIPE_LOGICOP_AND:
    130             /* Approximate with minimum - works for the 0 & anything case: */
    131             blend->rt[i].blend_enable = TRUE;
    132             blend->rt[i].srcblend       = SVGA3D_BLENDOP_SRCCOLOR;
    133             blend->rt[i].dstblend       = SVGA3D_BLENDOP_DESTCOLOR;
    134             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MINIMUM;
    135             break;
    136          case PIPE_LOGICOP_AND_REVERSE:
    137             blend->rt[i].blend_enable = TRUE;
    138             blend->rt[i].srcblend       = SVGA3D_BLENDOP_SRCCOLOR;
    139             blend->rt[i].dstblend       = SVGA3D_BLENDOP_INVDESTCOLOR;
    140             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MINIMUM;
    141             break;
    142          case PIPE_LOGICOP_AND_INVERTED:
    143             blend->rt[i].blend_enable = TRUE;
    144             blend->rt[i].srcblend       = SVGA3D_BLENDOP_INVSRCCOLOR;
    145             blend->rt[i].dstblend       = SVGA3D_BLENDOP_DESTCOLOR;
    146             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MINIMUM;
    147             break;
    148          case PIPE_LOGICOP_OR:
    149             /* Approximate with maximum - works for the 1 | anything case: */
    150             blend->rt[i].blend_enable = TRUE;
    151             blend->rt[i].srcblend       = SVGA3D_BLENDOP_SRCCOLOR;
    152             blend->rt[i].dstblend       = SVGA3D_BLENDOP_DESTCOLOR;
    153             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MAXIMUM;
    154             break;
    155          case PIPE_LOGICOP_OR_REVERSE:
    156             blend->rt[i].blend_enable = TRUE;
    157             blend->rt[i].srcblend       = SVGA3D_BLENDOP_SRCCOLOR;
    158             blend->rt[i].dstblend       = SVGA3D_BLENDOP_INVDESTCOLOR;
    159             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MAXIMUM;
    160             break;
    161          case PIPE_LOGICOP_OR_INVERTED:
    162             blend->rt[i].blend_enable = TRUE;
    163             blend->rt[i].srcblend       = SVGA3D_BLENDOP_INVSRCCOLOR;
    164             blend->rt[i].dstblend       = SVGA3D_BLENDOP_DESTCOLOR;
    165             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MAXIMUM;
    166             break;
    167          case PIPE_LOGICOP_NAND:
    168          case PIPE_LOGICOP_NOR:
    169          case PIPE_LOGICOP_EQUIV:
    170             /* Fill these in with plausible values */
    171             blend->rt[i].blend_enable = FALSE;
    172             break;
    173          default:
    174             assert(0);
    175             break;
    176          }
    177       }
    178       else {
    179          blend->rt[i].blend_enable   = templ->rt[0].blend_enable;
    180 
    181          if (templ->rt[0].blend_enable) {
    182             blend->rt[i].srcblend       = svga_translate_blend_factor(templ->rt[0].rgb_src_factor);
    183             blend->rt[i].dstblend       = svga_translate_blend_factor(templ->rt[0].rgb_dst_factor);
    184             blend->rt[i].blendeq        = svga_translate_blend_func(templ->rt[0].rgb_func);
    185             blend->rt[i].srcblend_alpha = svga_translate_blend_factor(templ->rt[0].alpha_src_factor);
    186             blend->rt[i].dstblend_alpha = svga_translate_blend_factor(templ->rt[0].alpha_dst_factor);
    187             blend->rt[i].blendeq_alpha  = svga_translate_blend_func(templ->rt[0].alpha_func);
    188 
    189             if (blend->rt[i].srcblend_alpha != blend->rt[i].srcblend ||
    190                 blend->rt[i].dstblend_alpha != blend->rt[i].dstblend ||
    191                 blend->rt[i].blendeq_alpha  != blend->rt[i].blendeq)
    192             {
    193                blend->rt[i].separate_alpha_blend_enable = TRUE;
    194             }
    195          }
    196       }
    197 
    198       blend->rt[i].writemask = templ->rt[0].colormask;
    199    }
    200 
    201    return blend;
    202 }
    203 
    204 static void svga_bind_blend_state(struct pipe_context *pipe,
    205                                   void *blend)
    206 {
    207    struct svga_context *svga = svga_context(pipe);
    208 
    209    svga->curr.blend = (struct svga_blend_state*)blend;
    210    svga->dirty |= SVGA_NEW_BLEND;
    211 }
    212 
    213 
    214 static void svga_delete_blend_state(struct pipe_context *pipe, void *blend)
    215 {
    216    FREE(blend);
    217 }
    218 
    219 static void svga_set_blend_color( struct pipe_context *pipe,
    220                                   const struct pipe_blend_color *blend_color )
    221 {
    222    struct svga_context *svga = svga_context(pipe);
    223 
    224    svga->curr.blend_color = *blend_color;
    225 
    226    svga->dirty |= SVGA_NEW_BLEND_COLOR;
    227 }
    228 
    229 
    230 void svga_init_blend_functions( struct svga_context *svga )
    231 {
    232    svga->pipe.create_blend_state = svga_create_blend_state;
    233    svga->pipe.bind_blend_state = svga_bind_blend_state;
    234    svga->pipe.delete_blend_state = svga_delete_blend_state;
    235 
    236    svga->pipe.set_blend_color = svga_set_blend_color;
    237 }
    238 
    239 
    240 
    241