summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/i965/brw_pipe_blend.c
blob: cc9ee2e8dbc5500e52b9bc003d09edbb0775ab44 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200

#include "util/u_memory.h"
#include "pipe/p_context.h"
#include "pipe/p_state.h"

#include "brw_context.h"
#include "brw_defines.h"
#include "brw_debug.h"

static int translate_logicop(unsigned logicop)
{
   switch (logicop) {
   case PIPE_LOGICOP_CLEAR:
      return BRW_LOGICOPFUNCTION_CLEAR;
   case PIPE_LOGICOP_AND:
      return BRW_LOGICOPFUNCTION_AND;
   case PIPE_LOGICOP_AND_REVERSE:
      return BRW_LOGICOPFUNCTION_AND_REVERSE;
   case PIPE_LOGICOP_COPY:
      return BRW_LOGICOPFUNCTION_COPY;
   case PIPE_LOGICOP_COPY_INVERTED:
      return BRW_LOGICOPFUNCTION_COPY_INVERTED;
   case PIPE_LOGICOP_AND_INVERTED:
      return BRW_LOGICOPFUNCTION_AND_INVERTED;
   case PIPE_LOGICOP_NOOP:
      return BRW_LOGICOPFUNCTION_NOOP;
   case PIPE_LOGICOP_XOR:
      return BRW_LOGICOPFUNCTION_XOR;
   case PIPE_LOGICOP_OR:
      return BRW_LOGICOPFUNCTION_OR;
   case PIPE_LOGICOP_OR_INVERTED:
      return BRW_LOGICOPFUNCTION_OR_INVERTED;
   case PIPE_LOGICOP_NOR:
      return BRW_LOGICOPFUNCTION_NOR;
   case PIPE_LOGICOP_EQUIV:
      return BRW_LOGICOPFUNCTION_EQUIV;
   case PIPE_LOGICOP_INVERT:
      return BRW_LOGICOPFUNCTION_INVERT;
   case PIPE_LOGICOP_OR_REVERSE:
      return BRW_LOGICOPFUNCTION_OR_REVERSE;
   case PIPE_LOGICOP_NAND:
      return BRW_LOGICOPFUNCTION_NAND;
   case PIPE_LOGICOP_SET:
      return BRW_LOGICOPFUNCTION_SET;
   default:
      assert(0);
      return BRW_LOGICOPFUNCTION_SET;
   }
}


static unsigned translate_blend_equation( unsigned mode )
{
   switch (mode) {
   case PIPE_BLEND_ADD: 
      return BRW_BLENDFUNCTION_ADD; 
   case PIPE_BLEND_MIN: 
      return BRW_BLENDFUNCTION_MIN; 
   case PIPE_BLEND_MAX: 
      return BRW_BLENDFUNCTION_MAX; 
   case PIPE_BLEND_SUBTRACT: 
      return BRW_BLENDFUNCTION_SUBTRACT; 
   case PIPE_BLEND_REVERSE_SUBTRACT: 
      return BRW_BLENDFUNCTION_REVERSE_SUBTRACT; 
   default: 
      assert(0);
      return BRW_BLENDFUNCTION_ADD;
   }
}

static unsigned translate_blend_factor( unsigned factor )
{
   switch(factor) {
   case PIPE_BLENDFACTOR_ZERO: 
      return BRW_BLENDFACTOR_ZERO; 
   case PIPE_BLENDFACTOR_SRC_ALPHA: 
      return BRW_BLENDFACTOR_SRC_ALPHA; 
   case PIPE_BLENDFACTOR_ONE: 
      return BRW_BLENDFACTOR_ONE; 
   case PIPE_BLENDFACTOR_SRC_COLOR: 
      return BRW_BLENDFACTOR_SRC_COLOR; 
   case PIPE_BLENDFACTOR_INV_SRC_COLOR: 
      return BRW_BLENDFACTOR_INV_SRC_COLOR; 
   case PIPE_BLENDFACTOR_DST_COLOR: 
      return BRW_BLENDFACTOR_DST_COLOR; 
   case PIPE_BLENDFACTOR_INV_DST_COLOR: 
      return BRW_BLENDFACTOR_INV_DST_COLOR; 
   case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
      return BRW_BLENDFACTOR_INV_SRC_ALPHA; 
   case PIPE_BLENDFACTOR_DST_ALPHA: 
      return BRW_BLENDFACTOR_DST_ALPHA; 
   case PIPE_BLENDFACTOR_INV_DST_ALPHA:
      return BRW_BLENDFACTOR_INV_DST_ALPHA; 
   case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: 
      return BRW_BLENDFACTOR_SRC_ALPHA_SATURATE;
   case PIPE_BLENDFACTOR_CONST_COLOR:
      return BRW_BLENDFACTOR_CONST_COLOR; 
   case PIPE_BLENDFACTOR_INV_CONST_COLOR:
      return BRW_BLENDFACTOR_INV_CONST_COLOR;
   case PIPE_BLENDFACTOR_CONST_ALPHA:
      return BRW_BLENDFACTOR_CONST_ALPHA; 
   case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
      return BRW_BLENDFACTOR_INV_CONST_ALPHA;
   default:
      assert(0);
      return BRW_BLENDFACTOR_ZERO;
   }   
}

static void *brw_create_blend_state( struct pipe_context *pipe,
				     const struct pipe_blend_state *templ )
{
   struct brw_blend_state *blend = CALLOC_STRUCT(brw_blend_state);

   if (templ->logicop_enable) {
      blend->cc2.logicop_enable = 1;
      blend->cc5.logicop_func = translate_logicop(templ->logicop_func);
   } 
   else if (templ->blend_enable) {
      blend->cc6.dest_blend_factor = translate_blend_factor(templ->rgb_dst_factor);
      blend->cc6.src_blend_factor = translate_blend_factor(templ->rgb_src_factor);
      blend->cc6.blend_function = translate_blend_equation(templ->rgb_func);

      blend->cc5.ia_dest_blend_factor = translate_blend_factor(templ->alpha_dst_factor);
      blend->cc5.ia_src_blend_factor = translate_blend_factor(templ->alpha_src_factor);
      blend->cc5.ia_blend_function = translate_blend_equation(templ->alpha_func);

      blend->cc3.blend_enable = 1;
      blend->cc3.ia_blend_enable = 
	 (blend->cc6.dest_blend_factor != blend->cc5.ia_dest_blend_factor ||
	  blend->cc6.src_blend_factor != blend->cc5.ia_src_blend_factor ||
	  blend->cc6.blend_function != blend->cc5.ia_blend_function);

      /* Per-surface blend enables, currently just follow global
       * state:
       */
      blend->ss0.color_blend = 1;
   }

   blend->cc5.dither_enable = templ->dither;

   if (BRW_DEBUG & DEBUG_STATS)
      blend->cc5.statistics_enable = 1;

   /* Per-surface color mask -- just follow global state:
    */
   blend->ss0.writedisable_red   = (templ->colormask & PIPE_MASK_R) ? 1 : 0;
   blend->ss0.writedisable_green = (templ->colormask & PIPE_MASK_G) ? 1 : 0;
   blend->ss0.writedisable_blue  = (templ->colormask & PIPE_MASK_B) ? 1 : 0;
   blend->ss0.writedisable_alpha = (templ->colormask & PIPE_MASK_A) ? 1 : 0;

   return (void *)blend;
}

static void brw_bind_blend_state(struct pipe_context *pipe,
				 void *cso)
{
   struct brw_context *brw = brw_context(pipe);
   brw->curr.blend = (const struct brw_blend_state *)cso;
   brw->state.dirty.mesa |= PIPE_NEW_BLEND;
}

static void brw_delete_blend_state(struct pipe_context *pipe,
				  void *cso)
{
   struct brw_context *brw = brw_context(pipe);
   assert((const void *)cso != (const void *)brw->curr.blend);
   FREE(cso);
}


static void brw_set_blend_color(struct pipe_context *pipe,
				const struct pipe_blend_color *blend_color)
{
   struct brw_context *brw = brw_context(pipe);
   struct brw_blend_constant_color *bcc = &brw->curr.bcc;

   memset(bcc, 0, sizeof(*bcc));      
   bcc->header.opcode = CMD_BLEND_CONSTANT_COLOR;
   bcc->header.length = sizeof(*bcc)/4-2;
   bcc->blend_constant_color[0] = blend_color->color[0];
   bcc->blend_constant_color[1] = blend_color->color[1];
   bcc->blend_constant_color[2] = blend_color->color[2];
   bcc->blend_constant_color[3] = blend_color->color[3];

   brw->state.dirty.mesa |= PIPE_NEW_BLEND_COLOR;
}


void brw_pipe_blend_init( struct brw_context *brw )
{
   brw->base.set_blend_color = brw_set_blend_color;
   brw->base.create_blend_state = brw_create_blend_state;
   brw->base.bind_blend_state = brw_bind_blend_state;
   brw->base.delete_blend_state = brw_delete_blend_state;
}

void brw_pipe_blend_cleanup( struct brw_context *brw )
{
}