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 setting functions ------------------------------------------------
11 
12 #include <config.h>
13 
14 #include "uc_hw.h"
15 #include <core/state.h>
16 #include <core/palette.h>
17 #include <gfx/convert.h>
18 
19 /// Integer 2-logarithm, y = log2(x), where x and y are integers.
20 #define ILOG2(x,y) ILOG2_PORTABLE(x,y)
21 
22 #define ILOG2_PORTABLE(x,y) \
23     do {                    \
24         unsigned int i = 0; \
25         y = x;              \
26         while (y != 0) {    \
27             i++;            \
28             y = y >> 1;     \
29         }                   \
30         y = i-1;            \
31     } while (0)
32 
33 #define ILOG2_X86(x,y)  // TODO - use BSR (bit scan reverse) instruction
34 
35 /// Set alpha blending function (3D)
36 void
uc_set_blending_fn(UcDriverData * ucdrv,UcDeviceData * ucdev,CardState * state)37 uc_set_blending_fn( UcDriverData *ucdrv,
38                     UcDeviceData *ucdev,
39                     CardState    *state )
40 {
41      struct uc_fifo     *fifo    = ucdrv->fifo;
42      struct uc_hw_alpha *hwalpha = &ucdev->hwalpha;
43 
44      if (UC_IS_VALID( uc_blending_fn ))
45           return;
46 
47      uc_map_blending_fn( hwalpha, state->src_blend, state->dst_blend,
48                          state->destination->config.format );
49 
50      UC_FIFO_PREPARE( fifo, 14 );
51      UC_FIFO_ADD_HDR( fifo, HC_ParaType_NotTex << 16 );
52 
53      UC_FIFO_ADD_3D ( fifo, HC_SubA_HABLCsat,   hwalpha->regHABLCsat   );
54      UC_FIFO_ADD_3D ( fifo, HC_SubA_HABLCop,    hwalpha->regHABLCop    );
55      UC_FIFO_ADD_3D ( fifo, HC_SubA_HABLAsat,   hwalpha->regHABLAsat   );
56      UC_FIFO_ADD_3D ( fifo, HC_SubA_HABLAop,    hwalpha->regHABLAop    );
57      UC_FIFO_ADD_3D ( fifo, HC_SubA_HABLRCa,    hwalpha->regHABLRCa    );
58      UC_FIFO_ADD_3D ( fifo, HC_SubA_HABLRFCa,   hwalpha->regHABLRFCa   );
59      UC_FIFO_ADD_3D ( fifo, HC_SubA_HABLRCbias, hwalpha->regHABLRCbias );
60      UC_FIFO_ADD_3D ( fifo, HC_SubA_HABLRCb,    hwalpha->regHABLRCb    );
61      UC_FIFO_ADD_3D ( fifo, HC_SubA_HABLRFCb,   hwalpha->regHABLRFCb   );
62      UC_FIFO_ADD_3D ( fifo, HC_SubA_HABLRAa,    hwalpha->regHABLRAa    );
63      UC_FIFO_ADD_3D ( fifo, HC_SubA_HABLRAb,    hwalpha->regHABLRAb    );
64 
65      UC_FIFO_PAD_EVEN( fifo );
66 
67      UC_FIFO_CHECK( fifo );
68 
69      UC_VALIDATE( uc_blending_fn );
70 }
71 
72 /// Set texture environment (3D)
73 void
uc_set_texenv(UcDriverData * ucdrv,UcDeviceData * ucdev,CardState * state)74 uc_set_texenv( UcDriverData *ucdrv,
75                UcDeviceData *ucdev,
76                CardState    *state )
77 {
78      struct uc_fifo       *fifo  = ucdrv->fifo;
79      struct uc_hw_texture *hwtex = &ucdev->hwtex;
80 
81      if (UC_IS_VALID( uc_texenv ))
82           return;
83 
84      uc_map_blitflags( hwtex, state->blittingflags, state->source->config.format );
85 
86      // Texture mapping method
87      hwtex->regHTXnTB   = HC_HTXnFLSs_Linear | HC_HTXnFLTs_Linear |
88                           HC_HTXnFLSe_Linear | HC_HTXnFLTe_Linear;
89 
90      hwtex->regHTXnMPMD = HC_HTXnMPMD_Sclamp | HC_HTXnMPMD_Tclamp;
91 
92      UC_FIFO_PREPARE( fifo, 12 );
93      UC_FIFO_ADD_HDR( fifo, (HC_ParaType_Tex << 16) | (HC_SubType_Tex0 << 24) );
94 
95      UC_FIFO_ADD_3D ( fifo, HC_SubA_HTXnTB,       hwtex->regHTXnTB         );
96      UC_FIFO_ADD_3D ( fifo, HC_SubA_HTXnMPMD,     hwtex->regHTXnMPMD       );
97 
98      UC_FIFO_ADD_3D ( fifo, HC_SubA_HTXnTBLCsat,  hwtex->regHTXnTBLCsat_0  );
99      UC_FIFO_ADD_3D ( fifo, HC_SubA_HTXnTBLCop,   hwtex->regHTXnTBLCop_0   );
100      UC_FIFO_ADD_3D ( fifo, HC_SubA_HTXnTBLMPfog, hwtex->regHTXnTBLMPfog_0 );
101      UC_FIFO_ADD_3D ( fifo, HC_SubA_HTXnTBLAsat,  hwtex->regHTXnTBLAsat_0  );
102      UC_FIFO_ADD_3D ( fifo, HC_SubA_HTXnTBLRCb,   hwtex->regHTXnTBLRCb_0   );
103      UC_FIFO_ADD_3D ( fifo, HC_SubA_HTXnTBLRAa,   hwtex->regHTXnTBLRAa_0   );
104      UC_FIFO_ADD_3D ( fifo, HC_SubA_HTXnTBLRFog,  hwtex->regHTXnTBLRFog_0  );
105 
106      UC_FIFO_PAD_EVEN( fifo );
107 
108      UC_FIFO_CHECK( fifo );
109 
110      UC_VALIDATE( uc_texenv );
111 }
112 
113 /// Set clipping rectangle (2D and 3D)
114 void
uc_set_clip(UcDriverData * ucdrv,UcDeviceData * ucdev,CardState * state)115 uc_set_clip( UcDriverData *ucdrv,
116              UcDeviceData *ucdev,
117              CardState    *state )
118 {
119      struct uc_fifo *fifo = ucdrv->fifo;
120 
121      if (DFB_REGION_EQUAL( ucdev->clip, state->clip ))
122           return;
123 
124      UC_FIFO_PREPARE( fifo, 8 );
125      UC_FIFO_ADD_HDR( fifo, HC_ParaType_NotTex << 16 );
126 
127 #ifdef UC_ENABLE_3D
128 
129      UC_FIFO_ADD_3D ( fifo, HC_SubA_HClipTB,
130                       (RS12(state->clip.y1) << 12) | RS12(state->clip.y2+1) );
131      UC_FIFO_ADD_3D ( fifo, HC_SubA_HClipLR,
132                       (RS12(state->clip.x1) << 12) | RS12(state->clip.x2+1) );
133 
134 #endif
135 
136      UC_FIFO_ADD_2D ( fifo, VIA_REG_CLIPTL,
137                       (RS16(state->clip.y1) << 16) | RS16(state->clip.x1) );
138      UC_FIFO_ADD_2D ( fifo, VIA_REG_CLIPBR,
139                       (RS16(state->clip.y2) << 16) | RS16(state->clip.x2) );
140 
141      UC_FIFO_CHECK( fifo );
142 
143      ucdev->clip = state->clip;
144 }
145 
146 /// Set destination (2D and 3D)
147 void
uc_set_destination(UcDriverData * ucdrv,UcDeviceData * ucdev,CardState * state)148 uc_set_destination( UcDriverData *ucdrv,
149                     UcDeviceData *ucdev,
150                     CardState    *state )
151 {
152      struct uc_fifo        *fifo        = ucdrv->fifo;
153 
154      CoreSurface           *destination = state->destination;
155 
156      DFBSurfacePixelFormat  dst_format  = destination->config.format;
157      int                    dst_offset  = state->dst.offset;
158      int                    dst_pitch   = state->dst.pitch;
159      int                    dst_bpp     = DFB_BYTES_PER_PIXEL( dst_format );
160 
161 
162      /* Save FIFO space and CPU cycles. */
163      if (ucdev->dst_format == dst_format &&
164          ucdev->dst_offset == dst_offset &&
165          ucdev->dst_pitch  == dst_pitch)
166           return;
167 
168      // 2D engine setting
169 
170      ucdev->pitch = (ucdev->pitch & 0x7fff) | (((dst_pitch >> 3) & 0x7fff) << 16);
171 
172      UC_FIFO_PREPARE( fifo, 12 );
173      UC_FIFO_ADD_HDR( fifo, HC_ParaType_NotTex << 16 );
174 
175 
176      UC_FIFO_ADD_2D ( fifo, VIA_REG_PITCH,   (VIA_PITCH_ENABLE | ucdev->pitch) );
177      UC_FIFO_ADD_2D ( fifo, VIA_REG_DSTBASE, (dst_offset >> 3) );
178      UC_FIFO_ADD_2D ( fifo, VIA_REG_GEMODE,  (dst_bpp - 1) << 8 );
179 
180 #ifdef UC_ENABLE_3D
181      // 3D engine setting
182 
183      UC_FIFO_ADD_3D ( fifo, HC_SubA_HDBBasL, dst_offset & 0xffffff );
184      UC_FIFO_ADD_3D ( fifo, HC_SubA_HDBBasH, dst_offset >> 24 );
185      UC_FIFO_ADD_3D ( fifo, HC_SubA_HDBFM,   (uc_map_dst_format( dst_format ) |
186                                               (dst_pitch & HC_HDBPit_MASK)    |
187                                               HC_HDBLoc_Local) );
188 
189      UC_FIFO_PAD_EVEN(fifo);
190 #endif
191 
192      UC_FIFO_CHECK( fifo );
193 
194      ucdev->dst_format = dst_format;
195      ucdev->dst_offset = dst_offset;
196      ucdev->dst_pitch  = dst_pitch;
197 }
198 
199 /// Set new source (2D)
200 void
uc_set_source_2d(UcDriverData * ucdrv,UcDeviceData * ucdev,CardState * state)201 uc_set_source_2d( UcDriverData *ucdrv,
202                   UcDeviceData *ucdev,
203                   CardState    *state )
204 {
205      struct uc_fifo *fifo   = ucdrv->fifo;
206 
207      if (UC_IS_VALID( uc_source2d ))
208           return;
209 
210      ucdev->pitch &= 0x7fff0000;
211      ucdev->pitch |= (state->src.pitch >> 3) & 0x7fff;
212 
213      UC_FIFO_PREPARE( fifo, 6 );
214      UC_FIFO_ADD_HDR( fifo, HC_ParaType_NotTex << 16 );
215 
216      UC_FIFO_ADD_2D ( fifo, VIA_REG_SRCBASE, state->src.offset >> 3 );
217      UC_FIFO_ADD_2D ( fifo, VIA_REG_PITCH,   VIA_PITCH_ENABLE | ucdev->pitch );
218 
219      UC_FIFO_CHECK( fifo );
220 
221      UC_VALIDATE( uc_source2d );
222 }
223 
224 /// Set new source (3D)
225 void
uc_set_source_3d(UcDriverData * ucdrv,UcDeviceData * ucdev,CardState * state)226 uc_set_source_3d( UcDriverData *ucdrv,
227                   UcDeviceData *ucdev,
228                   CardState    *state )
229 {
230      struct uc_fifo       *fifo   = ucdrv->fifo;
231      struct uc_hw_texture *hwtex  = &ucdev->hwtex;
232 
233      CoreSurface          *source = state->source;
234 
235      int src_height, src_offset, src_pitch;
236 
237      if (UC_IS_VALID( uc_source3d ))
238           return;
239 
240      src_height = source->config.size.h;
241      src_offset = state->src.offset;
242      src_pitch  = state->src.pitch;
243 
244      /*
245       * TODO: Check if we can set the odd/even field as L1/L2 texture and select
246       * between L0/L1/L2 upon blit. Otherwise we depend on SMF_BLITTINGFLAGS ;(
247       */
248 
249      if (state->blittingflags & DSBLIT_DEINTERLACE) {
250           if (source->field)
251                src_offset += src_pitch;
252 
253           src_height >>= 1;
254           src_pitch  <<= 1;
255      }
256 
257      ucdev->field = source->field;
258 
259      // Round texture size up to nearest
260      // value evenly divisible by 2^n
261 
262      ILOG2(source->config.size.w, hwtex->we);
263      hwtex->l2w = 1 << hwtex->we;
264      if (hwtex->l2w < source->config.size.w) {
265           hwtex->we++;
266           hwtex->l2w <<= 1;
267      }
268 
269      ILOG2(src_height, hwtex->he);
270      hwtex->l2h = 1 << hwtex->he;
271      if (hwtex->l2h < src_height) {
272           hwtex->he++;
273           hwtex->l2h <<= 1;
274      }
275 
276      hwtex->format = uc_map_src_format_3d( source->config.format );
277 
278      UC_FIFO_PREPARE( fifo, 10);
279 
280      UC_FIFO_ADD_HDR( fifo, (HC_ParaType_Tex << 16) | (HC_SubType_Tex0 << 24));
281 
282      UC_FIFO_ADD_3D ( fifo, HC_SubA_HTXnFM,       HC_HTXnLoc_Local | hwtex->format );
283      UC_FIFO_ADD_3D ( fifo, HC_SubA_HTXnL0OS,     (0 << HC_HTXnLVmax_SHIFT) );
284      UC_FIFO_ADD_3D ( fifo, HC_SubA_HTXnL0_5WE,   hwtex->we );
285      UC_FIFO_ADD_3D ( fifo, HC_SubA_HTXnL0_5HE,   hwtex->he );
286 
287      UC_FIFO_ADD_3D ( fifo, HC_SubA_HTXnL012BasH, (src_offset >> 24) & 0xff );
288      UC_FIFO_ADD_3D ( fifo, HC_SubA_HTXnL0BasL,   (src_offset      ) & 0xffffff );
289      UC_FIFO_ADD_3D ( fifo, HC_SubA_HTXnL0Pit,    (HC_HTXnEnPit_MASK | src_pitch) );
290 
291      UC_FIFO_PAD_EVEN( fifo );
292 
293      UC_FIFO_CHECK( fifo );
294 
295      // Upload the palette of a 256 color texture.
296 
297      if (hwtex->format == HC_HTXnFM_Index8) {
298           int       i, num;
299           DFBColor *colors;
300 
301           UC_FIFO_PREPARE( fifo, 258 );
302 
303           UC_FIFO_ADD_HDR( fifo, ((HC_ParaType_Palette    << 16) |
304                                   (HC_SubType_TexPalette0 << 24)) );
305 
306           colors = source->palette->entries;
307           num    = source->palette->num_entries;
308 
309           if (num > 256)
310                num = 256;
311 
312           /* What about the last entry? -- dok */
313           for (i = 0; i < num; i++)
314                UC_FIFO_ADD( fifo, PIXEL_ARGB(colors[i].a, colors[i].r,
315                                              colors[i].g, colors[i].b) );
316 
317           for (; i < 256; i++)
318                UC_FIFO_ADD( fifo, 0 );
319 
320           UC_FIFO_CHECK( fifo );
321      }
322 
323      UC_VALIDATE( uc_source3d );
324 }
325 
326 /// Set either destination color key, or fill color, as needed. (2D)
327 void
uc_set_color_2d(UcDriverData * ucdrv,UcDeviceData * ucdev,CardState * state)328 uc_set_color_2d( UcDriverData *ucdrv,
329                  UcDeviceData *ucdev,
330                  CardState    *state )
331 {
332      struct uc_fifo *fifo  = ucdrv->fifo;
333      u32             color = 0;
334 
335      if (UC_IS_VALID( uc_color2d ))
336           return;
337 
338      switch (state->destination->config.format) {
339           case DSPF_ARGB1555:
340                color = PIXEL_ARGB1555( state->color.a,
341                                        state->color.r,
342                                        state->color.g,
343                                        state->color.b );
344                color |= color << 16;
345                break;
346 
347           case DSPF_RGB16:
348                color = PIXEL_RGB16( state->color.r,
349                                     state->color.g,
350                                     state->color.b);
351                color |= color << 16;
352                break;
353 
354           case DSPF_RGB32:
355           case DSPF_ARGB:
356                color = PIXEL_ARGB( state->color.a,
357                                    state->color.r,
358                                    state->color.g,
359                                    state->color.b );
360                break;
361 
362           default:
363                D_BUG( "unexpected pixel format" );
364      }
365 
366 
367      UC_FIFO_PREPARE( fifo, 8 );
368      UC_FIFO_ADD_HDR( fifo, HC_ParaType_NotTex << 16 );
369 
370      // Opaque line drawing needs this
371      UC_FIFO_ADD_2D( fifo, VIA_REG_MONOPAT0,   0xff );
372 
373      UC_FIFO_ADD_2D( fifo, VIA_REG_KEYCONTROL, 0 );
374      UC_FIFO_ADD_2D( fifo, VIA_REG_FGCOLOR,    color );
375 
376      UC_FIFO_CHECK( fifo );
377 
378      UC_VALIDATE( uc_color2d );
379      UC_INVALIDATE( uc_colorkey2d );
380 }
381 
382 void
uc_set_colorkey_2d(UcDriverData * ucdrv,UcDeviceData * ucdev,CardState * state)383 uc_set_colorkey_2d( UcDriverData *ucdrv,
384                     UcDeviceData *ucdev,
385                     CardState    *state )
386 {
387      struct uc_fifo *fifo = ucdrv->fifo;
388 
389      if (UC_IS_VALID( uc_colorkey2d ))
390           return;
391 
392      if (state->blittingflags & DSBLIT_SRC_COLORKEY) {
393           UC_FIFO_PREPARE( fifo, 6 );
394           UC_FIFO_ADD_HDR( fifo, HC_ParaType_NotTex << 16 );
395 
396           UC_FIFO_ADD_2D ( fifo, VIA_REG_KEYCONTROL, VIA_KEY_ENABLE_SRCKEY );
397           UC_FIFO_ADD_2D ( fifo, VIA_REG_BGCOLOR, state->src_colorkey );
398      }
399      else if (state->blittingflags & DSBLIT_DST_COLORKEY) {
400           UC_FIFO_PREPARE( fifo, 6 );
401           UC_FIFO_ADD_HDR( fifo, HC_ParaType_NotTex << 16 );
402 
403           UC_FIFO_ADD_2D ( fifo, VIA_REG_KEYCONTROL,
404                            VIA_KEY_ENABLE_DSTKEY | VIA_KEY_INVERT_KEY );
405           UC_FIFO_ADD_2D ( fifo, VIA_REG_FGCOLOR, state->dst_colorkey );
406      }
407      else {
408           UC_FIFO_PREPARE( fifo, 4 );
409           UC_FIFO_ADD_HDR( fifo, HC_ParaType_NotTex << 16 );
410 
411           UC_FIFO_ADD_2D ( fifo, VIA_REG_KEYCONTROL, 0 );
412      }
413 
414      UC_FIFO_CHECK( fifo );
415 
416      UC_VALIDATE( uc_colorkey2d );
417      UC_INVALIDATE( uc_color2d );
418 }
419 
420