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 * Translate gallium logicop mode to SVGA3D logicop mode. 96 */ 97static int 98translate_logicop(enum pipe_logicop op) 99{ 100 switch (op) { 101 case PIPE_LOGICOP_CLEAR: 102 return SVGA3D_DX11_LOGICOP_CLEAR; 103 case PIPE_LOGICOP_NOR: 104 return SVGA3D_DX11_LOGICOP_NOR; 105 case PIPE_LOGICOP_AND_INVERTED: 106 return SVGA3D_DX11_LOGICOP_AND_INVERTED; 107 case PIPE_LOGICOP_COPY_INVERTED: 108 return SVGA3D_DX11_LOGICOP_COPY_INVERTED; 109 case PIPE_LOGICOP_AND_REVERSE: 110 return SVGA3D_DX11_LOGICOP_AND_REVERSE; 111 case PIPE_LOGICOP_INVERT: 112 return SVGA3D_DX11_LOGICOP_INVERT; 113 case PIPE_LOGICOP_XOR: 114 return SVGA3D_DX11_LOGICOP_XOR; 115 case PIPE_LOGICOP_NAND: 116 return SVGA3D_DX11_LOGICOP_NAND; 117 case PIPE_LOGICOP_AND: 118 return SVGA3D_DX11_LOGICOP_AND; 119 case PIPE_LOGICOP_EQUIV: 120 return SVGA3D_DX11_LOGICOP_EQUIV; 121 case PIPE_LOGICOP_NOOP: 122 return SVGA3D_DX11_LOGICOP_NOOP; 123 case PIPE_LOGICOP_OR_INVERTED: 124 return SVGA3D_DX11_LOGICOP_OR_INVERTED; 125 case PIPE_LOGICOP_COPY: 126 return SVGA3D_DX11_LOGICOP_COPY; 127 case PIPE_LOGICOP_OR_REVERSE: 128 return SVGA3D_DX11_LOGICOP_OR_REVERSE; 129 case PIPE_LOGICOP_OR: 130 return SVGA3D_DX11_LOGICOP_OR; 131 case PIPE_LOGICOP_SET: 132 return SVGA3D_DX11_LOGICOP_SET; 133 default: 134 return SVGA3D_DX11_LOGICOP_COPY; 135 } 136}; 137 138 139/** 140 * Define a vgpu10 blend state object for the given 141 * svga blend state. 142 */ 143static void 144define_blend_state_object(struct svga_context *svga, 145 struct svga_blend_state *bs) 146{ 147 SVGA3dDXBlendStatePerRT perRT[SVGA3D_MAX_RENDER_TARGETS]; 148 int i; 149 150 assert(svga_have_vgpu10(svga)); 151 152 bs->id = util_bitmask_add(svga->blend_object_id_bm); 153 154 for (i = 0; i < SVGA3D_DX_MAX_RENDER_TARGETS; i++) { 155 perRT[i].blendEnable = bs->rt[i].blend_enable; 156 perRT[i].srcBlend = bs->rt[i].srcblend; 157 perRT[i].destBlend = bs->rt[i].dstblend; 158 perRT[i].blendOp = bs->rt[i].blendeq; 159 perRT[i].srcBlendAlpha = bs->rt[i].srcblend_alpha; 160 perRT[i].destBlendAlpha = bs->rt[i].dstblend_alpha; 161 perRT[i].blendOpAlpha = bs->rt[i].blendeq_alpha; 162 perRT[i].renderTargetWriteMask = bs->rt[i].writemask; 163 perRT[i].logicOpEnable = bs->logicop_enabled; 164 perRT[i].logicOp = bs->logicop_mode; 165 } 166 167 SVGA_RETRY(svga, SVGA3D_vgpu10_DefineBlendState(svga->swc, 168 bs->id, 169 bs->alpha_to_coverage, 170 bs->independent_blend_enable, 171 perRT)); 172} 173 174 175/** 176 * If SVGA3D_DEVCAP_LOGIC_BLENDOPS is false, we can't directly implement 177 * GL's logicops. But we can emulate some of them. We set up the blending 178 * state for that here. 179 */ 180static void 181emulate_logicop(struct svga_context *svga, 182 unsigned logicop_func, 183 struct svga_blend_state *blend, 184 unsigned buffer) 185{ 186 switch (logicop_func) { 187 case PIPE_LOGICOP_XOR: 188 case PIPE_LOGICOP_INVERT: 189 blend->need_white_fragments = TRUE; 190 blend->rt[buffer].blend_enable = TRUE; 191 blend->rt[buffer].srcblend = SVGA3D_BLENDOP_ONE; 192 blend->rt[buffer].dstblend = SVGA3D_BLENDOP_ONE; 193 blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_SUBTRACT; 194 break; 195 case PIPE_LOGICOP_CLEAR: 196 blend->rt[buffer].blend_enable = TRUE; 197 blend->rt[buffer].srcblend = SVGA3D_BLENDOP_ZERO; 198 blend->rt[buffer].dstblend = SVGA3D_BLENDOP_ZERO; 199 blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_MINIMUM; 200 break; 201 case PIPE_LOGICOP_COPY: 202 blend->rt[buffer].blend_enable = FALSE; 203 blend->rt[buffer].srcblend = SVGA3D_BLENDOP_ONE; 204 blend->rt[buffer].dstblend = SVGA3D_BLENDOP_ZERO; 205 blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_ADD; 206 break; 207 case PIPE_LOGICOP_COPY_INVERTED: 208 blend->rt[buffer].blend_enable = TRUE; 209 blend->rt[buffer].srcblend = SVGA3D_BLENDOP_INVSRCCOLOR; 210 blend->rt[buffer].dstblend = SVGA3D_BLENDOP_ZERO; 211 blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_ADD; 212 break; 213 case PIPE_LOGICOP_NOOP: 214 blend->rt[buffer].blend_enable = TRUE; 215 blend->rt[buffer].srcblend = SVGA3D_BLENDOP_ZERO; 216 blend->rt[buffer].dstblend = SVGA3D_BLENDOP_DESTCOLOR; 217 blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_ADD; 218 break; 219 case PIPE_LOGICOP_SET: 220 blend->rt[buffer].blend_enable = TRUE; 221 blend->rt[buffer].srcblend = SVGA3D_BLENDOP_ONE; 222 blend->rt[buffer].dstblend = SVGA3D_BLENDOP_ONE; 223 blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_MAXIMUM; 224 break; 225 case PIPE_LOGICOP_AND: 226 /* Approximate with minimum - works for the 0 & anything case: */ 227 blend->rt[buffer].blend_enable = TRUE; 228 blend->rt[buffer].srcblend = SVGA3D_BLENDOP_SRCCOLOR; 229 blend->rt[buffer].dstblend = SVGA3D_BLENDOP_DESTCOLOR; 230 blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_MINIMUM; 231 break; 232 case PIPE_LOGICOP_AND_REVERSE: 233 blend->rt[buffer].blend_enable = TRUE; 234 blend->rt[buffer].srcblend = SVGA3D_BLENDOP_SRCCOLOR; 235 blend->rt[buffer].dstblend = SVGA3D_BLENDOP_INVDESTCOLOR; 236 blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_MINIMUM; 237 break; 238 case PIPE_LOGICOP_AND_INVERTED: 239 blend->rt[buffer].blend_enable = TRUE; 240 blend->rt[buffer].srcblend = SVGA3D_BLENDOP_INVSRCCOLOR; 241 blend->rt[buffer].dstblend = SVGA3D_BLENDOP_DESTCOLOR; 242 blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_MINIMUM; 243 break; 244 case PIPE_LOGICOP_OR: 245 /* Approximate with maximum - works for the 1 | anything case: */ 246 blend->rt[buffer].blend_enable = TRUE; 247 blend->rt[buffer].srcblend = SVGA3D_BLENDOP_SRCCOLOR; 248 blend->rt[buffer].dstblend = SVGA3D_BLENDOP_DESTCOLOR; 249 blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_MAXIMUM; 250 break; 251 case PIPE_LOGICOP_OR_REVERSE: 252 blend->rt[buffer].blend_enable = TRUE; 253 blend->rt[buffer].srcblend = SVGA3D_BLENDOP_SRCCOLOR; 254 blend->rt[buffer].dstblend = SVGA3D_BLENDOP_INVDESTCOLOR; 255 blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_MAXIMUM; 256 break; 257 case PIPE_LOGICOP_OR_INVERTED: 258 blend->rt[buffer].blend_enable = TRUE; 259 blend->rt[buffer].srcblend = SVGA3D_BLENDOP_INVSRCCOLOR; 260 blend->rt[buffer].dstblend = SVGA3D_BLENDOP_DESTCOLOR; 261 blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_MAXIMUM; 262 break; 263 case PIPE_LOGICOP_NAND: 264 case PIPE_LOGICOP_NOR: 265 case PIPE_LOGICOP_EQUIV: 266 /* Fill these in with plausible values */ 267 blend->rt[buffer].blend_enable = FALSE; 268 blend->rt[buffer].srcblend = SVGA3D_BLENDOP_ONE; 269 blend->rt[buffer].dstblend = SVGA3D_BLENDOP_ZERO; 270 blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_ADD; 271 break; 272 default: 273 assert(0); 274 break; 275 } 276 blend->rt[buffer].srcblend_alpha = blend->rt[buffer].srcblend; 277 blend->rt[buffer].dstblend_alpha = blend->rt[buffer].dstblend; 278 blend->rt[buffer].blendeq_alpha = blend->rt[buffer].blendeq; 279 280 if (logicop_func == PIPE_LOGICOP_XOR) { 281 util_debug_message(&svga->debug.callback, CONFORMANCE, 282 "XOR logicop mode has limited support"); 283 } 284 else if (logicop_func != PIPE_LOGICOP_COPY) { 285 util_debug_message(&svga->debug.callback, CONFORMANCE, 286 "general logicops are not supported"); 287 } 288} 289 290 291 292static void * 293svga_create_blend_state(struct pipe_context *pipe, 294 const struct pipe_blend_state *templ) 295{ 296 struct svga_context *svga = svga_context(pipe); 297 struct svga_screen *ss = svga_screen(pipe->screen); 298 struct svga_blend_state *blend = CALLOC_STRUCT( svga_blend_state ); 299 unsigned i; 300 301 if (!blend) 302 return NULL; 303 304 /* Find index of first target with blending enabled. If no blending is 305 * enabled at all, first_enabled will be zero. 306 */ 307 unsigned first_enabled = 0; 308 for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { 309 if (templ->rt[i].blend_enable) { 310 first_enabled = i; 311 break; 312 } 313 } 314 315 /* Fill in the per-rendertarget blend state. We currently only 316 * support independent blend enable and colormask per render target. 317 */ 318 for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { 319 /* No way to set this in SVGA3D, and no way to correctly implement it on 320 * top of D3D9 API. Instead we try to simulate with various blend modes. 321 */ 322 if (templ->logicop_enable) { 323 if (ss->haveBlendLogicops) { 324 blend->logicop_enabled = TRUE; 325 blend->logicop_mode = translate_logicop(templ->logicop_func); 326 blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD; 327 blend->rt[i].blendeq_alpha = SVGA3D_BLENDEQ_ADD; 328 blend->rt[i].srcblend = SVGA3D_BLENDOP_ZERO; 329 blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO; 330 blend->rt[i].srcblend_alpha = SVGA3D_BLENDOP_ZERO; 331 blend->rt[i].dstblend_alpha = SVGA3D_BLENDOP_ZERO; 332 } 333 else { 334 emulate_logicop(svga, templ->logicop_func, blend, i); 335 } 336 } 337 else { 338 /* Note: per-target blend terms are only supported for sm4_1 339 * device. For vgpu10 device, the blending terms must be identical 340 * for all targets (this is why we need the first_enabled index). 341 */ 342 const unsigned j = 343 svga_have_sm4_1(svga) && templ->independent_blend_enable 344 ? i : first_enabled; 345 if (templ->independent_blend_enable || templ->rt[j].blend_enable) { 346 blend->rt[i].srcblend = 347 svga_translate_blend_factor(svga, templ->rt[j].rgb_src_factor); 348 blend->rt[i].dstblend = 349 svga_translate_blend_factor(svga, templ->rt[j].rgb_dst_factor); 350 blend->rt[i].blendeq = 351 svga_translate_blend_func(templ->rt[j].rgb_func); 352 blend->rt[i].srcblend_alpha = 353 svga_translate_blend_factor(svga, templ->rt[j].alpha_src_factor); 354 blend->rt[i].dstblend_alpha = 355 svga_translate_blend_factor(svga, templ->rt[j].alpha_dst_factor); 356 blend->rt[i].blendeq_alpha = 357 svga_translate_blend_func(templ->rt[j].alpha_func); 358 359 if (blend->rt[i].srcblend_alpha != blend->rt[i].srcblend || 360 blend->rt[i].dstblend_alpha != blend->rt[i].dstblend || 361 blend->rt[i].blendeq_alpha != blend->rt[i].blendeq) { 362 blend->rt[i].separate_alpha_blend_enable = TRUE; 363 } 364 } 365 else { 366 /* disabled - default blend terms */ 367 blend->rt[i].srcblend = SVGA3D_BLENDOP_ONE; 368 blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO; 369 blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD; 370 blend->rt[i].srcblend_alpha = SVGA3D_BLENDOP_ONE; 371 blend->rt[i].dstblend_alpha = SVGA3D_BLENDOP_ZERO; 372 blend->rt[i].blendeq_alpha = SVGA3D_BLENDEQ_ADD; 373 } 374 375 if (templ->independent_blend_enable) { 376 blend->rt[i].blend_enable = templ->rt[i].blend_enable; 377 } 378 else { 379 blend->rt[i].blend_enable = templ->rt[0].blend_enable; 380 } 381 } 382 383 /* Some GL blend modes are not supported by the VGPU9 device (there's 384 * no equivalent of PIPE_BLENDFACTOR_[INV_]CONST_ALPHA). 385 * When we set this flag, we copy the constant blend alpha value 386 * to the R, G, B components. 387 * This works as long as the src/dst RGB blend factors doesn't use 388 * PIPE_BLENDFACTOR_CONST_COLOR and PIPE_BLENDFACTOR_CONST_ALPHA 389 * at the same time. There's no work-around for that. 390 */ 391 if (!svga_have_vgpu10(svga)) { 392 if (templ->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_CONST_ALPHA || 393 templ->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_CONST_ALPHA || 394 templ->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_INV_CONST_ALPHA || 395 templ->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_INV_CONST_ALPHA) { 396 blend->blend_color_alpha = TRUE; 397 } 398 } 399 400 if (templ->independent_blend_enable) { 401 blend->rt[i].writemask = templ->rt[i].colormask; 402 } 403 else { 404 blend->rt[i].writemask = templ->rt[0].colormask; 405 } 406 } 407 408 blend->independent_blend_enable = templ->independent_blend_enable; 409 410 blend->alpha_to_coverage = templ->alpha_to_coverage; 411 blend->alpha_to_one = templ->alpha_to_one; 412 413 if (svga_have_vgpu10(svga)) { 414 define_blend_state_object(svga, blend); 415 } 416 417 svga->hud.num_blend_objects++; 418 SVGA_STATS_COUNT_INC(svga_screen(svga->pipe.screen)->sws, 419 SVGA_STATS_COUNT_BLENDSTATE); 420 421 return blend; 422} 423 424 425static void svga_bind_blend_state(struct pipe_context *pipe, 426 void *blend) 427{ 428 struct svga_context *svga = svga_context(pipe); 429 430 svga->curr.blend = (struct svga_blend_state*)blend; 431 svga->dirty |= SVGA_NEW_BLEND; 432} 433 434static void svga_delete_blend_state(struct pipe_context *pipe, 435 void *blend) 436{ 437 struct svga_context *svga = svga_context(pipe); 438 struct svga_blend_state *bs = 439 (struct svga_blend_state *) blend; 440 441 if (svga_have_vgpu10(svga) && bs->id != SVGA3D_INVALID_ID) { 442 SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyBlendState(svga->swc, bs->id)); 443 444 if (bs->id == svga->state.hw_draw.blend_id) 445 svga->state.hw_draw.blend_id = SVGA3D_INVALID_ID; 446 447 util_bitmask_clear(svga->blend_object_id_bm, bs->id); 448 bs->id = SVGA3D_INVALID_ID; 449 } 450 451 FREE(blend); 452 svga->hud.num_blend_objects--; 453} 454 455static void svga_set_blend_color( struct pipe_context *pipe, 456 const struct pipe_blend_color *blend_color ) 457{ 458 struct svga_context *svga = svga_context(pipe); 459 460 svga->curr.blend_color = *blend_color; 461 462 svga->dirty |= SVGA_NEW_BLEND_COLOR; 463} 464 465 466void svga_init_blend_functions( struct svga_context *svga ) 467{ 468 svga->pipe.create_blend_state = svga_create_blend_state; 469 svga->pipe.bind_blend_state = svga_bind_blend_state; 470 svga->pipe.delete_blend_state = svga_delete_blend_state; 471 472 svga->pipe.set_blend_color = svga_set_blend_color; 473} 474