typedef void (*scanFetchProc)(pixman_image_t *, int, int, int, uint32_t *,
uint32_t *, uint32_t);
+static inline scanFetchProc get_fetch_source_pict(const int wide)
+{
+ if (wide)
+ return (scanFetchProc)pixmanFetchSourcePict64;
+ else
+ return (scanFetchProc)pixmanFetchSourcePict;
+}
+
+static inline scanFetchProc get_fetch_solid(const int wide)
+{
+ if (wide)
+ return (scanFetchProc)fbFetchSolid64;
+ else
+ return (scanFetchProc)fbFetchSolid;
+}
+
+static inline scanFetchProc get_fetch(const int wide)
+{
+ if (wide)
+ return (scanFetchProc)fbFetch64;
+ else
+ return (scanFetchProc)fbFetch;
+}
+
+static inline scanFetchProc get_fetch_external_alpha(const int wide)
+{
+ if (wide)
+ return (scanFetchProc)ACCESS(fbFetchExternalAlpha64);
+ else
+ return (scanFetchProc)ACCESS(fbFetchExternalAlpha);
+}
+
+static inline scanFetchProc get_fetch_transformed(const int wide)
+{
+ if (wide)
+ return (scanFetchProc)ACCESS(fbFetchTransformed64);
+ else
+ return (scanFetchProc)ACCESS(fbFetchTransformed);
+}
+
+static inline scanStoreProc get_store(const int wide)
+{
+ if (wide)
+ return (scanStoreProc)fbStore64;
+ else
+ return (scanStoreProc)fbStore;
+}
+
+static inline scanStoreProc get_store_external_alpha(const int wide)
+{
+ if (wide)
+ return (scanStoreProc)ACCESS(fbStoreExternalAlpha64);
+ else
+ return (scanStoreProc)ACCESS(fbStoreExternalAlpha);
+}
+
#ifndef PIXMAN_FB_ACCESSORS
static
#endif
fetchSrc = NULL;
else if (IS_SOURCE_IMAGE (data->src))
{
- fetchSrc = (scanFetchProc)pixmanFetchSourcePict;
+ fetchSrc = get_fetch_source_pict(wide);
srcClass = SourcePictureClassify ((source_image_t *)data->src,
data->xSrc, data->ySrc,
data->width, data->height);
if (bits->common.alpha_map)
{
- // TODO: Need wide external alpha routine.
- fetchSrc = (scanFetchProc)ACCESS(fbFetchExternalAlpha);
+ fetchSrc = get_fetch_external_alpha(wide);
}
else if ((bits->common.repeat == PIXMAN_REPEAT_NORMAL || bits->common.repeat == PIXMAN_REPEAT_PAD) &&
bits->width == 1 &&
bits->height == 1)
{
- fetchSrc = wide ? (scanFetchProc)fbFetchSolid64 : (scanFetchProc)fbFetchSolid;
+ fetchSrc = get_fetch_solid(wide);
srcClass = SOURCE_IMAGE_CLASS_HORIZONTAL;
}
else if (!bits->common.transform && bits->common.filter != PIXMAN_FILTER_CONVOLUTION
&& bits->common.repeat != PIXMAN_REPEAT_PAD)
{
- fetchSrc = wide ? (scanFetchProc)fbFetch64 : (scanFetchProc)fbFetch;
+ fetchSrc = get_fetch(wide);
}
else
{
- // TODO: Need wide transformed fetch.
- fetchSrc = (scanFetchProc)ACCESS(fbFetchTransformed);
+ fetchSrc = get_fetch_transformed(wide);
}
}
if (bits->common.alpha_map)
{
- // TODO: Need wide external alpha routine.
- fetchMask = (scanFetchProc)ACCESS(fbFetchExternalAlpha);
+ fetchMask = get_fetch_external_alpha(wide);
}
else if ((bits->common.repeat == PIXMAN_REPEAT_NORMAL || bits->common.repeat == PIXMAN_REPEAT_PAD) &&
bits->width == 1 && bits->height == 1)
{
- fetchMask = wide ? (scanFetchProc)fbFetchSolid64 : (scanFetchProc)fbFetchSolid;
+ fetchMask = get_fetch_solid(wide);
maskClass = SOURCE_IMAGE_CLASS_HORIZONTAL;
}
else if (!bits->common.transform && bits->common.filter != PIXMAN_FILTER_CONVOLUTION
&& bits->common.repeat != PIXMAN_REPEAT_PAD)
- fetchMask = wide ? (scanFetchProc)fbFetch64 : (scanFetchProc)fbFetch;
+ fetchMask = get_fetch(wide);
else
- // TODO: Need wide transformed fetch.
- fetchMask = (scanFetchProc)ACCESS(fbFetchTransformed);
+ fetchMask = get_fetch_transformed(wide);
}
}
if (data->dest->common.alpha_map)
{
- // TODO: Need wide external alpha routine.
- fetchDest = (scanFetchProc)ACCESS(fbFetchExternalAlpha);
- store = (scanStoreProc)ACCESS(fbStoreExternalAlpha);
+ fetchDest = get_fetch_external_alpha(wide);
+ store = get_store_external_alpha(wide);
if (data->op == PIXMAN_OP_CLEAR || data->op == PIXMAN_OP_SRC)
fetchDest = NULL;
}
else
{
- fetchDest = wide ? (scanFetchProc)fbFetch64 : (scanFetchProc)fbFetch;
- store = wide ? (scanStoreProc)fbStore64 : (scanStoreProc)fbStore;
+ fetchDest = get_fetch(wide);
+ store = get_store(wide);
switch (data->op)
{
void pixmanFetchSourcePict(source_image_t *, int x, int y, int width,
uint32_t *buffer, uint32_t *mask, uint32_t maskBits);
+void pixmanFetchSourcePict64(source_image_t *, int x, int y, int width,
+ uint64_t *buffer, uint64_t *mask, uint32_t maskBits);
void fbFetchTransformed(bits_image_t *, int x, int y, int width,
uint32_t *buffer, uint32_t *mask, uint32_t maskBits);
uint32_t *buffer, uint32_t *mask,
uint32_t maskBits);
+void fbFetchTransformed64(bits_image_t *, int x, int y, int width,
+ uint64_t *buffer, uint64_t *mask, uint32_t maskBits);
+void fbStoreExternalAlpha64(bits_image_t *, int x, int y, int width,
+ uint64_t *buffer);
+void fbFetchExternalAlpha64(bits_image_t *, int x, int y, int width,
+ uint64_t *buffer, uint64_t *mask, uint32_t maskBits);
+
+void fbFetchTransformed64_accessors(bits_image_t *, int x, int y, int width,
+ uint64_t *buffer, uint64_t *mask,
+ uint32_t maskBits);
+void fbStoreExternalAlpha64_accessors(bits_image_t *, int x, int y, int width,
+ uint64_t *buffer);
+void fbFetchExternalAlpha64_accessors(bits_image_t *, int x, int y, int width,
+ uint64_t *buffer, uint64_t *mask,
+ uint32_t maskBits);
+
/* end */
typedef enum
(uint32_t) ((uint8_t) ((t) | (0 - ((t) >> 8)))) << (i))
#define div_255(x) (((x) + 0x80 + (((x) + 0x80) >> 8)) >> 8)
+#define div_65535(x) (((x) + 0x8000 + (((x) + 0x8000) >> 16)) >> 16)
#define MOD(a,b) ((a) < 0 ? ((b) - ((-(a) - 1) % (b))) - 1 : (a) % (b))
#include <config.h>
#endif
+#include <stdlib.h>
#include <math.h>
#include "pixman-private.h"
}
}
}
+
+/*
+ * For now, just evaluate the source picture at 32bpp and expand. We could
+ * produce smoother gradients by evaluating them at higher color depth, but
+ * that's a project for the future.
+ */
+void pixmanFetchSourcePict64(source_image_t * pict, int x, int y, int width,
+ uint64_t *buffer, uint64_t *mask, uint32_t maskBits)
+{
+ uint32_t *mask8 = NULL;
+
+ // Contract the mask image, if one exists, so that the 32-bit fetch function
+ // can use it.
+ if (mask) {
+ mask8 = pixman_malloc_ab(width, sizeof(uint32_t));
+ pixman_contract(mask8, mask, width);
+ }
+
+ // Fetch the source image into the first half of buffer.
+ pixmanFetchSourcePict(pict, x, y, width, (uint32_t*)buffer, mask8,
+ maskBits);
+
+ // Expand from 32bpp to 64bpp in place.
+ pixman_expand(buffer, (uint32_t*)buffer, PIXMAN_a8r8g8b8, width);
+
+ free(mask8);
+}
*
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
* 2005 Lars Knoll & Zack Rusin, Trolltech
+ * 2008 Aaron Plattner, NVIDIA Corporation
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
#define Green(x) (((x) >> 8) & 0xff)
#define Blue(x) ((x) & 0xff)
+#define Alpha64(x) ((x) >> 48)
+#define Red64(x) (((x) >> 32) & 0xffff)
+#define Green64(x) (((x) >> 16) & 0xffff)
+#define Blue64(x) ((x) & 0xffff)
+
/*
* Fetch from region strategies
*/
}
}
+void
+ACCESS(fbFetchTransformed64)(bits_image_t * pict, int x, int y, int width,
+ uint64_t *buffer, uint64_t *mask, uint32_t maskBits)
+{
+ // TODO: Don't lose precision for wide pictures!
+ uint32_t *mask8 = NULL;
+
+ // Contract the mask image, if one exists, so that the 32-bit fetch function
+ // can use it.
+ if (mask) {
+ mask8 = pixman_malloc_ab(width, sizeof(uint32_t));
+ pixman_contract(mask8, mask, width);
+ }
+
+ // Fetch the image into the first half of buffer.
+ ACCESS(fbFetchTransformed)(pict, x, y, width, (uint32_t*)buffer, mask8,
+ maskBits);
+
+ // Expand from 32bpp to 64bpp in place.
+ pixman_expand(buffer, (uint32_t*)buffer, pict->format, width);
+
+ free(mask8);
+}
+
#define SCANLINE_BUFFER_LENGTH 2048
void
free(alpha_buffer);
}
+void
+ACCESS(fbFetchExternalAlpha64)(bits_image_t * pict, int x, int y, int width,
+ uint64_t *buffer, uint64_t *mask,
+ uint32_t maskBits)
+{
+ int i;
+ uint64_t _alpha_buffer[SCANLINE_BUFFER_LENGTH];
+ uint64_t *alpha_buffer = _alpha_buffer;
+ uint64_t maskBits64;
+
+ if (!pict->common.alpha_map) {
+ ACCESS(fbFetchTransformed64) (pict, x, y, width, buffer, mask, maskBits);
+ return;
+ }
+ if (width > SCANLINE_BUFFER_LENGTH)
+ alpha_buffer = (uint64_t *) pixman_malloc_ab (width, sizeof(uint64_t));
+
+ ACCESS(fbFetchTransformed64)(pict, x, y, width, buffer, mask, maskBits);
+ ACCESS(fbFetchTransformed64)((bits_image_t *)pict->common.alpha_map, x - pict->common.alpha_origin.x,
+ y - pict->common.alpha_origin.y, width,
+ alpha_buffer, mask, maskBits);
+
+ pixman_expand(&maskBits64, &maskBits, PIXMAN_a8r8g8b8, 1);
+
+ for (i = 0; i < width; ++i) {
+ if (!mask || mask[i] & maskBits64)
+ {
+ int64_t a = alpha_buffer[i]>>48;
+ *(buffer + i) = (a << 48)
+ | (div_65535(Red64(*(buffer + i)) * a) << 32)
+ | (div_65535(Green64(*(buffer + i)) * a) << 16)
+ | (div_65535(Blue64(*(buffer + i)) * a));
+ }
+ }
+
+ if (alpha_buffer != _alpha_buffer)
+ free(alpha_buffer);
+}
+
void
ACCESS(fbStoreExternalAlpha)(bits_image_t * pict, int x, int y, int width,
uint32_t *buffer)
alpha_bits, buffer, ax - pict->common.alpha_origin.x, width, aindexed);
}
+void
+ACCESS(fbStoreExternalAlpha64)(bits_image_t * pict, int x, int y, int width,
+ uint64_t *buffer)
+{
+ uint32_t *bits, *alpha_bits;
+ int32_t stride, astride;
+ int ax, ay;
+ storeProc64 store;
+ storeProc64 astore;
+ const pixman_indexed_t * indexed = pict->indexed;
+ const pixman_indexed_t * aindexed;
+
+ store = ACCESS(pixman_storeProcForPicture64)(pict);
+ astore = ACCESS(pixman_storeProcForPicture64)(pict->common.alpha_map);
+ aindexed = pict->common.alpha_map->indexed;
+
+ ax = x;
+ ay = y;
+
+ bits = pict->bits;
+ stride = pict->rowstride;
+
+ alpha_bits = pict->common.alpha_map->bits;
+ astride = pict->common.alpha_map->rowstride;
+
+ bits += y*stride;
+ alpha_bits += (ay - pict->common.alpha_origin.y)*astride;
+
+
+ store((pixman_image_t *)pict, bits, buffer, x, width, indexed);
+ astore((pixman_image_t *)pict->common.alpha_map,
+ alpha_bits, buffer, ax - pict->common.alpha_origin.x, width, aindexed);
+}