Move pixman_format_t from heap to stack allocations.

pixman_format_t is a simple structure used in short-term allocations and
suitable for on-stack allocation.

Killing the pixman_format_create()/pixman_format_destroy() pairs avoid
around 6% of the allocations during cairo-perf (e.g. 426,158 allocs out
of a total of 7,063,469).
This commit is contained in:
Chris Wilson 2007-04-11 23:34:24 +01:00
parent 3bc413343a
commit 52435e99f3
7 changed files with 202 additions and 295 deletions

View file

@ -29,66 +29,88 @@
#define Mask(n) ((n) == 32 ? 0xffffffff : (unsigned) ((1 << (n))-1))
pixman_format_t *
pixman_format_create (pixman_format_name_t name)
int
pixman_format_init (pixman_format_t *format, pixman_format_name_t name)
{
switch (name) {
case PIXMAN_FORMAT_NAME_ARGB32:
return pixman_format_create_masks (32,
0xff000000,
0x00ff0000,
0x0000ff00,
0x000000ff);
pixman_format_init_masks (format, 32,
0xff000000,
0x00ff0000,
0x0000ff00,
0x000000ff);
break;
case PIXMAN_FORMAT_NAME_RGB24:
return pixman_format_create_masks (32,
0x0,
0xff0000,
0x00ff00,
0x0000ff);
pixman_format_init_masks (format, 32,
0x0,
0xff0000,
0x00ff00,
0x0000ff);
break;
case PIXMAN_FORMAT_NAME_A8:
return pixman_format_create_masks (8, 0xff,
0, 0, 0);
pixman_format_init_masks (format, 8,
0xff,
0,
0,
0);
break;
case PIXMAN_FORMAT_NAME_A1:
return pixman_format_create_masks (1, 0x1,
0, 0, 0);
pixman_format_init_masks (format, 1,
0x1,
0,
0,
0);
break;
case PIXMAN_FORMAT_NAME_RGB16_565:
return pixman_format_create_masks (16,
0x0,
0xf800,
0x07e0,
0x001f);
pixman_format_init_masks (format, 16,
0x0,
0xf800,
0x07e0,
0x001f);
break;
case PIXMAN_FORMAT_NAME_ABGR32:
return pixman_format_create_masks (32,
0xff000000,
0x000000ff,
0x0000ff00,
0x00ff0000);
pixman_format_init_masks (format, 32,
0xff000000,
0x000000ff,
0x0000ff00,
0x00ff0000);
break;
case PIXMAN_FORMAT_NAME_BGR24:
return pixman_format_create_masks (32,
0x0,
0x000000ff,
0x0000ff00,
0x00ff0000);
pixman_format_init_masks (format, 32,
0x0,
0x000000ff,
0x0000ff00,
0x00ff0000);
break;
default:
return 0;
}
return NULL;
return 1;
}
/* XXX: There's some nonsense going on here. The macros above help
pixman_format_create_masks to encode a format into an int, while
immediately afterwards pixman_format_init goes through the effort of
immediately afterwards pixman_format_init_code goes through the effort of
decoding it. This should all be disentagled, (it's probably
possible to just eliminate the encoding macros altogether). */
pixman_format_t *
pixman_format_create_masks (int bpp,
int alpha_mask,
int red_mask,
int green_mask,
int blue_mask)
void
pixman_format_init_masks (pixman_format_t *format,
int bpp,
int alpha_mask,
int red_mask,
int green_mask,
int blue_mask)
{
int type;
int format_code;
pixman_format_t *format;
if (red_mask == 0 && green_mask == 0 && blue_mask == 0)
type = PICT_TYPE_A;
@ -103,17 +125,11 @@ pixman_format_create_masks (int bpp,
_FbOnes (green_mask),
_FbOnes (blue_mask));
format = malloc (sizeof (pixman_format_t));
if (format == NULL)
return NULL;
pixman_format_init (format, format_code);
return format;
pixman_format_init_code (format, format_code);
}
void
pixman_format_init (pixman_format_t *format, int format_code)
pixman_format_init_code (pixman_format_t *format, int format_code)
{
memset (format, 0, sizeof (pixman_format_t));
@ -176,12 +192,6 @@ pixman_format_init (pixman_format_t *format, int format_code)
(format->greenMask << format->green));
}
void
pixman_format_destroy (pixman_format_t *format)
{
free (format);
}
void
pixman_format_get_masks (pixman_format_t *format,
unsigned int *bpp,

View file

@ -738,16 +738,6 @@ fbStipple (pixman_bits_t *dst,
int xRot,
int yRot);
/* XXX: Is depth redundant here? */
struct pixman_format {
int format_code;
int depth;
int red, redMask;
int green, greenMask;
int blue, blueMask;
int alpha, alphaMask;
};
typedef struct _FbPixels {
pixman_bits_t *data;
unsigned int width;
@ -808,7 +798,7 @@ _FbOnes(unsigned int mask);
/* icformat.c */
pixman_private void
pixman_format_init (pixman_format_t *format, int format_code);
pixman_format_init_code (pixman_format_t *format, int format_code);
/* icimage.c */

View file

@ -363,7 +363,7 @@ pixman_fill_rectangles (pixman_operator_t op,
pixman_image_t *src;
pixman_bits_t pixel;
pixman_format_init (&rgbaFormat, PICT_a8r8g8b8);
pixman_format_init_code (&rgbaFormat, PICT_a8r8g8b8);
pixels = FbPixelsCreate (1, 1, rgbaFormat.depth);
if (!pixels)

View file

@ -25,6 +25,7 @@
#endif
#include "icint.h"
#include <assert.h>
pixman_image_t *
FbCreateAlphaPicture (pixman_image_t *dst,
@ -32,30 +33,24 @@ FbCreateAlphaPicture (pixman_image_t *dst,
uint16_t width,
uint16_t height)
{
pixman_image_t *image;
int own_format = 0;
pixman_format_t local_format;
if (width > 32767 || height > 32767)
return NULL;
if (!format)
{
own_format = 1;
int ret;
format = &local_format;
if (dst->polyEdge == PolyEdgeSharp)
format = pixman_format_create (PIXMAN_FORMAT_NAME_A1);
ret = pixman_format_init (format, PIXMAN_FORMAT_NAME_A1);
else
format = pixman_format_create (PIXMAN_FORMAT_NAME_A8);
if (!format)
return NULL;
ret = pixman_format_init (format, PIXMAN_FORMAT_NAME_A8);
assert (ret);
}
/* pixman_image_create zeroes out the pixels, so we don't have to */
image = pixman_image_create (format, width, height);
if (own_format)
pixman_format_destroy (format);
return image;
return pixman_image_create (format, width, height);
}
static pixman_fixed16_16_t
@ -116,8 +111,9 @@ pixman_composite_trapezoids (pixman_operator_t op,
pixman_region16_t traps_region, dst_region;
int16_t xDst, yDst;
int16_t xRel, yRel;
pixman_format_t *format;
pixman_format_t format;
pixman_region_status_t status;
int ret;
if (ntraps == 0)
return 0;
@ -162,18 +158,14 @@ pixman_composite_trapezoids (pixman_operator_t op,
if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
return 0;
format = pixman_format_create (PIXMAN_FORMAT_NAME_A8);
if (!format)
return 1;
ret = pixman_format_init (&format, PIXMAN_FORMAT_NAME_A8);
assert (ret);
image = FbCreateAlphaPicture (dst, format,
image = FbCreateAlphaPicture (dst, &format,
bounds.x2 - bounds.x1,
bounds.y2 - bounds.y1);
if (!image)
{
pixman_format_destroy (format);
return 1;
}
for (; ntraps; ntraps--, traps++)
{
@ -191,8 +183,6 @@ pixman_composite_trapezoids (pixman_operator_t op,
bounds.y2 - bounds.y1);
pixman_image_destroy (image);
pixman_format_destroy (format);
return 0;
}

View file

@ -25,6 +25,7 @@
#endif
#include "icint.h"
#include <assert.h>
static void
pixman_point_fixed_bounds (int npoint, const pixman_point_fixed_t *points, pixman_box16_t *bounds)
@ -151,62 +152,38 @@ pixman_composite_triangles (pixman_operator_t op,
pixman_image_t *image = NULL;
int xDst, yDst;
int xRel, yRel;
pixman_format_t *format;
pixman_format_t format;
int ret;
xDst = tris[0].p1.x >> 16;
yDst = tris[0].p1.y >> 16;
format = pixman_format_create (PIXMAN_FORMAT_NAME_A8);
ret = pixman_format_init (&format, PIXMAN_FORMAT_NAME_A8);
assert (ret);
pixman_triangle_bounds (ntris, tris, &bounds);
if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1)
return;
image = FbCreateAlphaPicture (dst,
&format,
bounds.x2 - bounds.x1,
bounds.y2 - bounds.y1);
if (!image)
return;
if (format)
{
pixman_triangle_bounds (ntris, tris, &bounds);
if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1)
return;
image = FbCreateAlphaPicture (dst,
format,
bounds.x2 - bounds.x1,
bounds.y2 - bounds.y1);
if (!image)
return;
}
for (; ntris; ntris--, tris++)
{
if (!format)
{
pixman_triangle_bounds (1, tris, &bounds);
if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1)
continue;
image = FbCreateAlphaPicture (dst,
format,
bounds.x2 - bounds.x1,
bounds.y2 - bounds.y1);
if (!image)
break;
}
FbRasterizeTriangle (image, tris, -bounds.x1, -bounds.y1);
if (!format)
{
xRel = bounds.x1 + xSrc - xDst;
yRel = bounds.y1 + ySrc - yDst;
pixman_composite (op, src, image, dst,
xRel, yRel, 0, 0, bounds.x1, bounds.y1,
bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
pixman_image_destroy (image);
}
/* XXX adjust xSrc and ySrc */
}
if (format)
{
xRel = bounds.x1 + xSrc - xDst;
yRel = bounds.y1 + ySrc - yDst;
pixman_composite (op, src, image, dst,
xRel, yRel, 0, 0, bounds.x1, bounds.y1,
bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
pixman_image_destroy (image);
}
pixman_format_destroy (format);
xRel = bounds.x1 + xSrc - xDst;
yRel = bounds.y1 + ySrc - yDst;
pixman_composite (op, src, image, dst,
xRel, yRel, 0, 0, bounds.x1, bounds.y1,
bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
pixman_image_destroy (image);
}
void
@ -223,7 +200,8 @@ pixman_composite_tri_strip (pixman_operator_t op,
pixman_image_t *image = NULL;
int xDst, yDst;
int xRel, yRel;
pixman_format_t *format;
pixman_format_t format;
int ret;
if (npoints < 3)
return;
@ -231,59 +209,34 @@ pixman_composite_tri_strip (pixman_operator_t op,
xDst = points[0].x >> 16;
yDst = points[0].y >> 16;
format = pixman_format_create (PIXMAN_FORMAT_NAME_A8);
ret = pixman_format_init (&format, PIXMAN_FORMAT_NAME_A8);
assert (ret);
pixman_point_fixed_bounds (npoints, points, &bounds);
if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1)
return;
image = FbCreateAlphaPicture (dst,
&format,
bounds.x2 - bounds.x1,
bounds.y2 - bounds.y1);
if (!image)
return;
if (format)
{
pixman_point_fixed_bounds (npoints, points, &bounds);
if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1)
return;
image = FbCreateAlphaPicture (dst,
format,
bounds.x2 - bounds.x1,
bounds.y2 - bounds.y1);
if (!image)
return;
}
for (; npoints >= 3; npoints--, points++)
{
tri.p1 = points[0];
tri.p2 = points[1];
tri.p3 = points[2];
if (!format)
{
pixman_triangle_bounds (1, &tri, &bounds);
if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1)
continue;
image = FbCreateAlphaPicture (dst,
format,
bounds.x2 - bounds.x1,
bounds.y2 - bounds.y1);
if (!image)
continue;
}
FbRasterizeTriangle (image, &tri, -bounds.x1, -bounds.y1);
if (!format)
{
xRel = bounds.x1 + xSrc - xDst;
yRel = bounds.y1 + ySrc - yDst;
pixman_composite (op, src, image, dst,
xRel, yRel, 0, 0, bounds.x1, bounds.y1,
bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
pixman_image_destroy (image);
}
}
if (format)
{
xRel = bounds.x1 + xSrc - xDst;
yRel = bounds.y1 + ySrc - yDst;
pixman_composite (op, src, image, dst,
xRel, yRel, 0, 0, bounds.x1, bounds.y1,
bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
pixman_image_destroy (image);
}
pixman_format_destroy (format);
xRel = bounds.x1 + xSrc - xDst;
yRel = bounds.y1 + ySrc - yDst;
pixman_composite (op, src, image, dst,
xRel, yRel, 0, 0, bounds.x1, bounds.y1,
bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
pixman_image_destroy (image);
}
void
@ -301,7 +254,8 @@ pixman_composite_tri_fan (pixman_operator_t op,
const pixman_point_fixed_t *first;
int xDst, yDst;
int xRel, yRel;
pixman_format_t *format;
pixman_format_t format;
int ret;
if (npoints < 3)
return;
@ -309,20 +263,20 @@ pixman_composite_tri_fan (pixman_operator_t op,
xDst = points[0].x >> 16;
yDst = points[0].y >> 16;
format = pixman_format_create (PIXMAN_FORMAT_NAME_A8);
ret = pixman_format_init (&format, PIXMAN_FORMAT_NAME_A8);
assert (ret);
pixman_point_fixed_bounds (npoints, points, &bounds);
if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1)
return;
image = FbCreateAlphaPicture (dst,
&format,
bounds.x2 - bounds.x1,
bounds.y2 - bounds.y1);
if (!image)
return;
if (format)
{
pixman_point_fixed_bounds (npoints, points, &bounds);
if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1)
return;
image = FbCreateAlphaPicture (dst,
format,
bounds.x2 - bounds.x1,
bounds.y2 - bounds.y1);
if (!image)
return;
}
first = points++;
npoints--;
for (; npoints >= 2; npoints--, points++)
@ -330,38 +284,13 @@ pixman_composite_tri_fan (pixman_operator_t op,
tri.p1 = *first;
tri.p2 = points[0];
tri.p3 = points[1];
if (!format)
{
pixman_triangle_bounds (1, &tri, &bounds);
if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1)
continue;
image = FbCreateAlphaPicture (dst,
format,
bounds.x2 - bounds.x1,
bounds.y2 - bounds.y1);
if (!image)
continue;
}
FbRasterizeTriangle (image, &tri, -bounds.x1, -bounds.y1);
if (!format)
{
xRel = bounds.x1 + xSrc - xDst;
yRel = bounds.y1 + ySrc - yDst;
pixman_composite (op, src, image, dst,
xRel, yRel, 0, 0, bounds.x1, bounds.y1,
bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
pixman_image_destroy (image);
}
}
if (format)
{
xRel = bounds.x1 + xSrc - xDst;
yRel = bounds.y1 + ySrc - yDst;
pixman_composite (op, src, image, dst,
xRel, yRel, 0, 0, bounds.x1, bounds.y1,
bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
pixman_image_destroy (image);
}
pixman_format_destroy (format);
xRel = bounds.x1 + xSrc - xDst;
yRel = bounds.y1 + ySrc - yDst;
pixman_composite (op, src, image, dst,
xRel, yRel, 0, 0, bounds.x1, bounds.y1,
bounds.x2 - bounds.x1, bounds.y2 - bounds.y1);
pixman_image_destroy (image);
}

View file

@ -250,20 +250,27 @@ typedef enum pixman_format_name {
PIXMAN_FORMAT_NAME_BGR24
} pixman_format_name_t;
typedef struct pixman_format pixman_format_t;
/* XXX: Is depth redundant here? */
typedef struct pixman_format {
int format_code;
int depth;
int red, redMask;
int green, greenMask;
int blue, blueMask;
int alpha, alphaMask;
} pixman_format_t;
pixman_private pixman_format_t *
pixman_format_create (pixman_format_name_t name);
pixman_private pixman_format_t *
pixman_format_create_masks (int bpp,
int alpha_mask,
int red_mask,
int green_mask,
int blue_mask);
pixman_private int
pixman_format_init (pixman_format_t *format, pixman_format_name_t name);
pixman_private void
pixman_format_destroy (pixman_format_t *format);
pixman_format_init_masks (pixman_format_t *format,
int bpp,
int alpha_mask,
int red_mask,
int green_mask,
int blue_mask);
pixman_private void
pixman_format_get_masks (pixman_format_t *format,

View file

@ -212,28 +212,23 @@ _cairo_image_surface_create_with_masks (unsigned char *data,
int stride)
{
cairo_surface_t *surface;
pixman_format_t *pixman_format;
pixman_image_t *pixman_image;
cairo_format_t cairo_format;
pixman_format_t pixman_format;
pixman_image_t *pixman_image;
cairo_format_t cairo_format;
pixman_format = pixman_format_create_masks (format->bpp,
format->alpha_mask,
format->red_mask,
format->green_mask,
format->blue_mask);
pixman_format_init_masks (&pixman_format,
format->bpp,
format->alpha_mask,
format->red_mask,
format->green_mask,
format->blue_mask);
if (pixman_format == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t*) &_cairo_surface_nil;
}
cairo_format = _cairo_format_from_pixman_format (&pixman_format);
cairo_format = _cairo_format_from_pixman_format (pixman_format);
pixman_image = pixman_image_create_for_data ((pixman_bits_t *) data, pixman_format,
pixman_image = pixman_image_create_for_data ((pixman_bits_t *) data,
&pixman_format,
width, height, format->bpp, stride);
pixman_format_destroy (pixman_format);
if (pixman_image == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t*) &_cairo_surface_nil;
@ -248,24 +243,26 @@ _cairo_image_surface_create_with_masks (unsigned char *data,
return surface;
}
static pixman_format_t *
_create_pixman_format (cairo_format_t format)
static void
_init_pixman_format (pixman_format_t *pixman_format, cairo_format_t format)
{
int ret;
switch (format) {
case CAIRO_FORMAT_A1:
return pixman_format_create (PIXMAN_FORMAT_NAME_A1);
ret = pixman_format_init (pixman_format, PIXMAN_FORMAT_NAME_A1);
break;
case CAIRO_FORMAT_A8:
return pixman_format_create (PIXMAN_FORMAT_NAME_A8);
ret = pixman_format_init (pixman_format, PIXMAN_FORMAT_NAME_A8);
break;
case CAIRO_FORMAT_RGB24:
return pixman_format_create (PIXMAN_FORMAT_NAME_RGB24);
ret = pixman_format_init (pixman_format, PIXMAN_FORMAT_NAME_RGB24);
break;
case CAIRO_FORMAT_ARGB32:
default:
return pixman_format_create (PIXMAN_FORMAT_NAME_ARGB32);
ret = pixman_format_init (pixman_format, PIXMAN_FORMAT_NAME_ARGB32);
break;
}
assert (ret);
}
/**
@ -293,25 +290,18 @@ cairo_image_surface_create (cairo_format_t format,
int width,
int height)
{
cairo_surface_t *surface;
pixman_format_t *pixman_format;
pixman_image_t *pixman_image;
cairo_surface_t *surface;
pixman_format_t pixman_format;
pixman_image_t *pixman_image;
if (! CAIRO_FORMAT_VALID (format)) {
_cairo_error (CAIRO_STATUS_INVALID_FORMAT);
return (cairo_surface_t*) &_cairo_image_surface_nil_invalid_format;
}
pixman_format = _create_pixman_format (format);
if (pixman_format == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t*) &_cairo_surface_nil;
}
pixman_image = pixman_image_create (pixman_format, width, height);
pixman_format_destroy (pixman_format);
_init_pixman_format (&pixman_format, format);
pixman_image = pixman_image_create (&pixman_format, width, height);
if (pixman_image == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t*) &_cairo_surface_nil;
@ -375,26 +365,20 @@ cairo_image_surface_create_for_data (unsigned char *data,
int height,
int stride)
{
cairo_surface_t *surface;
pixman_format_t *pixman_format;
pixman_image_t *pixman_image;
cairo_surface_t *surface;
pixman_format_t pixman_format;
pixman_image_t *pixman_image;
if (! CAIRO_FORMAT_VALID (format))
return (cairo_surface_t*) &_cairo_surface_nil;
pixman_format = _create_pixman_format (format);
if (pixman_format == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t*) &_cairo_surface_nil;
}
_init_pixman_format (&pixman_format, format);
pixman_image = pixman_image_create_for_data ((pixman_bits_t *) data, pixman_format,
pixman_image = pixman_image_create_for_data ((pixman_bits_t *) data,
&pixman_format,
width, height,
_cairo_format_bpp (format),
stride);
pixman_format_destroy (pixman_format);
if (pixman_image == NULL) {
_cairo_error (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t*) &_cairo_surface_nil;
@ -944,10 +928,11 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
cairo_image_surface_t *src;
cairo_int_status_t status;
pixman_image_t *mask;
pixman_format_t *format;
pixman_format_t format;
pixman_bits_t *mask_data;
int mask_stride;
int mask_bpp;
int mask_stride;
int mask_bpp;
int ret;
/* Special case adding trapezoids onto a mask surface; we want to avoid
* creating an intermediate temporary mask unecessarily.
@ -986,7 +971,8 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
switch (antialias) {
case CAIRO_ANTIALIAS_NONE:
format = pixman_format_create (PIXMAN_FORMAT_NAME_A1);
ret = pixman_format_init (&format, PIXMAN_FORMAT_NAME_A1);
assert (ret);
mask_stride = (width + 31)/8;
mask_bpp = 1;
break;
@ -994,28 +980,23 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
case CAIRO_ANTIALIAS_SUBPIXEL:
case CAIRO_ANTIALIAS_DEFAULT:
default:
format = pixman_format_create (PIXMAN_FORMAT_NAME_A8);
ret = pixman_format_init (&format, PIXMAN_FORMAT_NAME_A8);
assert (ret);
mask_stride = (width + 3) & ~3;
mask_bpp = 8;
break;
}
if (!format) {
status = CAIRO_STATUS_NO_MEMORY;
goto CLEANUP_SOURCE;
}
/* The image must be initially transparent */
mask_data = calloc (1, mask_stride * height);
if (!mask_data) {
if (mask_data == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
pixman_format_destroy (format);
goto CLEANUP_SOURCE;
}
mask = pixman_image_create_for_data (mask_data, format, width, height,
mask = pixman_image_create_for_data (mask_data, &format, width, height,
mask_bpp, mask_stride);
pixman_format_destroy (format);
if (!mask) {
if (mask == NULL) {
status = CAIRO_STATUS_NO_MEMORY;
goto CLEANUP_IMAGE_DATA;
}