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 <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <errno.h>
35
36 #include <directfb.h>
37
38 #include <direct/debug.h>
39 #include <direct/mem.h>
40 #include <direct/memcpy.h>
41 #include <direct/messages.h>
42
43 #include <fusion/shmalloc.h>
44 #include <fusion/arena.h>
45 #include <fusion/property.h>
46
47 #include <core/CoreLayer.h>
48
49 #include <core/core.h>
50 #include <core/coredefs.h>
51 #include <core/coretypes.h>
52
53 #include <core/core_parts.h>
54
55 #include <core/input.h>
56 #include <core/gfxcard.h>
57 #include <core/layer_context.h>
58 #include <core/layer_control.h>
59 #include <core/layer_region.h>
60 #include <core/layers.h>
61 #include <core/state.h>
62 #include <core/palette.h>
63 #include <core/system.h>
64 #include <core/windows.h>
65
66 #include <gfx/convert.h>
67 #include <gfx/util.h>
68
69 #include <misc/conf.h>
70 #include <misc/util.h>
71
72 #include <core/layers_internal.h>
73 #include <core/screens_internal.h>
74
75
76 D_DEBUG_DOMAIN( Core_Layer, "Core/Layer", "DirectFB Display Layer Core" );
77
78 /**********************************************************************************************************************/
79
80 typedef struct {
81 int magic;
82
83 int num;
84 CoreLayerShared *layers[MAX_LAYERS];
85 } DFBLayerCoreShared;
86
87 struct __DFB_DFBLayerCore {
88 int magic;
89
90 CoreDFB *core;
91
92 DFBLayerCoreShared *shared;
93 };
94
95
96 DFB_CORE_PART( layer_core, LayerCore );
97
98 /**********************************************************************************************************************/
99
100 static int dfb_num_layers;
101 static CoreLayer *dfb_layers[MAX_LAYERS];
102
103 /** FIXME: Add proper error paths! **/
104
105 static DFBResult
dfb_layer_core_initialize(CoreDFB * core,DFBLayerCore * data,DFBLayerCoreShared * shared)106 dfb_layer_core_initialize( CoreDFB *core,
107 DFBLayerCore *data,
108 DFBLayerCoreShared *shared )
109 {
110 int i;
111 DFBResult ret;
112 FusionSHMPoolShared *pool;
113
114 D_DEBUG_AT( Core_Layer, "dfb_layer_core_initialize( %p, %p, %p )\n", core, data, shared );
115
116 D_ASSERT( data != NULL );
117 D_ASSERT( shared != NULL );
118
119 data->core = core;
120 data->shared = shared;
121
122
123 pool = dfb_core_shmpool( core );
124
125 /* Initialize all registered layers. */
126 for (i=0; i<dfb_num_layers; i++) {
127 char buf[24];
128 CoreLayerShared *lshared;
129 CoreLayer *layer = dfb_layers[i];
130 const DisplayLayerFuncs *funcs = layer->funcs;
131
132 /* Allocate shared data. */
133 lshared = SHCALLOC( pool, 1, sizeof(CoreLayerShared) );
134
135 /* Assign ID (zero based index). */
136 lshared->layer_id = i;
137 lshared->shmpool = pool;
138
139 snprintf( buf, sizeof(buf), "Display Layer %d", i );
140
141 /* Initialize the lock. */
142 ret = fusion_skirmish_init( &lshared->lock, buf, dfb_core_world(core) );
143 if (ret)
144 return ret;
145
146 /* Allocate driver's layer data. */
147 if (funcs->LayerDataSize) {
148 int size = funcs->LayerDataSize();
149
150 if (size > 0) {
151 lshared->layer_data = SHCALLOC( pool, 1, size );
152 if (!lshared->layer_data)
153 return D_OOSHM();
154 }
155 }
156
157 /* Initialize the layer, get the layer description,
158 the default configuration and default color adjustment. */
159 ret = funcs->InitLayer( layer,
160 layer->driver_data,
161 lshared->layer_data,
162 &lshared->description,
163 &lshared->default_config,
164 &lshared->default_adjustment );
165 if (ret) {
166 D_DERROR( ret, "DirectFB/Core/layers: "
167 "Failed to initialize layer %d!\n", lshared->layer_id );
168 return ret;
169 }
170
171 if (lshared->description.caps & DLCAPS_SOURCES) {
172 int n;
173
174 lshared->sources = SHCALLOC( pool, lshared->description.sources, sizeof(CoreLayerSource) );
175 if (!lshared->sources)
176 return D_OOSHM();
177
178 for (n=0; n<lshared->description.sources; n++) {
179 CoreLayerSource *source = &lshared->sources[n];
180
181 source->index = n;
182
183 ret = funcs->InitSource( layer, layer->driver_data,
184 lshared->layer_data, n, &source->description );
185 if (ret) {
186 D_DERROR( ret, "DirectFB/Core/layers: Failed to initialize source %d "
187 "of layer %d!\n", n, lshared->layer_id );
188 return ret;
189 }
190 }
191 }
192
193 if (D_FLAGS_IS_SET( lshared->description.caps, DLCAPS_SCREEN_LOCATION ))
194 D_FLAGS_SET( lshared->description.caps, DLCAPS_SCREEN_POSITION | DLCAPS_SCREEN_SIZE );
195
196 if (D_FLAGS_ARE_SET( lshared->description.caps,
197 DLCAPS_SCREEN_POSITION | DLCAPS_SCREEN_SIZE ))
198 D_FLAGS_SET( lshared->description.caps, DLCAPS_SCREEN_LOCATION );
199
200 /* Initialize the vector for the contexts. */
201 fusion_vector_init( &lshared->contexts.stack, 4, pool );
202
203 /* Initialize the vector for realized (added) regions. */
204 fusion_vector_init( &lshared->added_regions, 4, pool );
205
206 /* No active context by default. */
207 lshared->contexts.active = -1;
208
209 /* Store layer data. */
210 layer->layer_data = lshared->layer_data;
211
212 /* Store pointer to shared data and core. */
213 layer->shared = lshared;
214 layer->core = core;
215
216 CoreLayer_Init_Dispatch( core, layer, &lshared->call );
217
218 fusion_call_add_permissions( &lshared->call, 0, FUSION_CALL_PERMIT_EXECUTE );
219
220 /* Add the layer to the shared list. */
221 shared->layers[ shared->num++ ] = lshared;
222 }
223
224
225 D_MAGIC_SET( data, DFBLayerCore );
226 D_MAGIC_SET( shared, DFBLayerCoreShared );
227
228 return DFB_OK;
229 }
230
231 static DFBResult
dfb_layer_core_join(CoreDFB * core,DFBLayerCore * data,DFBLayerCoreShared * shared)232 dfb_layer_core_join( CoreDFB *core,
233 DFBLayerCore *data,
234 DFBLayerCoreShared *shared )
235 {
236 int i;
237
238 D_DEBUG_AT( Core_Layer, "dfb_layer_core_join( %p, %p, %p )\n", core, data, shared );
239
240 D_ASSERT( data != NULL );
241 D_MAGIC_ASSERT( shared, DFBLayerCoreShared );
242
243 data->core = core;
244 data->shared = shared;
245
246
247 if (dfb_num_layers != shared->num) {
248 D_ERROR("DirectFB/core/layers: Number of layers does not match!\n");
249 return DFB_BUG;
250 }
251
252 for (i=0; i<dfb_num_layers; i++) {
253 CoreLayer *layer = dfb_layers[i];
254 CoreLayerShared *lshared = shared->layers[i];
255
256 /* make a copy for faster access */
257 layer->layer_data = lshared->layer_data;
258
259 /* store pointer to shared data and core */
260 layer->shared = lshared;
261 layer->core = core;
262 }
263
264
265 D_MAGIC_SET( data, DFBLayerCore );
266
267 return DFB_OK;
268 }
269
270 static DFBResult
dfb_layer_core_shutdown(DFBLayerCore * data,bool emergency)271 dfb_layer_core_shutdown( DFBLayerCore *data,
272 bool emergency )
273 {
274 int i;
275 DFBResult ret;
276 DFBLayerCoreShared *shared;
277
278 D_DEBUG_AT( Core_Layer, "dfb_layer_core_shutdown( %p, %semergency )\n", data, emergency ? "" : "no " );
279
280 D_MAGIC_ASSERT( data, DFBLayerCore );
281 D_MAGIC_ASSERT( data->shared, DFBLayerCoreShared );
282
283 shared = data->shared;
284
285
286 /* Begin with the most recently added layer. */
287 for (i=dfb_num_layers-1; i>=0; i--) {
288 CoreLayer *layer = dfb_layers[i];
289 CoreLayerShared *shared = layer->shared;
290 const DisplayLayerFuncs *funcs = layer->funcs;
291
292 D_ASSUME( emergency || fusion_vector_is_empty( &shared->added_regions ) );
293
294 /* Remove all regions during emergency shutdown. */
295 if (emergency && funcs->RemoveRegion) {
296 int n;
297 CoreLayerRegion *region;
298
299 fusion_vector_foreach( region, n, shared->added_regions ) {
300 D_DEBUG_AT( Core_Layer, "Removing region (%d, %d - %dx%d) from '%s'.\n",
301 DFB_RECTANGLE_VALS( ®ion->config.dest ),
302 shared->description.name );
303
304 ret = funcs->RemoveRegion( layer, layer->driver_data,
305 layer->layer_data, region->region_data );
306 if (ret)
307 D_DERROR( ret, "Core/Layers: Could not remove region!\n" );
308 }
309 }
310
311 /* Shut the layer down. */
312 if (funcs->ShutdownLayer) {
313 ret = funcs->ShutdownLayer( layer,
314 layer->driver_data,
315 shared->layer_data );
316 if (ret)
317 D_DERROR( ret, "DirectFB/Core/layers: "
318 "Failed to shutdown layer %d!\n", shared->layer_id );
319 }
320
321 CoreLayer_Deinit_Dispatch( &shared->call );
322
323 /* Deinitialize the lock. */
324 fusion_skirmish_destroy( &shared->lock );
325
326 /* Deinitialize the state for window stack repaints. */
327 dfb_state_destroy( &layer->state );
328
329 /* Deinitialize the vector for the contexts. */
330 fusion_vector_destroy( &shared->contexts.stack );
331
332 /* Deinitialize the vector for the realized (added) regions. */
333 fusion_vector_destroy( &shared->added_regions );
334
335 /* Free the driver's layer data. */
336 if (shared->layer_data)
337 SHFREE( shared->shmpool, shared->layer_data );
338
339 /* Free the shared layer data. */
340 SHFREE( shared->shmpool, shared );
341
342 /* Free the local layer data. */
343 D_FREE( layer );
344 }
345
346 dfb_num_layers = 0;
347
348
349 D_MAGIC_CLEAR( data );
350 D_MAGIC_CLEAR( shared );
351
352 return DFB_OK;
353 }
354
355 static DFBResult
dfb_layer_core_leave(DFBLayerCore * data,bool emergency)356 dfb_layer_core_leave( DFBLayerCore *data,
357 bool emergency )
358 {
359 int i;
360 DFBLayerCoreShared *shared;
361
362 D_DEBUG_AT( Core_Layer, "dfb_layer_core_leave( %p, %semergency )\n", data, emergency ? "" : "no " );
363
364 D_MAGIC_ASSERT( data, DFBLayerCore );
365 D_MAGIC_ASSERT( data->shared, DFBLayerCoreShared );
366
367 shared = data->shared;
368
369
370 /* Deinitialize all local stuff. */
371 for (i=0; i<dfb_num_layers; i++) {
372 CoreLayer *layer = dfb_layers[i];
373
374 /* Deinitialize the state for window stack repaints. */
375 dfb_state_destroy( &layer->state );
376
377 /* Free local layer data. */
378 D_FREE( layer );
379 }
380
381 dfb_num_layers = 0;
382
383
384 D_MAGIC_CLEAR( data );
385
386 return DFB_OK;
387 }
388
389 static DFBResult
dfb_layer_core_suspend(DFBLayerCore * data)390 dfb_layer_core_suspend( DFBLayerCore *data )
391 {
392 int i;
393 DFBLayerCoreShared *shared;
394
395 D_DEBUG_AT( Core_Layer, "dfb_layer_core_suspend( %p )\n", data );
396
397 D_MAGIC_ASSERT( data, DFBLayerCore );
398 D_MAGIC_ASSERT( data->shared, DFBLayerCoreShared );
399
400 shared = data->shared;
401
402 for (i=dfb_num_layers-1; i>=0; i--)
403 dfb_layer_suspend( dfb_layers[i] );
404
405 return DFB_OK;
406 }
407
408 static DFBResult
dfb_layer_core_resume(DFBLayerCore * data)409 dfb_layer_core_resume( DFBLayerCore *data )
410 {
411 int i;
412 DFBLayerCoreShared *shared;
413
414 D_DEBUG_AT( Core_Layer, "dfb_layer_core_resume( %p )\n", data );
415
416 D_MAGIC_ASSERT( data, DFBLayerCore );
417 D_MAGIC_ASSERT( data->shared, DFBLayerCoreShared );
418
419 shared = data->shared;
420
421 for (i=0; i<dfb_num_layers; i++)
422 dfb_layer_resume( dfb_layers[i] );
423
424 return DFB_OK;
425 }
426
427 /**********************************************************************************************************************/
428
429 CoreLayer *
dfb_layers_register(CoreScreen * screen,void * driver_data,const DisplayLayerFuncs * funcs)430 dfb_layers_register( CoreScreen *screen,
431 void *driver_data,
432 const DisplayLayerFuncs *funcs )
433 {
434 CoreLayer *layer;
435
436 D_ASSERT( screen != NULL );
437 D_ASSERT( funcs != NULL );
438
439 if (dfb_num_layers == MAX_LAYERS) {
440 D_ERROR( "DirectFB/Core/Layers: "
441 "Maximum number of layers reached!\n" );
442 return NULL;
443 }
444
445 /* allocate local data */
446 layer = D_CALLOC( 1, sizeof(CoreLayer) );
447
448 /* assign local pointers */
449 layer->device = screen->device;
450 layer->screen = screen;
451 layer->driver_data = driver_data;
452 layer->funcs = funcs;
453
454 /* Initialize the state for window stack repaints */
455 dfb_state_init( &layer->state, NULL );
456
457 /* add it to the local list */
458 dfb_layers[dfb_num_layers++] = layer;
459
460 return layer;
461 }
462
463 typedef void (*AnyFunc)( void );
464
465 CoreLayer *
dfb_layers_hook_primary(CoreGraphicsDevice * device,void * driver_data,DisplayLayerFuncs * funcs,DisplayLayerFuncs * primary_funcs,void ** primary_driver_data)466 dfb_layers_hook_primary( CoreGraphicsDevice *device,
467 void *driver_data,
468 DisplayLayerFuncs *funcs,
469 DisplayLayerFuncs *primary_funcs,
470 void **primary_driver_data )
471 {
472 int i;
473 int entries;
474 CoreLayer *primary = dfb_layers[0];
475
476 D_ASSERT( primary != NULL );
477 D_ASSERT( device != NULL );
478 D_ASSERT( funcs != NULL );
479
480 /* copy content of original function table */
481 if (primary_funcs)
482 direct_memcpy( primary_funcs, primary->funcs, sizeof(DisplayLayerFuncs) );
483
484 /* copy pointer to original driver data */
485 if (primary_driver_data)
486 *primary_driver_data = primary->driver_data;
487
488 /* replace all entries in the old table that aren't NULL in the new one */
489 entries = sizeof(DisplayLayerFuncs) / sizeof(void(*)( void ));
490 for (i=0; i<entries; i++) {
491 AnyFunc *newfuncs = (AnyFunc*) funcs;
492 AnyFunc *oldfuncs = (AnyFunc*) primary->funcs;
493
494 if (newfuncs[i])
495 oldfuncs[i] = newfuncs[i];
496 }
497
498 /* replace device and driver data pointer */
499 primary->device = device;
500 primary->driver_data = driver_data;
501
502 return primary;
503 }
504
505 CoreLayer *
dfb_layers_replace_primary(CoreGraphicsDevice * device,void * driver_data,DisplayLayerFuncs * funcs)506 dfb_layers_replace_primary( CoreGraphicsDevice *device,
507 void *driver_data,
508 DisplayLayerFuncs *funcs )
509 {
510 CoreLayer *primary = dfb_layers[0];
511
512 D_ASSERT( primary != NULL );
513 D_ASSERT( device != NULL );
514 D_ASSERT( funcs != NULL );
515
516 /* replace device, function table and driver data pointer */
517 primary->device = device;
518 primary->funcs = funcs;
519 primary->driver_data = driver_data;
520
521 return primary;
522 }
523
524 void
dfb_layers_enumerate(DisplayLayerCallback callback,void * ctx)525 dfb_layers_enumerate( DisplayLayerCallback callback,
526 void *ctx )
527 {
528 int i;
529
530 D_ASSERT( callback != NULL );
531
532 for (i=0; i<dfb_num_layers; i++) {
533 if (callback( dfb_layers[i], ctx ) == DFENUM_CANCEL)
534 break;
535 }
536 }
537
538 int
dfb_layer_num(void)539 dfb_layer_num( void )
540 {
541 return dfb_num_layers;
542 }
543
544 CoreLayer *
dfb_layer_at(DFBDisplayLayerID id)545 dfb_layer_at( DFBDisplayLayerID id )
546 {
547 D_ASSERT( id >= 0);
548 D_ASSERT( id < dfb_num_layers);
549
550 return dfb_layers[id];
551 }
552
553 CoreLayer *
dfb_layer_at_translated(DFBDisplayLayerID id)554 dfb_layer_at_translated( DFBDisplayLayerID id )
555 {
556 D_ASSERT( id >= 0);
557 D_ASSERT( id < dfb_num_layers);
558 D_ASSERT( dfb_config != NULL );
559
560 if (dfb_config->primary_layer > 0 &&
561 dfb_config->primary_layer < dfb_num_layers)
562 {
563 if (id == DLID_PRIMARY)
564 return dfb_layer_at( dfb_config->primary_layer );
565
566 if (id == dfb_config->primary_layer)
567 return dfb_layer_at( DLID_PRIMARY );
568 }
569
570 return dfb_layer_at( id );
571 }
572
573 void
dfb_layer_get_description(const CoreLayer * layer,DFBDisplayLayerDescription * desc)574 dfb_layer_get_description( const CoreLayer *layer,
575 DFBDisplayLayerDescription *desc )
576 {
577 D_ASSERT( layer != NULL );
578 D_ASSERT( layer->shared != NULL );
579 D_ASSERT( desc != NULL );
580
581 *desc = layer->shared->description;
582 }
583
584 CoreScreen *
dfb_layer_screen(const CoreLayer * layer)585 dfb_layer_screen( const CoreLayer *layer )
586 {
587 D_ASSERT( layer != NULL );
588
589 return layer->screen;
590 }
591
592 CardState *
dfb_layer_state(CoreLayer * layer)593 dfb_layer_state( CoreLayer *layer )
594 {
595 D_ASSERT( layer != NULL );
596
597 return &layer->state;
598 }
599
600 DFBDisplayLayerID
dfb_layer_id(const CoreLayer * layer)601 dfb_layer_id( const CoreLayer *layer )
602 {
603 D_ASSERT( layer != NULL );
604 D_ASSERT( layer->shared != NULL );
605
606 return layer->shared->layer_id;
607 }
608
609 DFBDisplayLayerID
dfb_layer_id_translated(const CoreLayer * layer)610 dfb_layer_id_translated( const CoreLayer *layer )
611 {
612 CoreLayerShared *shared;
613
614 D_ASSERT( layer != NULL );
615 D_ASSERT( layer->shared != NULL );
616 D_ASSERT( dfb_config != NULL );
617
618 shared = layer->shared;
619
620 if (dfb_config->primary_layer > 0 &&
621 dfb_config->primary_layer < dfb_num_layers)
622 {
623 if (shared->layer_id == DLID_PRIMARY)
624 return dfb_config->primary_layer;
625
626 if (shared->layer_id == dfb_config->primary_layer)
627 return DLID_PRIMARY;
628 }
629
630 return shared->layer_id;
631 }
632
633 DFBDisplayLayerID
dfb_layer_id_translate(DFBDisplayLayerID layer_id)634 dfb_layer_id_translate( DFBDisplayLayerID layer_id )
635 {
636 D_ASSERT( dfb_config != NULL );
637
638 if (dfb_config->primary_layer > 0 &&
639 dfb_config->primary_layer < dfb_num_layers)
640 {
641 if (layer_id == DLID_PRIMARY)
642 return dfb_config->primary_layer;
643
644 if (layer_id == dfb_config->primary_layer)
645 return DLID_PRIMARY;
646 }
647
648 return layer_id;
649 }
650
651 DFBSurfacePixelFormat
dfb_primary_layer_pixelformat(void)652 dfb_primary_layer_pixelformat( void )
653 {
654 CoreLayerShared *shared;
655 CoreLayer *layer = dfb_layer_at_translated(DLID_PRIMARY);
656
657 D_ASSERT( layer != NULL );
658
659 shared = layer->shared;
660 D_ASSERT( shared != NULL );
661
662 return shared->pixelformat;
663 }
664
665