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