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