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 37static inline unsigned 38svga_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 78static inline unsigned 79svga_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 */ 98static void 99define_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 140static void * 141svga_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 347static 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 356static 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 384static 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 395void 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