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