103b705cfSriastradh/* 203b705cfSriastradh * Copyright © 1998 Keith Packard 303b705cfSriastradh * Copyright © 2012 Intel Corporation 403b705cfSriastradh * 503b705cfSriastradh * Permission to use, copy, modify, distribute, and sell this software and its 603b705cfSriastradh * documentation for any purpose is hereby granted without fee, provided that 703b705cfSriastradh * the above copyright notice appear in all copies and that both that 803b705cfSriastradh * copyright notice and this permission notice appear in supporting 903b705cfSriastradh * documentation, and that the name of Keith Packard not be used in 1003b705cfSriastradh * advertising or publicity pertaining to distribution of the software without 1103b705cfSriastradh * specific, written prior permission. Keith Packard makes no 1203b705cfSriastradh * representations about the suitability of this software for any purpose. It 1303b705cfSriastradh * is provided "as is" without express or implied warranty. 1403b705cfSriastradh * 1503b705cfSriastradh * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1603b705cfSriastradh * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1703b705cfSriastradh * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1803b705cfSriastradh * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1903b705cfSriastradh * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 2003b705cfSriastradh * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 2103b705cfSriastradh * PERFORMANCE OF THIS SOFTWARE. 2203b705cfSriastradh */ 2303b705cfSriastradh 2403b705cfSriastradh#include <stdlib.h> 2503b705cfSriastradh 2603b705cfSriastradh#include "fb.h" 2703b705cfSriastradh 2803b705cfSriastradhstatic Bool region_grow(RegionPtr region) 2903b705cfSriastradh{ 3003b705cfSriastradh RegDataPtr data; 3103b705cfSriastradh int n; 3203b705cfSriastradh 3303b705cfSriastradh n = 16; 3403b705cfSriastradh if (!region->data) { 3503b705cfSriastradh region->data = malloc(RegionSizeof(n)); 3603b705cfSriastradh if (!region->data) 3703b705cfSriastradh return RegionBreak(region); 3803b705cfSriastradh region->data->numRects = 1; 3903b705cfSriastradh *RegionBoxptr(region) = region->extents; 4003b705cfSriastradh } else if (!region->data->size) { 4103b705cfSriastradh region->data = malloc(RegionSizeof(n)); 4203b705cfSriastradh if (!region->data) 4303b705cfSriastradh return RegionBreak(region); 4403b705cfSriastradh region->data->numRects = 0; 4503b705cfSriastradh } else { 4603b705cfSriastradh n = 2 * region->data->numRects; 4703b705cfSriastradh data = (RegDataPtr) realloc(region->data, RegionSizeof(n)); 4803b705cfSriastradh if (!data) 4903b705cfSriastradh return RegionBreak(region); 5003b705cfSriastradh region->data = data; 5103b705cfSriastradh } 5203b705cfSriastradh region->data->size = n; 5303b705cfSriastradh return TRUE; 5403b705cfSriastradh} 5503b705cfSriastradh 5603b705cfSriastradhstatic inline void add(RegionPtr region, 5703b705cfSriastradh int16_t x1, int16_t y1, int16_t x2, int16_t y2) 5803b705cfSriastradh{ 5903b705cfSriastradh BoxPtr r; 6003b705cfSriastradh 6103b705cfSriastradh if (region->data->numRects == region->data->size && 6203b705cfSriastradh !region_grow(region)) 6303b705cfSriastradh return; 6403b705cfSriastradh 6503b705cfSriastradh r = RegionBoxptr(region) + region->data->numRects++; 6603b705cfSriastradh r->x1 = x1; r->y1 = y1; 6703b705cfSriastradh r->x2 = x2; r->y2 = y2; 6803b705cfSriastradh 6903b705cfSriastradh DBG(("%s[%ld/%ld]: (%d, %d), (%d, %d)\n", 7003b705cfSriastradh __FUNCTION__, 7103b705cfSriastradh (long)region->data->numRects, (long)region->data->size, 7203b705cfSriastradh x1, y1, x2, y2)); 7303b705cfSriastradh 7403b705cfSriastradh if (x1 < region->extents.x1) 7503b705cfSriastradh region->extents.x1 = x1; 7603b705cfSriastradh if (x2 > region->extents.x2) 7703b705cfSriastradh region->extents.x2 = x2; 7803b705cfSriastradh} 7903b705cfSriastradh 8003b705cfSriastradh#define MASK_0 (FB_ALLONES & ~FbScrRight(FB_ALLONES, 1)) 8103b705cfSriastradh 8203b705cfSriastradh/* Convert bitmap clip mask into clipping region. 8303b705cfSriastradh * First, goes through each line and makes boxes by noting the transitions 8403b705cfSriastradh * from 0 to 1 and 1 to 0. 8503b705cfSriastradh * Then it coalesces the current line with the previous if they have boxes 8603b705cfSriastradh * at the same X coordinates. 8703b705cfSriastradh */ 8803b705cfSriastradhRegionPtr 8903b705cfSriastradhfbBitmapToRegion(PixmapPtr pixmap) 9003b705cfSriastradh{ 9103b705cfSriastradh FbBits maskw; 9203b705cfSriastradh register RegionPtr region; 9303b705cfSriastradh const FbBits *bits, *line, *end; 9403b705cfSriastradh int width, y1, y2, base, x1; 9503b705cfSriastradh int stride, i; 9603b705cfSriastradh 9703b705cfSriastradh DBG(("%s bitmap=%dx%d\n", __FUNCTION__, 9803b705cfSriastradh pixmap->drawable.width, pixmap->drawable.height)); 9903b705cfSriastradh 10003b705cfSriastradh region = RegionCreate(NULL, 1); 10103b705cfSriastradh if (!region) 10203b705cfSriastradh return NullRegion; 10303b705cfSriastradh 10403b705cfSriastradh line = (FbBits *) pixmap->devPrivate.ptr; 10503b705cfSriastradh stride = pixmap->devKind >> (FB_SHIFT - 3); 10603b705cfSriastradh 10703b705cfSriastradh width = pixmap->drawable.width; 10803b705cfSriastradh maskw = 0; 10903b705cfSriastradh if (width & 7) 11003b705cfSriastradh maskw = FB_ALLONES & ~FbScrRight(FB_ALLONES, width & FB_MASK); 11103b705cfSriastradh region->extents.x1 = width; 11203b705cfSriastradh region->extents.x2 = 0; 11303b705cfSriastradh y2 = 0; 11403b705cfSriastradh while (y2 < pixmap->drawable.height) { 11503b705cfSriastradh y1 = y2++; 11603b705cfSriastradh bits = line; 11703b705cfSriastradh line += stride; 11803b705cfSriastradh while (y2 < pixmap->drawable.height && 11903b705cfSriastradh memcmp(bits, line, width >> 3) == 0 && 12003b705cfSriastradh (maskw == 0 || (bits[width >> FB_SHIFT] & maskw) == (line[width >> FB_SHIFT] & maskw))) 12103b705cfSriastradh line += stride, y2++; 12203b705cfSriastradh 12303b705cfSriastradh if (READ(bits) & MASK_0) 12403b705cfSriastradh x1 = 0; 12503b705cfSriastradh else 12603b705cfSriastradh x1 = -1; 12703b705cfSriastradh 12803b705cfSriastradh /* Process all words which are fully in the pixmap */ 12903b705cfSriastradh end = bits + (width >> FB_SHIFT); 13003b705cfSriastradh for (base = 0; bits < end; base += FB_UNIT) { 13103b705cfSriastradh FbBits w = READ(bits++); 13203b705cfSriastradh if (x1 < 0) { 13303b705cfSriastradh if (!w) 13403b705cfSriastradh continue; 13503b705cfSriastradh } else { 13603b705cfSriastradh if (!~w) 13703b705cfSriastradh continue; 13803b705cfSriastradh } 13903b705cfSriastradh for (i = 0; i < FB_UNIT; i++) { 14003b705cfSriastradh if (w & MASK_0) { 14103b705cfSriastradh if (x1 < 0) 14203b705cfSriastradh x1 = base + i; 14303b705cfSriastradh } else { 14403b705cfSriastradh if (x1 >= 0) { 14503b705cfSriastradh add(region, x1, y1, base + i, y2); 14603b705cfSriastradh x1 = -1; 14703b705cfSriastradh } 14803b705cfSriastradh } 14903b705cfSriastradh w = FbScrLeft(w, 1); 15003b705cfSriastradh } 15103b705cfSriastradh } 15203b705cfSriastradh if (width & FB_MASK) { 15303b705cfSriastradh FbBits w = READ(bits++); 15403b705cfSriastradh for (i = 0; i < (width & FB_MASK); i++) { 15503b705cfSriastradh if (w & MASK_0) { 15603b705cfSriastradh if (x1 < 0) 15703b705cfSriastradh x1 = base + i; 15803b705cfSriastradh } else { 15903b705cfSriastradh if (x1 >= 0) { 16003b705cfSriastradh add(region, x1, y1, base + i, y2); 16103b705cfSriastradh x1 = -1; 16203b705cfSriastradh } 16303b705cfSriastradh } 16403b705cfSriastradh w = FbScrLeft(w, 1); 16503b705cfSriastradh } 16603b705cfSriastradh } 16703b705cfSriastradh if (x1 >= 0) 16803b705cfSriastradh add(region, x1, y1, width, y2); 16903b705cfSriastradh } 17003b705cfSriastradh 17103b705cfSriastradh if (region->data->numRects) { 17203b705cfSriastradh region->extents.y1 = RegionBoxptr(region)->y1; 17303b705cfSriastradh region->extents.y2 = RegionEnd(region)->y2; 17403b705cfSriastradh if (region->data->numRects == 1) { 17503b705cfSriastradh free(region->data); 17603b705cfSriastradh region->data = NULL; 17703b705cfSriastradh } 17803b705cfSriastradh } else 17903b705cfSriastradh region->extents.x1 = region->extents.x2 = 0; 18003b705cfSriastradh 18142542f5fSchristos DBG(("%s: region extents=(%d, %d), (%d, %d) x %d\n", 18203b705cfSriastradh __FUNCTION__, 18303b705cfSriastradh region->extents.x1, region->extents.y1, 18403b705cfSriastradh region->extents.x2, region->extents.y2, 18542542f5fSchristos region_num_rects(region))); 18603b705cfSriastradh 18703b705cfSriastradh return region; 18803b705cfSriastradh} 189