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 #include <config.h>
30
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <dirent.h>
34 #include <errno.h>
35
36 #include <pthread.h>
37
38 #include <direct/hash.h>
39 #include <direct/list.h>
40
41 #include <fusion/fusion.h>
42 #include <fusion/arena.h>
43 #include <fusion/shmalloc.h>
44 #include <fusion/shm/shm_internal.h>
45
46 #include <directfb.h>
47
48 #include <core/coredefs.h>
49 #include <core/coretypes.h>
50
51 #include <core/core.h>
52 #include <core/core_parts.h>
53 #include <core/fonts.h>
54 #include <core/graphics_state.h>
55 #include <core/layer_context.h>
56 #include <core/layer_region.h>
57 #include <core/palette.h>
58 #include <core/surface.h>
59 #include <core/system.h>
60 #include <core/windows.h>
61 #include <core/windows_internal.h>
62
63 #include <core/CoreDFB.h>
64 #include <core/CoreSlave.h>
65
66 #include <direct/build.h>
67 #include <direct/debug.h>
68 #include <direct/direct.h>
69 #include <direct/interface.h>
70 #include <direct/mem.h>
71 #include <direct/memcpy.h>
72 #include <direct/messages.h>
73 #include <direct/signals.h>
74 #include <direct/thread.h>
75 #include <direct/util.h>
76
77 #include <fusion/build.h>
78 #include <fusion/conf.h>
79
80 #include <misc/conf.h>
81 #include <misc/util.h>
82
83 #if defined(DFB_DYNAMIC_LINKING) && defined(SOPATH)
84 #include <dlfcn.h>
85 #endif
86
87 D_DEBUG_DOMAIN( DirectFB_Core, "DirectFB/Core", "DirectFB Core" );
88
89 /******************************************************************************/
90
91 extern CorePart dfb_clipboard_core;
92 extern CorePart dfb_colorhash_core;
93 extern CorePart dfb_graphics_core;
94 extern CorePart dfb_input_core;
95 extern CorePart dfb_layer_core;
96 extern CorePart dfb_screen_core;
97 extern CorePart dfb_surface_core;
98 extern CorePart dfb_system_core;
99 extern CorePart dfb_wm_core;
100
101 static CorePart *core_parts[] = {
102 &dfb_clipboard_core,
103 &dfb_colorhash_core,
104 &dfb_surface_core,
105 &dfb_system_core,
106 &dfb_input_core,
107 &dfb_graphics_core,
108 &dfb_screen_core,
109 &dfb_layer_core,
110 &dfb_wm_core
111 };
112
113 void *
dfb_core_get_part(CoreDFB * core,DFBCorePartID part_id)114 dfb_core_get_part( CoreDFB *core,
115 DFBCorePartID part_id )
116 {
117 switch (part_id) {
118 case DFCP_CLIPBOARD:
119 return dfb_clipboard_core.data_local;
120
121 case DFCP_COLORHASH:
122 return dfb_colorhash_core.data_local;
123
124 case DFCP_GRAPHICS:
125 return dfb_graphics_core.data_local;
126
127 case DFCP_INPUT:
128 return dfb_input_core.data_local;
129
130 case DFCP_LAYER:
131 return dfb_layer_core.data_local;
132
133 case DFCP_SCREEN:
134 return dfb_screen_core.data_local;
135
136 case DFCP_SURFACE:
137 return dfb_surface_core.data_local;
138
139 case DFCP_SYSTEM:
140 return dfb_system_core.data_local;
141
142 case DFCP_WM:
143 return dfb_wm_core.data_local;
144
145 default:
146 D_BUG( "unknown core part" );
147 }
148
149 return NULL;
150 }
151
152 /******************************************************************************/
153
154 /*
155 * one entry in the cleanup stack
156 */
157 struct _CoreCleanup {
158 DirectLink link;
159
160 CoreCleanupFunc func; /* the cleanup function to be called */
161 void *data; /* context of the cleanup function */
162 bool emergency; /* if true, cleanup is also done during
163 emergency shutdown (from signal hadler) */
164 };
165
166 /******************************************************************************/
167
168 /*
169 * ckecks if stack is clean, otherwise prints warning, then calls core_deinit()
170 */
171 static void dfb_core_deinit_check( void *ctx );
172
173 static void dfb_core_thread_init_handler( DirectThread *thread, void *arg );
174
175 static void dfb_core_process_cleanups( CoreDFB *core, bool emergency );
176
177 static DirectSignalHandlerResult dfb_core_signal_handler( int num,
178 void *addr,
179 void *ctx );
180
181 /******************************************************************************/
182
183 static int dfb_core_arena_initialize( FusionArena *arena,
184 void *ctx );
185 static int dfb_core_arena_shutdown ( FusionArena *arena,
186 void *ctx,
187 bool emergency );
188 static int dfb_core_arena_join ( FusionArena *arena,
189 void *ctx );
190 static int dfb_core_arena_leave ( FusionArena *arena,
191 void *ctx,
192 bool emergency );
193
194 /******************************************************************************/
195
196 #if defined(DFB_DYNAMIC_LINKING) && defined(SOPATH)
197 /*
198 * the library handle for dlopen'ing ourselves
199 */
200 static void* dfb_lib_handle = NULL;
201 #endif
202
203 /******************************************************************************/
204
205 CoreDFB *core_dfb = NULL;
206 static pthread_mutex_t core_dfb_lock = PTHREAD_MUTEX_INITIALIZER;
207
208 /******************************************************************************/
209
210 static FusionCallHandlerResult
Core_AsyncCall_Handler(int caller,int call_arg,void * call_ptr,void * ctx,unsigned int serial,int * ret_val)211 Core_AsyncCall_Handler( int caller, /* fusion id of the caller */
212 int call_arg, /* optional call parameter */
213 void *call_ptr, /* optional call parameter */
214 void *ctx, /* optional handler context */
215 unsigned int serial,
216 int *ret_val )
217 {
218 AsyncCall *call = call_ptr;
219
220 call->func( call->ctx, call->ctx2 );
221
222 return FCHR_RETURN;
223 }
224
225 /******************************************************************************/
226
227 DFBResult
dfb_core_create(CoreDFB ** ret_core)228 dfb_core_create( CoreDFB **ret_core )
229 {
230 int ret;
231 #if FUSION_BUILD_MULTI
232 char buf[16];
233 #endif
234 CoreDFB *core = NULL;
235 CoreDFBShared *shared = NULL;
236
237 D_ASSERT( ret_core != NULL );
238 D_ASSERT( dfb_config != NULL );
239
240 D_DEBUG_AT( DirectFB_Core, "%s...\n", __FUNCTION__ );
241
242 pthread_mutex_lock( &core_dfb_lock );
243
244 D_ASSERT( core_dfb == NULL || core_dfb->refs > 0 );
245
246 if (core_dfb) {
247 D_MAGIC_ASSERT( core_dfb, CoreDFB );
248
249 core_dfb->refs++;
250
251 *ret_core = core_dfb;
252
253 pthread_mutex_unlock( &core_dfb_lock );
254
255 return DFB_OK;
256 }
257
258 direct_initialize();
259
260
261 D_INFO( "DirectFB/Core: %s Application Core. ("BUILDTIME") %s%s\n",
262 FUSION_BUILD_MULTI ? "Multi" : "Single",
263 DIRECT_BUILD_DEBUG ? "[ DEBUG ]" : "",
264 DIRECT_BUILD_TRACE ? "[ TRACE ]" : "" );
265
266
267 #if defined(DFB_DYNAMIC_LINKING) && defined(SOPATH)
268 if (!dfb_lib_handle)
269 #ifdef RTLD_GLOBAL
270 dfb_lib_handle = dlopen(SOPATH, RTLD_GLOBAL|RTLD_LAZY);
271 #else
272 /* RTLD_GLOBAL is not defined on OpenBSD */
273 dfb_lib_handle = dlopen(SOPATH, RTLD_LAZY);
274 #endif
275 #endif
276
277 ret = dfb_system_lookup();
278 if (ret)
279 goto error;
280
281
282 /* Allocate local core structure. */
283 core = D_CALLOC( 1, sizeof(CoreDFB) );
284 if (!core) {
285 ret = D_OOM();
286 goto error;
287 }
288
289 core->refs = 1;
290
291 core->init_handler = direct_thread_add_init_handler( dfb_core_thread_init_handler, core );
292
293 #if FUSION_BUILD_MULTI
294 dfb_system_thread_init();
295 #endif
296
297 direct_find_best_memcpy();
298
299 D_MAGIC_SET( core, CoreDFB );
300
301 core_dfb = core;
302
303 ret = fusion_enter( dfb_config->session, DIRECTFB_CORE_ABI, FER_ANY, &core->world );
304 if (ret)
305 goto error;
306
307 core->fusion_id = fusion_id( core->world );
308
309 #if FUSION_BUILD_MULTI
310 D_DEBUG_AT( DirectFB_Core, "world %d, fusion id %d\n", fusion_world_index(core->world), core->fusion_id );
311
312 snprintf( buf, sizeof(buf), "%d", fusion_world_index(core->world) );
313
314 setenv( "DIRECTFB_SESSION", buf, true );
315 #endif
316
317 if (dfb_config->sync) {
318 D_INFO( "DirectFB/Core: calling sync()...\n" );
319 sync();
320 }
321
322 if (dfb_config->core_sighandler)
323 direct_signal_handler_add( DIRECT_SIGNAL_ANY, dfb_core_signal_handler, core, &core->signal_handler );
324
325 fusion_call_init( &core_dfb->async_call, Core_AsyncCall_Handler, core, core_dfb->world );
326
327 if (fusion_arena_enter( core->world, "DirectFB/Core",
328 dfb_core_arena_initialize, dfb_core_arena_join,
329 core, &core->arena, &ret ) || ret)
330 {
331 ret = ret ? ret : DFB_FUSION;
332 goto error;
333 }
334
335 shared = core->shared;
336 D_MAGIC_ASSERT( shared, CoreDFBShared );
337
338 if (dfb_config->block_all_signals)
339 direct_signals_block_all();
340
341 if (dfb_config->deinit_check)
342 direct_cleanup_handler_add( dfb_core_deinit_check, NULL, &core->cleanup_handler );
343
344 fusion_skirmish_prevail( &shared->lock );
345
346 if (!core->master) {
347 while (!shared->active)
348 fusion_skirmish_wait( &shared->lock, 0 );
349 }
350
351 fusion_skirmish_dismiss( &shared->lock );
352
353 dfb_font_manager_create( core, &core->font_manager );
354
355 *ret_core = core;
356
357 pthread_mutex_unlock( &core_dfb_lock );
358
359 D_DEBUG_AT( DirectFB_Core, "Core successfully created.\n" );
360
361 return DFB_OK;
362
363
364 error:
365 if (core) {
366 if (core->world) {
367 fusion_call_destroy( &core_dfb->async_call );
368
369 fusion_exit( core->world, false );
370 }
371
372 if (core->init_handler)
373 direct_thread_remove_init_handler( core->init_handler );
374
375 if (core->signal_handler)
376 direct_signal_handler_remove( core->signal_handler );
377
378 D_MAGIC_CLEAR( core );
379
380 D_FREE( core );
381 core_dfb = NULL;
382 }
383
384 pthread_mutex_unlock( &core_dfb_lock );
385
386 direct_shutdown();
387
388 return ret;
389 }
390
391 DFBResult
dfb_core_destroy(CoreDFB * core,bool emergency)392 dfb_core_destroy( CoreDFB *core, bool emergency )
393 {
394 D_MAGIC_ASSERT( core, CoreDFB );
395 D_ASSERT( core->refs > 0 );
396 D_ASSERT( core == core_dfb );
397
398 D_DEBUG_AT( DirectFB_Core, "%s...\n", __FUNCTION__ );
399
400 pthread_mutex_lock( &core_dfb_lock );
401
402 if (!core->shutdown_running)
403 core->shutdown_running = 1;
404 else {
405 pthread_mutex_unlock( &core_dfb_lock );
406 return DFB_OK;
407 }
408
409 if (!emergency) {
410 if (--core->refs) {
411 pthread_mutex_unlock( &core_dfb_lock );
412 return DFB_OK;
413 }
414 }
415 else
416 usleep( 500000 );
417
418 if (core->font_manager)
419 dfb_font_manager_destroy( core->font_manager );
420
421 if (core->signal_handler)
422 direct_signal_handler_remove( core->signal_handler );
423
424 if (core->cleanup_handler)
425 direct_cleanup_handler_remove( core->cleanup_handler );
426
427 if (core->master) {
428 if (emergency) {
429 fusion_kill( core->world, 0, SIGKILL, 1000 );
430 }
431 else {
432 fusion_kill( core->world, 0, SIGTERM, 5000 );
433 fusion_kill( core->world, 0, SIGKILL, 2000 );
434 }
435 }
436
437 dfb_core_process_cleanups( core, emergency );
438
439 while (fusion_arena_exit( core->arena, dfb_core_arena_shutdown,
440 core->master ? NULL : dfb_core_arena_leave,
441 core, emergency, NULL ) == DR_BUSY)
442 {
443 D_ONCE( "waiting for DirectFB slaves to terminate" );
444 usleep( 100000 );
445 }
446
447 fusion_call_destroy( &core_dfb->async_call );
448
449 fusion_exit( core->world, emergency );
450
451 if (!emergency)
452 direct_thread_remove_init_handler( core->init_handler );
453
454 D_MAGIC_CLEAR( core );
455
456 D_FREE( core );
457 core_dfb = NULL;
458
459 pthread_mutex_unlock( &core_dfb_lock );
460
461 direct_shutdown();
462
463 return DFB_OK;
464 }
465
466 CoreGraphicsState *
dfb_core_create_graphics_state(CoreDFB * core)467 dfb_core_create_graphics_state( CoreDFB *core )
468 {
469 CoreDFBShared *shared;
470
471 D_ASSUME( core != NULL );
472
473 if (!core)
474 core = core_dfb;
475
476 D_MAGIC_ASSERT( core, CoreDFB );
477
478 shared = core->shared;
479
480 D_MAGIC_ASSERT( shared, CoreDFBShared );
481 D_ASSERT( core->shared->graphics_state_pool != NULL );
482
483 return (CoreGraphicsState*) fusion_object_create( core->shared->graphics_state_pool, core->world, Core_GetIdentity() );
484 }
485
486 CoreLayerContext *
dfb_core_create_layer_context(CoreDFB * core)487 dfb_core_create_layer_context( CoreDFB *core )
488 {
489 CoreDFBShared *shared;
490
491 D_ASSUME( core != NULL );
492
493 if (!core)
494 core = core_dfb;
495
496 D_MAGIC_ASSERT( core, CoreDFB );
497
498 shared = core->shared;
499
500 D_MAGIC_ASSERT( shared, CoreDFBShared );
501 D_ASSERT( shared->layer_context_pool != NULL );
502
503 return (CoreLayerContext*) fusion_object_create( shared->layer_context_pool, core->world, Core_GetIdentity() );
504 }
505
506 CoreLayerRegion *
dfb_core_create_layer_region(CoreDFB * core)507 dfb_core_create_layer_region( CoreDFB *core )
508 {
509 CoreDFBShared *shared;
510
511 D_ASSUME( core != NULL );
512
513 if (!core)
514 core = core_dfb;
515
516 D_MAGIC_ASSERT( core, CoreDFB );
517
518 shared = core->shared;
519
520 D_MAGIC_ASSERT( shared, CoreDFBShared );
521 D_ASSERT( core->shared->layer_region_pool != NULL );
522
523 return (CoreLayerRegion*) fusion_object_create( core->shared->layer_region_pool, core->world, Core_GetIdentity() );
524 }
525
526 CorePalette *
dfb_core_create_palette(CoreDFB * core)527 dfb_core_create_palette( CoreDFB *core )
528 {
529 CoreDFBShared *shared;
530
531 D_ASSUME( core != NULL );
532
533 if (!core)
534 core = core_dfb;
535
536 D_MAGIC_ASSERT( core, CoreDFB );
537
538 shared = core->shared;
539
540 D_MAGIC_ASSERT( shared, CoreDFBShared );
541 D_ASSERT( core->shared->palette_pool != NULL );
542
543 return (CorePalette*) fusion_object_create( core->shared->palette_pool, core->world, Core_GetIdentity() );
544 }
545
546 CoreSurface *
dfb_core_create_surface(CoreDFB * core)547 dfb_core_create_surface( CoreDFB *core )
548 {
549 CoreDFBShared *shared;
550
551 D_ASSUME( core != NULL );
552
553 if (!core)
554 core = core_dfb;
555
556 D_MAGIC_ASSERT( core, CoreDFB );
557
558 shared = core->shared;
559
560 D_MAGIC_ASSERT( shared, CoreDFBShared );
561 D_ASSERT( core->shared->surface_pool != NULL );
562
563 return (CoreSurface*) fusion_object_create( core->shared->surface_pool, core->world, Core_GetIdentity() );
564 }
565
566 CoreSurfaceAllocation *
dfb_core_create_surface_allocation(CoreDFB * core)567 dfb_core_create_surface_allocation( CoreDFB *core )
568 {
569 CoreDFBShared *shared;
570
571 D_ASSUME( core != NULL );
572
573 if (!core)
574 core = core_dfb;
575
576 D_MAGIC_ASSERT( core, CoreDFB );
577
578 shared = core->shared;
579
580 D_MAGIC_ASSERT( shared, CoreDFBShared );
581 D_ASSERT( core->shared->surface_allocation_pool != NULL );
582
583 return (CoreSurfaceAllocation*) fusion_object_create( core->shared->surface_allocation_pool, core->world, Core_GetIdentity() );
584 }
585
586 CoreSurfaceBuffer *
dfb_core_create_surface_buffer(CoreDFB * core)587 dfb_core_create_surface_buffer( CoreDFB *core )
588 {
589 CoreDFBShared *shared;
590
591 D_ASSUME( core != NULL );
592
593 if (!core)
594 core = core_dfb;
595
596 D_MAGIC_ASSERT( core, CoreDFB );
597
598 shared = core->shared;
599
600 D_MAGIC_ASSERT( shared, CoreDFBShared );
601 D_ASSERT( core->shared->surface_buffer_pool != NULL );
602
603 return (CoreSurfaceBuffer*) fusion_object_create( core->shared->surface_buffer_pool, core->world, Core_GetIdentity() );
604 }
605
606 CoreWindow *
dfb_core_create_window(CoreDFB * core)607 dfb_core_create_window( CoreDFB *core )
608 {
609 CoreDFBShared *shared;
610
611 D_ASSUME( core != NULL );
612
613 if (!core)
614 core = core_dfb;
615
616 D_MAGIC_ASSERT( core, CoreDFB );
617
618 shared = core->shared;
619
620 D_MAGIC_ASSERT( shared, CoreDFBShared );
621 D_ASSERT( core->shared->window_pool != NULL );
622
623 return (CoreWindow*) fusion_object_create( core->shared->window_pool, core->world, Core_GetIdentity() );
624 }
625
626 DFBResult
dfb_core_get_graphics_state(CoreDFB * core,u32 object_id,CoreGraphicsState ** ret_state)627 dfb_core_get_graphics_state( CoreDFB *core,
628 u32 object_id,
629 CoreGraphicsState **ret_state )
630 {
631 DFBResult ret;
632 FusionObject *object;
633
634 CoreDFBShared *shared;
635
636 D_ASSUME( core != NULL );
637 D_ASSERT( ret_state != NULL );
638
639 if (!core)
640 core = core_dfb;
641
642 D_MAGIC_ASSERT( core, CoreDFB );
643
644 shared = core->shared;
645
646 D_MAGIC_ASSERT( shared, CoreDFBShared );
647 D_ASSERT( core->shared->graphics_state_pool != NULL );
648
649 ret = fusion_object_get( core->shared->graphics_state_pool, object_id, &object );
650 if (ret)
651 return ret;
652
653 *ret_state = (CoreGraphicsState*) object;
654
655 return DFB_OK;
656 }
657
658 DFBResult
dfb_core_get_layer_context(CoreDFB * core,u32 object_id,CoreLayerContext ** ret_context)659 dfb_core_get_layer_context( CoreDFB *core,
660 u32 object_id,
661 CoreLayerContext **ret_context )
662 {
663 DFBResult ret;
664 FusionObject *object;
665
666 CoreDFBShared *shared;
667
668 D_ASSUME( core != NULL );
669 D_ASSERT( ret_context != NULL );
670
671 if (!core)
672 core = core_dfb;
673
674 D_MAGIC_ASSERT( core, CoreDFB );
675
676 shared = core->shared;
677
678 D_MAGIC_ASSERT( shared, CoreDFBShared );
679 D_ASSERT( core->shared->layer_context_pool != NULL );
680
681 ret = fusion_object_get( core->shared->layer_context_pool, object_id, &object );
682 if (ret)
683 return ret;
684
685 *ret_context = (CoreLayerContext*) object;
686
687 return DFB_OK;
688 }
689
690 DFBResult
dfb_core_get_layer_region(CoreDFB * core,u32 object_id,CoreLayerRegion ** ret_region)691 dfb_core_get_layer_region( CoreDFB *core,
692 u32 object_id,
693 CoreLayerRegion **ret_region )
694 {
695 DFBResult ret;
696 FusionObject *object;
697
698 CoreDFBShared *shared;
699
700 D_ASSUME( core != NULL );
701 D_ASSERT( ret_region != NULL );
702
703 if (!core)
704 core = core_dfb;
705
706 D_MAGIC_ASSERT( core, CoreDFB );
707
708 shared = core->shared;
709
710 D_MAGIC_ASSERT( shared, CoreDFBShared );
711 D_ASSERT( core->shared->layer_region_pool != NULL );
712
713 ret = fusion_object_get( core->shared->layer_region_pool, object_id, &object );
714 if (ret)
715 return ret;
716
717 *ret_region = (CoreLayerRegion*) object;
718
719 return DFB_OK;
720 }
721
722 DFBResult
dfb_core_get_palette(CoreDFB * core,u32 object_id,CorePalette ** ret_palette)723 dfb_core_get_palette( CoreDFB *core,
724 u32 object_id,
725 CorePalette **ret_palette )
726 {
727 DFBResult ret;
728 FusionObject *object;
729
730 CoreDFBShared *shared;
731
732 D_ASSUME( core != NULL );
733 D_ASSERT( ret_palette != NULL );
734
735 if (!core)
736 core = core_dfb;
737
738 D_MAGIC_ASSERT( core, CoreDFB );
739
740 shared = core->shared;
741
742 D_MAGIC_ASSERT( shared, CoreDFBShared );
743 D_ASSERT( core->shared->palette_pool != NULL );
744
745 ret = fusion_object_get( core->shared->palette_pool, object_id, &object );
746 if (ret)
747 return ret;
748
749 *ret_palette = (CorePalette*) object;
750
751 return DFB_OK;
752 }
753
754 DFBResult
dfb_core_get_surface(CoreDFB * core,u32 object_id,CoreSurface ** ret_surface)755 dfb_core_get_surface( CoreDFB *core,
756 u32 object_id,
757 CoreSurface **ret_surface )
758 {
759 DFBResult ret;
760 FusionObject *object;
761
762 CoreDFBShared *shared;
763
764 D_ASSUME( core != NULL );
765 D_ASSERT( ret_surface != NULL );
766
767 if (!core)
768 core = core_dfb;
769
770 D_MAGIC_ASSERT( core, CoreDFB );
771
772 shared = core->shared;
773
774 D_MAGIC_ASSERT( shared, CoreDFBShared );
775 D_ASSERT( core->shared->surface_pool != NULL );
776
777 ret = fusion_object_get( core->shared->surface_pool, object_id, &object );
778 if (ret)
779 return ret;
780
781 *ret_surface = (CoreSurface*) object;
782
783 return DFB_OK;
784 }
785
786 DFBResult
dfb_core_get_surface_allocation(CoreDFB * core,u32 object_id,CoreSurfaceAllocation ** ret_allocation)787 dfb_core_get_surface_allocation( CoreDFB *core,
788 u32 object_id,
789 CoreSurfaceAllocation **ret_allocation )
790 {
791 DFBResult ret;
792 FusionObject *object;
793
794 CoreDFBShared *shared;
795
796 D_ASSUME( core != NULL );
797 D_ASSERT( ret_allocation != NULL );
798
799 if (!core)
800 core = core_dfb;
801
802 D_MAGIC_ASSERT( core, CoreDFB );
803
804 shared = core->shared;
805
806 D_MAGIC_ASSERT( shared, CoreDFBShared );
807 D_ASSERT( core->shared->surface_allocation_pool != NULL );
808
809 ret = fusion_object_get( core->shared->surface_allocation_pool, object_id, &object );
810 if (ret)
811 return ret;
812
813 *ret_allocation = (CoreSurfaceAllocation*) object;
814
815 return DFB_OK;
816 }
817
818 DFBResult
dfb_core_get_surface_buffer(CoreDFB * core,u32 object_id,CoreSurfaceBuffer ** ret_buffer)819 dfb_core_get_surface_buffer( CoreDFB *core,
820 u32 object_id,
821 CoreSurfaceBuffer **ret_buffer )
822 {
823 DFBResult ret;
824 FusionObject *object;
825
826 CoreDFBShared *shared;
827
828 D_ASSUME( core != NULL );
829 D_ASSERT( ret_buffer != NULL );
830
831 if (!core)
832 core = core_dfb;
833
834 D_MAGIC_ASSERT( core, CoreDFB );
835
836 shared = core->shared;
837
838 D_MAGIC_ASSERT( shared, CoreDFBShared );
839 D_ASSERT( core->shared->surface_buffer_pool != NULL );
840
841 ret = fusion_object_get( core->shared->surface_buffer_pool, object_id, &object );
842 if (ret)
843 return ret;
844
845 *ret_buffer = (CoreSurfaceBuffer*) object;
846
847 return DFB_OK;
848 }
849
850 DFBResult
dfb_core_get_window(CoreDFB * core,u32 object_id,CoreWindow ** ret_window)851 dfb_core_get_window( CoreDFB *core,
852 u32 object_id,
853 CoreWindow **ret_window )
854 {
855 DFBResult ret;
856 FusionObject *object;
857
858 CoreDFBShared *shared;
859
860 D_ASSUME( core != NULL );
861 D_ASSERT( ret_window != NULL );
862
863 if (!core)
864 core = core_dfb;
865
866 D_MAGIC_ASSERT( core, CoreDFB );
867
868 shared = core->shared;
869
870 D_MAGIC_ASSERT( shared, CoreDFBShared );
871 D_ASSERT( core->shared->window_pool != NULL );
872
873 ret = fusion_object_get( core->shared->window_pool, object_id, &object );
874 if (ret)
875 return ret;
876
877 *ret_window = (CoreWindow*) object;
878
879 return DFB_OK;
880 }
881
882 DirectResult
dfb_core_enum_surfaces(CoreDFB * core,FusionObjectCallback callback,void * ctx)883 dfb_core_enum_surfaces( CoreDFB *core,
884 FusionObjectCallback callback,
885 void *ctx )
886 {
887 CoreDFBShared *shared;
888
889 D_ASSERT( core != NULL || core_dfb != NULL );
890
891 if (!core)
892 core = core_dfb;
893
894 D_MAGIC_ASSERT( core, CoreDFB );
895
896 shared = core->shared;
897
898 D_MAGIC_ASSERT( shared, CoreDFBShared );
899
900 return fusion_object_pool_enum( shared->surface_pool, callback, ctx );
901 }
902
903 DirectResult
dfb_core_enum_layer_contexts(CoreDFB * core,FusionObjectCallback callback,void * ctx)904 dfb_core_enum_layer_contexts( CoreDFB *core,
905 FusionObjectCallback callback,
906 void *ctx )
907 {
908 CoreDFBShared *shared;
909
910 D_ASSERT( core != NULL || core_dfb != NULL );
911
912 if (!core)
913 core = core_dfb;
914
915 D_MAGIC_ASSERT( core, CoreDFB );
916
917 shared = core->shared;
918
919 D_MAGIC_ASSERT( shared, CoreDFBShared );
920
921 return fusion_object_pool_enum( shared->layer_context_pool, callback, ctx );
922 }
923
924 DirectResult
dfb_core_enum_layer_regions(CoreDFB * core,FusionObjectCallback callback,void * ctx)925 dfb_core_enum_layer_regions( CoreDFB *core,
926 FusionObjectCallback callback,
927 void *ctx )
928 {
929 CoreDFBShared *shared;
930
931 D_ASSERT( core != NULL || core_dfb != NULL );
932
933 if (!core)
934 core = core_dfb;
935
936 D_MAGIC_ASSERT( core, CoreDFB );
937
938 shared = core->shared;
939
940 D_MAGIC_ASSERT( shared, CoreDFBShared );
941
942 return fusion_object_pool_enum( shared->layer_region_pool, callback, ctx );
943 }
944
945 bool
dfb_core_is_master(CoreDFB * core)946 dfb_core_is_master( CoreDFB *core )
947 {
948 D_MAGIC_ASSERT( core, CoreDFB );
949
950 return core->master;
951 }
952
953 void
dfb_core_activate(CoreDFB * core)954 dfb_core_activate( CoreDFB *core )
955 {
956 CoreDFBShared *shared;
957
958 D_MAGIC_ASSERT( core, CoreDFB );
959
960 shared = core->shared;
961 D_MAGIC_ASSERT( shared, CoreDFBShared );
962
963 fusion_skirmish_prevail( &shared->lock );
964
965 shared->active = true;
966
967 fusion_skirmish_notify( &shared->lock );
968
969 fusion_skirmish_dismiss( &shared->lock );
970 }
971
972 FusionWorld *
dfb_core_world(CoreDFB * core)973 dfb_core_world( CoreDFB *core )
974 {
975 // D_ASSUME( core != NULL );
976
977 if (!core)
978 core = core_dfb;
979
980 D_MAGIC_ASSERT( core, CoreDFB );
981
982 return core->world;
983 }
984
985 FusionArena *
dfb_core_arena(CoreDFB * core)986 dfb_core_arena( CoreDFB *core )
987 {
988 D_ASSUME( core != NULL );
989
990 if (!core)
991 core = core_dfb;
992
993 D_MAGIC_ASSERT( core, CoreDFB );
994
995 return core->arena;
996 }
997
998 FusionSHMPoolShared *
dfb_core_shmpool(CoreDFB * core)999 dfb_core_shmpool( CoreDFB *core )
1000 {
1001 CoreDFBShared *shared;
1002
1003 D_ASSUME( core != NULL );
1004
1005 if (!core)
1006 core = core_dfb;
1007
1008 D_MAGIC_ASSERT( core, CoreDFB );
1009
1010 shared = core->shared;
1011
1012 D_MAGIC_ASSERT( shared, CoreDFBShared );
1013
1014 return shared->shmpool;
1015 }
1016
1017 FusionSHMPoolShared *
dfb_core_shmpool_data(CoreDFB * core)1018 dfb_core_shmpool_data( CoreDFB *core )
1019 {
1020 CoreDFBShared *shared;
1021
1022 D_ASSUME( core != NULL );
1023
1024 if (!core)
1025 core = core_dfb;
1026
1027 D_MAGIC_ASSERT( core, CoreDFB );
1028
1029 shared = core->shared;
1030
1031 D_MAGIC_ASSERT( shared, CoreDFBShared );
1032
1033 return shared->shmpool_data;
1034 }
1035
1036 DFBResult
dfb_core_suspend(CoreDFB * core)1037 dfb_core_suspend( CoreDFB *core )
1038 {
1039 DFBResult ret;
1040
1041 D_ASSUME( core != NULL );
1042
1043 if (!core)
1044 core = core_dfb;
1045
1046 D_MAGIC_ASSERT( core, CoreDFB );
1047
1048 if (!core->master)
1049 return DFB_ACCESSDENIED;
1050
1051 if (core->suspended)
1052 return DFB_BUSY;
1053
1054 ret = dfb_input_core.Suspend( dfb_input_core.data_local );
1055 if (ret)
1056 goto error_input;
1057
1058 ret = dfb_layer_core.Suspend( dfb_layer_core.data_local );
1059 if (ret)
1060 goto error_layers;
1061
1062 ret = dfb_screen_core.Suspend( dfb_screen_core.data_local );
1063 if (ret)
1064 goto error_screens;
1065
1066 ret = dfb_graphics_core.Suspend( dfb_graphics_core.data_local );
1067 if (ret)
1068 goto error_graphics;
1069
1070 core->suspended = true;
1071
1072 return DFB_OK;
1073
1074 error_graphics:
1075 dfb_screen_core.Resume( dfb_screen_core.data_local );
1076 error_screens:
1077 dfb_layer_core.Resume( dfb_layer_core.data_local );
1078 error_layers:
1079 dfb_input_core.Resume( dfb_input_core.data_local );
1080 error_input:
1081 return ret;
1082 }
1083
1084 DFBResult
dfb_core_resume(CoreDFB * core)1085 dfb_core_resume( CoreDFB *core )
1086 {
1087 DFBResult ret;
1088
1089 D_ASSUME( core != NULL );
1090
1091 if (!core)
1092 core = core_dfb;
1093
1094 D_MAGIC_ASSERT( core, CoreDFB );
1095
1096 if (!core->master)
1097 return DFB_ACCESSDENIED;
1098
1099 if (!core->suspended)
1100 return DFB_BUSY;
1101
1102 ret = dfb_graphics_core.Resume( dfb_graphics_core.data_local );
1103 if (ret)
1104 goto error_graphics;
1105
1106 ret = dfb_screen_core.Resume( dfb_screen_core.data_local );
1107 if (ret)
1108 goto error_screens;
1109
1110 ret = dfb_layer_core.Resume( dfb_layer_core.data_local );
1111 if (ret)
1112 goto error_layers;
1113
1114 ret = dfb_input_core.Resume( dfb_input_core.data_local );
1115 if (ret)
1116 goto error_input;
1117
1118 core->suspended = false;
1119
1120 return DFB_OK;
1121
1122 error_input:
1123 dfb_layer_core.Suspend( dfb_layer_core.data_local );
1124 error_layers:
1125 dfb_screen_core.Suspend( dfb_screen_core.data_local );
1126 error_screens:
1127 dfb_graphics_core.Suspend( dfb_graphics_core.data_local );
1128 error_graphics:
1129 return ret;
1130 }
1131
1132 CoreCleanup *
dfb_core_cleanup_add(CoreDFB * core,CoreCleanupFunc func,void * data,bool emergency)1133 dfb_core_cleanup_add( CoreDFB *core,
1134 CoreCleanupFunc func,
1135 void *data,
1136 bool emergency )
1137 {
1138 CoreCleanup *cleanup;
1139
1140 D_ASSUME( core != NULL );
1141
1142 if (!core)
1143 core = core_dfb;
1144
1145 D_MAGIC_ASSERT( core, CoreDFB );
1146
1147 cleanup = D_CALLOC( 1, sizeof(CoreCleanup) );
1148
1149 cleanup->func = func;
1150 cleanup->data = data;
1151 cleanup->emergency = emergency;
1152
1153 direct_list_prepend( &core->cleanups, &cleanup->link );
1154
1155 return cleanup;
1156 }
1157
1158 void
dfb_core_cleanup_remove(CoreDFB * core,CoreCleanup * cleanup)1159 dfb_core_cleanup_remove( CoreDFB *core,
1160 CoreCleanup *cleanup )
1161 {
1162 D_ASSUME( core != NULL );
1163
1164 if (!core)
1165 core = core_dfb;
1166
1167 D_MAGIC_ASSERT( core, CoreDFB );
1168
1169 direct_list_remove( &core->cleanups, &cleanup->link );
1170
1171 D_FREE( cleanup );
1172 }
1173
1174 DFBFontManager *
dfb_core_font_manager(CoreDFB * core)1175 dfb_core_font_manager( CoreDFB *core )
1176 {
1177 D_ASSUME( core != NULL );
1178
1179 if (!core)
1180 core = core_dfb;
1181
1182 D_MAGIC_ASSERT( core, CoreDFB );
1183
1184 return core->font_manager;
1185 }
1186
1187 /******************************************************************************/
1188
1189 struct __CoreDFB_CoreMemoryPermission {
1190 DirectLink link;
1191
1192 CoreMemoryPermissionFlags flags;
1193
1194 void *data;
1195 void *end;
1196 size_t length;
1197 };
1198
1199 DFBResult
dfb_core_memory_permissions_add(CoreDFB * core,CoreMemoryPermissionFlags flags,void * data,size_t length,CoreMemoryPermission ** ret_permission)1200 dfb_core_memory_permissions_add( CoreDFB *core,
1201 CoreMemoryPermissionFlags flags,
1202 void *data,
1203 size_t length,
1204 CoreMemoryPermission **ret_permission )
1205 {
1206 CoreMemoryPermission *permission;
1207
1208 D_DEBUG_AT( DirectFB_Core, "%s( flags 0x%02x, data %p, length %zu )\n", __FUNCTION__, flags, data, length );
1209
1210 D_MAGIC_ASSERT( core, CoreDFB );
1211
1212 permission = D_CALLOC( 1, sizeof(CoreMemoryPermission) );
1213 if (!permission)
1214 return D_OOM();
1215
1216 permission->flags = flags;
1217 permission->data = data;
1218 permission->end = data + length;
1219 permission->length = length;
1220
1221 direct_mutex_lock( &core->memory_permissions_lock );
1222
1223 direct_list_prepend( &core->memory_permissions, &permission->link );
1224
1225 direct_mutex_unlock( &core->memory_permissions_lock );
1226
1227 *ret_permission = permission;
1228
1229 return DFB_OK;
1230 }
1231
1232 DFBResult
dfb_core_memory_permissions_remove(CoreDFB * core,CoreMemoryPermission * permission)1233 dfb_core_memory_permissions_remove( CoreDFB *core,
1234 CoreMemoryPermission *permission )
1235 {
1236 D_DEBUG_AT( DirectFB_Core, "%s( flags 0x%02x, data %p, length %zu )\n", __FUNCTION__,
1237 permission->flags, permission->data, permission->length );
1238
1239 D_MAGIC_ASSERT( core, CoreDFB );
1240
1241 direct_mutex_lock( &core->memory_permissions_lock );
1242
1243 direct_list_remove( &core->memory_permissions, &permission->link );
1244
1245 direct_mutex_unlock( &core->memory_permissions_lock );
1246
1247 D_FREE( permission );
1248
1249 return DFB_OK;
1250 }
1251
1252 DFBResult
dfb_core_memory_permissions_check(CoreDFB * core,CoreMemoryPermissionFlags flags,void * data,size_t length)1253 dfb_core_memory_permissions_check( CoreDFB *core,
1254 CoreMemoryPermissionFlags flags,
1255 void *data,
1256 size_t length )
1257 {
1258 CoreMemoryPermission *permission;
1259
1260 D_DEBUG_AT( DirectFB_Core, "%s( flags 0x%02x, data %p, length %zu )\n", __FUNCTION__, flags, data, length );
1261
1262 D_MAGIC_ASSERT( core, CoreDFB );
1263
1264 direct_mutex_lock( &core->memory_permissions_lock );
1265
1266 direct_list_foreach (permission, core->memory_permissions) {
1267 if (permission->data <= data && permission->end >= data + length &&
1268 D_FLAGS_ARE_SET( permission->flags, flags ))
1269 {
1270 D_DEBUG_AT( DirectFB_Core, " -> found flags 0x%02x, data %p, length %zu\n",
1271 permission->flags, permission->data, permission->length );
1272
1273 direct_mutex_unlock( &core->memory_permissions_lock );
1274
1275 return DFB_OK;
1276 }
1277 }
1278
1279 direct_mutex_unlock( &core->memory_permissions_lock );
1280
1281 return DFB_ITEMNOTFOUND;
1282 }
1283
1284 /******************************************************************************/
1285
1286 static void
dfb_core_deinit_check(void * ctx)1287 dfb_core_deinit_check( void *ctx )
1288 {
1289 if (core_dfb && core_dfb->refs) {
1290 D_WARN( "Application exited without deinitialization of DirectFB!" );
1291 dfb_core_destroy( core_dfb, true );
1292 }
1293 }
1294
1295 static void
dfb_core_thread_init_handler(DirectThread * thread,void * arg)1296 dfb_core_thread_init_handler( DirectThread *thread, void *arg )
1297 {
1298 dfb_system_thread_init();
1299 }
1300
1301 static void
dfb_core_process_cleanups(CoreDFB * core,bool emergency)1302 dfb_core_process_cleanups( CoreDFB *core, bool emergency )
1303 {
1304 D_MAGIC_ASSERT( core, CoreDFB );
1305
1306 while (core->cleanups) {
1307 CoreCleanup *cleanup = (CoreCleanup*) core->cleanups;
1308
1309 core->cleanups = core->cleanups->next;
1310
1311 if (cleanup->emergency || !emergency)
1312 cleanup->func( cleanup->data, emergency );
1313
1314 D_FREE( cleanup );
1315 }
1316 }
1317
1318 static DirectSignalHandlerResult
dfb_core_signal_handler(int num,void * addr,void * ctx)1319 dfb_core_signal_handler( int num,
1320 void *addr,
1321 void *ctx )
1322 {
1323 CoreDFB *core = ctx;
1324
1325 D_ASSERT( core == core_dfb );
1326
1327 dfb_core_destroy( core, true );
1328
1329 return DSHR_OK;
1330 }
1331
1332 /******************************************************************************/
1333
1334 static int
dfb_core_shutdown(CoreDFB * core,bool emergency)1335 dfb_core_shutdown( CoreDFB *core, bool emergency )
1336 {
1337 CoreDFBShared *shared;
1338
1339 D_MAGIC_ASSERT( core, CoreDFB );
1340
1341 shared = core->shared;
1342
1343 D_MAGIC_ASSERT( shared, CoreDFBShared );
1344
1345 /* Suspend input core to stop all input threads before shutting down. */
1346 if (dfb_input_core.initialized)
1347 dfb_input_core.Suspend( dfb_input_core.data_local );
1348
1349 core->shutdown_tid = direct_gettid();
1350
1351 /* Destroy window objects. */
1352 fusion_object_pool_destroy( shared->window_pool, core->world );
1353
1354 fusion_stop_dispatcher( core->world, emergency );
1355
1356 /* Close window stacks. */
1357 if (dfb_wm_core.initialized)
1358 dfb_wm_close_all_stacks( dfb_wm_core.data_local );
1359
1360 /* Destroy layer context and region objects. */
1361 fusion_object_pool_destroy( shared->layer_region_pool, core->world );
1362 fusion_object_pool_destroy( shared->layer_context_pool, core->world );
1363
1364 /* Shutdown WM core. */
1365 dfb_core_part_shutdown( core, &dfb_wm_core, emergency );
1366
1367 /* Shutdown layer core. */
1368 dfb_core_part_shutdown( core, &dfb_layer_core, emergency );
1369 dfb_core_part_shutdown( core, &dfb_screen_core, emergency );
1370
1371 /* Destroy surface and palette objects. */
1372 fusion_object_pool_destroy( shared->graphics_state_pool, core->world );
1373 fusion_object_pool_destroy( shared->surface_pool, core->world );
1374 fusion_object_pool_destroy( shared->surface_buffer_pool, core->world );
1375 fusion_object_pool_destroy( shared->surface_allocation_pool, core->world );
1376 fusion_object_pool_destroy( shared->palette_pool, core->world );
1377
1378 /* Destroy remaining core parts. */
1379 dfb_core_part_shutdown( core, &dfb_graphics_core, emergency );
1380 dfb_core_part_shutdown( core, &dfb_surface_core, emergency );
1381 dfb_core_part_shutdown( core, &dfb_input_core, emergency );
1382 dfb_core_part_shutdown( core, &dfb_system_core, emergency );
1383 dfb_core_part_shutdown( core, &dfb_colorhash_core, emergency );
1384 dfb_core_part_shutdown( core, &dfb_clipboard_core, emergency );
1385
1386 /* Destroy shared memory pool for surface data. */
1387 fusion_shm_pool_destroy( core->world, shared->shmpool_data );
1388
1389 // FIXME: cleanup items
1390 direct_hash_destroy( core->resource.identities );
1391
1392 direct_mutex_deinit( &core->memory_permissions_lock );
1393
1394 return 0;
1395 }
1396
1397 static DFBResult
dfb_core_initialize(CoreDFB * core)1398 dfb_core_initialize( CoreDFB *core )
1399 {
1400 int i;
1401 DFBResult ret;
1402 CoreDFBShared *shared;
1403
1404 D_MAGIC_ASSERT( core, CoreDFB );
1405
1406 direct_hash_create( 23, &core->resource.identities );
1407
1408 direct_mutex_init( &core->memory_permissions_lock );
1409
1410 shared = core->shared;
1411 D_MAGIC_ASSERT( shared, CoreDFBShared );
1412
1413 ret = fusion_shm_pool_create( core->world, "DirectFB Data Pool", 0x1000000,
1414 fusion_config->debugshm, &shared->shmpool_data );
1415 if (ret)
1416 return ret;
1417
1418 shared->graphics_state_pool = dfb_graphics_state_pool_create( core->world );
1419 shared->layer_context_pool = dfb_layer_context_pool_create( core->world );
1420 shared->layer_region_pool = dfb_layer_region_pool_create( core->world );
1421 shared->palette_pool = dfb_palette_pool_create( core->world );
1422 shared->surface_pool = dfb_surface_pool_create( core->world );
1423 shared->surface_allocation_pool = dfb_surface_allocation_pool_create( core->world );
1424 shared->surface_buffer_pool = dfb_surface_buffer_pool_create( core->world );
1425 shared->window_pool = dfb_window_pool_create( core->world );
1426
1427 for (i=0; i<D_ARRAY_SIZE(core_parts); i++) {
1428 if ((ret = dfb_core_part_initialize( core, core_parts[i] ))) {
1429 dfb_core_shutdown( core, true );
1430 return ret;
1431 }
1432 }
1433
1434 if (dfb_config->resource_manager) {
1435 DirectInterfaceFuncs *funcs;
1436
1437 ret = DirectGetInterface( &funcs, "ICoreResourceManager", dfb_config->resource_manager, NULL, NULL );
1438 if (ret == DFB_OK) {
1439 void *ptr;
1440
1441 ret = funcs->Allocate( &ptr );
1442 if (ret == DFB_OK) {
1443 ret = funcs->Construct( ptr, core );
1444 if (ret == DFB_OK) {
1445 D_INFO( "Core/Resource: Using resource manager '%s'\n", dfb_config->resource_manager );
1446
1447 core->resource.manager = ptr;
1448 }
1449 else
1450 D_DERROR( ret, "Core/Resource: Failed to construct manager '%s'!\n", dfb_config->resource_manager );
1451 }
1452 else
1453 D_DERROR( ret, "Core/Resource: Failed to allocate manager '%s'!\n", dfb_config->resource_manager );
1454 }
1455 else
1456 D_DERROR( ret, "Core/Resource: Failed to load manager '%s'!\n", dfb_config->resource_manager );
1457 }
1458
1459 return DFB_OK;
1460 }
1461
1462 static int
dfb_core_leave(CoreDFB * core,bool emergency)1463 dfb_core_leave( CoreDFB *core, bool emergency )
1464 {
1465 int i;
1466
1467 D_MAGIC_ASSERT( core, CoreDFB );
1468
1469 for (i=D_ARRAY_SIZE(core_parts)-1; i>=0; i--)
1470 dfb_core_part_leave( core, core_parts[i], emergency );
1471
1472 CoreSlave_Deinit_Dispatch( &core->slave_call );
1473
1474 // FIXME: cleanup items
1475 direct_hash_destroy( core->resource.identities );
1476
1477 direct_mutex_deinit( &core->memory_permissions_lock );
1478
1479 return DFB_OK;
1480 }
1481
1482 static int
dfb_core_join(CoreDFB * core)1483 dfb_core_join( CoreDFB *core )
1484 {
1485 int i;
1486
1487 D_MAGIC_ASSERT( core, CoreDFB );
1488
1489 direct_hash_create( 23, &core->resource.identities );
1490
1491 direct_mutex_init( &core->memory_permissions_lock );
1492
1493 CoreSlave_Init_Dispatch( core, core, &core->slave_call );
1494
1495 if (fusion_config->secure_fusion)
1496 CoreDFB_Register( core, core->slave_call.call_id );
1497
1498 for (i=0; i<D_ARRAY_SIZE(core_parts); i++) {
1499 DFBResult ret;
1500
1501 if ((ret = dfb_core_part_join( core, core_parts[i] ))) {
1502 dfb_core_leave( core, true );
1503 return ret;
1504 }
1505 }
1506
1507 return DFB_OK;
1508 }
1509
1510 /******************************************************************************/
1511
1512 static void
dfb_core_leave_callback(FusionWorld * world,FusionID fusion_id,void * ctx)1513 dfb_core_leave_callback( FusionWorld *world,
1514 FusionID fusion_id,
1515 void *ctx )
1516 {
1517 Core_Resource_DisposeIdentity( fusion_id );
1518 }
1519
1520 static int
dfb_core_arena_initialize(FusionArena * arena,void * ctx)1521 dfb_core_arena_initialize( FusionArena *arena,
1522 void *ctx )
1523 {
1524 DFBResult ret;
1525 CoreDFB *core = ctx;
1526 CoreDFBShared *shared;
1527 FusionSHMPoolShared *pool;
1528
1529 D_MAGIC_ASSERT( core, CoreDFB );
1530
1531 D_DEBUG_AT( DirectFB_Core, "Initializing...\n" );
1532
1533 /* Create the shared memory pool first! */
1534 ret = fusion_shm_pool_create( core->world, "DirectFB Main Pool", 0x400000,
1535 fusion_config->debugshm, &pool );
1536 if (ret)
1537 return ret;
1538
1539 /* Allocate shared structure in the new pool. */
1540 shared = SHCALLOC( pool, 1, sizeof(CoreDFBShared) );
1541 if (!shared) {
1542 fusion_shm_pool_destroy( core->world, pool );
1543 return D_OOSHM();
1544 }
1545
1546 core->shared = shared;
1547 core->master = true;
1548
1549 shared->shmpool = pool;
1550 shared->secure = fusion_config->secure_fusion;
1551
1552 D_MAGIC_SET( shared, CoreDFBShared );
1553
1554 /* Initialize. */
1555 ret = dfb_core_initialize( core );
1556 if (ret) {
1557 D_MAGIC_CLEAR( shared );
1558 SHFREE( pool, shared );
1559 fusion_shm_pool_destroy( core->world, pool );
1560 return ret;
1561 }
1562
1563 fusion_skirmish_init( &shared->lock, "DirectFB Core", core->world );
1564
1565 fusion_skirmish_add_permissions( &shared->lock, 0,
1566 FUSION_SKIRMISH_PERMIT_PREVAIL |
1567 FUSION_SKIRMISH_PERMIT_DISMISS |
1568 FUSION_SKIRMISH_PERMIT_WAIT );
1569
1570 CoreDFB_Init_Dispatch( core, core, &shared->call );
1571
1572 fusion_call_add_permissions( &shared->call, 0, FUSION_CALL_PERMIT_EXECUTE );
1573
1574 fusion_world_set_leave_callback( core->world, dfb_core_leave_callback, NULL );
1575
1576 /* Register shared data. */
1577 fusion_arena_add_shared_field( arena, "Core/Shared", shared );
1578
1579 return DFB_OK;
1580 }
1581
1582 static int
dfb_core_arena_shutdown(FusionArena * arena,void * ctx,bool emergency)1583 dfb_core_arena_shutdown( FusionArena *arena,
1584 void *ctx,
1585 bool emergency)
1586 {
1587 DFBResult ret;
1588 CoreDFB *core = ctx;
1589 CoreDFBShared *shared;
1590 FusionSHMPoolShared *pool;
1591
1592 D_MAGIC_ASSERT( core, CoreDFB );
1593
1594 shared = core->shared;
1595
1596 D_MAGIC_ASSERT( shared, CoreDFBShared );
1597
1598 pool = shared->shmpool;
1599
1600 D_DEBUG_AT( DirectFB_Core, "Shutting down...\n" );
1601
1602 if (!core->master) {
1603 D_WARN( "refusing shutdown in slave" );
1604 return dfb_core_leave( core, emergency );
1605 }
1606
1607 CoreDFB_Deinit_Dispatch( &shared->call );
1608
1609 /* Shutdown. */
1610 ret = dfb_core_shutdown( core, emergency );
1611
1612 fusion_skirmish_destroy( &shared->lock );
1613
1614 D_MAGIC_CLEAR( shared );
1615
1616 SHFREE( pool, shared );
1617
1618 fusion_shm_pool_destroy( core->world, pool );
1619
1620 return ret;
1621 }
1622
1623 static int
dfb_core_arena_join(FusionArena * arena,void * ctx)1624 dfb_core_arena_join( FusionArena *arena,
1625 void *ctx )
1626 {
1627 DFBResult ret;
1628 CoreDFB *core = ctx;
1629 void *field;
1630
1631 D_MAGIC_ASSERT( core, CoreDFB );
1632
1633 D_DEBUG_AT( DirectFB_Core, "Joining...\n" );
1634
1635 /* Get shared data. */
1636 if (fusion_arena_get_shared_field( arena, "Core/Shared", &field ))
1637 return DFB_FUSION;
1638
1639 core->shared = field;
1640
1641 if (fusion_config->secure_fusion != core->shared->secure) {
1642 D_ERROR( "DirectFB/Core: Local secure-fusion config (%d) does not match with running session (%d)!\n",
1643 fusion_config->secure_fusion, core->shared->secure );
1644
1645 return DFB_UNSUPPORTED;
1646 }
1647
1648 /* Join. */
1649 ret = dfb_core_join( core );
1650 if (ret)
1651 return ret;
1652
1653 return DFB_OK;
1654 }
1655
1656 static int
dfb_core_arena_leave(FusionArena * arena,void * ctx,bool emergency)1657 dfb_core_arena_leave( FusionArena *arena,
1658 void *ctx,
1659 bool emergency)
1660 {
1661 DFBResult ret;
1662 CoreDFB *core = ctx;
1663
1664 D_MAGIC_ASSERT( core, CoreDFB );
1665
1666 D_DEBUG_AT( DirectFB_Core, "Leaving...\n" );
1667
1668 /* Leave. */
1669 ret = dfb_core_leave( core, emergency );
1670 if (ret)
1671 return ret;
1672
1673 return DFB_OK;
1674 }
1675
1676 /*********************************************************************************************************************/
1677
1678 #define CORE_TLS_IDENTITY_STACK_MAX 8
1679
1680 typedef struct {
1681 int magic;
1682
1683 FusionID identity[CORE_TLS_IDENTITY_STACK_MAX];
1684 unsigned int identity_count;
1685
1686 int calling;
1687 } CoreTLS;
1688
1689 static pthread_key_t core_tls_key;
1690
1691 static void
core_tls_destroy(void * arg)1692 core_tls_destroy( void *arg )
1693 {
1694 CoreTLS *core_tls = arg;
1695
1696 D_MAGIC_ASSERT( core_tls, CoreTLS );
1697
1698 D_MAGIC_CLEAR( core_tls );
1699
1700 D_FREE( core_tls );
1701 }
1702
1703 __attribute__((constructor))
1704 void
Core_TLS__init(void)1705 Core_TLS__init( void )
1706 {
1707 pthread_key_create( &core_tls_key, core_tls_destroy );
1708 }
1709
1710 __attribute__((destructor))
1711 void
Core_TLS__deinit(void)1712 Core_TLS__deinit( void )
1713 {
1714 pthread_key_delete( core_tls_key );
1715 }
1716
1717
1718 static CoreTLS *
Core_GetTLS(void)1719 Core_GetTLS( void )
1720 {
1721 CoreTLS *core_tls;
1722
1723 core_tls = pthread_getspecific( core_tls_key );
1724 if (!core_tls) {
1725 core_tls = D_CALLOC( 1, sizeof(CoreTLS) );
1726 if (!core_tls) {
1727 D_OOM();
1728 return NULL;
1729 }
1730
1731 D_MAGIC_SET( core_tls, CoreTLS );
1732
1733 pthread_setspecific( core_tls_key, core_tls );
1734 }
1735
1736 D_MAGIC_ASSERT( core_tls, CoreTLS );
1737
1738 return core_tls;
1739 }
1740
1741 void
Core_PushIdentity(FusionID caller)1742 Core_PushIdentity( FusionID caller )
1743 {
1744 CoreTLS *core_tls = Core_GetTLS();
1745
1746 if (core_tls) {
1747 core_tls->identity_count++;
1748
1749 if (core_tls->identity_count <= CORE_TLS_IDENTITY_STACK_MAX)
1750 core_tls->identity[core_tls->identity_count-1] = caller ? caller : core_dfb->fusion_id;
1751 else
1752 D_WARN( "identity stack overflow" );
1753 }
1754 else
1755 D_WARN( "TLS error" );
1756 }
1757
1758 void
Core_PopIdentity()1759 Core_PopIdentity()
1760 {
1761 CoreTLS *core_tls = Core_GetTLS();
1762
1763 if (core_tls) {
1764 D_ASSERT( core_tls->identity_count > 0 );
1765
1766 if (core_tls->identity_count > 0)
1767 core_tls->identity_count--;
1768 else
1769 D_BUG( "no identity" );
1770 }
1771 else
1772 D_WARN( "TLS error" );
1773 }
1774
1775 FusionID
Core_GetIdentity()1776 Core_GetIdentity()
1777 {
1778 CoreTLS *core_tls = Core_GetTLS();
1779
1780 if (core_tls) {
1781 if (core_tls->identity_count == 0) {
1782 D_ASSERT( core_dfb != NULL );
1783
1784 D_ASSUME( core_dfb->fusion_id != 0 );
1785
1786 return core_dfb->fusion_id;
1787 }
1788
1789 if (core_tls->identity_count <= CORE_TLS_IDENTITY_STACK_MAX)
1790 return core_tls->identity[core_tls->identity_count-1];
1791
1792 D_WARN( "wrong identity due to overflow" );
1793
1794 return core_tls->identity[CORE_TLS_IDENTITY_STACK_MAX-1];
1795 }
1796
1797 D_WARN( "TLS error" );
1798
1799 return 0;
1800 }
1801
1802 void
Core_PushCalling(void)1803 Core_PushCalling( void )
1804 {
1805 CoreTLS *core_tls = Core_GetTLS();
1806
1807 if (core_tls)
1808 core_tls->calling++;
1809 else
1810 D_WARN( "TLS error" );
1811 }
1812
1813 void
Core_PopCalling(void)1814 Core_PopCalling( void )
1815 {
1816 CoreTLS *core_tls = Core_GetTLS();
1817
1818 if (core_tls) {
1819 if (core_tls->calling == 0) {
1820 D_BUG( "" );
1821 return;
1822 }
1823
1824 core_tls->calling--;
1825 }
1826 else
1827 D_WARN( "TLS error" );
1828 }
1829
1830 int
Core_GetCalling(void)1831 Core_GetCalling( void )
1832 {
1833 CoreTLS *core_tls = Core_GetTLS();
1834
1835 if (core_tls)
1836 return core_tls->calling;
1837
1838 D_WARN( "TLS error" );
1839
1840 return 0;
1841 }
1842
1843
1844 D_DEBUG_DOMAIN( Core_Resource, "Core/Resource", "Core Resource" );
1845
1846 DFBResult
Core_Resource_CheckSurface(const CoreSurfaceConfig * config,CoreSurfaceTypeFlags type,u64 resource_id,CorePalette * palette)1847 Core_Resource_CheckSurface( const CoreSurfaceConfig *config,
1848 CoreSurfaceTypeFlags type,
1849 u64 resource_id,
1850 CorePalette *palette )
1851 {
1852 ICoreResourceClient *client;
1853
1854 D_DEBUG_AT( Core_Resource, "%s( %dx%d, %s, type %d, resource id %llu ) <- identity %lu\n", __FUNCTION__, config->size.w, config->size.h,
1855 dfb_pixelformat_name( config->format ), type, resource_id, Core_GetIdentity() );
1856
1857 if (Core_GetIdentity() == core_dfb->fusion_id)
1858 return DFB_OK;
1859
1860 if (core_dfb->resource.manager) {
1861 client = Core_Resource_GetClient( Core_GetIdentity() );
1862 if (!client)
1863 return DFB_DEAD;
1864
1865 return client->CheckSurface( client, config, type, resource_id, palette );
1866 }
1867
1868 return DFB_OK;
1869 }
1870
1871 DFBResult
Core_Resource_CheckSurfaceUpdate(CoreSurface * surface,const CoreSurfaceConfig * config)1872 Core_Resource_CheckSurfaceUpdate( CoreSurface *surface,
1873 const CoreSurfaceConfig *config )
1874 {
1875 ICoreResourceClient *client;
1876
1877 D_DEBUG_AT( Core_Resource, "%s( %dx%d, %s, type %d, resource id %lu ) <- identity %lu\n", __FUNCTION__, config->size.w, config->size.h,
1878 dfb_pixelformat_name( config->format ), surface->type, surface->resource_id, surface->object.identity );
1879
1880 if (surface->object.identity == core_dfb->fusion_id)
1881 return DFB_OK;
1882
1883 if (core_dfb->resource.manager) {
1884 client = Core_Resource_GetClient( surface->object.identity );
1885 if (!client)
1886 return DFB_DEAD;
1887
1888 return client->CheckSurfaceUpdate( client, surface, config );
1889 }
1890
1891 return DFB_OK;
1892 }
1893
1894 DFBResult
Core_Resource_AddSurface(CoreSurface * surface)1895 Core_Resource_AddSurface( CoreSurface *surface )
1896 {
1897 ICoreResourceClient *client;
1898
1899 D_DEBUG_AT( Core_Resource, "%s( %dx%d, %s, type %d, resource id %lu ) <- identity %lu\n", __FUNCTION__, surface->config.size.w, surface->config.size.h,
1900 dfb_pixelformat_name( surface->config.format ), surface->type, surface->resource_id, Core_GetIdentity() );
1901
1902 if (surface->object.identity == core_dfb->fusion_id)
1903 return DFB_OK;
1904
1905 if (core_dfb->resource.manager) {
1906 client = Core_Resource_GetClient( surface->object.identity );
1907 if (!client)
1908 return DFB_DEAD;
1909
1910 return client->AddSurface( client, surface );
1911 }
1912
1913 return DFB_OK;
1914 }
1915
1916 DFBResult
Core_Resource_RemoveSurface(CoreSurface * surface)1917 Core_Resource_RemoveSurface( CoreSurface *surface )
1918 {
1919 ICoreResourceClient *client;
1920
1921 D_DEBUG_AT( Core_Resource, "%s( %dx%d, %s, type %d, resource id %lu ) <- identity %lu\n", __FUNCTION__, surface->config.size.w, surface->config.size.h,
1922 dfb_pixelformat_name( surface->config.format ), surface->type, surface->resource_id, surface->object.identity );
1923
1924 if (surface->object.identity == core_dfb->fusion_id)
1925 return DFB_OK;
1926
1927 if (core_dfb->resource.manager) {
1928 client = Core_Resource_GetClient( surface->object.identity );
1929 if (!client)
1930 return DFB_DEAD;
1931
1932 return client->RemoveSurface( client, surface );
1933 }
1934
1935 return DFB_OK;
1936 }
1937
1938 DFBResult
Core_Resource_UpdateSurface(CoreSurface * surface,const CoreSurfaceConfig * config)1939 Core_Resource_UpdateSurface( CoreSurface *surface,
1940 const CoreSurfaceConfig *config )
1941 {
1942 ICoreResourceClient *client;
1943
1944 D_DEBUG_AT( Core_Resource, "%s( %dx%d, %s, type %d, resource id %zu ) <- identity %lu\n", __FUNCTION__, config->size.w, config->size.h,
1945 dfb_pixelformat_name( config->format ), surface->type, surface->resource_id, surface->object.identity );
1946
1947 if (surface->object.identity == core_dfb->fusion_id)
1948 return DFB_OK;
1949
1950 if (core_dfb->resource.manager) {
1951 client = Core_Resource_GetClient( surface->object.identity );
1952 if (!client)
1953 return DFB_DEAD;
1954
1955 return client->UpdateSurface( client, surface, config );
1956 }
1957
1958 return DFB_OK;
1959 }
1960
1961
1962 struct __Core__CoreResourceCleanup {
1963 DirectLink link;
1964
1965 int magic;
1966
1967 FusionID fusion_id;
1968
1969 CoreResourceCleanupCallback callback;
1970 void *ctx;
1971 void *ctx2;
1972 };
1973
1974 typedef struct {
1975 ICoreResourceClient *client;
1976
1977 CoreSlave slave;
1978
1979 DirectLink *cleanups;
1980 } ResourceIdentity;
1981
1982 DFBResult
Core_Resource_AddIdentity(FusionID fusion_id,u32 slave_call)1983 Core_Resource_AddIdentity( FusionID fusion_id,
1984 u32 slave_call )
1985 {
1986 DFBResult ret;
1987 ResourceIdentity *identity;
1988 char buf[512] = { 0 };
1989 size_t len;
1990 FusionID call_owner;
1991
1992 D_DEBUG_AT( Core_Resource, "%s( %lu )\n", __FUNCTION__, fusion_id );
1993
1994 fusion_get_fusionee_path( core_dfb->world, fusion_id, buf, 512, &len );
1995
1996 D_INFO( "Core/Resource: Adding ID %lu - '%s'\n", fusion_id, buf );
1997
1998 identity = direct_hash_lookup( core_dfb->resource.identities, fusion_id );
1999 if (identity) {
2000 D_BUG( "alredy registered" );
2001 return DFB_BUSY;
2002 }
2003
2004 identity = D_CALLOC( 1, sizeof(ResourceIdentity) );
2005 if (!identity)
2006 return D_OOM();
2007
2008 fusion_call_init_from( &identity->slave.call, slave_call, dfb_core_world(core_dfb) );
2009
2010 ret = fusion_call_get_owner( &identity->slave.call, &call_owner );
2011 if (ret) {
2012 D_FREE( identity );
2013 return ret;
2014 }
2015
2016 if (call_owner != fusion_id) {
2017 D_ERROR( "Core/Resource: Slave call owner (%lu) does not match new identity (%lu)!\n", call_owner, fusion_id );
2018 D_FREE( identity );
2019 return ret;
2020 }
2021
2022 if (core_dfb->resource.manager) {
2023 ret = core_dfb->resource.manager->CreateClient( core_dfb->resource.manager, fusion_id, &identity->client );
2024 if (ret) {
2025 D_DERROR( ret, "Core/Resource: ICoreResourceManager::CreateClient() failed!\n" );
2026 D_FREE( identity );
2027 return ret;
2028 }
2029 }
2030
2031 ret = direct_hash_insert( core_dfb->resource.identities, fusion_id, identity );
2032 if (ret) {
2033 D_DERROR( ret, "Core/Resource: Could not insert identity into hash table!\n" );
2034
2035 if (identity->client)
2036 identity->client->Release( identity->client );
2037
2038 D_FREE( identity );
2039 }
2040
2041 return ret;
2042 }
2043
2044 void
Core_Resource_DisposeIdentity(FusionID fusion_id)2045 Core_Resource_DisposeIdentity( FusionID fusion_id )
2046 {
2047 ResourceIdentity *identity;
2048
2049 D_DEBUG_AT( Core_Resource, "%s( %lu )\n", __FUNCTION__, fusion_id );
2050
2051 identity = direct_hash_lookup( core_dfb->resource.identities, fusion_id );
2052 if (identity) {
2053 CoreResourceCleanup *cleanup, *next;
2054
2055 direct_list_foreach_safe (cleanup, next, identity->cleanups) {
2056 D_MAGIC_ASSERT( cleanup, CoreResourceCleanup );
2057
2058 D_DEBUG_AT( Core_Resource, " -> running cleanup callback %p\n", cleanup->callback );
2059 D_DEBUG_AT( Core_Resource, " -> '%s'\n", direct_trace_lookup_symbol_at( cleanup->callback ) );
2060
2061 cleanup->callback( cleanup->ctx, cleanup->ctx2 );
2062
2063 D_MAGIC_CLEAR( cleanup );
2064
2065 D_FREE( cleanup );
2066 }
2067
2068 if (identity->client)
2069 identity->client->Release( identity->client );
2070
2071 direct_hash_remove( core_dfb->resource.identities, fusion_id );
2072
2073 D_FREE( identity );
2074 }
2075 }
2076
2077
2078 ICoreResourceClient *
Core_Resource_GetClient(FusionID fusion_id)2079 Core_Resource_GetClient( FusionID fusion_id )
2080 {
2081 ResourceIdentity *identity;
2082
2083 D_DEBUG_AT( Core_Resource, "%s( %lu )\n", __FUNCTION__, fusion_id );
2084
2085 identity = direct_hash_lookup( core_dfb->resource.identities, fusion_id );
2086 if (identity)
2087 return identity->client;
2088
2089 return NULL;
2090 }
2091
2092 CoreSlave *
Core_Resource_GetSlave(FusionID fusion_id)2093 Core_Resource_GetSlave( FusionID fusion_id )
2094 {
2095 ResourceIdentity *identity;
2096
2097 D_DEBUG_AT( Core_Resource, "%s( %lu )\n", __FUNCTION__, fusion_id );
2098
2099 identity = direct_hash_lookup( core_dfb->resource.identities, fusion_id );
2100 if (identity)
2101 return &identity->slave;
2102
2103 return NULL;
2104 }
2105
2106 DFBResult
Core_Resource_AddCleanup(FusionID fusion_id,CoreResourceCleanupCallback callback,void * ctx,void * ctx2,CoreResourceCleanup ** ret_cleanup)2107 Core_Resource_AddCleanup( FusionID fusion_id,
2108 CoreResourceCleanupCallback callback,
2109 void *ctx,
2110 void *ctx2,
2111 CoreResourceCleanup **ret_cleanup )
2112 {
2113 ResourceIdentity *identity;
2114 CoreResourceCleanup *cleanup;
2115
2116 D_DEBUG_AT( Core_Resource, "%s( %lu, %p )\n", __FUNCTION__, fusion_id, callback );
2117
2118 D_ASSERT( fusion_id != 0 );
2119 D_ASSERT( callback != NULL );
2120
2121 identity = direct_hash_lookup( core_dfb->resource.identities, fusion_id );
2122 if (!identity)
2123 return DFB_DEAD;
2124
2125 cleanup = D_CALLOC( 1, sizeof(CoreResourceCleanup) );
2126 if (!cleanup)
2127 return D_OOM();
2128
2129 cleanup->fusion_id = fusion_id;
2130 cleanup->callback = callback;
2131 cleanup->ctx = ctx;
2132 cleanup->ctx2 = ctx2;
2133
2134 D_MAGIC_SET( cleanup, CoreResourceCleanup );
2135
2136 direct_list_append( &identity->cleanups, &cleanup->link );
2137
2138 *ret_cleanup = cleanup;
2139
2140 return DFB_OK;
2141 }
2142
2143 DFBResult
Core_Resource_DisposeCleanup(CoreResourceCleanup * cleanup)2144 Core_Resource_DisposeCleanup( CoreResourceCleanup *cleanup )
2145 {
2146 ResourceIdentity *identity;
2147
2148 D_DEBUG_AT( Core_Resource, "%s( %p )\n", __FUNCTION__, cleanup );
2149
2150 D_MAGIC_ASSERT( cleanup, CoreResourceCleanup );
2151
2152 identity = direct_hash_lookup( core_dfb->resource.identities, cleanup->fusion_id );
2153 if (!identity)
2154 return DFB_DEAD;
2155
2156 direct_list_remove( &identity->cleanups, &cleanup->link );
2157
2158 D_MAGIC_CLEAR( cleanup );
2159
2160 D_FREE( cleanup );
2161
2162 return DFB_OK;
2163 }
2164
2165