summaryrefslogtreecommitdiff
path: root/Source/DirectFB/src/core/palette.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DirectFB/src/core/palette.c')
-rwxr-xr-xSource/DirectFB/src/core/palette.c317
1 files changed, 317 insertions, 0 deletions
diff --git a/Source/DirectFB/src/core/palette.c b/Source/DirectFB/src/core/palette.c
new file mode 100755
index 0000000..3d66a54
--- /dev/null
+++ b/Source/DirectFB/src/core/palette.c
@@ -0,0 +1,317 @@
+/*
+ (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 <directfb.h>
+
+#include <fusion/shmalloc.h>
+
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+
+#include <core/core.h>
+#include <core/surface.h>
+#include <core/gfxcard.h>
+#include <core/palette.h>
+#include <core/colorhash.h>
+
+#include <gfx/convert.h>
+
+#include <misc/util.h>
+
+D_DEBUG_DOMAIN( Core_Palette, "Core/Palette", "DirectFB Palette Core" );
+
+/**********************************************************************************************************************/
+
+static const u8 lookup3to8[] = { 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff };
+static const u8 lookup2to8[] = { 0x00, 0x55, 0xaa, 0xff };
+
+static const ReactionFunc dfb_palette_globals[] = {
+/* 0 */ _dfb_surface_palette_listener,
+ NULL
+};
+
+/**********************************************************************************************************************/
+
+static void palette_destructor( FusionObject *object, bool zombie, void *ctx )
+{
+ CorePaletteNotification notification;
+ CorePalette *palette = (CorePalette*) object;
+
+ D_MAGIC_ASSERT( palette, CorePalette );
+
+ D_DEBUG_AT( Core_Palette, "destroying %p (%d)%s\n", palette,
+ palette->num_entries, zombie ? " (ZOMBIE)" : "");
+
+ D_ASSERT( palette->entries != NULL );
+ D_ASSERT( palette->entries_yuv != NULL );
+
+ notification.flags = CPNF_DESTROY;
+ notification.palette = palette;
+
+ dfb_palette_dispatch( palette, &notification, dfb_palette_globals );
+
+ if (palette->hash_attached) {
+ dfb_colorhash_invalidate( NULL, palette );
+ dfb_colorhash_detach( NULL, palette );
+ }
+
+ SHFREE( palette->shmpool, palette->entries_yuv );
+ SHFREE( palette->shmpool, palette->entries );
+
+ D_MAGIC_CLEAR( palette );
+
+ fusion_object_destroy( object );
+}
+
+FusionObjectPool *
+dfb_palette_pool_create( const FusionWorld *world )
+{
+ FusionObjectPool *pool;
+
+ pool = fusion_object_pool_create( "Palette Pool",
+ sizeof(CorePalette),
+ sizeof(CorePaletteNotification),
+ palette_destructor, NULL, world );
+
+ return pool;
+}
+
+/**********************************************************************************************************************/
+
+DFBResult
+dfb_palette_create( CoreDFB *core,
+ unsigned int size,
+ CorePalette **ret_palette )
+{
+ CorePalette *palette;
+
+ D_DEBUG_AT( Core_Palette, "%s( %d )\n", __FUNCTION__, size );
+
+ D_ASSERT( ret_palette );
+
+ palette = dfb_core_create_palette( core );
+ if (!palette)
+ return DFB_FUSION;
+
+ palette->shmpool = dfb_core_shmpool( core );
+
+ if (size) {
+ palette->entries = SHCALLOC( palette->shmpool, size, sizeof(DFBColor) );
+ if (!palette->entries) {
+ fusion_object_destroy( &palette->object );
+ return D_OOSHM();
+ }
+
+ palette->entries_yuv = SHCALLOC( palette->shmpool, size, sizeof(DFBColorYUV) );
+ if (!palette->entries_yuv) {
+ SHFREE( palette->shmpool, palette->entries );
+ fusion_object_destroy( &palette->object );
+ return D_OOSHM();
+ }
+ }
+
+ palette->num_entries = size;
+
+ /* reset cache */
+ palette->search_cache.index = -1;
+
+ D_MAGIC_SET( palette, CorePalette );
+
+ /* activate object */
+ fusion_object_activate( &palette->object );
+
+ /* return the new palette */
+ *ret_palette = palette;
+
+ D_DEBUG_AT( Core_Palette, " -> %p\n", palette );
+
+ return DFB_OK;
+}
+
+void
+dfb_palette_generate_rgb332_map( CorePalette *palette )
+{
+ unsigned int i;
+
+ D_DEBUG_AT( Core_Palette, "%s( %p )\n", __FUNCTION__, palette );
+
+ D_MAGIC_ASSERT( palette, CorePalette );
+
+ if (!palette->num_entries)
+ return;
+
+ for (i=0; i<palette->num_entries; i++) {
+ palette->entries[i].a = i ? 0xff : 0x00;
+ palette->entries[i].r = lookup3to8[ (i & 0xE0) >> 5 ];
+ palette->entries[i].g = lookup3to8[ (i & 0x1C) >> 2 ];
+ palette->entries[i].b = lookup2to8[ (i & 0x03) ];
+
+ palette->entries_yuv[i].a = palette->entries[i].a;
+
+ RGB_TO_YCBCR( palette->entries[i].r, palette->entries[i].g, palette->entries[i].b,
+ palette->entries_yuv[i].y, palette->entries_yuv[i].u, palette->entries_yuv[i].v );
+ }
+
+ dfb_palette_update( palette, 0, palette->num_entries - 1 );
+}
+
+void
+dfb_palette_generate_rgb121_map( CorePalette *palette )
+{
+ unsigned int i;
+
+ D_DEBUG_AT( Core_Palette, "%s( %p )\n", __FUNCTION__, palette );
+
+ D_MAGIC_ASSERT( palette, CorePalette );
+
+ if (!palette->num_entries)
+ return;
+
+ for (i=0; i<palette->num_entries; i++) {
+ palette->entries[i].a = i ? 0xff : 0x00;
+ palette->entries[i].r = (i & 0x8) ? 0xff : 0x00;
+ palette->entries[i].g = lookup2to8[ (i & 0x6) >> 1 ];
+ palette->entries[i].b = (i & 0x1) ? 0xff : 0x00;
+
+ palette->entries_yuv[i].a = palette->entries[i].a;
+
+ RGB_TO_YCBCR( palette->entries[i].r, palette->entries[i].g, palette->entries[i].b,
+ palette->entries_yuv[i].y, palette->entries_yuv[i].u, palette->entries_yuv[i].v );
+ }
+
+ dfb_palette_update( palette, 0, palette->num_entries - 1 );
+}
+
+unsigned int
+dfb_palette_search( CorePalette *palette,
+ u8 r,
+ u8 g,
+ u8 b,
+ u8 a )
+{
+ unsigned int index;
+
+ D_MAGIC_ASSERT( palette, CorePalette );
+
+ /* check local cache first */
+ if (palette->search_cache.index != -1 &&
+ palette->search_cache.color.a == a &&
+ palette->search_cache.color.r == r &&
+ palette->search_cache.color.g == g &&
+ palette->search_cache.color.b == b)
+ return palette->search_cache.index;
+
+ /* check the global color hash table, returns the closest match */
+ if (!palette->hash_attached) {
+ dfb_colorhash_attach( NULL, palette );
+ palette->hash_attached = true;
+ }
+
+ index = dfb_colorhash_lookup( NULL, palette, r, g, b, a );
+
+ /* write into local cache */
+ palette->search_cache.index = index;
+ palette->search_cache.color.a = a;
+ palette->search_cache.color.r = r;
+ palette->search_cache.color.g = g;
+ palette->search_cache.color.b = b;
+
+ return index;
+}
+
+void
+dfb_palette_update( CorePalette *palette, int first, int last )
+{
+ CorePaletteNotification notification;
+
+ D_DEBUG_AT( Core_Palette, "%s( %p, %d, %d )\n", __FUNCTION__, palette, first, last );
+
+ D_MAGIC_ASSERT( palette, CorePalette );
+ D_ASSERT( first >= 0 );
+ D_ASSERT( first < palette->num_entries );
+ D_ASSERT( last >= 0 );
+ D_ASSERT( last < palette->num_entries );
+ D_ASSERT( first <= last );
+
+ notification.flags = CPNF_ENTRIES;
+ notification.palette = palette;
+ notification.first = first;
+ notification.last = last;
+
+ /* reset cache */
+ if (palette->search_cache.index >= first &&
+ palette->search_cache.index <= last)
+ palette->search_cache.index = -1;
+
+ /* invalidate entries in colorhash */
+ if (palette->hash_attached)
+ dfb_colorhash_invalidate( NULL, palette );
+
+ /* post message about palette update */
+ dfb_palette_dispatch( palette, &notification, dfb_palette_globals );
+}
+
+bool
+dfb_palette_equal( CorePalette *palette1, CorePalette *palette2 )
+{
+ u32 *entries1;
+ u32 *entries2;
+ int i;
+
+ D_DEBUG_AT( Core_Palette, "%s( %p, %p )\n", __FUNCTION__, palette1, palette2 );
+
+ D_ASSERT( palette1 != NULL );
+ D_ASSERT( palette2 != NULL );
+
+ if (palette1 == palette2) {
+ D_DEBUG_AT( Core_Palette, " -> SAME\n" );
+ return true;
+ }
+
+ if (palette1->num_entries != palette2->num_entries) {
+ D_DEBUG_AT( Core_Palette, " -> NOT EQUAL (%d/%d)\n", palette1->num_entries, palette2->num_entries );
+ return false;
+ }
+
+ entries1 = (u32*)palette1->entries;
+ entries2 = (u32*)palette2->entries;
+
+ for (i = 0; i < palette1->num_entries; i++) {
+ if (entries1[i] != entries2[i]) {
+ D_DEBUG_AT( Core_Palette, " -> NOT EQUAL (%d)\n", i );
+ return false;
+ }
+ }
+
+ D_DEBUG_AT( Core_Palette, " -> EQUAL\n" );
+
+ return true;
+}
+