aboutsummaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/svga/svga_pipe_blend.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/svga/svga_pipe_blend.c')
-rw-r--r--src/gallium/drivers/svga/svga_pipe_blend.c246
1 files changed, 246 insertions, 0 deletions
diff --git a/src/gallium/drivers/svga/svga_pipe_blend.c b/src/gallium/drivers/svga/svga_pipe_blend.c
new file mode 100644
index 00000000000..855d228755f
--- /dev/null
+++ b/src/gallium/drivers/svga/svga_pipe_blend.c
@@ -0,0 +1,246 @@
+/**********************************************************
+ * Copyright 2008-2009 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ **********************************************************/
+
+#include "pipe/p_inlines.h"
+#include "pipe/p_defines.h"
+#include "util/u_math.h"
+#include "util/u_memory.h"
+
+#include "svga_context.h"
+#include "svga_state.h"
+
+#include "svga_hw_reg.h"
+
+
+static INLINE unsigned
+svga_translate_blend_factor(unsigned factor)
+{
+ switch (factor) {
+ case PIPE_BLENDFACTOR_ZERO: return SVGA3D_BLENDOP_ZERO;
+ case PIPE_BLENDFACTOR_SRC_ALPHA: return SVGA3D_BLENDOP_SRCALPHA;
+ case PIPE_BLENDFACTOR_ONE: return SVGA3D_BLENDOP_ONE;
+ case PIPE_BLENDFACTOR_SRC_COLOR: return SVGA3D_BLENDOP_SRCCOLOR;
+ case PIPE_BLENDFACTOR_INV_SRC_COLOR: return SVGA3D_BLENDOP_INVSRCCOLOR;
+ case PIPE_BLENDFACTOR_DST_COLOR: return SVGA3D_BLENDOP_DESTCOLOR;
+ case PIPE_BLENDFACTOR_INV_DST_COLOR: return SVGA3D_BLENDOP_INVDESTCOLOR;
+ case PIPE_BLENDFACTOR_INV_SRC_ALPHA: return SVGA3D_BLENDOP_INVSRCALPHA;
+ case PIPE_BLENDFACTOR_DST_ALPHA: return SVGA3D_BLENDOP_DESTALPHA;
+ case PIPE_BLENDFACTOR_INV_DST_ALPHA: return SVGA3D_BLENDOP_INVDESTALPHA;
+ case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return SVGA3D_BLENDOP_SRCALPHASAT;
+ case PIPE_BLENDFACTOR_CONST_COLOR: return SVGA3D_BLENDOP_BLENDFACTOR;
+ case PIPE_BLENDFACTOR_INV_CONST_COLOR: return SVGA3D_BLENDOP_INVBLENDFACTOR;
+ case PIPE_BLENDFACTOR_CONST_ALPHA: return SVGA3D_BLENDOP_BLENDFACTOR; /* ? */
+ case PIPE_BLENDFACTOR_INV_CONST_ALPHA: return SVGA3D_BLENDOP_INVBLENDFACTOR; /* ? */
+ default:
+ assert(0);
+ return SVGA3D_BLENDOP_ZERO;
+ }
+}
+
+static INLINE unsigned
+svga_translate_blend_func(unsigned mode)
+{
+ switch (mode) {
+ case PIPE_BLEND_ADD: return SVGA3D_BLENDEQ_ADD;
+ case PIPE_BLEND_SUBTRACT: return SVGA3D_BLENDEQ_SUBTRACT;
+ case PIPE_BLEND_REVERSE_SUBTRACT: return SVGA3D_BLENDEQ_REVSUBTRACT;
+ case PIPE_BLEND_MIN: return SVGA3D_BLENDEQ_MINIMUM;
+ case PIPE_BLEND_MAX: return SVGA3D_BLENDEQ_MAXIMUM;
+ default:
+ assert(0);
+ return SVGA3D_BLENDEQ_ADD;
+ }
+}
+
+
+static void *
+svga_create_blend_state(struct pipe_context *pipe,
+ const struct pipe_blend_state *templ)
+{
+ struct svga_blend_state *blend = CALLOC_STRUCT( svga_blend_state );
+ unsigned i;
+
+
+ /* Fill in the per-rendertarget blend state. We currently only
+ * have one rendertarget.
+ */
+ for (i = 0; i < 1; i++) {
+ /* No way to set this in SVGA3D, and no way to correctly implement it on
+ * top of D3D9 API. Instead we try to simulate with various blend modes.
+ */
+ if (templ->logicop_enable) {
+ switch (templ->logicop_func) {
+ case PIPE_LOGICOP_XOR:
+ blend->need_white_fragments = TRUE;
+ blend->rt[i].blend_enable = TRUE;
+ blend->rt[i].srcblend = SVGA3D_BLENDOP_ONE;
+ blend->rt[i].dstblend = SVGA3D_BLENDOP_ONE;
+ blend->rt[i].blendeq = SVGA3D_BLENDEQ_SUBTRACT;
+ break;
+ case PIPE_LOGICOP_CLEAR:
+ blend->rt[i].blend_enable = TRUE;
+ blend->rt[i].srcblend = SVGA3D_BLENDOP_ZERO;
+ blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO;
+ blend->rt[i].blendeq = SVGA3D_BLENDEQ_MINIMUM;
+ break;
+ case PIPE_LOGICOP_COPY:
+ blend->rt[i].blend_enable = FALSE;
+ break;
+ case PIPE_LOGICOP_COPY_INVERTED:
+ blend->rt[i].blend_enable = TRUE;
+ blend->rt[i].srcblend = SVGA3D_BLENDOP_INVSRCCOLOR;
+ blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO;
+ blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD;
+ break;
+ case PIPE_LOGICOP_NOOP:
+ blend->rt[i].blend_enable = TRUE;
+ blend->rt[i].srcblend = SVGA3D_BLENDOP_ZERO;
+ blend->rt[i].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
+ blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD;
+ break;
+ case PIPE_LOGICOP_SET:
+ blend->rt[i].blend_enable = TRUE;
+ blend->rt[i].srcblend = SVGA3D_BLENDOP_ONE;
+ blend->rt[i].dstblend = SVGA3D_BLENDOP_ONE;
+ blend->rt[i].blendeq = SVGA3D_BLENDEQ_MAXIMUM;
+ break;
+ case PIPE_LOGICOP_INVERT:
+ blend->rt[i].blend_enable = TRUE;
+ blend->rt[i].srcblend = SVGA3D_BLENDOP_INVSRCCOLOR;
+ blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO;
+ blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD;
+ break;
+ case PIPE_LOGICOP_AND:
+ /* Approximate with minimum - works for the 0 & anything case: */
+ blend->rt[i].blend_enable = TRUE;
+ blend->rt[i].srcblend = SVGA3D_BLENDOP_SRCCOLOR;
+ blend->rt[i].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
+ blend->rt[i].blendeq = SVGA3D_BLENDEQ_MINIMUM;
+ break;
+ case PIPE_LOGICOP_AND_REVERSE:
+ blend->rt[i].blend_enable = TRUE;
+ blend->rt[i].srcblend = SVGA3D_BLENDOP_SRCCOLOR;
+ blend->rt[i].dstblend = SVGA3D_BLENDOP_INVDESTCOLOR;
+ blend->rt[i].blendeq = SVGA3D_BLENDEQ_MINIMUM;
+ break;
+ case PIPE_LOGICOP_AND_INVERTED:
+ blend->rt[i].blend_enable = TRUE;
+ blend->rt[i].srcblend = SVGA3D_BLENDOP_INVSRCCOLOR;
+ blend->rt[i].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
+ blend->rt[i].blendeq = SVGA3D_BLENDEQ_MINIMUM;
+ break;
+ case PIPE_LOGICOP_OR:
+ /* Approximate with maximum - works for the 1 | anything case: */
+ blend->rt[i].blend_enable = TRUE;
+ blend->rt[i].srcblend = SVGA3D_BLENDOP_SRCCOLOR;
+ blend->rt[i].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
+ blend->rt[i].blendeq = SVGA3D_BLENDEQ_MAXIMUM;
+ break;
+ case PIPE_LOGICOP_OR_REVERSE:
+ blend->rt[i].blend_enable = TRUE;
+ blend->rt[i].srcblend = SVGA3D_BLENDOP_SRCCOLOR;
+ blend->rt[i].dstblend = SVGA3D_BLENDOP_INVDESTCOLOR;
+ blend->rt[i].blendeq = SVGA3D_BLENDEQ_MAXIMUM;
+ break;
+ case PIPE_LOGICOP_OR_INVERTED:
+ blend->rt[i].blend_enable = TRUE;
+ blend->rt[i].srcblend = SVGA3D_BLENDOP_INVSRCCOLOR;
+ blend->rt[i].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
+ blend->rt[i].blendeq = SVGA3D_BLENDEQ_MAXIMUM;
+ break;
+ case PIPE_LOGICOP_NAND:
+ case PIPE_LOGICOP_NOR:
+ case PIPE_LOGICOP_EQUIV:
+ /* Fill these in with plausible values */
+ blend->rt[i].blend_enable = FALSE;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+ else {
+ blend->rt[i].blend_enable = templ->blend_enable;
+
+ if (templ->blend_enable) {
+ blend->rt[i].srcblend = svga_translate_blend_factor(templ->rgb_src_factor);
+ blend->rt[i].dstblend = svga_translate_blend_factor(templ->rgb_dst_factor);
+ blend->rt[i].blendeq = svga_translate_blend_func(templ->rgb_func);
+ blend->rt[i].srcblend_alpha = svga_translate_blend_factor(templ->alpha_src_factor);
+ blend->rt[i].dstblend_alpha = svga_translate_blend_factor(templ->alpha_dst_factor);
+ blend->rt[i].blendeq_alpha = svga_translate_blend_func(templ->alpha_func);
+
+ if (blend->rt[i].srcblend_alpha != blend->rt[i].srcblend ||
+ blend->rt[i].dstblend_alpha != blend->rt[i].dstblend ||
+ blend->rt[i].blendeq_alpha != blend->rt[i].blendeq)
+ {
+ blend->rt[i].separate_alpha_blend_enable = TRUE;
+ }
+ }
+ }
+
+ blend->rt[i].writemask = templ->colormask;
+ }
+
+ return blend;
+}
+
+static void svga_bind_blend_state(struct pipe_context *pipe,
+ void *blend)
+{
+ struct svga_context *svga = svga_context(pipe);
+
+ svga->curr.blend = (struct svga_blend_state*)blend;
+ svga->dirty |= SVGA_NEW_BLEND;
+}
+
+
+static void svga_delete_blend_state(struct pipe_context *pipe, void *blend)
+{
+ FREE(blend);
+}
+
+static void svga_set_blend_color( struct pipe_context *pipe,
+ const struct pipe_blend_color *blend_color )
+{
+ struct svga_context *svga = svga_context(pipe);
+
+ svga->curr.blend_color = *blend_color;
+
+ svga->dirty |= SVGA_NEW_BLEND;
+}
+
+
+void svga_init_blend_functions( struct svga_context *svga )
+{
+ svga->pipe.create_blend_state = svga_create_blend_state;
+ svga->pipe.bind_blend_state = svga_bind_blend_state;
+ svga->pipe.delete_blend_state = svga_delete_blend_state;
+
+ svga->pipe.set_blend_color = svga_set_blend_color;
+}
+
+
+