1 /*
2 (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
3 (c) Copyright 2000-2004 Convergence (integrated media) GmbH
4
5 All rights reserved.
6
7 Written by Denis Oliver Kropp <dok@directfb.org>,
8 Andreas Hundt <andi@fischlustig.de>,
9 Sven Neumann <neo@directfb.org>,
10 Ville Syrjälä <syrjala@sci.fi> and
11 Claudio Ciccani <klan@users.sf.net>.
12
13 This library is free software; you can redistribute it and/or
14 modify it under the terms of the GNU Lesser General Public
15 License as published by the Free Software Foundation; either
16 version 2 of the License, or (at your option) any later version.
17
18 This library is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Lesser General Public License for more details.
22
23 You should have received a copy of the GNU Lesser General Public
24 License along with this library; if not, write to the
25 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26 Boston, MA 02111-1307, USA.
27 */
28
29 #include <config.h>
30
31 #include <directfb.h>
32
33 #include <core/coretypes.h>
34 #include <core/layers.h>
35 #include <core/surface.h>
36
37 #include "cyber5k.h"
38 #include "cyber5k_alpha.h"
39 #include "cyber5k_overlay.h"
40
41 typedef struct {
42 CoreLayerRegionConfig config;
43 } CyberUnderlayLayerData;
44
45 static void udl_set_all ( CyberDriverData *cdrv,
46 CyberUnderlayLayerData *cudl,
47 CoreLayerRegionConfig *config,
48 CoreSurface *surface,
49 CoreSurfaceBufferLock *lock );
50 static void udl_set_location( CyberDriverData *cdrv,
51 CyberUnderlayLayerData *cudl,
52 CoreLayerRegionConfig *config,
53 CoreSurface *surface );
54
55 #define CYBER_UNDERLAY_SUPPORTED_OPTIONS (DLOP_NONE)
56
57 /**********************/
58
59 static int
udlLayerDataSize(void)60 udlLayerDataSize( void )
61 {
62 return sizeof(CyberUnderlayLayerData);
63 }
64
65 static DFBResult
udlInitLayer(CoreLayer * layer,void * driver_data,void * layer_data,DFBDisplayLayerDescription * description,DFBDisplayLayerConfig * default_config,DFBColorAdjustment * default_adj)66 udlInitLayer( CoreLayer *layer,
67 void *driver_data,
68 void *layer_data,
69 DFBDisplayLayerDescription *description,
70 DFBDisplayLayerConfig *default_config,
71 DFBColorAdjustment *default_adj )
72 {
73 /* set capabilities and type */
74 description->caps = DLCAPS_SURFACE | DLCAPS_ALPHACHANNEL |
75 DLCAPS_OPACITY | DLCAPS_SRC_COLORKEY |
76 DLCAPS_SCREEN_LOCATION;
77 description->type = DLTF_GRAPHICS | DLTF_VIDEO | DLTF_STILL_PICTURE |
78 DLTF_BACKGROUND;
79
80 /* set name */
81 snprintf( description->name,
82 DFB_DISPLAY_LAYER_DESC_NAME_LENGTH, "CyberPro Underlay" );
83
84 /* fill out the default configuration */
85 default_config->flags = DLCONF_WIDTH | DLCONF_HEIGHT |
86 DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE |
87 DLCONF_OPTIONS;
88 default_config->width = 768;
89 default_config->height = 576;
90 default_config->pixelformat = DSPF_RGB16;
91 default_config->buffermode = DLBM_FRONTONLY;
92 default_config->options = DLOP_NONE;
93
94 /* initialize registers */
95 cyber_init_overlay();
96
97 /* workaround */
98 cyber_change_overlay_fifo();
99 cyber_cleanup_overlay();
100 cyber_init_overlay();
101
102 return DFB_OK;
103 }
104
105 static DFBResult
udlTestRegion(CoreLayer * layer,void * driver_data,void * layer_data,CoreLayerRegionConfig * config,CoreLayerRegionConfigFlags * failed)106 udlTestRegion( CoreLayer *layer,
107 void *driver_data,
108 void *layer_data,
109 CoreLayerRegionConfig *config,
110 CoreLayerRegionConfigFlags *failed )
111 {
112 CoreLayerRegionConfigFlags fail = 0;
113
114 /* check for unsupported options */
115 if (config->options & ~CYBER_UNDERLAY_SUPPORTED_OPTIONS)
116 fail |= CLRCF_OPTIONS;
117
118 /* check pixel format */
119 switch (config->format) {
120 case DSPF_RGB332:
121 case DSPF_ARGB1555:
122 case DSPF_RGB16:
123 case DSPF_RGB24:
124 case DSPF_RGB32:
125 case DSPF_ARGB:
126 case DSPF_YUY2:
127 break;
128
129 default:
130 fail |= CLRCF_FORMAT;
131 }
132
133 /* check width */
134 if (config->width > 1024 || config->width < 4)
135 fail |= CLRCF_WIDTH;
136
137 /* check height */
138 if (config->height > 1024 || config->height < 1)
139 fail |= CLRCF_HEIGHT;
140
141 /* write back failing fields */
142 if (failed)
143 *failed = fail;
144
145 /* return failure if any field failed */
146 if (fail)
147 return DFB_UNSUPPORTED;
148
149 return DFB_OK;
150 }
151
152 static DFBResult
udlSetRegion(CoreLayer * layer,void * driver_data,void * layer_data,void * region_data,CoreLayerRegionConfig * config,CoreLayerRegionConfigFlags updated,CoreSurface * surface,CorePalette * palette,CoreSurfaceBufferLock * lock)153 udlSetRegion( CoreLayer *layer,
154 void *driver_data,
155 void *layer_data,
156 void *region_data,
157 CoreLayerRegionConfig *config,
158 CoreLayerRegionConfigFlags updated,
159 CoreSurface *surface,
160 CorePalette *palette,
161 CoreSurfaceBufferLock *lock )
162 {
163 CyberDriverData *cdrv = (CyberDriverData*) driver_data;
164 CyberUnderlayLayerData *cudl = (CyberUnderlayLayerData*) layer_data;
165
166 /* remember configuration */
167 cudl->config = *config;
168
169 /* set up layer */
170 udl_set_all( cdrv, cudl, config, surface, lock );
171
172 return DFB_OK;
173 }
174
175 static DFBResult
udlRemoveRegion(CoreLayer * layer,void * driver_data,void * layer_data,void * region_data)176 udlRemoveRegion( CoreLayer *layer,
177 void *driver_data,
178 void *layer_data,
179 void *region_data )
180 {
181 /* disable and clean up */
182 cyber_enable_overlay(0);
183 cyber_cleanup_alpha();
184 cyber_cleanup_overlay();
185
186 return DFB_OK;
187 }
188
189 static DFBResult
udlFlipRegion(CoreLayer * layer,void * driver_data,void * layer_data,void * region_data,CoreSurface * surface,DFBSurfaceFlipFlags flags,CoreSurfaceBufferLock * lock)190 udlFlipRegion( CoreLayer *layer,
191 void *driver_data,
192 void *layer_data,
193 void *region_data,
194 CoreSurface *surface,
195 DFBSurfaceFlipFlags flags,
196 CoreSurfaceBufferLock *lock )
197 {
198 CyberDriverData *cdrv = (CyberDriverData*) driver_data;
199 CyberUnderlayLayerData *cudl = (CyberUnderlayLayerData*) layer_data;
200
201 dfb_surface_flip( surface, false );
202
203 udl_set_all( cdrv, cudl, &cudl->config, surface, lock );
204
205 return DFB_OK;
206 }
207
208
209 DisplayLayerFuncs cyberUnderlayFuncs = {
210 .LayerDataSize = udlLayerDataSize,
211 .InitLayer = udlInitLayer,
212
213 .TestRegion = udlTestRegion,
214 .SetRegion = udlSetRegion,
215 .RemoveRegion = udlRemoveRegion,
216 .FlipRegion = udlFlipRegion,
217 };
218
219
220 /* internal */
221
udl_set_all(CyberDriverData * cdrv,CyberUnderlayLayerData * cudl,CoreLayerRegionConfig * config,CoreSurface * surface,CoreSurfaceBufferLock * lock)222 static void udl_set_all( CyberDriverData *cdrv,
223 CyberUnderlayLayerData *cudl,
224 CoreLayerRegionConfig *config,
225 CoreSurface *surface,
226 CoreSurfaceBufferLock *lock )
227 {
228 /* set the pixel format */
229 switch (surface->config.format) {
230 case DSPF_RGB332:
231 cyber_set_overlay_format (OVERLAY_RGB8);
232 break;
233
234 case DSPF_ARGB1555:
235 cyber_set_overlay_format (OVERLAY_RGB555);
236 break;
237
238 case DSPF_RGB16:
239 cyber_set_overlay_format (OVERLAY_RGB565);
240 break;
241
242 case DSPF_RGB24:
243 cyber_set_overlay_format (OVERLAY_RGB888);
244 break;
245
246 case DSPF_ARGB:
247 case DSPF_RGB32:
248 cyber_set_overlay_format (OVERLAY_RGB8888);
249 break;
250
251 case DSPF_YUY2:
252 cyber_set_overlay_format (OVERLAY_YUV422);
253 break;
254
255 default:
256 D_BUG("unexpected pixelformat");
257 break;
258 }
259
260 cyber_set_overlay_mode( OVERLAY_WINDOWKEY );
261
262 /* set address */
263 cyber_set_overlay_srcaddr( lock->offset, 0, 0,
264 surface->config.size.w, lock->pitch );
265
266 /* set location and scaling */
267 udl_set_location( cdrv, cudl, config, surface );
268
269 /* tune fifo */
270 cyber_change_overlay_fifo();
271
272 /* set up alpha blending */
273 cyber_enable_alpha( 1 );
274 cyber_enable_fullscreen_alpha( 1 );
275 cyber_select_blend_src1( SRC1_GRAPHICS );
276 cyber_select_blend_src2( SRC2_OVERLAY1 );
277
278 /* FIXME: find out why the opacity can't be set outside of this function */
279 cyber_set_alpha_reg( 0xcc, 0xcc, 0xcc );
280
281 /* turn it on */
282 cyber_enable_overlay(1);
283 }
284
udl_set_location(CyberDriverData * cdrv,CyberUnderlayLayerData * cudl,CoreLayerRegionConfig * config,CoreSurface * surface)285 static void udl_set_location( CyberDriverData *cdrv,
286 CyberUnderlayLayerData *cudl,
287 CoreLayerRegionConfig *config,
288 CoreSurface *surface )
289 {
290 /* set location */
291 cyber_set_overlay_window( config->dest.x, config->dest.y,
292 config->dest.x + config->dest.w - 1,
293 config->dest.y + config->dest.h - 1 );
294
295 /* set scaling */
296 cyber_set_overlay_scale( surface->config.size.h == 576 ? /* HACK: support interlaced video */
297 OVERLAY_BOBMODE : OVERLAY_WEAVEMODE,
298 surface->config.size.w, config->dest.w,
299 surface->config.size.h, config->dest.h );
300 }
301
302