cairo/pixman/src/icrect.c
Nicholas Miell d598cd8d61 Fix the AMD64 final link by removing SLIM from pixman
In order for SLIM's PLT indirection avoidance to work, everything in
the library that makes internal function calls needs to see the
relevant slim_hidden_proto() macro in addition to the function's
prototype. However, external headers used by clients of the shared
library should not use the SLIM macros at all.

Pixman is a rather odd case -- it's mostly independent from cairo, so
it has it's own public interface, but it's built as a part of cairo
instead of its own shared library. This means that cairo would need to
see all of pixman's slim_hidden_proto() macros in order to function
and it doesn't currently, which results in a link failure on AMD64
systems and on i386 systems (I think, I haven't actually verified
this) it produces a shared object that isn't actally sharable.

I have no idea why exactly the link failure only showed up as a result
of commit e06246b9b1. I think it has
something to do with the pixman functions no longer having PLT entries
at all, but the exact interaction isn't clear to me.

However, all of these pixman functions aren't part of the cairo ABI
(which is why they were marked pixman_private in the first place),
which means that the SLIMification of pixman is largely pointless --
they aren't externally visible, so they don't need PLT entries at
all. Furthermore, while pixman may eventually be shared among cairo
and X, I'm told that this sharing will be source-level only, which
means it won't ever be an actual shared library and thus won't ever
need SLIM at all.

So, I just removed all use of SLIM in pixman (leaving behind
slim_internal.h for the future edification of anyone who cares).This
fixes the AMD64 link failure and passes the check-plt & check-def
parts of make check.

Signed-off-by: Nicholas Miell <nmiell@gmail.com>
2006-09-07 12:48:28 -07:00

365 lines
9 KiB
C

/*
* Copyright © 2000 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "icint.h"
typedef void (*FillFunc) (pixman_image_t *dst,
int16_t xDst,
int16_t yDst,
uint16_t width,
uint16_t height,
pixman_bits_t *pixel);
static void
pixman_fill_rect_1bpp (pixman_image_t *dst,
int16_t xDst,
int16_t yDst,
uint16_t width,
uint16_t height,
pixman_bits_t *pixel)
{
uint32_t value = *pixel ? 0xffffffff : 0;
char *line;
line = (char *)dst->pixels->data
+ yDst * dst->pixels->stride;
if ((width + xDst - 1) / 32 == xDst / 32) {
uint32_t mask = 0;
int pos = xDst / 32;
int i;
for (i = xDst; i < width; i++)
#if BITMAP_BIT_ORDER == MSBFirst
mask |= 1 << (0x1f - i);
#else
mask |= 1 << i;
#endif
while (height-- > 0) {
uint32_t *cur = (uint32_t *) line;
cur [pos] = (cur [pos] & ~mask) | (value & mask);
line += dst->pixels->stride;
}
} else {
uint32_t smask = 0, emask = 0;
int end = ((xDst + width) / 32);
int i;
if (xDst % 32)
for (i = (xDst % 32); i < 32; i++)
#if BITMAP_BIT_ORDER == MSBFirst
smask |= 1 << (0x1f - i);
#else
smask |= 1 << i;
#endif
if ((width + xDst) % 32)
for (i = 0; i < (width + xDst) % 32; i++)
#if BITMAP_BIT_ORDER == MSBFirst
emask |= 1 << (0x1f - i);
#else
emask |= 1 << i;
#endif
while (height-- > 0) {
uint32_t *cur = (uint32_t *) line;
int start = (xDst / 32);
if (smask) {
cur [start] = (cur [start] & ~smask) | (value & smask);
start++;
}
if (emask)
cur [end] = (cur [end] & ~emask) | (value & emask);
if (end > start)
memset (cur + start, value, (end - start) * 4);
line += dst->pixels->stride;
}
}
}
static void
pixman_fill_rect_8bpp (pixman_image_t *dst,
int16_t xDst,
int16_t yDst,
uint16_t width,
uint16_t height,
pixman_bits_t *pixel)
{
int value = (int) (*pixel);
char *line;
line = (char *)dst->pixels->data +
xDst + yDst * dst->pixels->stride;
while (height-- > 0) {
memset (line, value, width);
line += dst->pixels->stride;
}
}
static void
pixman_fill_rect_32bpp (pixman_image_t *dst,
int16_t xDst,
int16_t yDst,
uint16_t width,
uint16_t height,
pixman_bits_t *pixel)
{
uint32_t int_pixel;
char *line;
char *data;
int w;
line = (char *)dst->pixels->data +
xDst * 4 + yDst * dst->pixels->stride;
int_pixel = *(uint32_t *)pixel;
while (height-- > 0) {
data = line;
w = width;
while (w-- > 0) {
*(uint32_t *)data = int_pixel;
data += 4;
}
line += dst->pixels->stride;
}
}
static void
pixman_fill_rect_general (pixman_image_t *dst,
int16_t xDst,
int16_t yDst,
uint16_t width,
uint16_t height,
pixman_bits_t *pixel)
{
int pixel_size;
char *line;
char *data;
int w;
pixel_size = dst->pixels->bpp >> 3;
line = (char *)dst->pixels->data +
xDst * pixel_size + yDst * dst->pixels->stride;
while (height-- > 0) {
data = line;
w = width;
while (w-- > 0) {
memcpy (data, pixel, pixel_size);
data += pixel_size;
}
line += dst->pixels->stride;
}
}
static void
pixman_color_rects (pixman_image_t *dst,
pixman_image_t *clipPict,
pixman_color_t *color,
int nRect,
pixman_rectangle_t *rects,
int xoff,
int yoff)
{
pixman_bits_t pixel;
pixman_region16_t *clip;
pixman_region16_t *rects_as_region;
pixman_box16_t *clipped_rects;
int i, n_clipped_rects;
FillFunc func;
pixman_color_to_pixel (&dst->image_format,
color,
&pixel);
/* offset to the right place on the destination image */
xoff -= dst->pixels->x;
yoff -= dst->pixels->y;
clip = pixman_region_create();
pixman_region_union_rect (clip, clip,
dst->pixels->x, dst->pixels->y,
dst->pixels->width, dst->pixels->height);
pixman_region_intersect (clip, clip, clipPict->pCompositeClip);
if (clipPict->alphaMap)
{
pixman_region_translate (clip,
-clipPict->alphaOrigin.x,
-clipPict->alphaOrigin.y);
pixman_region_intersect (clip, clip, clipPict->alphaMap->pCompositeClip);
pixman_region_translate (clip,
clipPict->alphaOrigin.x,
clipPict->alphaOrigin.y);
}
if (xoff || yoff)
{
for (i = 0; i < nRect; i++)
{
rects[i].x -= xoff;
rects[i].y -= yoff;
}
}
rects_as_region = pixman_region_create ();
for (i = 0; i < nRect; i++)
{
pixman_region_union_rect (rects_as_region, rects_as_region,
rects[i].x, rects[i].y,
rects[i].width, rects[i].height);
}
pixman_region_intersect (rects_as_region, rects_as_region, clip);
pixman_region_destroy (clip);
n_clipped_rects = pixman_region_num_rects (rects_as_region);
clipped_rects = pixman_region_rects (rects_as_region);
if (dst->pixels->bpp == 8)
func = pixman_fill_rect_8bpp;
else if (dst->pixels->bpp == 32)
func = pixman_fill_rect_32bpp;
else if (dst->pixels->bpp == 1)
func = pixman_fill_rect_1bpp;
else
func = pixman_fill_rect_general;
for (i = 0; i < n_clipped_rects; i++) {
(*func) (dst,
clipped_rects[i].x1,
clipped_rects[i].y1,
clipped_rects[i].x2 - clipped_rects[i].x1,
clipped_rects[i].y2 - clipped_rects[i].y1,
&pixel);
}
pixman_region_destroy (rects_as_region);
if (xoff || yoff)
{
for (i = 0; i < nRect; i++)
{
rects[i].x += xoff;
rects[i].y += yoff;
}
}
}
void pixman_fill_rectangle (pixman_operator_t op,
pixman_image_t *dst,
const pixman_color_t *color,
int x,
int y,
unsigned int width,
unsigned int height)
{
pixman_rectangle_t rect;
rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height;
pixman_fill_rectangles (op, dst, color, &rect, 1);
}
void
pixman_fill_rectangles (pixman_operator_t op,
pixman_image_t *dst,
const pixman_color_t *color,
const pixman_rectangle_t *rects,
int nRects)
{
pixman_color_t color_s = *color;
if (color_s.alpha == 0xffff)
{
if (op == PIXMAN_OPERATOR_OVER)
op = PIXMAN_OPERATOR_SRC;
}
if (op == PIXMAN_OPERATOR_CLEAR)
color_s.red = color_s.green = color_s.blue = color_s.alpha = 0;
if (op == PIXMAN_OPERATOR_SRC || op == PIXMAN_OPERATOR_CLEAR)
{
/* We cast away the constness of rects here, because pixman_color_rects
temporarily modifies it */
pixman_color_rects (dst, dst, &color_s, nRects, (pixman_rectangle_t *)rects, 0, 0);
if (dst->alphaMap)
pixman_color_rects (dst->alphaMap, dst,
&color_s, nRects, (pixman_rectangle_t *)rects,
dst->alphaOrigin.x,
dst->alphaOrigin.y);
}
else
{
pixman_format_t rgbaFormat;
FbPixels *pixels;
pixman_image_t *src;
pixman_bits_t pixel;
pixman_format_init (&rgbaFormat, PICT_a8r8g8b8);
pixels = FbPixelsCreate (1, 1, rgbaFormat.depth);
if (!pixels)
goto bail1;
pixman_color_to_pixel (&rgbaFormat, &color_s, &pixel);
/* XXX: Originally, fb had the following:
(*pGC->ops->PolyFillRect) (&pPixmap->drawable, pGC, 1, &one);
I haven't checked to see what I might be breaking with a
trivial assignment instead.
*/
pixels->data[0] = pixel;
src = pixman_image_createForPixels (pixels, &rgbaFormat);
if (!src)
goto bail2;
pixman_image_set_repeat (src, PIXMAN_REPEAT_NORMAL);
while (nRects--)
{
pixman_composite (op, src, NULL, dst, 0, 0, 0, 0,
rects->x,
rects->y,
rects->width,
rects->height);
rects++;
}
pixman_image_destroy (src);
bail2:
FbPixelsDestroy (pixels);
bail1:
;
}
}