1 /*
2 Copyright (c) 2003 Andreas Robinson, All rights reserved.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8 */
9
10 // Hardware mapping functions ------------------------------------------------
11
12 #include <config.h>
13
14 #include "uc_hw.h"
15 #include <gfx/convert.h>
16
17 /// Map DirectFB blending functions to hardware
18 void
uc_map_blending_fn(struct uc_hw_alpha * hwalpha,DFBSurfaceBlendFunction sblend,DFBSurfaceBlendFunction dblend,DFBSurfacePixelFormat dst_format)19 uc_map_blending_fn( struct uc_hw_alpha *hwalpha,
20 DFBSurfaceBlendFunction sblend,
21 DFBSurfaceBlendFunction dblend,
22 DFBSurfacePixelFormat dst_format )
23 {
24 bool dst_alpha = DFB_PIXELFORMAT_HAS_ALPHA(dst_format);
25
26 // The HW's blending equation is:
27 // (Ca * FCa + Cbias + Cb * FCb) << Cshift
28
29 // Set source blending function
30
31 // Ca -- always from source color.
32 hwalpha->regHABLCsat = HC_HABLCsat_MASK | HC_HABLCa_OPC | HC_HABLCa_Csrc;
33 // Aa -- always from source alpha.
34 hwalpha->regHABLAsat = HC_HABLAsat_MASK | HC_HABLAa_OPA | HC_HABLAa_Asrc;
35
36 // FCa and FAa depend on the following condition.
37 switch (sblend) {
38 case DSBF_ZERO:
39 // GL_ZERO -- (0, 0, 0, 0)
40 hwalpha->regHABLCsat |= HC_HABLFCa_OPC | HC_HABLFCa_HABLRCa;
41 hwalpha->regHABLAsat |= HC_HABLFAa_OPA | HC_HABLFAa_HABLFRA;
42 hwalpha->regHABLRFCa = 0x0;
43 hwalpha->regHABLRAa = 0x0;
44 break;
45
46 case DSBF_ONE:
47 // GL_ONE -- (1, 1, 1, 1)
48 hwalpha->regHABLCsat |= HC_HABLFCa_InvOPC | HC_HABLFCa_HABLRCa;
49 hwalpha->regHABLAsat |= HC_HABLFAa_InvOPA | HC_HABLFAa_HABLFRA;
50 hwalpha->regHABLRFCa = 0x0;
51 hwalpha->regHABLRAa = 0x0;
52 break;
53
54 case DSBF_SRCCOLOR:
55 // GL_SRC_COLOR -- (Rs, Gs, Bs, As)
56 hwalpha->regHABLCsat |= HC_HABLFCa_OPC | HC_HABLFCa_Csrc;
57 hwalpha->regHABLAsat |= HC_HABLFAa_OPA | HC_HABLFAa_Asrc;
58 break;
59
60 case DSBF_INVSRCCOLOR:
61 // GL_ONE_MINUS_SRC_COLOR -- (1, 1, 1, 1) - (Rs, Gs, Bs, As)
62 hwalpha->regHABLCsat |= HC_HABLFCa_InvOPC | HC_HABLFCa_Csrc;
63 hwalpha->regHABLAsat |= HC_HABLFAa_InvOPA | HC_HABLFAa_Asrc;
64 break;
65
66 case DSBF_SRCALPHA:
67 // GL_SRC_ALPHA -- (As, As, As, As)
68 hwalpha->regHABLCsat |= HC_HABLFCa_OPC | HC_HABLFCa_Asrc;
69 hwalpha->regHABLAsat |= HC_HABLFAa_OPA | HC_HABLFAa_Asrc;
70 break;
71
72 case DSBF_INVSRCALPHA:
73 // GL_ONE_MINUS_SRC_ALPHA -- (1, 1, 1, 1) - (As, As, As, As)
74 hwalpha->regHABLCsat |= HC_HABLFCa_InvOPC | HC_HABLFCa_Asrc;
75 hwalpha->regHABLAsat |= HC_HABLFAa_InvOPA | HC_HABLFAa_Asrc;
76 break;
77
78 case DSBF_DESTALPHA:
79 // GL_DST_ALPHA
80 if (!dst_alpha) { // (1, 1, 1, 1)
81 hwalpha->regHABLCsat |= HC_HABLFCa_InvOPC | HC_HABLFCa_HABLRCa;
82 hwalpha->regHABLAsat |= HC_HABLFAa_InvOPA | HC_HABLFAa_HABLFRA;
83 hwalpha->regHABLRFCa = 0x0;
84 hwalpha->regHABLRAa = 0x0;
85 }
86 else { // (Ad, Ad, Ad, Ad)
87 hwalpha->regHABLCsat |= HC_HABLFCa_OPC | HC_HABLFCa_Adst;
88 hwalpha->regHABLAsat |= HC_HABLFAa_OPA | HC_HABLFAa_Adst;
89 }
90 break;
91
92 case DSBF_INVDESTALPHA:
93 // GL_ONE_MINUS_DST_ALPHA
94 if (!dst_alpha) { // (1, 1, 1, 1) - (1, 1, 1, 1) = (0, 0, 0, 0)
95 hwalpha->regHABLCsat |= HC_HABLFCa_OPC | HC_HABLFCa_HABLRCa;
96 hwalpha->regHABLAsat |= HC_HABLFAa_OPA | HC_HABLFAa_HABLFRA;
97 hwalpha->regHABLRFCa = 0x0;
98 hwalpha->regHABLRAa = 0x0;
99 }
100 else { // (1, 1, 1, 1) - (Ad, Ad, Ad, Ad)
101 hwalpha->regHABLCsat |= HC_HABLFCa_InvOPC | HC_HABLFCa_Adst;
102 hwalpha->regHABLAsat |= HC_HABLFAa_InvOPA | HC_HABLFAa_Adst;
103 }
104 break;
105
106 case DSBF_DESTCOLOR:
107 // GL_DST_COLOR -- (Rd, Gd, Bd, Ad)
108 hwalpha->regHABLCsat |= HC_HABLFCa_OPC | HC_HABLFCa_Cdst;
109 hwalpha->regHABLAsat |= HC_HABLFAa_OPA | HC_HABLFAa_Adst;
110 break;
111
112 case DSBF_INVDESTCOLOR:
113 // GL_ONE_MINUS_DST_COLOR -- (1, 1, 1, 1) - (Rd, Gd, Bd, Ad)
114 hwalpha->regHABLCsat |= HC_HABLFCa_InvOPC | HC_HABLFCa_Cdst;
115 hwalpha->regHABLAsat |= HC_HABLFAa_InvOPA | HC_HABLFAa_Adst;
116 break;
117
118 case DSBF_SRCALPHASAT:
119 // GL_SRC_ALPHA_SATURATE
120 if (!dst_alpha) {
121 // (f, f, f, 1), f = min(As, 1 - Ad) = min(As, 1 - 1) = 0
122 // So (f, f, f, 1) = (0, 0, 0, 1)
123 hwalpha->regHABLCsat |= HC_HABLFCa_OPC | HC_HABLFCa_HABLRCa;
124 hwalpha->regHABLAsat |= HC_HABLFAa_InvOPA | HC_HABLFAa_HABLFRA;
125 hwalpha->regHABLRFCa = 0x0;
126 hwalpha->regHABLRAa = 0x0;
127 }
128 else {
129 // (f, f, f, 1), f = min(As, 1 - Ad)
130 hwalpha->regHABLCsat |= HC_HABLFCa_OPC | HC_HABLFCa_mimAsrcInvAdst;
131 hwalpha->regHABLAsat |= HC_HABLFAa_InvOPA | HC_HABLFAa_HABLFRA;
132 hwalpha->regHABLRFCa = 0x0;
133 hwalpha->regHABLRAa = 0x0;
134 }
135 break;
136 default:
137 D_BUG("Unsupported blending function!");
138 break;
139 }
140
141 // Set destination blending function
142
143 // Op is add.
144 // bias is 0.
145
146 hwalpha->regHABLCsat |= HC_HABLCbias_HABLRCbias;
147 hwalpha->regHABLAsat |= HC_HABLAbias_HABLRAbias;
148
149 // Cb -- always from destination color.
150 hwalpha->regHABLCop = HC_HABLCb_OPC | HC_HABLCb_Cdst;
151 // Ab -- always from destination alpha.
152 hwalpha->regHABLAop = HC_HABLAb_OPA | HC_HABLAb_Adst;
153
154 // FCb -- depends on the following condition.
155 switch (dblend) {
156 case DSBF_ZERO:
157 // GL_ZERO -- (0, 0, 0, 0)
158 hwalpha->regHABLCop |= HC_HABLFCb_OPC | HC_HABLFCb_HABLRCb;
159 hwalpha->regHABLAop |= HC_HABLFAb_OPA | HC_HABLFAb_HABLFRA;
160 hwalpha->regHABLRFCb = 0x0;
161 hwalpha->regHABLRAb = 0x0;
162 break;
163
164 case DSBF_ONE:
165 // GL_ONE -- (1, 1, 1, 1)
166 hwalpha->regHABLCop |= HC_HABLFCb_InvOPC | HC_HABLFCb_HABLRCb;
167 hwalpha->regHABLAop |= HC_HABLFAb_InvOPA | HC_HABLFAb_HABLFRA;
168 hwalpha->regHABLRFCb = 0x0;
169 hwalpha->regHABLRAb = 0x0;
170 break;
171
172 case DSBF_SRCCOLOR:
173 // GL_SRC_COLOR -- (Rs, Gs, Bs, As)
174 hwalpha->regHABLCop |= HC_HABLFCb_OPC | HC_HABLFCb_Csrc;
175 hwalpha->regHABLAop |= HC_HABLFAb_OPA | HC_HABLFAb_Asrc;
176 break;
177
178 case DSBF_INVSRCCOLOR:
179 // GL_ONE_MINUS_SRC_COLOR -- (1, 1, 1, 1) - (Rs, Gs, Bs, As)
180 hwalpha->regHABLCop |= HC_HABLFCb_InvOPC | HC_HABLFCb_Csrc;
181 hwalpha->regHABLAop |= HC_HABLFAb_InvOPA | HC_HABLFAb_Asrc;
182 break;
183
184 case DSBF_SRCALPHA:
185 // GL_SRC_ALPHA -- (As, As, As, As)
186 hwalpha->regHABLCop |= HC_HABLFCb_OPC | HC_HABLFCb_Asrc;
187 hwalpha->regHABLAop |= HC_HABLFAb_OPA | HC_HABLFAb_Asrc;
188 break;
189
190 case DSBF_INVSRCALPHA:
191 // GL_ONE_MINUS_SRC_ALPHA -- (1, 1, 1, 1) - (As, As, As, As)
192 hwalpha->regHABLCop |= HC_HABLFCb_InvOPC | HC_HABLFCb_Asrc;
193 hwalpha->regHABLAop |= HC_HABLFAb_InvOPA | HC_HABLFAb_0;
194 break;
195
196 case DSBF_DESTALPHA:
197 // GL_DST_ALPHA
198 if (!dst_alpha) { // (1, 1, 1, 1)
199 hwalpha->regHABLCop |= HC_HABLFCb_InvOPC | HC_HABLFCb_HABLRCb;
200 hwalpha->regHABLAop |= HC_HABLFAb_InvOPA | HC_HABLFAb_HABLFRA;
201 hwalpha->regHABLRFCb = 0x0;
202 hwalpha->regHABLRAb = 0x0;
203 }
204 else { // (Ad, Ad, Ad, Ad)
205 hwalpha->regHABLCop |= HC_HABLFCb_OPC | HC_HABLFCb_Adst;
206 hwalpha->regHABLAop |= HC_HABLFAb_OPA | HC_HABLFAb_Adst;
207 }
208 break;
209
210 case DSBF_INVDESTALPHA:
211 // GL_ONE_MINUS_DST_ALPHA
212 if (!dst_alpha) { // (1, 1, 1, 1) - (1, 1, 1, 1) = (0, 0, 0, 0)
213 hwalpha->regHABLCop |= HC_HABLFCb_OPC | HC_HABLFCb_HABLRCb;
214 hwalpha->regHABLAop |= HC_HABLFAb_OPA | HC_HABLFAb_HABLFRA;
215 hwalpha->regHABLRFCb = 0x0;
216 hwalpha->regHABLRAb = 0x0;
217 }
218 else { // (1, 1, 1, 1) - (Ad, Ad, Ad, Ad)
219 hwalpha->regHABLCop |= HC_HABLFCb_InvOPC | HC_HABLFCb_Adst;
220 hwalpha->regHABLAop |= HC_HABLFAb_InvOPA | HC_HABLFAb_Adst;
221 }
222 break;
223
224 case DSBF_DESTCOLOR:
225 // GL_DST_COLOR -- (Rd, Gd, Bd, Ad)
226 hwalpha->regHABLCop |= HC_HABLFCb_OPC | HC_HABLFCb_Cdst;
227 hwalpha->regHABLAop |= HC_HABLFAb_OPA | HC_HABLFAb_Adst;
228 break;
229
230 case DSBF_INVDESTCOLOR:
231 // GL_ONE_MINUS_DST_COLOR -- (1, 1, 1, 1) - (Rd, Gd, Bd, Ad)
232 hwalpha->regHABLCop |= HC_HABLFCb_InvOPC | HC_HABLFCb_Cdst;
233 hwalpha->regHABLAop |= HC_HABLFAb_InvOPA | HC_HABLFAb_Adst;
234 break;
235
236 case DSBF_SRCALPHASAT:
237 // Unsupported?
238
239 default:
240 hwalpha->regHABLCop |= HC_HABLFCb_OPC | HC_HABLFCb_HABLRCb;
241 hwalpha->regHABLAop |= HC_HABLFAb_OPA | HC_HABLFAb_HABLFRA;
242 hwalpha->regHABLRFCb = 0x0;
243 hwalpha->regHABLRAb = 0x0;
244 break;
245 }
246 }
247
248 /// Map DFBSurfaceBlittingFlags to the hardware
249 void
uc_map_blitflags(struct uc_hw_texture * tex,DFBSurfaceBlittingFlags bflags,DFBSurfacePixelFormat sformat)250 uc_map_blitflags( struct uc_hw_texture *tex,
251 DFBSurfaceBlittingFlags bflags,
252 DFBSurfacePixelFormat sformat )
253 {
254 bool gotalpha = DFB_PIXELFORMAT_HAS_ALPHA(sformat);
255
256 if (bflags & DSBLIT_COLORIZE) {
257 // Cv0 = Ct*Cf
258
259 // Hw setting:
260 // Ca = Ct, Cb = Cf, Cop = +, Cc = 0, Cbias = 0, Cshift = No.
261
262 tex->regHTXnTBLCsat_0 = HC_HTXnTBLCsat_MASK |
263 HC_HTXnTBLCa_TOPC | HC_HTXnTBLCa_Tex |
264 HC_HTXnTBLCb_TOPC | HC_HTXnTBLCb_Dif |
265 HC_HTXnTBLCc_TOPC | HC_HTXnTBLCc_0;
266 tex->regHTXnTBLCop_0 = HC_HTXnTBLCop_Add |
267 HC_HTXnTBLCbias_Cbias | HC_HTXnTBLCbias_0 |
268 HC_HTXnTBLCshift_No;
269 tex->regHTXnTBLMPfog_0 = HC_HTXnTBLMPfog_0;
270 }
271 else {
272 // Cv0 = Ct
273
274 // Hw setting:
275 // Ca = 0, Cb = 0, Cop = +, Cc = 0, Cbias = Ct, Cshift = No.
276
277 tex->regHTXnTBLCsat_0 = HC_HTXnTBLCsat_MASK |
278 HC_HTXnTBLCa_TOPC | HC_HTXnTBLCa_0 |
279 HC_HTXnTBLCb_TOPC | HC_HTXnTBLCb_0 |
280 HC_HTXnTBLCc_TOPC | HC_HTXnTBLCc_0;
281 tex->regHTXnTBLCop_0 = HC_HTXnTBLCop_Add |
282 HC_HTXnTBLCbias_Cbias | HC_HTXnTBLCbias_Tex |
283 HC_HTXnTBLCshift_No;
284 tex->regHTXnTBLMPfog_0 = HC_HTXnTBLMPfog_0;
285 }
286
287 if (bflags & DSBLIT_BLEND_COLORALPHA) {
288 if ((bflags & DSBLIT_BLEND_ALPHACHANNEL) && gotalpha) {
289 // Av0 = At*Af
290
291 // Hw setting:
292 // Aa = At, Ab = Af, Cop = +, Ac = 0, Abias = 0, Ashift = No.
293
294 tex->regHTXnTBLAsat_0 = HC_HTXnTBLAsat_MASK |
295 HC_HTXnTBLAa_TOPA | HC_HTXnTBLAa_Atex |
296 HC_HTXnTBLAb_TOPA | HC_HTXnTBLAb_Adif |
297 HC_HTXnTBLAc_TOPA | HC_HTXnTBLAc_HTXnTBLRA;
298 tex->regHTXnTBLCop_0 |= HC_HTXnTBLAop_Add |
299 HC_HTXnTBLAbias_HTXnTBLRAbias | HC_HTXnTBLAshift_No;
300 tex->regHTXnTBLRAa_0 = 0x0;
301 tex->regHTXnTBLRFog_0 = 0x0;
302 }
303 else {
304 // (!(bflags & DSBLIT_BLEND_ALPHACHANNEL) && gotalpha) || !gotalpha
305 // Av0 = Af
306
307 // Hw setting:
308 // Aa = 0, Ab = 0, Cop = +, Ac = 0, Abias = Af, Ashift = No.
309
310 tex->regHTXnTBLAsat_0 = HC_HTXnTBLAsat_MASK |
311 HC_HTXnTBLAa_TOPA | HC_HTXnTBLAa_HTXnTBLRA |
312 HC_HTXnTBLAb_TOPA | HC_HTXnTBLAb_HTXnTBLRA |
313 HC_HTXnTBLAc_TOPA | HC_HTXnTBLAc_HTXnTBLRA;
314 tex->regHTXnTBLCop_0 |= HC_HTXnTBLAop_Add |
315 HC_HTXnTBLAbias_Adif | HC_HTXnTBLAshift_No;
316 tex->regHTXnTBLRAa_0 = 0x0;
317 tex->regHTXnTBLRFog_0 = 0x0;
318 }
319 }
320 else { // !(bflags & DSBLIT_BLEND_COLORALPHA)
321 if ((bflags & DSBLIT_BLEND_ALPHACHANNEL) && gotalpha) {
322 // Av0 = At
323
324 // Hw setting:
325 // Aa = 0, Ab = 0, Cop = +, Ac = 0, Abias = At, Ashift = No.
326
327 tex->regHTXnTBLAsat_0 = HC_HTXnTBLAsat_MASK |
328 HC_HTXnTBLAa_TOPA | HC_HTXnTBLAa_HTXnTBLRA |
329 HC_HTXnTBLAb_TOPA | HC_HTXnTBLAb_HTXnTBLRA |
330 HC_HTXnTBLAc_TOPA | HC_HTXnTBLAc_HTXnTBLRA;
331 tex->regHTXnTBLCop_0 |= HC_HTXnTBLAop_Add |
332 HC_HTXnTBLAbias_Atex | HC_HTXnTBLAshift_No;
333 tex->regHTXnTBLRAa_0 = 0x0;
334 tex->regHTXnTBLRFog_0 = 0x0;
335 }
336 else { // !gotalpha
337 // Av0 = 1.0
338
339 // D_BUG warning: I'm guessing where values should go,
340 // and how big (0xff = 1.0 ?) it should be.
341
342 // Hw setting:
343 // Aa = 1.0, Ab = 1.0, Cop = -, Ac = 1.0, Abias = 1.0, Ashift = No.
344 // => Av = Aa*(Ab-Ac) + Abias = 1*(1-1)+1 = 1
345
346 tex->regHTXnTBLAsat_0 = HC_HTXnTBLAsat_MASK |
347 HC_HTXnTBLAa_TOPA | HC_HTXnTBLAa_HTXnTBLRA |
348 HC_HTXnTBLAb_TOPA | HC_HTXnTBLAb_HTXnTBLRA |
349 HC_HTXnTBLAc_TOPA | HC_HTXnTBLAc_HTXnTBLRA;
350 tex->regHTXnTBLCop_0 |= HC_HTXnTBLAop_Add |
351 HC_HTXnTBLAbias_Inv | HC_HTXnTBLAbias_HTXnTBLRAbias | HC_HTXnTBLAshift_No;
352 tex->regHTXnTBLRAa_0 = 0x0;
353 tex->regHTXnTBLRFog_0 = 0x0;
354 }
355 }
356 }
357
358