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 #include "util/u_bitmask.h"
     31 
     32 #include "svga_context.h"
     33 #include "svga_hw_reg.h"
     34 #include "svga_cmd.h"
     35 
     36 
     37 static inline unsigned
     38 svga_translate_blend_factor(const struct svga_context *svga, unsigned factor)
     39 {
     40    /* Note: there is no SVGA3D_BLENDOP_[INV]BLENDFACTORALPHA so
     41     * we can't translate PIPE_BLENDFACTOR_[INV_]CONST_ALPHA properly.
     42     */
     43    switch (factor) {
     44    case PIPE_BLENDFACTOR_ZERO:            return SVGA3D_BLENDOP_ZERO;
     45    case PIPE_BLENDFACTOR_SRC_ALPHA:       return SVGA3D_BLENDOP_SRCALPHA;
     46    case PIPE_BLENDFACTOR_ONE:             return SVGA3D_BLENDOP_ONE;
     47    case PIPE_BLENDFACTOR_SRC_COLOR:       return SVGA3D_BLENDOP_SRCCOLOR;
     48    case PIPE_BLENDFACTOR_INV_SRC_COLOR:   return SVGA3D_BLENDOP_INVSRCCOLOR;
     49    case PIPE_BLENDFACTOR_DST_COLOR:       return SVGA3D_BLENDOP_DESTCOLOR;
     50    case PIPE_BLENDFACTOR_INV_DST_COLOR:   return SVGA3D_BLENDOP_INVDESTCOLOR;
     51    case PIPE_BLENDFACTOR_INV_SRC_ALPHA:   return SVGA3D_BLENDOP_INVSRCALPHA;
     52    case PIPE_BLENDFACTOR_DST_ALPHA:       return SVGA3D_BLENDOP_DESTALPHA;
     53    case PIPE_BLENDFACTOR_INV_DST_ALPHA:   return SVGA3D_BLENDOP_INVDESTALPHA;
     54    case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return SVGA3D_BLENDOP_SRCALPHASAT;
     55    case PIPE_BLENDFACTOR_CONST_COLOR:     return SVGA3D_BLENDOP_BLENDFACTOR;
     56    case PIPE_BLENDFACTOR_INV_CONST_COLOR: return SVGA3D_BLENDOP_INVBLENDFACTOR;
     57    case PIPE_BLENDFACTOR_CONST_ALPHA:
     58       if (svga_have_vgpu10(svga))
     59          return SVGA3D_BLENDOP_BLENDFACTORALPHA;
     60       else
     61          return SVGA3D_BLENDOP_BLENDFACTOR; /* as close as we can get */
     62    case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
     63       if (svga_have_vgpu10(svga))
     64          return SVGA3D_BLENDOP_INVBLENDFACTORALPHA;
     65       else
     66          return SVGA3D_BLENDOP_INVBLENDFACTOR; /* as close as we can get */
     67    case PIPE_BLENDFACTOR_SRC1_COLOR:      return SVGA3D_BLENDOP_SRC1COLOR;
     68    case PIPE_BLENDFACTOR_INV_SRC1_COLOR:  return SVGA3D_BLENDOP_INVSRC1COLOR;
     69    case PIPE_BLENDFACTOR_SRC1_ALPHA:      return SVGA3D_BLENDOP_SRC1ALPHA;
     70    case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:  return SVGA3D_BLENDOP_INVSRC1ALPHA;
     71    case 0:                                return SVGA3D_BLENDOP_ONE;
     72    default:
     73       assert(0);
     74       return SVGA3D_BLENDOP_ZERO;
     75    }
     76 }
     77 
     78 static inline unsigned
     79 svga_translate_blend_func(unsigned mode)
     80 {
     81    switch (mode) {
     82    case PIPE_BLEND_ADD:              return SVGA3D_BLENDEQ_ADD;
     83    case PIPE_BLEND_SUBTRACT:         return SVGA3D_BLENDEQ_SUBTRACT;
     84    case PIPE_BLEND_REVERSE_SUBTRACT: return SVGA3D_BLENDEQ_REVSUBTRACT;
     85    case PIPE_BLEND_MIN:              return SVGA3D_BLENDEQ_MINIMUM;
     86    case PIPE_BLEND_MAX:              return SVGA3D_BLENDEQ_MAXIMUM;
     87    default:
     88       assert(0);
     89       return SVGA3D_BLENDEQ_ADD;
     90    }
     91 }
     92 
     93 
     94 /**
     95  * Define a vgpu10 blend state object for the given
     96  * svga blend state.
     97  */
     98 static void
     99 define_blend_state_object(struct svga_context *svga,
    100                           struct svga_blend_state *bs)
    101 {
    102    SVGA3dDXBlendStatePerRT perRT[SVGA3D_MAX_RENDER_TARGETS];
    103    unsigned try;
    104    int i;
    105 
    106    assert(svga_have_vgpu10(svga));
    107 
    108    bs->id = util_bitmask_add(svga->blend_object_id_bm);
    109 
    110    for (i = 0; i < SVGA3D_DX_MAX_RENDER_TARGETS; i++) {
    111       perRT[i].blendEnable = bs->rt[i].blend_enable;
    112       perRT[i].srcBlend = bs->rt[i].srcblend;
    113       perRT[i].destBlend = bs->rt[i].dstblend;
    114       perRT[i].blendOp = bs->rt[i].blendeq;
    115       perRT[i].srcBlendAlpha = bs->rt[i].srcblend_alpha;
    116       perRT[i].destBlendAlpha = bs->rt[i].dstblend_alpha;
    117       perRT[i].blendOpAlpha = bs->rt[i].blendeq_alpha;
    118       perRT[i].renderTargetWriteMask = bs->rt[i].writemask;
    119       perRT[i].logicOpEnable = 0;
    120       perRT[i].logicOp = SVGA3D_LOGICOP_COPY;
    121       assert(perRT[i].srcBlend == perRT[0].srcBlend);
    122    }
    123 
    124    /* Loop in case command buffer is full and we need to flush and retry */
    125    for (try = 0; try < 2; try++) {
    126       enum pipe_error ret;
    127 
    128       ret = SVGA3D_vgpu10_DefineBlendState(svga->swc,
    129                                            bs->id,
    130                                            bs->alpha_to_coverage,
    131                                            bs->independent_blend_enable,
    132                                            perRT);
    133       if (ret == PIPE_OK)
    134          return;
    135       svga_context_flush(svga, NULL);
    136    }
    137 }
    138 
    139 
    140 static void *
    141 svga_create_blend_state(struct pipe_context *pipe,
    142                         const struct pipe_blend_state *templ)
    143 {
    144    struct svga_context *svga = svga_context(pipe);
    145    struct svga_blend_state *blend = CALLOC_STRUCT( svga_blend_state );
    146    unsigned i;
    147 
    148    if (!blend)
    149       return NULL;
    150 
    151    /* Fill in the per-rendertarget blend state.  We currently only
    152     * support independent blend enable and colormask per render target.
    153     */
    154    for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
    155       /* No way to set this in SVGA3D, and no way to correctly implement it on
    156        * top of D3D9 API.  Instead we try to simulate with various blend modes.
    157        */
    158       if (templ->logicop_enable) {
    159          switch (templ->logicop_func) {
    160          case PIPE_LOGICOP_XOR:
    161          case PIPE_LOGICOP_INVERT:
    162             blend->need_white_fragments = TRUE;
    163             blend->rt[i].blend_enable = TRUE;
    164             blend->rt[i].srcblend       = SVGA3D_BLENDOP_ONE;
    165             blend->rt[i].dstblend       = SVGA3D_BLENDOP_ONE;
    166             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_SUBTRACT;
    167             break;
    168          case PIPE_LOGICOP_CLEAR:
    169             blend->rt[i].blend_enable = TRUE;
    170             blend->rt[i].srcblend       = SVGA3D_BLENDOP_ZERO;
    171             blend->rt[i].dstblend       = SVGA3D_BLENDOP_ZERO;
    172             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MINIMUM;
    173             break;
    174          case PIPE_LOGICOP_COPY:
    175             blend->rt[i].blend_enable = FALSE;
    176             blend->rt[i].srcblend       = SVGA3D_BLENDOP_ONE;
    177             blend->rt[i].dstblend       = SVGA3D_BLENDOP_ZERO;
    178             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_ADD;
    179             break;
    180          case PIPE_LOGICOP_COPY_INVERTED:
    181             blend->rt[i].blend_enable   = TRUE;
    182             blend->rt[i].srcblend       = SVGA3D_BLENDOP_INVSRCCOLOR;
    183             blend->rt[i].dstblend       = SVGA3D_BLENDOP_ZERO;
    184             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_ADD;
    185             break;
    186          case PIPE_LOGICOP_NOOP:
    187             blend->rt[i].blend_enable   = TRUE;
    188             blend->rt[i].srcblend       = SVGA3D_BLENDOP_ZERO;
    189             blend->rt[i].dstblend       = SVGA3D_BLENDOP_DESTCOLOR;
    190             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_ADD;
    191             break;
    192          case PIPE_LOGICOP_SET:
    193             blend->rt[i].blend_enable = TRUE;
    194             blend->rt[i].srcblend       = SVGA3D_BLENDOP_ONE;
    195             blend->rt[i].dstblend       = SVGA3D_BLENDOP_ONE;
    196             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MAXIMUM;
    197             break;
    198          case PIPE_LOGICOP_AND:
    199             /* Approximate with minimum - works for the 0 & anything case: */
    200             blend->rt[i].blend_enable = TRUE;
    201             blend->rt[i].srcblend       = SVGA3D_BLENDOP_SRCCOLOR;
    202             blend->rt[i].dstblend       = SVGA3D_BLENDOP_DESTCOLOR;
    203             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MINIMUM;
    204             break;
    205          case PIPE_LOGICOP_AND_REVERSE:
    206             blend->rt[i].blend_enable = TRUE;
    207             blend->rt[i].srcblend       = SVGA3D_BLENDOP_SRCCOLOR;
    208             blend->rt[i].dstblend       = SVGA3D_BLENDOP_INVDESTCOLOR;
    209             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MINIMUM;
    210             break;
    211          case PIPE_LOGICOP_AND_INVERTED:
    212             blend->rt[i].blend_enable = TRUE;
    213             blend->rt[i].srcblend       = SVGA3D_BLENDOP_INVSRCCOLOR;
    214             blend->rt[i].dstblend       = SVGA3D_BLENDOP_DESTCOLOR;
    215             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MINIMUM;
    216             break;
    217          case PIPE_LOGICOP_OR:
    218             /* Approximate with maximum - works for the 1 | anything case: */
    219             blend->rt[i].blend_enable = TRUE;
    220             blend->rt[i].srcblend       = SVGA3D_BLENDOP_SRCCOLOR;
    221             blend->rt[i].dstblend       = SVGA3D_BLENDOP_DESTCOLOR;
    222             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MAXIMUM;
    223             break;
    224          case PIPE_LOGICOP_OR_REVERSE:
    225             blend->rt[i].blend_enable = TRUE;
    226             blend->rt[i].srcblend       = SVGA3D_BLENDOP_SRCCOLOR;
    227             blend->rt[i].dstblend       = SVGA3D_BLENDOP_INVDESTCOLOR;
    228             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MAXIMUM;
    229             break;
    230          case PIPE_LOGICOP_OR_INVERTED:
    231             blend->rt[i].blend_enable = TRUE;
    232             blend->rt[i].srcblend       = SVGA3D_BLENDOP_INVSRCCOLOR;
    233             blend->rt[i].dstblend       = SVGA3D_BLENDOP_DESTCOLOR;
    234             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_MAXIMUM;
    235             break;
    236          case PIPE_LOGICOP_NAND:
    237          case PIPE_LOGICOP_NOR:
    238          case PIPE_LOGICOP_EQUIV:
    239             /* Fill these in with plausible values */
    240             blend->rt[i].blend_enable = FALSE;
    241             blend->rt[i].srcblend       = SVGA3D_BLENDOP_ONE;
    242             blend->rt[i].dstblend       = SVGA3D_BLENDOP_ZERO;
    243             blend->rt[i].blendeq        = SVGA3D_BLENDEQ_ADD;
    244             break;
    245          default:
    246             assert(0);
    247             break;
    248          }
    249          blend->rt[i].srcblend_alpha = blend->rt[i].srcblend;
    250          blend->rt[i].dstblend_alpha = blend->rt[i].dstblend;
    251          blend->rt[i].blendeq_alpha = blend->rt[i].blendeq;
    252 
    253          if (templ->logicop_func == PIPE_LOGICOP_XOR) {
    254             pipe_debug_message(&svga->debug.callback, CONFORMANCE,
    255                                "XOR logicop mode has limited support");
    256          }
    257          else if (templ->logicop_func != PIPE_LOGICOP_COPY) {
    258             pipe_debug_message(&svga->debug.callback, CONFORMANCE,
    259                                "general logicops are not supported");
    260          }
    261       }
    262       else {
    263          /* Note: the vgpu10 device does not yet support independent
    264           * blend terms per render target.  Target[0] always specifies the
    265           * blending terms.
    266           */
    267          if (templ->independent_blend_enable || templ->rt[0].blend_enable) {
    268             /* always use the 0th target's blending terms for now */
    269             blend->rt[i].srcblend =
    270                svga_translate_blend_factor(svga, templ->rt[0].rgb_src_factor);
    271             blend->rt[i].dstblend =
    272                svga_translate_blend_factor(svga, templ->rt[0].rgb_dst_factor);
    273             blend->rt[i].blendeq =
    274                svga_translate_blend_func(templ->rt[0].rgb_func);
    275             blend->rt[i].srcblend_alpha =
    276                svga_translate_blend_factor(svga, templ->rt[0].alpha_src_factor);
    277             blend->rt[i].dstblend_alpha =
    278                svga_translate_blend_factor(svga, templ->rt[0].alpha_dst_factor);
    279             blend->rt[i].blendeq_alpha =
    280                svga_translate_blend_func(templ->rt[0].alpha_func);
    281 
    282             if (blend->rt[i].srcblend_alpha != blend->rt[i].srcblend ||
    283                 blend->rt[i].dstblend_alpha != blend->rt[i].dstblend ||
    284                 blend->rt[i].blendeq_alpha  != blend->rt[i].blendeq) {
    285                blend->rt[i].separate_alpha_blend_enable = TRUE;
    286             }
    287          }
    288          else {
    289             /* disabled - default blend terms */
    290             blend->rt[i].srcblend = SVGA3D_BLENDOP_ONE;
    291             blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO;
    292             blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD;
    293             blend->rt[i].srcblend_alpha = SVGA3D_BLENDOP_ONE;
    294             blend->rt[i].dstblend_alpha = SVGA3D_BLENDOP_ZERO;
    295             blend->rt[i].blendeq_alpha = SVGA3D_BLENDEQ_ADD;
    296          }
    297 
    298          if (templ->independent_blend_enable) {
    299             blend->rt[i].blend_enable = templ->rt[i].blend_enable;
    300          }
    301          else {
    302             blend->rt[i].blend_enable = templ->rt[0].blend_enable;
    303          }
    304       }
    305 
    306       /* Some GL blend modes are not supported by the VGPU9 device (there's
    307        * no equivalent of PIPE_BLENDFACTOR_[INV_]CONST_ALPHA).
    308        * When we set this flag, we copy the constant blend alpha value
    309        * to the R, G, B components.
    310        * This works as long as the src/dst RGB blend factors doesn't use
    311        * PIPE_BLENDFACTOR_CONST_COLOR and PIPE_BLENDFACTOR_CONST_ALPHA
    312        * at the same time.  There's no work-around for that.
    313        */
    314       if (!svga_have_vgpu10(svga)) {
    315          if (templ->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_CONST_ALPHA ||
    316              templ->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_CONST_ALPHA ||
    317              templ->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_INV_CONST_ALPHA ||
    318              templ->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_INV_CONST_ALPHA) {
    319             blend->blend_color_alpha = TRUE;
    320          }
    321       }
    322 
    323       if (templ->independent_blend_enable) {
    324          blend->rt[i].writemask = templ->rt[i].colormask;
    325       }
    326       else {
    327          blend->rt[i].writemask = templ->rt[0].colormask;
    328       }
    329    }
    330 
    331    blend->independent_blend_enable = templ->independent_blend_enable;
    332 
    333    blend->alpha_to_coverage = templ->alpha_to_coverage;
    334 
    335    if (svga_have_vgpu10(svga)) {
    336       define_blend_state_object(svga, blend);
    337    }
    338 
    339    svga->hud.num_blend_objects++;
    340    SVGA_STATS_COUNT_INC(svga_screen(svga->pipe.screen)->sws,
    341                         SVGA_STATS_COUNT_BLENDSTATE);
    342 
    343    return blend;
    344 }
    345 
    346 
    347 static void svga_bind_blend_state(struct pipe_context *pipe,
    348                                   void *blend)
    349 {
    350    struct svga_context *svga = svga_context(pipe);
    351 
    352    svga->curr.blend = (struct svga_blend_state*)blend;
    353    svga->dirty |= SVGA_NEW_BLEND;
    354 }
    355 
    356 static void svga_delete_blend_state(struct pipe_context *pipe,
    357                                     void *blend)
    358 {
    359    struct svga_context *svga = svga_context(pipe);
    360    struct svga_blend_state *bs =
    361       (struct svga_blend_state *) blend;
    362 
    363    if (bs->id != SVGA3D_INVALID_ID) {
    364       enum pipe_error ret;
    365 
    366       ret = SVGA3D_vgpu10_DestroyBlendState(svga->swc, bs->id);
    367       if (ret != PIPE_OK) {
    368          svga_context_flush(svga, NULL);
    369          ret = SVGA3D_vgpu10_DestroyBlendState(svga->swc, bs->id);
    370          assert(ret == PIPE_OK);
    371       }
    372 
    373       if (bs->id == svga->state.hw_draw.blend_id)
    374          svga->state.hw_draw.blend_id = SVGA3D_INVALID_ID;
    375 
    376       util_bitmask_clear(svga->blend_object_id_bm, bs->id);
    377       bs->id = SVGA3D_INVALID_ID;
    378    }
    379 
    380    FREE(blend);
    381    svga->hud.num_blend_objects--;
    382 }
    383 
    384 static void svga_set_blend_color( struct pipe_context *pipe,
    385                                   const struct pipe_blend_color *blend_color )
    386 {
    387    struct svga_context *svga = svga_context(pipe);
    388 
    389    svga->curr.blend_color = *blend_color;
    390 
    391    svga->dirty |= SVGA_NEW_BLEND_COLOR;
    392 }
    393 
    394 
    395 void svga_init_blend_functions( struct svga_context *svga )
    396 {
    397    svga->pipe.create_blend_state = svga_create_blend_state;
    398    svga->pipe.bind_blend_state = svga_bind_blend_state;
    399    svga->pipe.delete_blend_state = svga_delete_blend_state;
    400 
    401    svga->pipe.set_blend_color = svga_set_blend_color;
    402 }
    403