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