summaryrefslogtreecommitdiff
path: root/Source/DirectFB/systems/osx/primary.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DirectFB/systems/osx/primary.c')
-rwxr-xr-xSource/DirectFB/systems/osx/primary.c623
1 files changed, 623 insertions, 0 deletions
diff --git a/Source/DirectFB/systems/osx/primary.c b/Source/DirectFB/systems/osx/primary.c
new file mode 100755
index 0000000..0d0cac6
--- /dev/null
+++ b/Source/DirectFB/systems/osx/primary.c
@@ -0,0 +1,623 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include <directfb.h>
+
+#include <fusion/shmalloc.h>
+#include <fusion/fusion.h>
+
+#include <core/core.h>
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+#include <core/layers.h>
+#include <core/palette.h>
+#include <core/surface.h>
+#include <core/system.h>
+
+#include <gfx/convert.h>
+
+#include <misc/conf.h>
+
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+
+#include <ApplicationServices/ApplicationServices.h>
+
+#include "osx.h"
+#include "primary.h"
+
+extern DFBOSX *dfb_osx;
+extern CoreDFB *dfb_osx_core;
+
+/******************************************************************************/
+
+static DFBResult dfb_osx_set_video_mode( CoreDFB *core, CoreLayerRegionConfig *config );
+static DFBResult dfb_osx_update_screen( CoreDFB *core, DFBRegion *region );
+static DFBResult dfb_osx_set_palette( CorePalette *palette );
+
+static DFBResult update_screen( CoreSurface *surface,
+ int x, int y, int w, int h );
+
+static CGDirectDisplayID screen = NULL;
+
+/******************************************************************************/
+
+static DFBResult
+primaryInitScreen( CoreScreen *screen,
+ GraphicsDevice *device,
+ void *driver_data,
+ void *screen_data,
+ DFBScreenDescription *description )
+{
+ /* Set the screen capabilities. */
+ description->caps = DSCCAPS_NONE;
+
+ /* Set the screen name. */
+ snprintf( description->name,
+ DFB_SCREEN_DESC_NAME_LENGTH, "OSX Primary Screen" );
+
+ return DFB_OK;
+}
+
+static DFBResult
+primaryGetScreenSize( CoreScreen *screen,
+ void *driver_data,
+ void *screen_data,
+ int *ret_width,
+ int *ret_height )
+{
+ D_ASSERT( dfb_osx != NULL );
+
+ if (dfb_osx->primary) {
+ *ret_width = dfb_osx->primary->width;
+ *ret_height = dfb_osx->primary->height;
+ }
+ else {
+ if (dfb_config->mode.width)
+ *ret_width = dfb_config->mode.width;
+ else
+ *ret_width = 640;
+
+ if (dfb_config->mode.height)
+ *ret_height = dfb_config->mode.height;
+ else
+ *ret_height = 480;
+ }
+
+ return DFB_OK;
+}
+
+ScreenFuncs osxPrimaryScreenFuncs = {
+ .InitScreen = primaryInitScreen,
+ .GetScreenSize = primaryGetScreenSize,
+};
+
+/******************************************************************************/
+
+static int
+primaryLayerDataSize( void )
+{
+ return 0;
+}
+
+static int
+primaryRegionDataSize( void )
+{
+ return 0;
+}
+
+static DFBResult
+primaryInitLayer( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ DFBDisplayLayerDescription *description,
+ DFBDisplayLayerConfig *config,
+ DFBColorAdjustment *adjustment )
+{
+ /* set capabilities and type */
+ description->caps = DLCAPS_SURFACE;
+ description->type = DLTF_GRAPHICS;
+
+ /* set name */
+ snprintf( description->name,
+ DFB_DISPLAY_LAYER_DESC_NAME_LENGTH, "OSX Primary Layer" );
+
+ /* fill out the default configuration */
+ config->flags = DLCONF_WIDTH | DLCONF_HEIGHT |
+ DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE;
+ config->buffermode = DLBM_FRONTONLY;
+
+ if (dfb_config->mode.width)
+ config->width = dfb_config->mode.width;
+ else
+ config->width = 640;
+
+ if (dfb_config->mode.height)
+ config->height = dfb_config->mode.height;
+ else
+ config->height = 480;
+
+ if (dfb_config->mode.format != DSPF_UNKNOWN)
+ config->pixelformat = dfb_config->mode.format;
+ else if (dfb_config->mode.depth > 0)
+ config->pixelformat = dfb_pixelformat_for_depth( dfb_config->mode.depth );
+ else
+ config->pixelformat = DSPF_ARGB1555;
+
+ return DFB_OK;
+}
+
+static DFBResult
+primaryTestRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ CoreLayerRegionConfig *config,
+ CoreLayerRegionConfigFlags *failed )
+{
+ CoreLayerRegionConfigFlags fail = 0;
+
+ switch (config->buffermode) {
+ case DLBM_FRONTONLY:
+ case DLBM_BACKSYSTEM:
+ case DLBM_BACKVIDEO:
+ break;
+
+ default:
+ fail |= CLRCF_BUFFERMODE;
+ break;
+ }
+
+ if (config->options)
+ fail |= CLRCF_OPTIONS;
+
+ if (failed)
+ *failed = fail;
+
+ if (fail)
+ return DFB_UNSUPPORTED;
+
+ return DFB_OK;
+}
+
+static DFBResult
+primaryAddRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreLayerRegionConfig *config )
+{
+ return DFB_OK;
+}
+
+static DFBResult
+primarySetRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreLayerRegionConfig *config,
+ CoreLayerRegionConfigFlags updated,
+ CoreSurface *surface,
+ CorePalette *palette )
+{
+ DFBResult ret;
+
+ if (surface)
+ dfb_osx->primary = surface;
+
+ ret = dfb_osx_set_video_mode( dfb_osx_core, config );
+ if (ret)
+ return ret;
+
+ if (palette)
+ dfb_osx_set_palette( palette );
+
+ return DFB_OK;
+}
+
+static DFBResult
+primaryRemoveRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data )
+{
+ dfb_osx->primary = NULL;
+
+ return DFB_OK;
+}
+
+static DFBResult
+primaryFlipRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreSurface *surface,
+ DFBSurfaceFlipFlags flags )
+{
+ dfb_surface_flip_buffers( surface, false );
+
+ return dfb_osx_update_screen( dfb_osx_core, NULL );
+}
+
+static DFBResult
+primaryUpdateRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreSurface *surface,
+ const DFBRegion *update )
+{
+
+ if (surface && (surface->caps & DSCAPS_FLIPPING)) {
+ if (update) {
+ DFBRegion region = *update;
+
+ return dfb_osx_update_screen( dfb_osx_core, &region );
+ }
+ else
+ return dfb_osx_update_screen( dfb_osx_core, NULL );
+ }
+
+ return DFB_OK;
+}
+
+static DFBResult
+primaryAllocateSurface( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreLayerRegionConfig *config,
+ CoreSurface **ret_surface )
+{
+ DFBSurfaceCapabilities caps = DSCAPS_SYSTEMONLY;
+
+ if (config->buffermode != DLBM_FRONTONLY) {
+ caps |= DSCAPS_DOUBLE;
+ return dfb_surface_create( NULL, config->width, config->height,
+ config->format, CSP_SYSTEMONLY,
+ caps, NULL, ret_surface );
+ }
+ else {
+ DFBResult ret;
+ CoreSurface *surface = NULL;
+
+ surface = dfb_core_create_surface( NULL );
+ if (!surface)
+ return DFB_FAILURE;
+
+ /* reallocation just needs an allocated buffer structure */
+ surface->idle_buffer = surface->back_buffer = surface->front_buffer
+ = SHCALLOC( dfb_core_shmpool(dfb_osx_core), 1, sizeof(SurfaceBuffer) );
+
+ surface->front_buffer->policy = CSP_SYSTEMONLY;
+ surface->front_buffer->format = config->format;
+
+ *ret_surface = surface;
+
+ ret = dfb_surface_init( NULL, surface,
+ config->width, config->height,
+ config->format, caps, NULL );
+
+ if (ret)
+ return ret;
+
+ /* activate object */
+ fusion_object_activate( &surface->object );
+
+ return ret;
+ }
+}
+
+static DFBResult
+primaryReallocateSurface( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreLayerRegionConfig *config,
+ CoreSurface *surface )
+{
+ DFBResult ret;
+
+ /* FIXME: write surface management functions
+ for easier configuration changes */
+ switch (config->buffermode) {
+ case DLBM_BACKVIDEO:
+ case DLBM_BACKSYSTEM:
+ surface->caps |= DSCAPS_DOUBLE;
+
+ ret = dfb_surface_reconfig( surface,
+ CSP_SYSTEMONLY, CSP_SYSTEMONLY );
+ break;
+
+ case DLBM_FRONTONLY:
+ surface->caps &= ~DSCAPS_DOUBLE;
+
+ ret = dfb_surface_reconfig( surface,
+ CSP_SYSTEMONLY, CSP_SYSTEMONLY );
+ break;
+
+ default:
+ D_BUG("unknown buffermode");
+ return DFB_BUG;
+ }
+ if (ret)
+ return ret;
+
+ ret = dfb_surface_reformat( NULL, surface, config->width,
+ config->height, config->format );
+ if (ret)
+ return ret;
+
+
+ if (DFB_PIXELFORMAT_IS_INDEXED(config->format) && !surface->palette) {
+ DFBResult ret;
+ CorePalette *palette;
+
+ ret = dfb_palette_create( NULL, /* FIXME */
+ 1 << DFB_COLOR_BITS_PER_PIXEL( config->format ),
+ &palette );
+ if (ret)
+ return ret;
+
+ if (config->format == DSPF_LUT8)
+ dfb_palette_generate_rgb332_map( palette );
+
+ dfb_surface_set_palette( surface, palette );
+
+ dfb_palette_unref( palette );
+ }
+
+ return DFB_OK;
+}
+
+DisplayLayerFuncs osxPrimaryLayerFuncs = {
+ .LayerDataSize = primaryLayerDataSize,
+ .RegionDataSize = primaryRegionDataSize,
+ .InitLayer = primaryInitLayer,
+
+ .TestRegion = primaryTestRegion,
+ .AddRegion = primaryAddRegion,
+ .SetRegion = primarySetRegion,
+ .RemoveRegion = primaryRemoveRegion,
+ .FlipRegion = primaryFlipRegion,
+ .UpdateRegion = primaryUpdateRegion,
+
+ .AllocateSurface = primaryAllocateSurface,
+ .ReallocateSurface = primaryReallocateSurface,
+};
+
+/******************************************************************************/
+
+static DFBResult
+update_screen( CoreSurface *surface, int x, int y, int w, int h )
+{
+ int i;
+ void *dst;
+ void *src;
+ int pitch;
+ int dst_pitch;
+ DFBResult ret;
+
+ D_ASSERT( surface != NULL );
+ ret = dfb_surface_soft_lock( dfb_osx_core, surface, DSLF_READ, &src, &pitch, true );
+ if (ret) {
+ D_ERROR( "DirectFB/OSX: Couldn't lock layer surface: %s\n",
+ DirectFBErrorString( ret ) );
+ return ret;
+ }
+
+ dst = CGDisplayBaseAddress( screen );
+ dst_pitch = CGDisplayBytesPerRow( screen );
+ src += DFB_BYTES_PER_LINE( surface->config.format, x ) + y * pitch;
+ dst += DFB_BYTES_PER_LINE( surface->config.format, x ) + y * dst_pitch;
+
+ for (i=0; i<h; ++i) {
+ direct_memcpy( dst, src, DFB_BYTES_PER_LINE( surface->config.format, w ) );
+
+ src += pitch;
+ dst += dst_pitch;
+ }
+
+ dfb_surface_unlock( surface, true );
+
+ return DFB_OK;
+}
+
+/******************************************************************************/
+
+typedef enum {
+ OSX_SET_VIDEO_MODE,
+ OSX_UPDATE_SCREEN,
+ OSX_SET_PALETTE
+} DFBOSXCall;
+
+static DFBResult
+dfb_osx_set_video_mode_handler( CoreLayerRegionConfig *config )
+{
+ boolean_t exactMatch;
+ CFDictionaryRef mode;
+
+ fusion_skirmish_prevail( &dfb_osx->lock );
+
+ mode = CGDisplayBestModeForParameters( screen, DFB_BITS_PER_PIXEL(config->format),
+ config->width, config->height, &exactMatch);
+ if (!mode || !exactMatch)
+ {
+ D_ERROR( "DirectFB/OSX: Couldn't set %dx%dx%d video mode.\n",
+ config->width, config->height,
+ DFB_COLOR_BITS_PER_PIXEL(config->format));
+
+ fusion_skirmish_dismiss( &dfb_osx->lock );
+
+ return DFB_FAILURE;
+ }
+ CGDisplaySwitchToMode( screen, mode );
+ CGDisplayCapture(screen);
+
+ if (config->buffermode == DLBM_FRONTONLY) {
+ /* update primary surface information */
+ dfb_osx->primary->front_buffer->system.addr = CGDisplayBaseAddress( screen );
+ dfb_osx->primary->front_buffer->system.pitch = CGDisplayBytesPerRow( screen );
+ }
+ fusion_skirmish_dismiss( &dfb_osx->lock );
+
+ return DFB_OK;
+}
+
+static DFBResult
+dfb_osx_update_screen_handler( DFBRegion *region )
+{
+ DFBResult ret;
+ CoreSurface *surface = dfb_osx->primary;
+
+ fusion_skirmish_prevail( &dfb_osx->lock );
+
+ if (!region)
+ ret = update_screen( surface, 0, 0, surface->config.size.w, surface->config.size.h );
+ else
+ ret = update_screen( surface,
+ region->x1, region->y1,
+ region->x2 - region->x1 + 1,
+ region->y2 - region->y1 + 1 );
+
+ fusion_skirmish_dismiss( &dfb_osx->lock );
+
+ return DFB_OK;
+}
+
+static DFBResult
+dfb_osx_set_palette_handler( CorePalette *palette )
+{
+ fusion_skirmish_prevail( &dfb_osx->lock );
+
+// do something usefull
+ fusion_skirmish_dismiss( &dfb_osx->lock );
+
+ return DFB_OK;
+}
+
+FusionCallHandlerResult
+dfb_osx_call_handler( int caller,
+ int call_arg,
+ void *call_ptr,
+ void *ctx,
+ unsigned int serial,
+ int *ret_val )
+{
+ switch (call_arg) {
+ case OSX_SET_VIDEO_MODE:
+ *ret_val = dfb_osx_set_video_mode_handler( call_ptr );
+ break;
+
+ case OSX_UPDATE_SCREEN:
+ *ret_val = dfb_osx_update_screen_handler( call_ptr );
+ break;
+
+ case OSX_SET_PALETTE:
+ *ret_val = dfb_osx_set_palette_handler( call_ptr );
+ break;
+
+ default:
+ D_BUG( "unknown call" );
+ *ret_val = DFB_BUG;
+ break;
+ }
+
+ return FCHR_RETURN;
+}
+
+static DFBResult
+dfb_osx_set_video_mode( CoreDFB *core, CoreLayerRegionConfig *config )
+{
+ int ret;
+ CoreLayerRegionConfig *tmp = NULL;
+
+ D_ASSERT( config != NULL );
+
+ if (dfb_core_is_master( core ))
+ return dfb_osx_set_video_mode_handler( config );
+
+ if (!fusion_is_shared( dfb_core_world(core), config )) {
+ tmp = SHMALLOC( dfb_core_shmpool(dfb_osx_core), sizeof(CoreLayerRegionConfig) );
+ if (!tmp)
+ return D_OOSHM();
+
+ direct_memcpy( tmp, config, sizeof(CoreLayerRegionConfig) );
+ }
+
+ fusion_call_execute( &dfb_osx->call, FCEF_NONE, OSX_SET_VIDEO_MODE,
+ tmp ? tmp : config, &ret );
+
+ if (tmp)
+ SHFREE( dfb_core_shmpool(dfb_osx_core), tmp );
+
+ return ret;
+}
+
+static DFBResult
+dfb_osx_update_screen( CoreDFB *core, DFBRegion *region )
+{
+ int ret;
+ DFBRegion *tmp = NULL;
+
+ if (dfb_core_is_master( core ))
+ return dfb_osx_update_screen_handler( region );
+
+ if (region) {
+ if (!fusion_is_shared( dfb_core_world(core), region )) {
+ tmp = SHMALLOC( dfb_core_shmpool(dfb_osx_core), sizeof(DFBRegion) );
+ if (!tmp)
+ return D_OOSHM();
+
+ direct_memcpy( tmp, region, sizeof(DFBRegion) );
+ }
+ }
+
+ fusion_call_execute( &dfb_osx->call, FCEF_ONEWAY, OSX_UPDATE_SCREEN,
+ tmp ? tmp : region, &ret );
+
+ if (tmp)
+ SHFREE( dfb_core_shmpool(dfb_osx_core), tmp );
+
+ return ret;
+}
+
+static DFBResult
+dfb_osx_set_palette( CorePalette *palette )
+{
+ int ret;
+
+ fusion_call_execute( &dfb_osx->call, FCEF_NONE, OSX_SET_PALETTE,
+ palette, &ret );
+
+ return ret;
+}
+