1 /*
2    (c) Copyright 2001-2010  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 #ifndef __CORE__SURFACE_H__
30 #define __CORE__SURFACE_H__
31 
32 #include <directfb.h>
33 
34 #include <direct/list.h>
35 #include <direct/serial.h>
36 #include <direct/util.h>
37 
38 #include <fusion/object.h>
39 #include <fusion/reactor.h>
40 
41 #include <core/coredefs.h>
42 #include <core/coretypes.h>
43 
44 
45 typedef enum {
46      CSNF_NONE           = 0x00000000,
47 
48      CSNF_SIZEFORMAT     = 0x00000001,  /* width, height, format */
49      CSNF_SYSTEM         = 0x00000002,  /* system instance information */
50      CSNF_VIDEO          = 0x00000004,  /* video instance information */
51      CSNF_DESTROY        = 0x00000008,  /* surface is about to be destroyed */
52      CSNF_FLIP           = 0x00000010,  /* surface buffer pointer swapped */
53      CSNF_FIELD          = 0x00000020,  /* active (displayed) field switched */
54      CSNF_PALETTE_CHANGE = 0x00000040,  /* another palette has been set */
55      CSNF_PALETTE_UPDATE = 0x00000080,  /* current palette has been altered */
56      CSNF_ALPHA_RAMP     = 0x00000100,  /* alpha ramp was modified */
57      CSNF_DISPLAY        = 0x00000200,  /* surface buffer displayed */
58 
59      CSNF_ALL            = 0x000003FF
60 } CoreSurfaceNotificationFlags;
61 
62 typedef struct {
63      CoreSurfaceNotificationFlags  flags;
64      CoreSurface                  *surface;
65 
66      int                           index;
67 } CoreSurfaceNotification;
68 
69 
70 typedef enum {
71      CSCONF_NONE         = 0x00000000,
72 
73      CSCONF_SIZE         = 0x00000001,
74      CSCONF_FORMAT       = 0x00000002,
75      CSCONF_CAPS         = 0x00000004,
76 
77      CSCONF_PREALLOCATED = 0x00000010,
78 
79      CSCONF_ALL          = 0x00000017
80 } CoreSurfaceConfigFlags;
81 
82 typedef enum {
83      CSTF_NONE           = 0x00000000,
84 
85      CSTF_LAYER          = 0x00000001,  /* surface for layer */
86      CSTF_WINDOW         = 0x00000002,  /* surface for window */
87      CSTF_CURSOR         = 0x00000004,  /* surface for cursor */
88      CSTF_FONT           = 0x00000008,  /* surface for font */
89 
90      CSTF_SHARED         = 0x00000010,  /* accessable by other processes */
91 
92      CSTF_INTERNAL       = 0x00000100,  /* system memory */
93      CSTF_EXTERNAL       = 0x00000200,  /* video memory */
94 
95      CSTF_PREALLOCATED   = 0x00000400,  /* preallocated memory */
96 
97      CSTF_ALL            = 0x0000071F
98 } CoreSurfaceTypeFlags;
99 
100 typedef struct {
101      CoreSurfaceConfigFlags   flags;
102 
103      DFBDimension             size;
104      DFBSurfacePixelFormat    format;
105      DFBSurfaceCapabilities   caps;
106 
107      struct {
108           void                    *addr;               /* " */
109           unsigned long            phys;               /* " */
110           unsigned long            offset;             /* " */
111           unsigned int             pitch;              /* " */
112 
113           void                    *handle;             /* " */
114      }                        preallocated[MAX_SURFACE_BUFFERS];
115 
116      CoreSurfacePoolID        preallocated_pool_id;
117 
118      DFBDimension             min_size;
119 } CoreSurfaceConfig;
120 
121 typedef enum {
122      CSP_SYSTEMONLY      = 0x00000000,  /* never try to swap
123                                            into video memory */
124      CSP_VIDEOLOW        = 0x00000001,  /* try to store in video memory,
125                                            low priority */
126      CSP_VIDEOHIGH       = 0x00000002,  /* try to store in video memory,
127                                            high priority */
128      CSP_VIDEOONLY       = 0x00000003   /* always and only
129                                            store in video memory */
130 } CoreSurfacePolicy;
131 
132 typedef enum {
133      CSAF_NONE           = 0x00000000,
134 
135      CSAF_READ           = 0x00000001,  /* accessor may read */
136      CSAF_WRITE          = 0x00000002,  /* accessor may write */
137 
138      CSAF_SHARED         = 0x00000010,  /* other processes can read/write at the same time (shared mapping) */
139 
140      CSAF_ALL            = 0x00000013
141 } CoreSurfaceAccessFlags;
142 
143 typedef enum {
144      CSAID_NONE          = 0x00000000,  /* none or unknown accessor */
145 
146      CSAID_CPU           = 0x00000001,  /* local processor, where DirectFB is running on, could be app or sw fallback */
147 
148      CSAID_GPU           = 0x00000002,  /* primary accelerator, as in traditional 'gfxcard' core (ACCEL0) */
149 
150      CSAID_ACCEL0        = 0x00000002,  /* accelerators, decoders etc. (CSAID_ACCEL0 + accel_id<0-5>) */
151      CSAID_ACCEL1        = 0x00000003,
152      CSAID_ACCEL2        = 0x00000004,
153      CSAID_ACCEL3        = 0x00000005,
154      CSAID_ACCEL4        = 0x00000006,
155      CSAID_ACCEL5        = 0x00000007,
156 
157      CSAID_LAYER0        = 0x00000008,  /* display layers, registered by layer core (CSAID_LAYER0 + layer_id<0-MAX_LAYERS>) */
158      CSAID_LAYER1        = 0x00000009,
159      CSAID_LAYER2        = 0x0000000a,
160      CSAID_LAYER3        = 0x0000000b,
161      CSAID_LAYER4        = 0x0000000c,
162      CSAID_LAYER5        = 0x0000000d,
163      CSAID_LAYER6        = 0x0000000e,
164      CSAID_LAYER7        = 0x0000000f,
165      CSAID_LAYER8        = 0x00000010,
166      CSAID_LAYER9        = 0x00000011,
167      CSAID_LAYER10       = 0x00000012,
168      CSAID_LAYER11       = 0x00000013,
169      CSAID_LAYER12       = 0x00000014,
170      CSAID_LAYER13       = 0x00000015,
171      CSAID_LAYER14       = 0x00000016,
172      CSAID_LAYER15       = 0x00000017,
173 
174      _CSAID_NUM          = 0x00000018,  /* number of statically assigned IDs for usage in static arrays */
175 
176      CSAID_ANY           = 0x00000100,  /* any other accessor needs to be registered using IDs starting from here */
177 } CoreSurfaceAccessorID;
178 
179 typedef enum {
180      CSBR_FRONT          = 0,
181      CSBR_BACK           = 1,
182      CSBR_IDLE           = 2
183 } CoreSurfaceBufferRole;
184 
185 typedef enum {
186      CSSF_NONE           = 0x00000000,
187 
188      CSSF_DESTROYED      = 0x00000001,  /* surface is being or has been destroyed */
189 
190      CSSF_ALL            = 0x00000001
191 } CoreSurfaceStateFlags;
192 
193 struct __DFB_CoreSurface
194 {
195      FusionObject             object;
196      int                      magic;
197 
198      FusionSkirmish           lock;
199 
200      CoreSurfaceStateFlags    state;
201 
202      CoreSurfaceConfig        config;
203      CoreSurfaceTypeFlags     type;
204      unsigned long            resource_id;   /* layer id, window id, or user specified */
205 
206      int                      rotation;
207 
208      CoreSurfaceNotificationFlags notifications;
209 
210      DirectSerial             serial;
211 
212      int                      field;
213      u8                       alpha_ramp[4];
214 
215      CoreSurfaceBuffer       *buffers[MAX_SURFACE_BUFFERS];
216      int                      num_buffers;
217 
218      int                      buffer_indices[MAX_SURFACE_BUFFERS];
219 
220      unsigned int             flips;
221 
222      CorePalette             *palette;
223      GlobalReaction           palette_reaction;
224 
225      FusionSHMPoolShared     *shmpool;
226 
227      void                    *data;         /* Shared system driver-specific data for this surface. */
228 
229      FusionCall               call;
230 };
231 
232 #define CORE_SURFACE_ASSERT(surface)                                                           \
233      do {                                                                                      \
234           D_MAGIC_ASSERT( surface, CoreSurface );                                              \
235      } while (0)
236 
237 
238 /*
239  * Creates a pool of surface objects.
240  */
241 FusionObjectPool *dfb_surface_pool_create( const FusionWorld *world );
242 
243 /*
244  * Generates dfb_surface_ref(), dfb_surface_attach() etc.
245  */
246 FUSION_OBJECT_METHODS( CoreSurface, dfb_surface )
247 
248 
249 DFBResult dfb_surface_create        ( CoreDFB                      *core,
250                                       const CoreSurfaceConfig      *config,
251                                       CoreSurfaceTypeFlags          type,
252                                       unsigned long                 resource_id,
253                                       CorePalette                  *palette,
254                                       CoreSurface                 **ret_surface );
255 
256 DFBResult dfb_surface_create_simple ( CoreDFB                      *core,
257                                       int                           width,
258                                       int                           height,
259                                       DFBSurfacePixelFormat         format,
260                                       DFBSurfaceCapabilities        caps,
261                                       CoreSurfaceTypeFlags          type,
262                                       unsigned long                 resource_id,
263                                       CorePalette                  *palette,
264                                       CoreSurface                 **ret_surface );
265 
266 DFBResult dfb_surface_init_palette  ( CoreDFB                      *core,
267                                       CoreSurface                  *surface );
268 
269 DFBResult dfb_surface_notify        ( CoreSurface                  *surface,
270                                       CoreSurfaceNotificationFlags  flags);
271 
272 DFBResult dfb_surface_notify_display( CoreSurface                  *surface,
273                                       CoreSurfaceBuffer            *buffer);
274 
275 DFBResult dfb_surface_flip          ( CoreSurface                  *surface,
276                                       bool                          swap );
277 
278 DFBResult dfb_surface_reconfig      ( CoreSurface                  *surface,
279                                       const CoreSurfaceConfig      *config );
280 
281 DFBResult dfb_surface_destroy_buffers( CoreSurface                 *surface );
282 
283 DFBResult dfb_surface_deallocate_buffers( CoreSurface              *surface );
284 
285 DFBResult dfb_surface_lock_buffer   ( CoreSurface                  *surface,
286                                       CoreSurfaceBufferRole         role,
287                                       CoreSurfaceAccessorID         accessor,
288                                       CoreSurfaceAccessFlags        access,
289                                       CoreSurfaceBufferLock        *ret_lock );
290 
291 DFBResult dfb_surface_unlock_buffer ( CoreSurface                  *surface,
292                                       CoreSurfaceBufferLock        *lock );
293 
294 DFBResult dfb_surface_read_buffer   ( CoreSurface                  *surface,
295                                       CoreSurfaceBufferRole         role,
296                                       void                         *destination,
297                                       int                           pitch,
298                                       const DFBRectangle           *rect );
299 
300 DFBResult dfb_surface_write_buffer  ( CoreSurface                  *surface,
301                                       CoreSurfaceBufferRole         role,
302                                       const void                   *source,
303                                       int                           pitch,
304                                       const DFBRectangle           *rect );
305 
306 DFBResult dfb_surface_dump_buffer   ( CoreSurface                  *surface,
307                                       CoreSurfaceBufferRole         role,
308                                       const char                   *path,
309                                       const char                   *prefix );
310 
311 DFBResult dfb_surface_set_palette   ( CoreSurface                  *surface,
312                                       CorePalette                  *palette );
313 
314 DFBResult dfb_surface_set_field     ( CoreSurface                  *surface,
315                                       int                           field );
316 
317 DFBResult dfb_surface_set_alpha_ramp( CoreSurface                  *surface,
318                                       u8                            a0,
319                                       u8                            a1,
320                                       u8                            a2,
321                                       u8                            a3 );
322 
323 DFBResult dfb_surface_clear_buffers  ( CoreSurface                  *surface );
324 
325 
326 static inline DirectResult
dfb_surface_lock(CoreSurface * surface)327 dfb_surface_lock( CoreSurface *surface )
328 {
329      D_MAGIC_ASSERT( surface, CoreSurface );
330 
331      return fusion_skirmish_prevail( &surface->lock );
332 }
333 
334 static inline DirectResult
dfb_surface_trylock(CoreSurface * surface)335 dfb_surface_trylock( CoreSurface *surface )
336 {
337      D_MAGIC_ASSERT( surface, CoreSurface );
338 
339      return fusion_skirmish_swoop( &surface->lock );
340 }
341 
342 static inline DirectResult
dfb_surface_unlock(CoreSurface * surface)343 dfb_surface_unlock( CoreSurface *surface )
344 {
345      D_MAGIC_ASSERT( surface, CoreSurface );
346 
347      return fusion_skirmish_dismiss( &surface->lock );
348 }
349 
350 static inline CoreSurfaceBuffer *
dfb_surface_get_buffer(CoreSurface * surface,CoreSurfaceBufferRole role)351 dfb_surface_get_buffer( CoreSurface           *surface,
352                         CoreSurfaceBufferRole  role )
353 {
354      D_MAGIC_ASSERT( surface, CoreSurface );
355      D_ASSERT( role == CSBR_FRONT || role == CSBR_BACK || role == CSBR_IDLE );
356 
357      D_ASSERT( surface->num_buffers > 0 );
358 
359      return surface->buffers[ surface->buffer_indices[(surface->flips + role) % surface->num_buffers] ];
360 }
361 
362 static inline void *
dfb_surface_data_offset(const CoreSurface * surface,void * data,int pitch,int x,int y)363 dfb_surface_data_offset( const CoreSurface *surface,
364                          void              *data,
365                          int                pitch,
366                          int                x,
367                          int                y )
368 {
369      D_ASSERT( surface != NULL );
370      D_ASSERT( data != NULL );
371      D_ASSERT( pitch > 0 );
372      D_ASSERT( x >= 0 );
373      D_ASSERT( x < surface->config.size.w );
374      D_ASSERT( y >= 0 );
375      D_ASSERT( y < surface->config.size.h );
376 
377      if (surface->config.caps & DSCAPS_SEPARATED) {
378           if (y & 1)
379                y += surface->config.size.h;
380 
381           y >>= 1;
382      }
383 
384      return (u8*)data + pitch * y + DFB_BYTES_PER_LINE( surface->config.format, x );
385 }
386 
387 static inline void
dfb_surface_calc_buffer_size(CoreSurface * surface,int byte_align,int pixel_align,int * ret_pitch,int * ret_size)388 dfb_surface_calc_buffer_size( CoreSurface *surface,
389                               int          byte_align,
390                               int          pixel_align,
391                               int         *ret_pitch,
392                               int         *ret_size )
393 {
394      DFBSurfacePixelFormat format;
395      int                   width;
396      int                   pitch;
397 
398      D_MAGIC_ASSERT( surface, CoreSurface );
399 
400      format = surface->config.format;
401 
402      width = direct_util_align( surface->config.size.w, pixel_align );
403      pitch = direct_util_align( DFB_BYTES_PER_LINE( format, width ), byte_align );
404 
405      if (ret_pitch)
406           *ret_pitch = pitch;
407 
408      if (ret_size)
409           *ret_size = pitch * DFB_PLANE_MULTIPLY( format, surface->config.size.h );
410 }
411 
412 static inline void
dfb_surface_caps_apply_policy(CoreSurfacePolicy policy,DFBSurfaceCapabilities * caps)413 dfb_surface_caps_apply_policy( CoreSurfacePolicy       policy,
414                                DFBSurfaceCapabilities *caps )
415 {
416      switch (policy) {
417           case CSP_SYSTEMONLY:
418                *caps = (DFBSurfaceCapabilities)((*caps & ~DSCAPS_VIDEOONLY) | DSCAPS_SYSTEMONLY);
419                break;
420 
421           case CSP_VIDEOONLY:
422                *caps = (DFBSurfaceCapabilities)((*caps & ~DSCAPS_SYSTEMONLY) | DSCAPS_VIDEOONLY);
423                break;
424 
425           default:
426                *caps = (DFBSurfaceCapabilities)(*caps & ~(DSCAPS_SYSTEMONLY | DSCAPS_VIDEOONLY));
427                break;
428      }
429 }
430 
431 static inline DFBResult
dfb_surface_resize(CoreSurface * surface,int width,int height)432 dfb_surface_resize( CoreSurface *surface,
433                     int          width,
434                     int          height )
435 {
436      CoreSurfaceConfig config;
437 
438      D_MAGIC_ASSERT( surface, CoreSurface );
439      D_ASSERT( width > 0 );
440      D_ASSERT( height > 0 );
441 
442      config.flags  = CSCONF_SIZE;
443      config.size.w = width;
444      config.size.h = height;
445 
446      return dfb_surface_reconfig( surface, &config );
447 }
448 
449 static inline DFBResult
dfb_surface_reformat(CoreSurface * surface,int width,int height,DFBSurfacePixelFormat format)450 dfb_surface_reformat( CoreSurface           *surface,
451                       int                    width,
452                       int                    height,
453                       DFBSurfacePixelFormat  format )
454 {
455      CoreSurfaceConfig config;
456 
457      D_MAGIC_ASSERT( surface, CoreSurface );
458      D_ASSERT( width > 0 );
459      D_ASSERT( height > 0 );
460 
461      config.flags  = (CoreSurfaceConfigFlags)(CSCONF_SIZE | CSCONF_FORMAT);
462      config.size.w = width;
463      config.size.h = height;
464      config.format = format;
465 
466      return dfb_surface_reconfig( surface, &config );
467 }
468 
469 /* global reactions */
470 ReactionResult _dfb_surface_palette_listener( const void *msg_data,
471                                               void       *ctx );
472 
473 typedef enum {
474      DFB_LAYER_REGION_SURFACE_LISTENER,
475      DFB_WINDOWSTACK_BACKGROUND_IMAGE_LISTENER
476 } DFB_SURFACE_GLOBALS;
477 
478 #endif
479 
480