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/misc/util.c | 471 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 471 insertions(+) create mode 100755 Source/DirectFB/src/misc/util.c (limited to 'Source/DirectFB/src/misc/util.c') diff --git a/Source/DirectFB/src/misc/util.c b/Source/DirectFB/src/misc/util.c new file mode 100755 index 0000000..7a80eec --- /dev/null +++ b/Source/DirectFB/src/misc/util.c @@ -0,0 +1,471 @@ +/* + (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( DFB_Updates, "DirectFB/Updates", "DirectFB Updates" ); + +/**********************************************************************************************************************/ + +const DirectFBPixelFormatNames( dfb_pixelformat_names ); + +/**********************************************************************************************************************/ + +bool +dfb_region_intersect( DFBRegion *region, + int x1, int y1, int x2, int y2 ) +{ + if (region->x2 < x1 || + region->y2 < y1 || + region->x1 > x2 || + region->y1 > y2) + return false; + + if (region->x1 < x1) + region->x1 = x1; + + if (region->y1 < y1) + region->y1 = y1; + + if (region->x2 > x2) + region->x2 = x2; + + if (region->y2 > y2) + region->y2 = y2; + + return true; +} + +bool +dfb_region_region_intersect( DFBRegion *region, + const DFBRegion *clip ) +{ + if (region->x2 < clip->x1 || + region->y2 < clip->y1 || + region->x1 > clip->x2 || + region->y1 > clip->y2) + return false; + + if (region->x1 < clip->x1) + region->x1 = clip->x1; + + if (region->y1 < clip->y1) + region->y1 = clip->y1; + + if (region->x2 > clip->x2) + region->x2 = clip->x2; + + if (region->y2 > clip->y2) + region->y2 = clip->y2; + + return true; +} + +bool +dfb_region_rectangle_intersect( DFBRegion *region, + const DFBRectangle *rect ) +{ + int x2 = rect->x + rect->w - 1; + int y2 = rect->y + rect->h - 1; + + if (region->x2 < rect->x || + region->y2 < rect->y || + region->x1 > x2 || + region->y1 > y2) + return false; + + if (region->x1 < rect->x) + region->x1 = rect->x; + + if (region->y1 < rect->y) + region->y1 = rect->y; + + if (region->x2 > x2) + region->x2 = x2; + + if (region->y2 > y2) + region->y2 = y2; + + return true; +} + +bool +dfb_unsafe_region_intersect( DFBRegion *region, + int x1, int y1, int x2, int y2 ) +{ + if (region->x1 > region->x2) { + int temp = region->x1; + region->x1 = region->x2; + region->x2 = temp; + } + + if (region->y1 > region->y2) { + int temp = region->y1; + region->y1 = region->y2; + region->y2 = temp; + } + + return dfb_region_intersect( region, x1, y1, x2, y2 ); +} + +bool +dfb_unsafe_region_rectangle_intersect( DFBRegion *region, + const DFBRectangle *rect ) +{ + if (region->x1 > region->x2) { + int temp = region->x1; + region->x1 = region->x2; + region->x2 = temp; + } + + if (region->y1 > region->y2) { + int temp = region->y1; + region->y1 = region->y2; + region->y2 = temp; + } + + return dfb_region_rectangle_intersect( region, rect ); +} + +bool +dfb_rectangle_intersect_by_unsafe_region( DFBRectangle *rectangle, + DFBRegion *region ) +{ + /* validate region */ + if (region->x1 > region->x2) { + int temp = region->x1; + region->x1 = region->x2; + region->x2 = temp; + } + + if (region->y1 > region->y2) { + int temp = region->y1; + region->y1 = region->y2; + region->y2 = temp; + } + + /* adjust position */ + if (region->x1 > rectangle->x) { + rectangle->w -= region->x1 - rectangle->x; + rectangle->x = region->x1; + } + + if (region->y1 > rectangle->y) { + rectangle->h -= region->y1 - rectangle->y; + rectangle->y = region->y1; + } + + /* adjust size */ + if (region->x2 < rectangle->x + rectangle->w - 1) + rectangle->w = region->x2 - rectangle->x + 1; + + if (region->y2 < rectangle->y + rectangle->h - 1) + rectangle->h = region->y2 - rectangle->y + 1; + + /* set size to zero if there's no intersection */ + if (rectangle->w <= 0 || rectangle->h <= 0) { + rectangle->w = 0; + rectangle->h = 0; + + return false; + } + + return true; +} + +bool +dfb_rectangle_intersect_by_region( DFBRectangle *rectangle, + const DFBRegion *region ) +{ + /* adjust position */ + if (region->x1 > rectangle->x) { + rectangle->w -= region->x1 - rectangle->x; + rectangle->x = region->x1; + } + + if (region->y1 > rectangle->y) { + rectangle->h -= region->y1 - rectangle->y; + rectangle->y = region->y1; + } + + /* adjust size */ + if (region->x2 < rectangle->x + rectangle->w - 1) + rectangle->w = region->x2 - rectangle->x + 1; + + if (region->y2 < rectangle->y + rectangle->h - 1) + rectangle->h = region->y2 - rectangle->y + 1; + + /* set size to zero if there's no intersection */ + if (rectangle->w <= 0 || rectangle->h <= 0) { + rectangle->w = 0; + rectangle->h = 0; + + return false; + } + + return true; +} + +bool dfb_rectangle_intersect( DFBRectangle *rectangle, + const DFBRectangle *clip ) +{ + DFBRegion region = { clip->x, clip->y, + clip->x + clip->w - 1, clip->y + clip->h - 1 }; + + /* adjust position */ + if (region.x1 > rectangle->x) { + rectangle->w -= region.x1 - rectangle->x; + rectangle->x = region.x1; + } + + if (region.y1 > rectangle->y) { + rectangle->h -= region.y1 - rectangle->y; + rectangle->y = region.y1; + } + + /* adjust size */ + if (region.x2 < rectangle->x + rectangle->w - 1) + rectangle->w = region.x2 - rectangle->x + 1; + + if (region.y2 < rectangle->y + rectangle->h - 1) + rectangle->h = region.y2 - rectangle->y + 1; + + /* set size to zero if there's no intersection */ + if (rectangle->w <= 0 || rectangle->h <= 0) { + rectangle->w = 0; + rectangle->h = 0; + + return false; + } + + return true; +} + +void dfb_rectangle_union ( DFBRectangle *rect1, + const DFBRectangle *rect2 ) +{ + if (!rect2->w || !rect2->h) + return; + + /* FIXME: OPTIMIZE */ + + if (rect1->w) { + int temp = MIN (rect1->x, rect2->x); + rect1->w = MAX (rect1->x + rect1->w, rect2->x + rect2->w) - temp; + rect1->x = temp; + } + else { + rect1->x = rect2->x; + rect1->w = rect2->w; + } + + if (rect1->h) { + int temp = MIN (rect1->y, rect2->y); + rect1->h = MAX (rect1->y + rect1->h, rect2->y + rect2->h) - temp; + rect1->y = temp; + } + else { + rect1->y = rect2->y; + rect1->h = rect2->h; + } +} + +void +dfb_updates_init( DFBUpdates *updates, + DFBRegion *regions, + int max_regions ) +{ + D_ASSERT( updates != NULL ); + D_ASSERT( regions != NULL ); + D_ASSERT( max_regions > 0 ); + + updates->regions = regions; + updates->max_regions = max_regions; + updates->num_regions = 0; + + D_MAGIC_SET( updates, DFBUpdates ); +} + +void +dfb_updates_add( DFBUpdates *updates, + const DFBRegion *region ) +{ + int i; + + D_MAGIC_ASSERT( updates, DFBUpdates ); + DFB_REGION_ASSERT( region ); + D_ASSERT( updates->regions != NULL ); + D_ASSERT( updates->num_regions >= 0 ); + D_ASSERT( updates->num_regions <= updates->max_regions ); + + D_DEBUG_AT( DFB_Updates, "%s( %p, %4d,%4d-%4dx%4d )\n", __FUNCTION__, updates, + DFB_RECTANGLE_VALS_FROM_REGION(region) ); + + if (updates->num_regions == 0) { + D_DEBUG_AT( DFB_Updates, " -> added as first\n" ); + + updates->regions[0] = updates->bounding = *region; + updates->num_regions = 1; + + return; + } + + for (i=0; inum_regions; i++) { + if (dfb_region_region_extends( &updates->regions[i], region ) || + dfb_region_region_intersects( &updates->regions[i], region )) + { + D_DEBUG_AT( DFB_Updates, " -> combined with [%d] %4d,%4d-%4dx%4d\n", i, + DFB_RECTANGLE_VALS_FROM_REGION(&updates->regions[i]) ); + + dfb_region_region_union( &updates->regions[i], region ); + + dfb_region_region_union( &updates->bounding, region ); + + D_DEBUG_AT( DFB_Updates, " -> resulting in [%d] %4d,%4d-%4dx%4d\n", i, + DFB_RECTANGLE_VALS_FROM_REGION(&updates->regions[i]) ); + + return; + } + } + + if (updates->num_regions == updates->max_regions) { + dfb_region_region_union( &updates->bounding, region ); + + updates->regions[0] = updates->bounding; + updates->num_regions = 1; + + D_DEBUG_AT( DFB_Updates, " -> collapsing to [0] %4d,%4d-%4dx%4d\n", + DFB_RECTANGLE_VALS_FROM_REGION(&updates->regions[0]) ); + } + else { + updates->regions[updates->num_regions++] = *region; + + dfb_region_region_union( &updates->bounding, region ); + + D_DEBUG_AT( DFB_Updates, " -> added as [%d] %4d,%4d-%4dx%4d\n", updates->num_regions - 1, + DFB_RECTANGLE_VALS_FROM_REGION(&updates->regions[updates->num_regions - 1]) ); + } +} + +void +dfb_updates_stat( DFBUpdates *updates, + int *ret_total, + int *ret_bounding ) +{ + int i; + + D_MAGIC_ASSERT( updates, DFBUpdates ); + D_ASSERT( updates->regions != NULL ); + D_ASSERT( updates->num_regions >= 0 ); + D_ASSERT( updates->num_regions <= updates->max_regions ); + + if (updates->num_regions == 0) { + if (ret_total) + *ret_total = 0; + + if (ret_bounding) + *ret_bounding = 0; + + return; + } + + if (ret_total) { + int total = 0; + + for (i=0; inum_regions; i++) { + const DFBRegion *r = &updates->regions[i]; + + total += (r->x2 - r->x1 + 1) * (r->y2 - r->y1 + 1); + } + + *ret_total = total; + } + + if (ret_bounding) + *ret_bounding = (updates->bounding.x2 - updates->bounding.x1 + 1) * + (updates->bounding.y2 - updates->bounding.y1 + 1); +} + +void +dfb_updates_get_rectangles( DFBUpdates *updates, + DFBRectangle *ret_rects, + int *ret_num ) +{ + D_MAGIC_ASSERT( updates, DFBUpdates ); + D_ASSERT( updates->regions != NULL ); + D_ASSERT( updates->num_regions >= 0 ); + D_ASSERT( updates->num_regions <= updates->max_regions ); + + switch (updates->num_regions) { + case 0: + *ret_num = 0; + break; + + default: { + int n, d, total, bounding; + + dfb_updates_stat( updates, &total, &bounding ); + + n = updates->max_regions - updates->num_regions + 1; + d = n + 1; + + /* Try to optimize updates. Use individual regions only if not too much overhead. */ + if (total < bounding * n / d) { + *ret_num = updates->num_regions; + + for (n=0; nnum_regions; n++) + ret_rects[n] = DFB_RECTANGLE_INIT_FROM_REGION( &updates->regions[n] ); + + break; + } + } + /* fall through */ + + case 1: + *ret_num = 1; + *ret_rects = DFB_RECTANGLE_INIT_FROM_REGION( &updates->bounding ); + break; + } +} -- cgit