Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/**************************************************************************
2
 *
3
 * Copyright 2012 VMware, Inc.
4
 * All Rights Reserved.
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the
8
 * "Software"), to deal in the Software without restriction, including
9
 * without limitation the rights to use, copy, modify, merge, publish,
10
 * distribute, sub license, and/or sell copies of the Software, and to
11
 * permit persons to whom the Software is furnished to do so, subject to
12
 * the following conditions:
13
 *
14
 * The above copyright notice and this permission notice (including the
15
 * next paragraph) shall be included in all copies or substantial portions
16
 * of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21
 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 *
26
 **************************************************************************/
27
 
28
#include "pipe/p_state.h"
29
#include "util/u_debug.h"
30
 
31
#include "gallivm/lp_bld_type.h"
32
#include "gallivm/lp_bld_arit.h"
33
 
34
#include "lp_bld_blend.h"
35
 
36
/**
37
 * Is (a OP b) == (b OP a)?
38
 */
39
boolean
40
lp_build_blend_func_commutative(unsigned func)
41
{
42
   switch (func) {
43
   case PIPE_BLEND_ADD:
44
   case PIPE_BLEND_MIN:
45
   case PIPE_BLEND_MAX:
46
      return TRUE;
47
   case PIPE_BLEND_SUBTRACT:
48
   case PIPE_BLEND_REVERSE_SUBTRACT:
49
      return FALSE;
50
   default:
51
      assert(0);
52
      return TRUE;
53
   }
54
}
55
 
56
 
57
/**
58
 * Whether the blending functions are the reverse of each other.
59
 */
60
boolean
61
lp_build_blend_func_reverse(unsigned rgb_func, unsigned alpha_func)
62
{
63
   if(rgb_func == alpha_func)
64
      return FALSE;
65
   if(rgb_func == PIPE_BLEND_SUBTRACT && alpha_func == PIPE_BLEND_REVERSE_SUBTRACT)
66
      return TRUE;
67
   if(rgb_func == PIPE_BLEND_REVERSE_SUBTRACT && alpha_func == PIPE_BLEND_SUBTRACT)
68
      return TRUE;
69
   return FALSE;
70
}
71
 
72
 
73
/**
74
 * Whether the blending factors are complementary of each other.
75
 */
76
static INLINE boolean
77
lp_build_blend_factor_complementary(unsigned src_factor, unsigned dst_factor)
78
{
79
   return dst_factor == (src_factor ^ 0x10);
80
}
81
 
82
 
83
/**
84
 * @sa http://www.opengl.org/sdk/docs/man/xhtml/glBlendEquationSeparate.xml
85
 */
86
LLVMValueRef
87
lp_build_blend_func(struct lp_build_context *bld,
88
                    unsigned func,
89
                    LLVMValueRef term1,
90
                    LLVMValueRef term2)
91
{
92
   switch (func) {
93
   case PIPE_BLEND_ADD:
94
      return lp_build_add(bld, term1, term2);
95
   case PIPE_BLEND_SUBTRACT:
96
      return lp_build_sub(bld, term1, term2);
97
   case PIPE_BLEND_REVERSE_SUBTRACT:
98
      return lp_build_sub(bld, term2, term1);
99
   case PIPE_BLEND_MIN:
100
      return lp_build_min(bld, term1, term2);
101
   case PIPE_BLEND_MAX:
102
      return lp_build_max(bld, term1, term2);
103
   default:
104
      assert(0);
105
      return bld->zero;
106
   }
107
}
108
 
109
 
110
/**
111
 * Performs optimisations and blending independent of SoA/AoS
112
 *
113
 * @param func                   the blend function
114
 * @param factor_src             PIPE_BLENDFACTOR_xxx
115
 * @param factor_dst             PIPE_BLENDFACTOR_xxx
116
 * @param src                    source rgba
117
 * @param dst                    dest rgba
118
 * @param src_factor             src factor computed value
119
 * @param dst_factor             dst factor computed value
120
 * @param not_alpha_dependent    same factors accross all channels of src/dst
121
 *
122
 * not_alpha_dependent should be:
123
 *  SoA: always true as it is only one channel at a time
124
 *  AoS: rgb_src_factor == alpha_src_factor && rgb_dst_factor == alpha_dst_factor
125
 *
126
 * Note that pretty much every possible optimisation can only be done on non-unorm targets
127
 * due to unorm values not going above 1.0 meaning factorisation can change results.
128
 * e.g. (0.9 * 0.9) + (0.9 * 0.9) != 0.9 * (0.9 + 0.9) as result of + is always <= 1.
129
 */
130
LLVMValueRef
131
lp_build_blend(struct lp_build_context *bld,
132
               unsigned func,
133
               unsigned factor_src,
134
               unsigned factor_dst,
135
               LLVMValueRef src,
136
               LLVMValueRef dst,
137
               LLVMValueRef src_factor,
138
               LLVMValueRef dst_factor,
139
               boolean not_alpha_dependent,
140
               boolean optimise_only)
141
{
142
   LLVMValueRef result, src_term, dst_term;
143
 
144
   /* If we are not alpha dependent we can mess with the src/dst factors */
145
   if (not_alpha_dependent) {
146
      if (lp_build_blend_factor_complementary(factor_src, factor_dst)) {
147
         if (func == PIPE_BLEND_ADD) {
148
            if (factor_src < factor_dst) {
149
               return lp_build_lerp(bld, src_factor, dst, src, 0);
150
            } else {
151
               return lp_build_lerp(bld, dst_factor, src, dst, 0);
152
            }
153
         } else if(bld->type.floating && func == PIPE_BLEND_SUBTRACT) {
154
            result = lp_build_add(bld, src, dst);
155
 
156
            if (factor_src < factor_dst) {
157
               result = lp_build_mul(bld, result, src_factor);
158
               return lp_build_sub(bld, result, dst);
159
            } else {
160
               result = lp_build_mul(bld, result, dst_factor);
161
               return lp_build_sub(bld, src, result);
162
            }
163
         } else if(bld->type.floating && func == PIPE_BLEND_REVERSE_SUBTRACT) {
164
            result = lp_build_add(bld, src, dst);
165
 
166
            if (factor_src < factor_dst) {
167
               result = lp_build_mul(bld, result, src_factor);
168
               return lp_build_sub(bld, dst, result);
169
            } else {
170
               result = lp_build_mul(bld, result, dst_factor);
171
               return lp_build_sub(bld, result, src);
172
            }
173
         }
174
      }
175
 
176
      if (bld->type.floating && factor_src == factor_dst) {
177
         if (func == PIPE_BLEND_ADD ||
178
             func == PIPE_BLEND_SUBTRACT ||
179
             func == PIPE_BLEND_REVERSE_SUBTRACT) {
180
            LLVMValueRef result;
181
            result = lp_build_blend_func(bld, func, src, dst);
182
            return lp_build_mul(bld, result, src_factor);
183
         }
184
      }
185
   }
186
 
187
   if (optimise_only)
188
      return NULL;
189
 
190
   src_term = lp_build_mul(bld, src, src_factor);
191
   dst_term = lp_build_mul(bld, dst, dst_factor);
192
   return lp_build_blend_func(bld, func, src_term, dst_term);
193
}