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 #include <config.h>
11 
12 #include <gfx/convert.h>
13 #include "unichrome.h"
14 #include "uc_state.h"
15 #include "uc_accel.h"
16 #include "uc_hw.h"
17 
18 enum uc_state_type {
19      UC_TYPE_UNSUPPORTED,
20      UC_TYPE_2D,
21      UC_TYPE_3D
22 };
23 
24 /// GPU selecting functions --------------------------------------------------
25 
26 static inline bool
uc_has_dst_format(DFBSurfacePixelFormat format)27 uc_has_dst_format( DFBSurfacePixelFormat format )
28 {
29      switch (format) {
30           case DSPF_ARGB1555:
31           case DSPF_RGB16:
32           case DSPF_RGB32:
33           case DSPF_ARGB:
34                return true;
35 
36           default:
37                break;
38      }
39 
40      return false;
41 }
42 
43 static inline bool
uc_has_src_format_3d(DFBSurfacePixelFormat format)44 uc_has_src_format_3d( DFBSurfacePixelFormat format )
45 {
46      switch (format) {
47           case DSPF_ARGB1555:
48           case DSPF_RGB16:
49           case DSPF_RGB32:
50           case DSPF_ARGB:
51           case DSPF_A8:
52           case DSPF_LUT8:
53                return true;
54 
55           default:
56                break;
57      }
58 
59      return false;
60 }
61 
62 static inline enum uc_state_type
uc_select_drawtype(CardState * state,DFBAccelerationMask accel)63 uc_select_drawtype( CardState* state,
64                     DFBAccelerationMask accel )
65 {
66      if (!(state->drawingflags & ~UC_DRAWING_FLAGS_2D) &&
67          !(accel & DFXL_FILLTRIANGLE))
68           return UC_TYPE_2D;
69 
70      if (!(state->drawingflags & ~UC_DRAWING_FLAGS_3D))
71           return UC_TYPE_3D;
72 
73      return UC_TYPE_UNSUPPORTED;
74 }
75 
76 static inline enum uc_state_type
uc_select_blittype(CardState * state,DFBAccelerationMask accel)77 uc_select_blittype( CardState* state,
78                     DFBAccelerationMask accel )
79 {
80      if (!(state->blittingflags & ~UC_BLITTING_FLAGS_2D)) {
81           if ((state->source->config.format == state->destination->config.format) &&
82               !((state->blittingflags & DSBLIT_SRC_COLORKEY) &&
83                 (state->blittingflags & DSBLIT_DST_COLORKEY)) &&
84               !(accel & (DFXL_STRETCHBLIT | DFXL_TEXTRIANGLES)))
85                return UC_TYPE_2D;
86      }
87 
88      if (!(state->blittingflags & ~UC_BLITTING_FLAGS_3D)) {
89           if (uc_has_src_format_3d( state->source->config.format ))
90                return UC_TYPE_3D;
91      }
92 
93      return UC_TYPE_UNSUPPORTED;
94 }
95 
96 // DirectFB interfacing functions --------------------------------------------
97 
uc_check_state(void * drv,void * dev,CardState * state,DFBAccelerationMask accel)98 void uc_check_state(void *drv, void *dev,
99                     CardState *state, DFBAccelerationMask accel)
100 {
101      /* Check destination format. */
102      if (!uc_has_dst_format( state->destination->config.format ))
103           return;
104 
105      if (DFB_DRAWING_FUNCTION(accel)) {
106           /* Check drawing parameters. */
107           switch (uc_select_drawtype(state, accel)) {
108                case UC_TYPE_2D:
109                     state->accel |= UC_DRAWING_FUNCTIONS_2D;
110                     break;
111                case UC_TYPE_3D:
112                     state->accel |= UC_DRAWING_FUNCTIONS_3D;
113                     break;
114                default:
115                     return;
116           }
117      }
118      else {
119           /* Check blitting parameters. */
120           switch (uc_select_blittype(state, accel)) {
121                case UC_TYPE_2D:
122                     state->accel |= UC_BLITTING_FUNCTIONS_2D;
123                     break;
124                case UC_TYPE_3D:
125                     state->accel |= UC_BLITTING_FUNCTIONS_3D;
126                     break;
127                default:
128                     return;
129           }
130      }
131 }
132 
uc_set_state(void * drv,void * dev,GraphicsDeviceFuncs * funcs,CardState * state,DFBAccelerationMask accel)133 void uc_set_state(void *drv, void *dev, GraphicsDeviceFuncs *funcs,
134                   CardState *state, DFBAccelerationMask accel)
135 {
136      UcDriverData   *ucdrv = (UcDriverData*) drv;
137      UcDeviceData   *ucdev = (UcDeviceData*) dev;
138      struct uc_fifo *fifo  = ucdrv->fifo;
139 
140      u32 rop3d     = HC_HROP_P;
141      u32 regEnable = HC_HenCW_MASK | HC_HenAW_MASK;
142 
143      StateModificationFlags modified = state->mod_hw;
144 
145      // Check modified states and update hw
146 
147      if (modified & SMF_SOURCE)
148           UC_INVALIDATE( uc_source2d );
149 
150      if (modified & (SMF_BLITTING_FLAGS | SMF_SOURCE))
151           UC_INVALIDATE( uc_source3d | uc_texenv );
152 
153      if (modified & (SMF_BLITTING_FLAGS | SMF_SRC_COLORKEY | SMF_DST_COLORKEY))
154           UC_INVALIDATE( uc_colorkey2d );
155 
156      if (modified & (SMF_COLOR | SMF_DESTINATION | SMF_DRAWING_FLAGS))
157           UC_INVALIDATE( uc_color2d );
158 
159      if (modified & (SMF_SRC_BLEND | SMF_DST_BLEND))
160           UC_INVALIDATE( uc_blending_fn );
161 
162 
163      if (modified & SMF_COLOR)
164           ucdev->color3d = PIXEL_ARGB( state->color.a, state->color.r,
165                                        state->color.g, state->color.b );
166 
167      if (modified & SMF_DRAWING_FLAGS) {
168           if (state->drawingflags & DSDRAW_XOR) {
169                ucdev->draw_rop3d = HC_HROP_DPx;
170                ucdev->draw_rop2d = VIA_ROP_DPx;
171           }
172           else {
173                ucdev->draw_rop3d = HC_HROP_P;
174                ucdev->draw_rop2d = VIA_ROP_P;
175           }
176      }
177 
178      ucdev->bflags = state->blittingflags;
179 
180      if (modified & SMF_DESTINATION)
181           uc_set_destination(ucdrv, ucdev, state);
182 
183      if (modified & SMF_CLIP)
184           uc_set_clip(ucdrv, ucdev, state);
185 
186 
187      // Select GPU and check remaining states
188 
189      if (DFB_DRAWING_FUNCTION(accel)) {
190 
191           switch (uc_select_drawtype(state, accel)) {
192                case UC_TYPE_2D:
193                     funcs->FillRectangle = uc_fill_rectangle;
194                     funcs->DrawRectangle = uc_draw_rectangle;
195                     funcs->DrawLine = uc_draw_line;
196 
197                     uc_set_color_2d(ucdrv, ucdev, state);
198 
199                     state->set = UC_DRAWING_FUNCTIONS_2D;
200                     break;
201 
202                case UC_TYPE_3D:
203                     funcs->FillRectangle = uc_fill_rectangle_3d;
204                     funcs->DrawRectangle = uc_draw_rectangle_3d;
205                     funcs->DrawLine = uc_draw_line_3d;
206 
207                     if (state->drawingflags & DSDRAW_BLEND) {
208                          uc_set_blending_fn(ucdrv, ucdev, state);
209                          regEnable |= HC_HenABL_MASK;
210                     }
211 
212                     rop3d = ucdev->draw_rop3d;
213 
214                     state->set = UC_DRAWING_FUNCTIONS_3D;
215                     break;
216 
217                case UC_TYPE_UNSUPPORTED:
218                     D_BUG("Unsupported drawing function!");
219                     break;
220           }
221      }
222      else { // DFB_BLITTING_FUNCTION(accel)
223           switch (uc_select_blittype(state, accel)) {
224                case UC_TYPE_2D:
225                     uc_set_source_2d(ucdrv, ucdev, state);
226                     funcs->Blit = uc_blit;
227 
228                     uc_set_colorkey_2d(ucdrv, ucdev, state);
229                     state->set = UC_BLITTING_FUNCTIONS_2D;
230                     break;
231 
232                case UC_TYPE_3D:
233                     funcs->Blit = uc_blit_3d;
234                     uc_set_source_3d(ucdrv, ucdev, state);
235                     uc_set_texenv(ucdrv, ucdev, state);
236                     uc_set_blending_fn(ucdrv, ucdev, state);
237 
238                     regEnable |= HC_HenTXMP_MASK | HC_HenTXCH_MASK | HC_HenTXPP_MASK | HC_HenDT_MASK;
239 
240                     if (state->blittingflags & (DSBLIT_BLEND_ALPHACHANNEL |
241                                                 DSBLIT_BLEND_COLORALPHA))
242                          regEnable |= HC_HenABL_MASK;
243 
244                     state->set = UC_BLITTING_FUNCTIONS_3D;
245                     break;
246 
247                case UC_TYPE_UNSUPPORTED:
248                     D_BUG("Unsupported drawing function!");
249                     break;
250           }
251      }
252 
253 #ifdef UC_ENABLE_3D
254      UC_FIFO_PREPARE( fifo, 6 );
255      UC_FIFO_ADD_HDR( fifo, HC_ParaType_NotTex << 16 );
256 
257      /* Don't know what this does. DRI code always clears it. */
258      UC_FIFO_ADD_3D ( fifo, HC_SubA_HPixGC,   0 );
259 
260      UC_FIFO_ADD_3D ( fifo, HC_SubA_HEnable,  regEnable );
261      UC_FIFO_ADD_3D ( fifo, HC_SubA_HFBBMSKL, 0xffffff );
262      UC_FIFO_ADD_3D ( fifo, HC_SubA_HROP,     rop3d | 0xff );
263 #endif
264 
265      UC_FIFO_CHECK(fifo);
266 
267      state->mod_hw = 0;
268 }
269 
270