From 7fe60435bce6595a9c58a9bfd8244d74b5320e96 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 15 Jan 2013 08:46:13 +0100 Subject: Import DirectFB141_2k11R3_beta5 --- Source/DirectFB/src/core/colorhash.c | 366 +++++++++++++++++++++++++++++++++++ 1 file changed, 366 insertions(+) create mode 100755 Source/DirectFB/src/core/colorhash.c (limited to 'Source/DirectFB/src/core/colorhash.c') diff --git a/Source/DirectFB/src/core/colorhash.c b/Source/DirectFB/src/core/colorhash.c new file mode 100755 index 0000000..370697d --- /dev/null +++ b/Source/DirectFB/src/core/colorhash.c @@ -0,0 +1,366 @@ +/* + (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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include + + +D_DEBUG_DOMAIN( Core_ColorHash, "Core/ColorHash", "DirectFB ColorHash Core" ); + + +#define HASH_SIZE 823 + +typedef struct { + unsigned int pixel; + unsigned int index; + CorePalette *palette; +} Colorhash; + +/**********************************************************************************************************************/ + +typedef struct { + int magic; + + Colorhash *hash; + unsigned int hash_users; + FusionSkirmish hash_lock; + + FusionSHMPoolShared *shmpool; +} DFBColorHashCoreShared; + +struct __DFB_DFBColorHashCore { + int magic; + + CoreDFB *core; + + DFBColorHashCoreShared *shared; +}; + +DFB_CORE_PART( colorhash_core, ColorHashCore ); + +/**********************************************************************************************************************/ + +static DFBColorHashCore *core_colorhash; /* FIXME */ + + +static DFBResult +dfb_colorhash_core_initialize( CoreDFB *core, + DFBColorHashCore *data, + DFBColorHashCoreShared *shared ) +{ + D_DEBUG_AT( Core_ColorHash, "dfb_colorhash_core_initialize( %p, %p, %p )\n", core, data, shared ); + + D_ASSERT( data != NULL ); + D_ASSERT( shared != NULL ); + + core_colorhash = data; /* FIXME */ + + data->core = core; + data->shared = shared; + + shared->shmpool = dfb_core_shmpool( core ); + + fusion_skirmish_init( &shared->hash_lock, "Colorhash Core", dfb_core_world(core) ); + + D_MAGIC_SET( data, DFBColorHashCore ); + D_MAGIC_SET( shared, DFBColorHashCoreShared ); + + return DFB_OK; +} + +static DFBResult +dfb_colorhash_core_join( CoreDFB *core, + DFBColorHashCore *data, + DFBColorHashCoreShared *shared ) +{ + D_DEBUG_AT( Core_ColorHash, "dfb_colorhash_core_join( %p, %p, %p )\n", core, data, shared ); + + D_ASSERT( data != NULL ); + D_MAGIC_ASSERT( shared, DFBColorHashCoreShared ); + + core_colorhash = data; /* FIXME */ + + data->core = core; + data->shared = shared; + + D_MAGIC_SET( data, DFBColorHashCore ); + + return DFB_OK; +} + +static DFBResult +dfb_colorhash_core_shutdown( DFBColorHashCore *data, + bool emergency ) +{ + DFBColorHashCoreShared *shared; + + D_DEBUG_AT( Core_ColorHash, "dfb_colorhash_core_shutdown( %p, %semergency )\n", data, emergency ? "" : "no " ); + + D_MAGIC_ASSERT( data, DFBColorHashCore ); + D_MAGIC_ASSERT( data->shared, DFBColorHashCoreShared ); + + shared = data->shared; + + fusion_skirmish_destroy( &shared->hash_lock ); + + D_MAGIC_CLEAR( data ); + D_MAGIC_CLEAR( shared ); + + return DFB_OK; +} + +static DFBResult +dfb_colorhash_core_leave( DFBColorHashCore *data, + bool emergency ) +{ + DFBColorHashCoreShared *shared; + + D_DEBUG_AT( Core_ColorHash, "dfb_colorhash_core_leave( %p, %semergency )\n", data, emergency ? "" : "no " ); + + D_MAGIC_ASSERT( data, DFBColorHashCore ); + D_MAGIC_ASSERT( data->shared, DFBColorHashCoreShared ); + + shared = data->shared; + + D_MAGIC_CLEAR( data ); + + return DFB_OK; +} + +static DFBResult +dfb_colorhash_core_suspend( DFBColorHashCore *data ) +{ + DFBColorHashCoreShared *shared; + + D_DEBUG_AT( Core_ColorHash, "dfb_colorhash_core_suspend( %p )\n", data ); + + D_MAGIC_ASSERT( data, DFBColorHashCore ); + D_MAGIC_ASSERT( data->shared, DFBColorHashCoreShared ); + + shared = data->shared; + + return DFB_OK; +} + +static DFBResult +dfb_colorhash_core_resume( DFBColorHashCore *data ) +{ + DFBColorHashCoreShared *shared; + + D_DEBUG_AT( Core_ColorHash, "dfb_colorhash_core_resume( %p )\n", data ); + + D_MAGIC_ASSERT( data, DFBColorHashCore ); + D_MAGIC_ASSERT( data->shared, DFBColorHashCoreShared ); + + shared = data->shared; + + return DFB_OK; +} + +/**********************************************************************************************************************/ + +void +dfb_colorhash_attach( DFBColorHashCore *core, + CorePalette *palette ) +{ + DFBColorHashCoreShared *shared; + + D_ASSUME( core != NULL ); + + if (core) { + D_MAGIC_ASSERT( core, DFBColorHashCore ); + D_MAGIC_ASSERT( core->shared, DFBColorHashCoreShared ); + } + else + core = core_colorhash; + + shared = core->shared; + + fusion_skirmish_prevail( &shared->hash_lock ); + + if (!shared->hash) { + D_ASSERT( shared->hash_users == 0 ); + + shared->hash = SHCALLOC( shared->shmpool, HASH_SIZE, sizeof (Colorhash) ); + } + + shared->hash_users++; + + fusion_skirmish_dismiss( &shared->hash_lock ); +} + +void +dfb_colorhash_detach( DFBColorHashCore *core, + CorePalette *palette ) +{ + DFBColorHashCoreShared *shared; + + D_ASSUME( core != NULL ); + + if (core) { + D_MAGIC_ASSERT( core, DFBColorHashCore ); + D_MAGIC_ASSERT( core->shared, DFBColorHashCoreShared ); + } + else + core = core_colorhash; + + shared = core->shared; + + D_ASSERT( shared->hash_users > 0 ); + D_ASSERT( shared->hash != NULL ); + + fusion_skirmish_prevail( &shared->hash_lock ); + + shared->hash_users--; + + if (!shared->hash_users) { + /* no more users, free allocated resources */ + SHFREE( shared->shmpool, shared->hash ); + shared->hash = NULL; + } + + fusion_skirmish_dismiss( &shared->hash_lock ); +} + +unsigned int +dfb_colorhash_lookup( DFBColorHashCore *core, + CorePalette *palette, + u8 r, + u8 g, + u8 b, + u8 a ) +{ + unsigned int pixel = PIXEL_ARGB(a, r, g, b); + unsigned int index = (pixel ^ (unsigned long) palette) % HASH_SIZE; + DFBColorHashCoreShared *shared; + +// D_ASSUME( core != NULL ); + + if (core) { + D_MAGIC_ASSERT( core, DFBColorHashCore ); + D_MAGIC_ASSERT( core->shared, DFBColorHashCoreShared ); + } + else + core = core_colorhash; + + shared = core->shared; + + D_ASSERT( shared->hash != NULL ); + + fusion_skirmish_prevail( &shared->hash_lock ); + + /* try a lookup in the hash table */ + if (shared->hash[index].palette == palette && shared->hash[index].pixel == pixel) { + /* set the return value */ + index = shared->hash[index].index; + } else { /* look for the closest match */ + DFBColor *entries = palette->entries; + int min_diff = 0; + unsigned int i, min_index = 0; + + for (i = 0; i < palette->num_entries; i++) { + int diff; + + int r_diff = (int) entries[i].r - (int) r; + int g_diff = (int) entries[i].g - (int) g; + int b_diff = (int) entries[i].b - (int) b; + int a_diff = (int) entries[i].a - (int) a; + + if (a) + diff = (r_diff * r_diff + g_diff * g_diff + + b_diff * b_diff + ((a_diff * a_diff) >> 6)); + else + diff = (r_diff + g_diff + b_diff + (a_diff * a_diff)); + + if (i == 0 || diff < min_diff) { + min_diff = diff; + min_index = i; + } + + if (!diff) + break; + } + + /* store the matching entry in the hash table */ + shared->hash[index].pixel = pixel; + shared->hash[index].index = min_index; + shared->hash[index].palette = palette; + + /* set the return value */ + index = min_index; + } + + fusion_skirmish_dismiss( &shared->hash_lock ); + + return index; +} + +void +dfb_colorhash_invalidate( DFBColorHashCore *core, + CorePalette *palette ) +{ + unsigned int index = HASH_SIZE - 1; + DFBColorHashCoreShared *shared; + + D_ASSUME( core != NULL ); + + if (core) { + D_MAGIC_ASSERT( core, DFBColorHashCore ); + D_MAGIC_ASSERT( core->shared, DFBColorHashCoreShared ); + } + else + core = core_colorhash; + + shared = core->shared; + + D_ASSERT( shared->hash != NULL ); + + fusion_skirmish_prevail( &shared->hash_lock ); + + /* invalidate all entries owned by this palette */ + do { + if (shared->hash[index].palette == palette) + shared->hash[index].palette = NULL; + } while (index--); + + fusion_skirmish_dismiss( &shared->hash_lock ); +} + -- cgit