[cairo-commit] 3 commits - pixman/src src/cairoint.h
src/cairo-win32-private.h src/cairo-win32-surface.c
src/Makefile.win32 test/Makefile.win32
Vladimir Vukicevic
vladimir at kemper.freedesktop.org
Tue Nov 7 13:16:07 PST 2006
pixman/src/Makefile.win32 | 3
pixman/src/fbmmx.c | 187 +++++++++------
pixman/src/fbpict.c | 57 ++++
src/Makefile.win32 | 3
src/cairo-win32-private.h | 5
src/cairo-win32-surface.c | 550 +++++++++++++++++++++++++++++++++-------------
src/cairoint.h | 5
test/Makefile.win32 | 1
8 files changed, 581 insertions(+), 230 deletions(-)
New commits:
diff-tree 1e4515c548bd2a1440c630d779a948e5b02890e9 (from 6db219c3a16bbbe736653946ea5a4758656a9cd9)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date: Tue Nov 7 13:15:28 2006 -0800
[win32] implement EXTEND_REPEAT in composite when possible
Optimizes EXTEND_REPEAT, especially when DDBs are in use through the
use of PatBlt or manually expanding out the repeated blits (up to a
limit). Will still fall back to fallback code as necessary.
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
old mode 100755
new mode 100644
index cb67147..f11895a
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -41,6 +41,8 @@
#include "cairo-clip-private.h"
#include "cairo-win32-private.h"
+#undef DEBUG_COMPOSITE
+
/* for older SDKs */
#ifndef SHADEBLENDCAPS
#define SHADEBLENDCAPS 120
@@ -667,8 +669,6 @@ _composite_alpha_blend (cairo_win32_surf
static unsigned alpha_blend_checked = FALSE;
static cairo_alpha_blend_func_t alpha_blend = NULL;
- int oldstretchmode;
- BOOL success;
BLENDFUNCTION blend_function;
/* Check for AlphaBlend dynamically to allow compiling on
@@ -707,7 +707,6 @@ _composite_alpha_blend (cairo_win32_surf
blend_function.SourceConstantAlpha = alpha;
blend_function.AlphaFormat = (src->format == CAIRO_FORMAT_ARGB32) ? AC_SRC_ALPHA : 0;
- /*oldstretchmode = SetStretchBltMode(dst->dc, HALFTONE);*/
if (!alpha_blend (dst->dc,
dst_x, dst_y,
dst_w, dst_h,
@@ -716,7 +715,92 @@ _composite_alpha_blend (cairo_win32_surf
src_w, src_h,
blend_function))
return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(AlphaBlend)");
- /*SetStretchBltMode(dst->dc, oldstretchmode);*/
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+_cairo_win32_surface_composite_inner (cairo_win32_surface_t *src,
+ cairo_image_surface_t *src_image,
+ cairo_win32_surface_t *dst,
+ cairo_rectangle_int16_t src_extents,
+ cairo_rectangle_int32_t src_r,
+ cairo_rectangle_int32_t dst_r,
+ int alpha,
+ cairo_bool_t needs_alpha,
+ cairo_bool_t needs_scale)
+{
+ /* Then do BitBlt, StretchDIBits, StretchBlt, AlphaBlend, or MaskBlt */
+ if (src_image) {
+ if (needs_alpha || needs_scale)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ if (dst->flags & CAIRO_WIN32_SURFACE_CAN_STRETCHBLT) {
+ BITMAPINFO bi;
+ bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bi.bmiHeader.biWidth = src_image->width;
+ bi.bmiHeader.biHeight = - src_image->height;
+ bi.bmiHeader.biSizeImage = 0;
+ bi.bmiHeader.biXPelsPerMeter = PELS_72DPI;
+ bi.bmiHeader.biYPelsPerMeter = PELS_72DPI;
+ bi.bmiHeader.biPlanes = 1;
+ bi.bmiHeader.biBitCount = 32;
+ bi.bmiHeader.biCompression = BI_RGB;
+ bi.bmiHeader.biClrUsed = 0;
+ bi.bmiHeader.biClrImportant = 0;
+
+ /* StretchDIBits is broken with top-down dibs; you need to do some
+ * special munging to make the coordinate space work (basically,
+ * need to address everything based on the bottom left, instead of top left,
+ * and need to tell it to flip the resulting image.
+ *
+ * See http://blog.vlad1.com/archives/2006/10/26/134/ and comments.
+ */
+ if (!StretchDIBits (dst->dc,
+ /* dst x,y,w,h */
+ dst_r.x, dst_r.y + dst_r.height - 1,
+ dst_r.width, - (int) dst_r.height,
+ /* src x,y,w,h */
+ src_r.x, src_extents.height - src_r.y + 1,
+ src_r.width, - (int) src_r.height,
+ src_image->data,
+ &bi,
+ DIB_RGB_COLORS,
+ SRCCOPY))
+ return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(StretchDIBits)");
+ }
+ } else if (!needs_alpha) {
+ /* BitBlt or StretchBlt? */
+ if (!needs_scale && (dst->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT)) {
+ if (!BitBlt (dst->dc,
+ dst_r.x, dst_r.y,
+ dst_r.width, dst_r.height,
+ src->dc,
+ src_r.x, src_r.y,
+ SRCCOPY))
+ return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(BitBlt)");
+ } else if (dst->flags & CAIRO_WIN32_SURFACE_CAN_STRETCHBLT) {
+ /* StretchBlt? */
+ /* XXX check if we want HALFTONE, based on the src filter */
+ BOOL success;
+ int oldmode = SetStretchBltMode(dst->dc, HALFTONE);
+ success = StretchBlt(dst->dc,
+ dst_r.x, dst_r.y,
+ dst_r.width, dst_r.height,
+ src->dc,
+ src_r.x, src_r.y,
+ src_r.width, src_r.height,
+ SRCCOPY);
+ SetStretchBltMode(dst->dc, oldmode);
+
+ if (!success)
+ return _cairo_win32_print_gdi_error ("StretchBlt");
+ }
+ } else if (needs_alpha && !needs_scale) {
+ return _composite_alpha_blend (dst, src, alpha,
+ src_r.x, src_r.y, src_r.width, src_r.height,
+ dst_r.x, dst_r.y, dst_r.width, dst_r.height);
+ }
return CAIRO_STATUS_SUCCESS;
}
@@ -741,8 +825,9 @@ _cairo_win32_surface_composite (cairo_op
int alpha;
double scalex, scaley;
cairo_fixed_t x0_fixed, y0_fixed;
+ cairo_int_status_t status;
- cairo_bool_t needs_alpha, needs_scale;
+ cairo_bool_t needs_alpha, needs_scale, needs_repeat;
cairo_image_surface_t *src_image = NULL;
cairo_format_t src_format;
@@ -751,8 +836,8 @@ _cairo_win32_surface_composite (cairo_op
cairo_rectangle_int32_t src_r = { src_x, src_y, width, height };
cairo_rectangle_int32_t dst_r = { dst_x, dst_y, width, height };
-#if 0
- fprintf (stderr, "composite: %d %p %p %p [%d %d] [%d %d] [%d %d] %dx%d\n",
+#ifdef DEBUG_COMPOSITE
+ fprintf (stderr, "+++ composite: %d %p %p %p [%d %d] [%d %d] [%d %d] %dx%d\n",
op, pattern, mask_pattern, abstract_dst, src_x, src_y, mask_x, mask_y, dst_x, dst_y, width, height);
#endif
@@ -772,7 +857,8 @@ _cairo_win32_surface_composite (cairo_op
if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
goto UNSUPPORTED;
- if (pattern->extend != CAIRO_EXTEND_NONE)
+ if (pattern->extend != CAIRO_EXTEND_NONE &&
+ pattern->extend != CAIRO_EXTEND_REPEAT)
goto UNSUPPORTED;
if (mask_pattern) {
@@ -825,8 +911,8 @@ _cairo_win32_surface_composite (cairo_op
}
-#if 0
- fprintf (stderr, "Before check: (%d %d) [%d %d] -> [%d %d %d %d] {mat %f %f %f %f}\n",
+#ifdef DEBUG_COMPOSITE
+ fprintf (stderr, "Before check: src size: (%d %d) xy [%d %d] -> dst [%d %d %d %d] {srcmat %f %f %f %f}\n",
src_extents.width, src_extents.height,
src_x, src_y,
dst_x, dst_y, width, height,
@@ -865,48 +951,61 @@ _cairo_win32_surface_composite (cairo_op
* functions.
*/
- /* If the src rect and the extents of the source image don't overlap at all,
- * we can't do anything useful here.
- */
- if (src_r.x > src_extents.width || src_r.y > src_extents.height ||
- (src_r.x + src_r.width) < 0 || (src_r.y + src_r.height) < 0)
- {
- if (op == CAIRO_OPERATOR_OVER)
- return CAIRO_STATUS_SUCCESS;
- goto UNSUPPORTED;
- }
+#ifdef DEBUG_COMPOSITE
+ fprintf (stderr, "before: [%d %d %d %d] -> [%d %d %d %d]\n",
+ src_r.x, src_r.y, src_r.width, src_r.height,
+ dst_r.x, dst_r.y, dst_r.width, dst_r.height);
+ fflush (stderr);
+#endif
- /* Otherwise, if the src recangle doesn't wholly lie within the
- * src extents, fudge things. We really need to do fixup on the
- * unpainted region -- e.g. the SOURCE operator is broken for
- * areas outside of the extents, because it won't clear that area
- * to transparent black.
+ /* If the src recangle doesn't wholly lie within the src extents,
+ * fudge things. We really need to do fixup on the unpainted
+ * region -- e.g. the SOURCE operator is broken for areas outside
+ * of the extents, because it won't clear that area to transparent
+ * black.
*/
- if (src_r.x < 0) {
- src_r.width += src_r.x;
- src_r.x = 0;
+ if (pattern->extend != CAIRO_EXTEND_REPEAT) {
+ needs_repeat = FALSE;
- dst_r.width += src_r.x;
- dst_r.x -= src_r.x;
- }
+ /* If the src rect and the extents of the source image don't overlap at all,
+ * we can't do anything useful here.
+ */
+ if (src_r.x > src_extents.width || src_r.y > src_extents.height ||
+ (src_r.x + src_r.width) < 0 || (src_r.y + src_r.height) < 0)
+ {
+ if (op == CAIRO_OPERATOR_OVER)
+ return CAIRO_STATUS_SUCCESS;
+ goto UNSUPPORTED;
+ }
- if (src_r.y < 0) {
- src_r.height += src_r.y;
- src_r.y = 0;
+ if (src_r.x < 0) {
+ src_r.width += src_r.x;
+ src_r.x = 0;
- dst_r.height += dst_r.y;
- dst_r.y -= src_r.y;
- }
+ dst_r.width += src_r.x;
+ dst_r.x -= src_r.x;
+ }
- if (src_r.x + src_r.width > src_extents.width) {
- src_r.width = src_extents.width - src_r.x;
- dst_r.width = src_r.width;
- }
+ if (src_r.y < 0) {
+ src_r.height += src_r.y;
+ src_r.y = 0;
- if (src_r.y + src_r.height > src_extents.height) {
- src_r.height = src_extents.height - src_r.y;
- dst_r.height = src_r.height;
+ dst_r.height += dst_r.y;
+ dst_r.y -= src_r.y;
+ }
+
+ if (src_r.x + src_r.width > src_extents.width) {
+ src_r.width = src_extents.width - src_r.x;
+ dst_r.width = src_r.width;
+ }
+
+ if (src_r.y + src_r.height > src_extents.height) {
+ src_r.height = src_extents.height - src_r.y;
+ dst_r.height = src_r.height;
+ }
+ } else {
+ needs_repeat = TRUE;
}
/*
@@ -972,94 +1071,141 @@ _cairo_win32_surface_composite (cairo_op
needs_scale = TRUE;
}
-#if 0
+#ifdef DEBUG_COMPOSITE
fprintf (stderr, "action: [%d %d %d %d] -> [%d %d %d %d]\n",
src_r.x, src_r.y, src_r.width, src_r.height,
dst_r.x, dst_r.y, dst_r.width, dst_r.height);
fflush (stderr);
#endif
- /* Then do BitBlt, StretchDIBits, StretchBlt, AlphaBlend, or MaskBlt */
- if (src_image) {
- if (needs_alpha || needs_scale)
+ /* If we need to repeat, we turn the repeated blit into
+ * a bunch of piece-by-piece blits.
+ */
+ if (needs_repeat) {
+ cairo_rectangle_int32_t piece_src_r, piece_dst_r;
+ uint32_t rendered_width = 0, rendered_height = 0;
+ uint32_t to_render_height, to_render_width;
+ int32_t piece_x, piece_y;
+ int32_t src_start_x = src_r.x % src_extents.width;
+ int32_t src_start_y = src_r.y % src_extents.height;
+
+ if (needs_scale)
goto UNSUPPORTED;
- if (dst->flags & CAIRO_WIN32_SURFACE_CAN_STRETCHBLT) {
- BITMAPINFO bi;
- bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bi.bmiHeader.biWidth = src_image->width;
- bi.bmiHeader.biHeight = - src_image->height;
- bi.bmiHeader.biSizeImage = 0;
- bi.bmiHeader.biXPelsPerMeter = PELS_72DPI;
- bi.bmiHeader.biYPelsPerMeter = PELS_72DPI;
- bi.bmiHeader.biPlanes = 1;
- bi.bmiHeader.biBitCount = 32;
- bi.bmiHeader.biCompression = BI_RGB;
- bi.bmiHeader.biClrUsed = 0;
- bi.bmiHeader.biClrImportant = 0;
+ /* If both the src and dest have an image, we may as well fall
+ * back, because it will be faster than our separate blits.
+ * Our blit code will be fastest when the src is a DDB and the
+ * destination is a DDB.
+ */
+ if ((src_image || src->image) && dst->image)
+ goto UNSUPPORTED;
- /* StretchDIBits is broken with top-down dibs; you need to do some
- * special munging to make the coordinate space work (basically,
- * need to address everything based on the bottom left, instead of top left,
- * and need to tell it to flip the resulting image.
- *
- * See http://blog.vlad1.com/archives/2006/10/26/134/ and comments.
+ /* If the src is not a bitmap but an on-screen (or unknown)
+ * DC, chances are that fallback will be faster.
+ */
+ if (src->bitmap == NULL)
+ goto UNSUPPORTED;
+
+ /* If we can use PatBlt, just do so */
+ if (!src_image && !needs_alpha)
+ {
+ HBRUSH brush;
+ HGDIOBJ old_brush;
+ POINT old_brush_origin;
+
+ /* Set up the brush with our bitmap */
+ brush = CreatePatternBrush (src->bitmap);
+
+ /* SetBrushOrgEx sets the coordinates in the destination DC of where the
+ * pattern should start.
*/
- if (!StretchDIBits (dst->dc,
- /* dst x,y,w,h */
- dst_r.x, dst_r.y + dst_r.height - 1,
- dst_r.width, - dst_r.height,
- /* src x,y,w,h */
- src_r.x, src_extents.height - src_r.y + 1,
- src_r.width, - src_r.height,
- src_image->data,
- &bi,
- DIB_RGB_COLORS,
- SRCCOPY))
- return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(StretchDIBits)");
+ SetBrushOrgEx (dst->dc, dst_r.x - src_start_x,
+ dst_r.y - src_start_y, &old_brush_origin);
+
+ old_brush = SelectObject (dst->dc, brush);
+
+ PatBlt (dst->dc, dst_r.x, dst_r.y, dst_r.width, dst_r.height, PATCOPY);
+
+ /* Restore the old brush and pen */
+ SetBrushOrgEx (dst->dc, old_brush_origin.x, old_brush_origin.y, NULL);
+ SelectObject (dst->dc, old_brush);
+ DeleteObject (brush);
return CAIRO_STATUS_SUCCESS;
}
- } else if (!needs_alpha) {
- /* BitBlt or StretchBlt? */
- if (!needs_scale && (dst->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT)) {
- if (!BitBlt (dst->dc,
- dst_r.x, dst_r.y,
- dst_r.width, dst_r.height,
- src->dc,
- src_r.x, src_r.y,
- SRCCOPY))
- return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(BitBlt)");
- return CAIRO_STATUS_SUCCESS;
- } else if (dst->flags & CAIRO_WIN32_SURFACE_CAN_STRETCHBLT) {
- /* StretchBlt? */
- /* XXX check if we want HALFTONE, based on the src filter */
- BOOL success;
- int oldmode = SetStretchBltMode(dst->dc, HALFTONE);
- success = StretchBlt(dst->dc,
- dst_r.x, dst_r.y,
- dst_r.width, dst_r.height,
- src->dc,
- src_r.x, src_r.y,
- src_r.width, src_r.height,
- SRCCOPY);
- SetStretchBltMode(dst->dc, oldmode);
+ /* If we were not able to use PatBlt, then manually expand out the blit */
- if (!success)
- return _cairo_win32_print_gdi_error ("StretchBlt");
-
- return CAIRO_STATUS_SUCCESS;
+ /* Arbitrary factor; we think that going through
+ * fallback will be faster if we have to do more
+ * than this amount of blits in either direction.
+ */
+ if (dst_r.width / src_extents.width > 5 ||
+ dst_r.height / src_extents.height > 5)
+ goto UNSUPPORTED;
+
+ for (rendered_height = 0;
+ rendered_height < dst_r.height;
+ rendered_height += to_render_height)
+ {
+ piece_y = (src_start_y + rendered_height) % src_extents.height;
+ to_render_height = src_extents.height - piece_y;
+
+ if (rendered_height + to_render_height > dst_r.height)
+ to_render_height = dst_r.height - rendered_height;
+
+ for (rendered_width = 0;
+ rendered_width < dst_r.width;
+ rendered_width += to_render_width)
+ {
+ piece_x = (src_start_x + rendered_width) % src_extents.width;
+ to_render_width = src_extents.width - piece_x;
+
+ if (rendered_width + to_render_width > dst_r.width)
+ to_render_width = dst_r.width - rendered_width;
+
+ piece_src_r.x = piece_x;
+ piece_src_r.y = piece_y;
+ piece_src_r.width = to_render_width;
+ piece_src_r.height = to_render_height;
+
+ piece_dst_r.x = dst_r.x + rendered_width;
+ piece_dst_r.y = dst_r.y + rendered_height;
+ piece_dst_r.width = to_render_width;
+ piece_dst_r.height = to_render_height;
+
+ status = _cairo_win32_surface_composite_inner (src, src_image, dst,
+ src_extents, piece_src_r, piece_dst_r,
+ alpha, needs_alpha, needs_scale);
+ if (status != CAIRO_STATUS_SUCCESS) {
+ /* Uh oh. If something failed, and it's the first
+ * piece, then we can jump to UNSUPPORTED.
+ * Otherwise, this is bad times, because part of the
+ * rendering was already done. */
+ if (rendered_width == 0 &&
+ rendered_height == 0)
+ {
+ goto UNSUPPORTED;
+ }
+
+ return status;
+ }
+ }
}
- } else if (needs_alpha && !needs_scale) {
- return _composite_alpha_blend (dst, src, alpha,
- src_r.x, src_r.y, src_r.width, src_r.height,
- dst_r.x, dst_r.y, dst_r.width, dst_r.height);
+ } else {
+ status = _cairo_win32_surface_composite_inner (src, src_image, dst,
+ src_extents, src_r, dst_r,
+ alpha, needs_alpha, needs_scale);
}
+ if (status == CAIRO_STATUS_SUCCESS)
+ return status;
+
UNSUPPORTED:
/* Fall back to image surface directly, if this is a DIB surface */
if (dst->image) {
+ GdiFlush();
+
return dst->image->backend->composite (op, pattern, mask_pattern,
dst->image,
src_x, src_y,
@@ -1391,23 +1537,23 @@ _cairo_win32_surface_show_glyphs (void
for (i = 0; i < num_glyphs; ++i) {
output_count++;
- glyph_buf[i] = glyphs[i].index;
+ glyph_buf[i] = (WORD) glyphs[i].index;
if (i == num_glyphs - 1)
dx_buf[i] = 0;
else
- dx_buf[i] = floor(((glyphs[i+1].x - glyphs[i].x) * WIN32_FONT_LOGICAL_SCALE) + 0.5);
+ dx_buf[i] = (int) floor(((glyphs[i+1].x - glyphs[i].x) * WIN32_FONT_LOGICAL_SCALE) + 0.5);
if (i == num_glyphs - 1 || glyphs[i].y != glyphs[i+1].y) {
const int offset = (i - output_count) + 1;
double user_x = glyphs[offset].x;
double user_y = last_y;
- double logical_x, logical_y;
+ int logical_x, logical_y;
cairo_matrix_transform_point(&device_to_logical,
&user_x, &user_y);
- logical_x = floor(user_x + 0.5);
- logical_y = floor(user_y + 0.5);
+ logical_x = (int) floor(user_x + 0.5);
+ logical_y = (int) floor(user_y + 0.5);
win_result = ExtTextOutW(dst->dc,
logical_x,
@@ -1509,10 +1655,10 @@ cairo_win32_surface_create (HDC hdc)
surface->is_dib = FALSE;
surface->saved_dc_bitmap = NULL;
- surface->clip_rect.x = rect.left;
- surface->clip_rect.y = rect.top;
- surface->clip_rect.width = rect.right - rect.left;
- surface->clip_rect.height = rect.bottom - rect.top;
+ surface->clip_rect.x = (int16_t) rect.left;
+ surface->clip_rect.y = (int16_t) rect.top;
+ surface->clip_rect.width = (uint16_t) (rect.right - rect.left);
+ surface->clip_rect.height = (uint16_t) (rect.bottom - rect.top);
if (surface->clip_rect.width == 0 ||
surface->clip_rect.height == 0)
diff-tree 6db219c3a16bbbe736653946ea5a4758656a9cd9 (from 3e002a474b64c83f8768ba8918209eca9d7599a3)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date: Fri Nov 3 10:04:28 2006 -0800
[win32] clean up win32_surface_composite
Make sure that all operations are correct (the operations chosen
are listed in cairo-win32-surface.c); in particular, deal with the extra
byte present in FORMAT_RGB24 surfaces correctly.
Also adds support for calling StretchDIBits to draw RGB24
cairo_image_surfaces directly.
diff --git a/src/Makefile.win32 b/src/Makefile.win32
index 1b91d4d..27d17d0 100644
--- a/src/Makefile.win32
+++ b/src/Makefile.win32
@@ -1,7 +1,7 @@
CC = cl
LINK = link
-CFLAGS = /MD /Zi /nologo /O2 /c /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /I../pixman/src /I. /DPACKAGE_VERSION="" /DPACKAGE_BUGREPORT=""
+CFLAGS = /MD /Zi /nologo /O2 /c /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /I../pixman/src /I. /DPACKAGE_VERSION="" /DPACKAGE_BUGREPORT="" /DCAIRO_BUILD
DEFFILE = cairo.def
srcdir = `pwd`
@@ -43,6 +43,7 @@ SOURCES = \
cairo-surface-fallback.c \
cairo-surface.c \
cairo-traps.c \
+ cairo-cff-subset.c \
cairo-truetype-subset.c \
cairo-type1-fallback.c \
cairo-unicode.c \
diff --git a/src/cairo-win32-private.h b/src/cairo-win32-private.h
index 2f7fc84..220c9d3 100644
--- a/src/cairo-win32-private.h
+++ b/src/cairo-win32-private.h
@@ -93,7 +93,10 @@ enum {
CAIRO_WIN32_SURFACE_CAN_ALPHABLEND = (1<<3),
/* Whether we can use StretchBlt with this surface */
- CAIRO_WIN32_SURFACE_CAN_STRETCHBLT = (1<<4)
+ CAIRO_WIN32_SURFACE_CAN_STRETCHBLT = (1<<4),
+
+ /* Whether we can use StretchDIBits with this surface */
+ CAIRO_WIN32_SURFACE_CAN_STRETCHDIB = (1<<5)
};
cairo_status_t
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index 7aeb256..cb67147 100755
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -49,7 +49,7 @@
#define SB_NONE 0x00000000
#endif
-#define PELS_72DPI (72. / 0.0254)
+#define PELS_72DPI ((LONG)(72. / 0.0254))
#define NIL_SURFACE ((cairo_surface_t*)&_cairo_surface_nil)
static const cairo_surface_backend_t cairo_win32_surface_backend;
@@ -108,6 +108,7 @@ _cairo_win32_flags_for_dc (HDC dc)
flags |= CAIRO_WIN32_SURFACE_CAN_BITBLT;
flags |= CAIRO_WIN32_SURFACE_CAN_ALPHABLEND;
flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHBLT;
+ flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHDIB;
} else {
int cap;
@@ -120,6 +121,8 @@ _cairo_win32_flags_for_dc (HDC dc)
flags |= CAIRO_WIN32_SURFACE_CAN_BITBLT;
if (cap & RC_STRETCHBLT)
flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHBLT;
+ if (cap & RC_STRETCHDIB)
+ flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHDIB;
}
return flags;
@@ -223,8 +226,9 @@ _create_dc_and_bitmap (cairo_win32_surfa
bitmap_info->bmiColors[i].rgbGreen = i * 255;
bitmap_info->bmiColors[i].rgbRed = i * 255;
bitmap_info->bmiColors[i].rgbReserved = 0;
- break;
}
+
+ break;
}
surface->dc = CreateCompatibleDC (original_dc);
@@ -695,17 +699,8 @@ _composite_alpha_blend (cairo_win32_surf
return CAIRO_INT_STATUS_UNSUPPORTED;
if (!(dst->flags & CAIRO_WIN32_SURFACE_CAN_ALPHABLEND))
return CAIRO_INT_STATUS_UNSUPPORTED;
-
if (src->format == CAIRO_FORMAT_RGB24 && dst->format == CAIRO_FORMAT_ARGB32)
- {
- /* Both of these are represented as 32bpp internally, and AlphaBlend
- * DOES NOT throw away source alpha is AC_SRC_ALPHA is not specified,
- * it just multiplies it by the SourceConstantAlpha, along with the
- * R G B components.
- * XXX there has to be a way to do this!
- */
return CAIRO_INT_STATUS_UNSUPPORTED;
- }
blend_function.BlendOp = AC_SRC_OVER;
blend_function.BlendFlags = 0;
@@ -720,7 +715,7 @@ _composite_alpha_blend (cairo_win32_surf
src_x, src_y,
src_w, src_h,
blend_function))
- return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite");
+ return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(AlphaBlend)");
/*SetStretchBltMode(dst->dc, oldstretchmode);*/
return CAIRO_STATUS_SUCCESS;
@@ -744,18 +739,18 @@ _cairo_win32_surface_composite (cairo_op
cairo_win32_surface_t *src;
cairo_surface_pattern_t *src_surface_pattern;
int alpha;
- int itx, ity;
double scalex, scaley;
cairo_fixed_t x0_fixed, y0_fixed;
- int orig_dst_x = dst_x, orig_dst_y = dst_y;
- int real_src_width, real_src_height;
- int src_width, src_height;
- int dst_width, dst_height;
-
cairo_bool_t needs_alpha, needs_scale;
cairo_image_surface_t *src_image = NULL;
+ cairo_format_t src_format;
+ cairo_rectangle_int16_t src_extents;
+
+ cairo_rectangle_int32_t src_r = { src_x, src_y, width, height };
+ cairo_rectangle_int32_t dst_r = { dst_x, dst_y, width, height };
+
#if 0
fprintf (stderr, "composite: %d %p %p %p [%d %d] [%d %d] [%d %d] %dx%d\n",
op, pattern, mask_pattern, abstract_dst, src_x, src_y, mask_x, mask_y, dst_x, dst_y, width, height);
@@ -767,17 +762,18 @@ _cairo_win32_surface_composite (cairo_op
*/
if ((dst->flags & (CAIRO_WIN32_SURFACE_CAN_BITBLT |
CAIRO_WIN32_SURFACE_CAN_ALPHABLEND |
- CAIRO_WIN32_SURFACE_CAN_STRETCHBLT))
+ CAIRO_WIN32_SURFACE_CAN_STRETCHBLT |
+ CAIRO_WIN32_SURFACE_CAN_STRETCHDIB))
== 0)
{
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ goto UNSUPPORTED;
}
if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ goto UNSUPPORTED;
if (pattern->extend != CAIRO_EXTEND_NONE)
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ goto UNSUPPORTED;
if (mask_pattern) {
/* FIXME: When we fully support RENDER style 4-channel
@@ -794,22 +790,44 @@ _cairo_win32_surface_composite (cairo_op
src_surface_pattern = (cairo_surface_pattern_t *)pattern;
src = (cairo_win32_surface_t *)src_surface_pattern->surface;
- /* Disable this for now */
-#if 0
- if (src->base.type == CAIRO_SURFACE_TYPE_IMAGE) {
+ if (src->base.type == CAIRO_SURFACE_TYPE_IMAGE &&
+ dst->flags & (CAIRO_WIN32_SURFACE_CAN_STRETCHDIB))
+ {
+ /* In some very limited cases, we can use StretchDIBits to draw
+ * an image surface directly:
+ * - source is CAIRO_FORMAT_ARGB32
+ * - dest is CAIRO_FORMAT_ARGB32
+ * - alpha is 255
+ * - operator is SOURCE or OVER
+ * - image stride is 4*width
+ */
src_image = (cairo_image_surface_t*) src;
- if (src_image->format != CAIRO_FORMAT_RGB24)
- return CAIRO_INT_STATUS_UNSUPPORTED;
- } else
-#endif
- if (src->base.backend != dst->base.backend) {
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ if (src_image->format != CAIRO_FORMAT_RGB24 ||
+ dst->format != CAIRO_FORMAT_RGB24 ||
+ alpha != 255 ||
+ (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_OVER) ||
+ src_image->stride != (src_image->width * 4))
+ {
+ goto UNSUPPORTED;
+ }
+
+ src_format = src_image->format;
+ src_extents.x = 0;
+ src_extents.y = 0;
+ src_extents.width = src_image->width;
+ src_extents.height = src_image->height;
+ } else if (src->base.backend != dst->base.backend) {
+ goto UNSUPPORTED;
+ } else {
+ src_format = src->format;
+ src_extents = src->extents;
}
+
#if 0
fprintf (stderr, "Before check: (%d %d) [%d %d] -> [%d %d %d %d] {mat %f %f %f %f}\n",
- src->extents.width, src->extents.height,
+ src_extents.width, src_extents.height,
src_x, src_y,
dst_x, dst_y, width, height,
pattern->matrix.x0, pattern->matrix.y0, pattern->matrix.xx, pattern->matrix.yy);
@@ -826,121 +844,190 @@ _cairo_win32_surface_composite (cairo_op
!_cairo_fixed_is_integer(x0_fixed) ||
!_cairo_fixed_is_integer(y0_fixed))
{
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ goto UNSUPPORTED;
}
- itx = _cairo_fixed_integer_part(x0_fixed);
- ity = _cairo_fixed_integer_part(y0_fixed);
-
scalex = pattern->matrix.xx;
scaley = pattern->matrix.yy;
- src_x += itx;
- src_y += ity;
+ src_r.x += _cairo_fixed_integer_part(x0_fixed);
+ src_r.y += _cairo_fixed_integer_part(y0_fixed);
- if (scalex <= 0.0 || scaley <= 0.0)
+ /* Success, right? */
+ if (scalex == 0.0 || scaley == 0.0)
return CAIRO_STATUS_SUCCESS;
if (scalex != 1.0 || scaley != 1.0)
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ goto UNSUPPORTED;
/* If the src coordinates are outside of the source surface bounds,
* we have to fix them up, because this is an error for the GDI
* functions.
- * XXX Make sure to correctly clear out the unpainted region.
*/
- if (src_x < 0) {
- width += src_x;
- dst_x -= src_x;
- src_x = 0;
+ /* If the src rect and the extents of the source image don't overlap at all,
+ * we can't do anything useful here.
+ */
+ if (src_r.x > src_extents.width || src_r.y > src_extents.height ||
+ (src_r.x + src_r.width) < 0 || (src_r.y + src_r.height) < 0)
+ {
+ if (op == CAIRO_OPERATOR_OVER)
+ return CAIRO_STATUS_SUCCESS;
+ goto UNSUPPORTED;
}
- if (src_y < 0) {
- height += src_y;
- dst_y -= src_y;
- src_y = 0;
+ /* Otherwise, if the src recangle doesn't wholly lie within the
+ * src extents, fudge things. We really need to do fixup on the
+ * unpainted region -- e.g. the SOURCE operator is broken for
+ * areas outside of the extents, because it won't clear that area
+ * to transparent black.
+ */
+
+ if (src_r.x < 0) {
+ src_r.width += src_r.x;
+ src_r.x = 0;
+
+ dst_r.width += src_r.x;
+ dst_r.x -= src_r.x;
}
- if (src_x + width > src->extents.width)
- dst_width = src->extents.width - src_x;
- else
- dst_width = width;
+ if (src_r.y < 0) {
+ src_r.height += src_r.y;
+ src_r.y = 0;
- if (src_y + height > src->extents.height)
- dst_height = src->extents.height - src_y;
- else
- dst_height = height;
+ dst_r.height += dst_r.y;
+ dst_r.y -= src_r.y;
+ }
+
+ if (src_r.x + src_r.width > src_extents.width) {
+ src_r.width = src_extents.width - src_r.x;
+ dst_r.width = src_r.width;
+ }
+
+ if (src_r.y + src_r.height > src_extents.height) {
+ src_r.height = src_extents.height - src_r.y;
+ dst_r.height = src_r.height;
+ }
- src_width = dst_width;
- src_height = dst_height;
+ /*
+ * Operations that we can do:
+ *
+ * RGB OVER RGB -> BitBlt (same as SOURCE)
+ * RGB OVER ARGB -> UNSUPPORTED (AlphaBlend treats this as a BitBlt, even with SCA 255 and no AC_SRC_ALPHA)
+ * ARGB OVER ARGB -> AlphaBlend, with AC_SRC_ALPHA
+ * ARGB OVER RGB -> AlphaBlend, with AC_SRC_ALPHA; we'll have junk in the dst A byte
+ *
+ * RGB OVER RGB + mask -> AlphaBlend, no AC_SRC_ALPHA
+ * RGB OVER ARGB + mask -> UNSUPPORTED
+ * ARGB OVER ARGB + mask -> AlphaBlend, with AC_SRC_ALPHA
+ * ARGB OVER RGB + mask -> AlphaBlend, with AC_SRC_ALPHA; junk in the dst A byte
+ *
+ * RGB SOURCE RGB -> BitBlt
+ * RGB SOURCE ARGB -> UNSUPPORTED (AlphaBlend treats this as a BitBlt, even with SCA 255 and no AC_SRC_ALPHA)
+ * ARGB SOURCE ARGB -> BitBlt
+ * ARGB SOURCE RGB -> BitBlt
+ *
+ * RGB SOURCE RGB + mask -> unsupported
+ * RGB SOURCE ARGB + mask -> unsupported
+ * ARGB SOURCE ARGB + mask -> unsupported
+ * ARGB SOURCE RGB + mask -> unsupported
+ */
/*
* Figure out what action to take.
- * XXX handle SOURCE with alpha != 255
*/
- if (alpha == 255 &&
- (dst->format == src->format) &&
- ((op == CAIRO_OPERATOR_SOURCE && (dst->format == CAIRO_FORMAT_ARGB32 ||
- dst->format == CAIRO_FORMAT_RGB24)) ||
- (op == CAIRO_OPERATOR_OVER && dst->format == CAIRO_FORMAT_RGB24)))
- {
- needs_alpha = FALSE;
- } else if ((op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_SOURCE) &&
- (src->format == CAIRO_FORMAT_RGB24 || src->format == CAIRO_FORMAT_ARGB32) &&
- (dst->format == CAIRO_FORMAT_RGB24 || dst->format == CAIRO_FORMAT_ARGB32))
- {
- needs_alpha = TRUE;
+ if (op == CAIRO_OPERATOR_OVER) {
+ if (alpha == 0)
+ return CAIRO_STATUS_SUCCESS;
+
+ if (src_format == dst->format) {
+ if (alpha == 255 && src_format == CAIRO_FORMAT_RGB24) {
+ needs_alpha = FALSE;
+ } else {
+ needs_alpha = TRUE;
+ }
+ } else if (src_format == CAIRO_FORMAT_ARGB32 &&
+ dst->format == CAIRO_FORMAT_RGB24)
+ {
+ needs_alpha = TRUE;
+ } else {
+ goto UNSUPPORTED;
+ }
+ } else if (alpha == 255 && op == CAIRO_OPERATOR_SOURCE) {
+ if ((src_format == dst->format) ||
+ (src_format == CAIRO_FORMAT_ARGB32 && dst->format == CAIRO_FORMAT_RGB24))
+ {
+ needs_alpha = FALSE;
+ } else {
+ goto UNSUPPORTED;
+ }
} else {
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ goto UNSUPPORTED;
}
-
+
if (scalex == 1.0 && scaley == 1.0) {
needs_scale = FALSE;
} else {
+ /* Should never be reached until we turn StretchBlt back on */
needs_scale = TRUE;
}
#if 0
fprintf (stderr, "action: [%d %d %d %d] -> [%d %d %d %d]\n",
- src_x, src_y, src_width, src_height,
- dst_x, dst_y, dst_width, dst_height);
+ src_r.x, src_r.y, src_r.width, src_r.height,
+ dst_r.x, dst_r.y, dst_r.width, dst_r.height);
fflush (stderr);
#endif
/* Then do BitBlt, StretchDIBits, StretchBlt, AlphaBlend, or MaskBlt */
if (src_image) {
- BITMAPINFO bi;
- bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bi.bmiHeader.biWidth = src_image->width;
- bi.bmiHeader.biHeight = src_image->height;
- bi.bmiHeader.biSizeImage = 0;
- bi.bmiHeader.biXPelsPerMeter = PELS_72DPI;
- bi.bmiHeader.biYPelsPerMeter = PELS_72DPI;
- bi.bmiHeader.biPlanes = 1;
- bi.bmiHeader.biBitCount = 32;
- bi.bmiHeader.biCompression = BI_RGB;
- bi.bmiHeader.biClrUsed = 0;
- bi.bmiHeader.biClrImportant = 0;
-
- if (!StretchDIBits (dst->dc,
- dst_x, dst_y, dst_width, dst_height,
- src_x, src_y, src_width, src_height,
- src_image->data,
- &bi,
- DIB_RGB_COLORS,
- SRCCOPY))
- return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(StretchDIBits)");
+ if (needs_alpha || needs_scale)
+ goto UNSUPPORTED;
- return CAIRO_STATUS_SUCCESS;
+ if (dst->flags & CAIRO_WIN32_SURFACE_CAN_STRETCHBLT) {
+ BITMAPINFO bi;
+ bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bi.bmiHeader.biWidth = src_image->width;
+ bi.bmiHeader.biHeight = - src_image->height;
+ bi.bmiHeader.biSizeImage = 0;
+ bi.bmiHeader.biXPelsPerMeter = PELS_72DPI;
+ bi.bmiHeader.biYPelsPerMeter = PELS_72DPI;
+ bi.bmiHeader.biPlanes = 1;
+ bi.bmiHeader.biBitCount = 32;
+ bi.bmiHeader.biCompression = BI_RGB;
+ bi.bmiHeader.biClrUsed = 0;
+ bi.bmiHeader.biClrImportant = 0;
+
+ /* StretchDIBits is broken with top-down dibs; you need to do some
+ * special munging to make the coordinate space work (basically,
+ * need to address everything based on the bottom left, instead of top left,
+ * and need to tell it to flip the resulting image.
+ *
+ * See http://blog.vlad1.com/archives/2006/10/26/134/ and comments.
+ */
+ if (!StretchDIBits (dst->dc,
+ /* dst x,y,w,h */
+ dst_r.x, dst_r.y + dst_r.height - 1,
+ dst_r.width, - dst_r.height,
+ /* src x,y,w,h */
+ src_r.x, src_extents.height - src_r.y + 1,
+ src_r.width, - src_r.height,
+ src_image->data,
+ &bi,
+ DIB_RGB_COLORS,
+ SRCCOPY))
+ return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(StretchDIBits)");
+
+ return CAIRO_STATUS_SUCCESS;
+ }
} else if (!needs_alpha) {
/* BitBlt or StretchBlt? */
if (!needs_scale && (dst->flags & CAIRO_WIN32_SURFACE_CAN_BITBLT)) {
if (!BitBlt (dst->dc,
- dst_x, dst_y,
- dst_width, dst_height,
+ dst_r.x, dst_r.y,
+ dst_r.width, dst_r.height,
src->dc,
- src_x, src_y,
+ src_r.x, src_r.y,
SRCCOPY))
return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite(BitBlt)");
@@ -951,25 +1038,34 @@ _cairo_win32_surface_composite (cairo_op
BOOL success;
int oldmode = SetStretchBltMode(dst->dc, HALFTONE);
success = StretchBlt(dst->dc,
- dst_x, dst_y,
- dst_width, dst_height,
+ dst_r.x, dst_r.y,
+ dst_r.width, dst_r.height,
src->dc,
- src_x, src_y,
- src_width, src_height,
+ src_r.x, src_r.y,
+ src_r.width, src_r.height,
SRCCOPY);
SetStretchBltMode(dst->dc, oldmode);
- if (!success) {
- _cairo_win32_print_gdi_error ("StretchBlt");
- return CAIRO_INT_STATUS_UNSUPPORTED;
- }
+ if (!success)
+ return _cairo_win32_print_gdi_error ("StretchBlt");
return CAIRO_STATUS_SUCCESS;
}
} else if (needs_alpha && !needs_scale) {
return _composite_alpha_blend (dst, src, alpha,
- src_x, src_y, src_width, src_height,
- dst_x, dst_y, dst_width, dst_height);
+ src_r.x, src_r.y, src_r.width, src_r.height,
+ dst_r.x, dst_r.y, dst_r.width, dst_r.height);
+ }
+
+UNSUPPORTED:
+ /* Fall back to image surface directly, if this is a DIB surface */
+ if (dst->image) {
+ return dst->image->backend->composite (op, pattern, mask_pattern,
+ dst->image,
+ src_x, src_y,
+ mask_x, mask_y,
+ dst_x, dst_y,
+ width, height);
}
return CAIRO_INT_STATUS_UNSUPPORTED;
diff --git a/src/cairoint.h b/src/cairoint.h
index ed0beee..d15064d 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -281,6 +281,11 @@ typedef struct _cairo_rectangle_int16 {
uint16_t width, height;
} cairo_rectangle_int16_t, cairo_glyph_size_t;
+typedef struct _cairo_rectangle_int32 {
+ int32_t x, y;
+ uint32_t width, height;
+} cairo_rectangle_int32_t;
+
/* Sure wish C had a real enum type so that this would be distinct
from cairo_status_t. Oh well, without that, I'll use this bogus 1000
offset */
diff --git a/test/Makefile.win32 b/test/Makefile.win32
index c2e7338..9797b75 100644
--- a/test/Makefile.win32
+++ b/test/Makefile.win32
@@ -57,7 +57,6 @@ operator-source \
paint \
paint-source-alpha \
paint-with-alpha \
-path-data \
pattern-get-type \
pattern-getters \
pixman-rotate \
diff-tree 3e002a474b64c83f8768ba8918209eca9d7599a3 (from fc87d4148131ce01f645aec12a5e1b6d6b55d337)
Author: Vladimir Vukicevic <vladimir at pobox.com>
Date: Fri Nov 3 09:47:31 2006 -0800
[win32] Update pixman MMX code to work with MSVC
Patch from Tor Lillqvist.
diff --git a/pixman/src/Makefile.win32 b/pixman/src/Makefile.win32
index ec83f73..7fda0bb 100644
--- a/pixman/src/Makefile.win32
+++ b/pixman/src/Makefile.win32
@@ -1,5 +1,5 @@
CC = cl
-CFLAGS = /nologo /MD /Zi /O2 /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE
+CFLAGS = /nologo /MD /Zi /O2 /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DUSE_MMX
SOURCES = \
fbcompose.c \
@@ -20,6 +20,7 @@ SOURCES = \
icutil.c \
pixregion.c \
renderedge.c \
+ fbmmx.c \
$(NULL)
OBJECTS = $(subst .c,.obj,$(SOURCES))
diff --git a/pixman/src/fbmmx.c b/pixman/src/fbmmx.c
index 4d603bf..a99168c 100644
--- a/pixman/src/fbmmx.c
+++ b/pixman/src/fbmmx.c
@@ -80,32 +80,41 @@
/* --------------- MMX primitivess ------------------------------------ */
+#ifdef __GNUC__
typedef unsigned long long ullong;
+typedef ullong mmxdatafield;
+#endif
+#ifdef _MSC_VER
+typedef unsigned __int64 ullong;
+typedef __m64 mmxdatafield;
+#endif
typedef struct
{
- ullong mmx_4x00ff;
- ullong mmx_4x0080;
- ullong mmx_565_rgb;
- ullong mmx_565_unpack_multiplier;
- ullong mmx_565_r;
- ullong mmx_565_g;
- ullong mmx_565_b;
- ullong mmx_mask_0;
- ullong mmx_mask_1;
- ullong mmx_mask_2;
- ullong mmx_mask_3;
- ullong mmx_full_alpha;
- ullong mmx_ffff0000ffff0000;
- ullong mmx_0000ffff00000000;
- ullong mmx_000000000000ffff;
+ mmxdatafield mmx_4x00ff;
+ mmxdatafield mmx_4x0080;
+ mmxdatafield mmx_565_rgb;
+ mmxdatafield mmx_565_unpack_multiplier;
+ mmxdatafield mmx_565_r;
+ mmxdatafield mmx_565_g;
+ mmxdatafield mmx_565_b;
+ mmxdatafield mmx_mask_0;
+ mmxdatafield mmx_mask_1;
+ mmxdatafield mmx_mask_2;
+ mmxdatafield mmx_mask_3;
+ mmxdatafield mmx_full_alpha;
+ mmxdatafield mmx_ffff0000ffff0000;
+ mmxdatafield mmx_0000ffff00000000;
+ mmxdatafield mmx_000000000000ffff;
} MMXData;
static const MMXData c =
{
+#ifdef __GNUC__
.mmx_4x00ff = 0x00ff00ff00ff00ffULL,
.mmx_4x0080 = 0x0080008000800080ULL,
.mmx_565_rgb = 0x000001f0003f001fULL,
+ .mmx_565_unpack_multiplier = 0x0000008404100840ULL,
.mmx_565_r = 0x000000f800000000ULL,
.mmx_565_g = 0x0000000000fc0000ULL,
.mmx_565_b = 0x00000000000000f8ULL,
@@ -114,13 +123,39 @@ static const MMXData c =
.mmx_mask_2 = 0xffff0000ffffffffULL,
.mmx_mask_3 = 0x0000ffffffffffffULL,
.mmx_full_alpha = 0x00ff000000000000ULL,
- .mmx_565_unpack_multiplier = 0x0000008404100840ULL,
.mmx_ffff0000ffff0000 = 0xffff0000ffff0000ULL,
.mmx_0000ffff00000000 = 0x0000ffff00000000ULL,
.mmx_000000000000ffff = 0x000000000000ffffULL,
+#endif
+#ifdef _MSC_VER
+ { 0x00ff00ff00ff00ffUI64 },
+ { 0x0080008000800080UI64 },
+ { 0x000001f0003f001fUI64 },
+ { 0x0000008404100840UI64 },
+ { 0x000000f800000000UI64 },
+ { 0x0000000000fc0000UI64 },
+ { 0x00000000000000f8UI64 },
+ { 0xffffffffffff0000UI64 },
+ { 0xffffffff0000ffffUI64 },
+ { 0xffff0000ffffffffUI64 },
+ { 0x0000ffffffffffffUI64 },
+ { 0x00ff000000000000UI64 },
+ { 0xffff0000ffff0000UI64 },
+ { 0x0000ffff00000000UI64 },
+ { 0x000000000000ffffUI64 },
+#endif
};
+#ifdef _MSC_VER
+#define __inline__ __forceinline
+#endif
+
+#ifdef __GNUC__
#define MC(x) ((__m64) c.mmx_##x)
+#endif
+#ifdef _MSC_VER
+#define MC(x) c.mmx_##x
+#endif
static __inline__ __m64
shift (__m64 v, int s)
@@ -255,6 +290,7 @@ in (__m64 src,
return pix_multiply (src, mask);
}
+#ifndef _MSC_VER
static __inline__ __m64
in_over (__m64 src,
__m64 srca,
@@ -263,6 +299,9 @@ in_over (__m64 src,
{
return over(in(src, mask), pix_multiply(srca, mask), dest);
}
+#else
+#define in_over(src, srca, mask, dest) over(in(src, mask), pix_multiply(srca, mask), dest)
+#endif
static __inline__ __m64
load8888 (CARD32 v)
@@ -355,6 +394,7 @@ pack565 (__m64 pixel, __m64 target, int
return _mm_or_si64 (b, p);
}
+#ifndef _MSC_VER
static __inline__ __m64
pix_add_mul (__m64 x, __m64 a, __m64 y, __m64 b)
{
@@ -367,6 +407,15 @@ pix_add_mul (__m64 x, __m64 a, __m64 y,
return x;
}
+#else
+#define pix_add_mul(x, a, y, b) \
+( x = _mm_mullo_pi16 (x, a), \
+ y = _mm_mullo_pi16 (y, b), \
+ x = _mm_adds_pu16 (x, MC(4x0080)), \
+ x = _mm_adds_pu16 (x, y), \
+ x = _mm_adds_pu16 (x, _mm_srli_pi16 (x, 8)), \
+ _mm_srli_pi16 (x, 8) )
+#endif
/* --------------- MMX code patch for fbcompose.c --------------------- */
@@ -981,10 +1030,9 @@ fbCompositeSolid_nx0565mmx (pixman_opera
while (w && (unsigned long)dst & 7)
{
- ullong d = *dst;
- __m64 vdest = expand565 ((__m64)d, 0);
+ __m64 vdest = expand565 (_mm_cvtsi32_si64 (*dst), 0);
vdest = pack565(over(vsrc, vsrca, vdest), vdest, 0);
- *dst = (ullong)vdest;
+ *dst = _mm_cvtsi64_si32 (vdest);
w--;
dst++;
@@ -1011,10 +1059,9 @@ fbCompositeSolid_nx0565mmx (pixman_opera
while (w)
{
- ullong d = *dst;
- __m64 vdest = expand565 ((__m64)d, 0);
+ __m64 vdest = expand565 (_mm_cvtsi32_si64 (*dst), 0);
vdest = pack565(over(vsrc, vsrca, vdest), vdest, 0);
- *dst = (ullong)vdest;
+ *dst = _mm_cvtsi64_si32 (vdest);
w--;
dst++;
@@ -1187,7 +1234,7 @@ fbCompositeSrc_8888x8x8888mmx (pixman_op
__m64 vsrc0 = expand8888 (vs, 0);
__m64 vsrc1 = expand8888 (vs, 1);
- *(__m64 *)dst = (__m64)pack8888 (
+ *(__m64 *)dst = pack8888 (
in_over (vsrc0, expand_alpha (vsrc0), vmask, expand8888 (vd, 0)),
in_over (vsrc1, expand_alpha (vsrc1), vmask, expand8888 (vd, 1)));
@@ -1285,35 +1332,35 @@ fbCompositeSrc_x888x8x8888mmx (pixman_op
__m64 vs6 = *(__m64 *)(src + 12);
__m64 vs7 = *(__m64 *)(src + 14);
- vd0 = (__m64)pack8888 (
+ vd0 = pack8888 (
in_over (expand8888 (vs0, 0), srca, vmask, expand8888 (vd0, 0)),
in_over (expand8888 (vs0, 1), srca, vmask, expand8888 (vd0, 1)));
- vd1 = (__m64)pack8888 (
+ vd1 = pack8888 (
in_over (expand8888 (vs1, 0), srca, vmask, expand8888 (vd1, 0)),
in_over (expand8888 (vs1, 1), srca, vmask, expand8888 (vd1, 1)));
- vd2 = (__m64)pack8888 (
+ vd2 = pack8888 (
in_over (expand8888 (vs2, 0), srca, vmask, expand8888 (vd2, 0)),
in_over (expand8888 (vs2, 1), srca, vmask, expand8888 (vd2, 1)));
- vd3 = (__m64)pack8888 (
+ vd3 = pack8888 (
in_over (expand8888 (vs3, 0), srca, vmask, expand8888 (vd3, 0)),
in_over (expand8888 (vs3, 1), srca, vmask, expand8888 (vd3, 1)));
- vd4 = (__m64)pack8888 (
+ vd4 = pack8888 (
in_over (expand8888 (vs4, 0), srca, vmask, expand8888 (vd4, 0)),
in_over (expand8888 (vs4, 1), srca, vmask, expand8888 (vd4, 1)));
- vd5 = (__m64)pack8888 (
+ vd5 = pack8888 (
in_over (expand8888 (vs5, 0), srca, vmask, expand8888 (vd5, 0)),
in_over (expand8888 (vs5, 1), srca, vmask, expand8888 (vd5, 1)));
- vd6 = (__m64)pack8888 (
+ vd6 = pack8888 (
in_over (expand8888 (vs6, 0), srca, vmask, expand8888 (vd6, 0)),
in_over (expand8888 (vs6, 1), srca, vmask, expand8888 (vd6, 1)));
- vd7 = (__m64)pack8888 (
+ vd7 = pack8888 (
in_over (expand8888 (vs7, 0), srca, vmask, expand8888 (vd7, 0)),
in_over (expand8888 (vs7, 1), srca, vmask, expand8888 (vd7, 1)));
@@ -1426,7 +1473,7 @@ fbCompositeSolidMask_nx8x8888mmx (pixman
if (srca == 0)
return;
- srcsrc = (unsigned long long)src << 32 | src;
+ srcsrc = (ullong)src << 32 | src;
fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1);
fbComposeGetStart (pMask, xMask, yMask, CARD8, maskStride, maskLine, 1);
@@ -1450,7 +1497,7 @@ fbCompositeSolidMask_nx8x8888mmx (pixman
if (m)
{
- __m64 vdest = in_over(vsrc, vsrca, expand_alpha_rev ((__m64)m), load8888(*dst));
+ __m64 vdest = in_over(vsrc, vsrca, expand_alpha_rev (*(__m64*)(&m)), load8888(*dst));
*dst = store8888(vdest);
}
@@ -1469,7 +1516,7 @@ fbCompositeSolidMask_nx8x8888mmx (pixman
if (srca == 0xff && (m0 & m1) == 0xff)
{
- *(unsigned long long *)dst = srcsrc;
+ *(ullong *)dst = srcsrc;
}
else if (m0 | m1)
{
@@ -1478,8 +1525,8 @@ fbCompositeSolidMask_nx8x8888mmx (pixman
vdest = *(__m64 *)dst;
- dest0 = in_over(vsrc, vsrca, expand_alpha_rev ((__m64)m0), expand8888(vdest, 0));
- dest1 = in_over(vsrc, vsrca, expand_alpha_rev ((__m64)m1), expand8888(vdest, 1));
+ dest0 = in_over(vsrc, vsrca, expand_alpha_rev (*(__m64*)(&m0)), expand8888(vdest, 0));
+ dest1 = in_over(vsrc, vsrca, expand_alpha_rev (*(__m64*)(&m1)), expand8888(vdest, 1));
*(__m64 *)dst = pack8888(dest0, dest1);
}
@@ -1498,7 +1545,7 @@ fbCompositeSolidMask_nx8x8888mmx (pixman
if (m)
{
__m64 vdest = load8888(*dst);
- vdest = in_over(vsrc, vsrca, expand_alpha_rev ((__m64)m), vdest);
+ vdest = in_over(vsrc, vsrca, expand_alpha_rev (*(__m64*)(&m)), vdest);
*dst = store8888(vdest);
}
@@ -1544,7 +1591,7 @@ fbCompositeSolidMaskSrc_nx8x8888mmx (pix
return;
}
- srcsrc = (unsigned long long)src << 32 | src;
+ srcsrc = (ullong)src << 32 | src;
fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1);
fbComposeGetStart (pMask, xMask, yMask, CARD8, maskStride, maskLine, 1);
@@ -1568,7 +1615,7 @@ fbCompositeSolidMaskSrc_nx8x8888mmx (pix
if (m)
{
- __m64 vdest = in(vsrc, expand_alpha_rev ((__m64)m));
+ __m64 vdest = in(vsrc, expand_alpha_rev (*(__m64*)(&m)));
*dst = store8888(vdest);
}
else
@@ -1591,7 +1638,7 @@ fbCompositeSolidMaskSrc_nx8x8888mmx (pix
if (srca == 0xff && (m0 & m1) == 0xff)
{
- *(unsigned long long *)dst = srcsrc;
+ *(ullong *)dst = srcsrc;
}
else if (m0 | m1)
{
@@ -1600,8 +1647,8 @@ fbCompositeSolidMaskSrc_nx8x8888mmx (pix
vdest = *(__m64 *)dst;
- dest0 = in(vsrc, expand_alpha_rev ((__m64)m0));
- dest1 = in(vsrc, expand_alpha_rev ((__m64)m1));
+ dest0 = in(vsrc, expand_alpha_rev (*(__m64*)(&m0)));
+ dest1 = in(vsrc, expand_alpha_rev (*(__m64*)(&m1)));
*(__m64 *)dst = pack8888(dest0, dest1);
}
@@ -1624,7 +1671,7 @@ fbCompositeSolidMaskSrc_nx8x8888mmx (pix
if (m)
{
__m64 vdest = load8888(*dst);
- vdest = in(vsrc, expand_alpha_rev ((__m64)m));
+ vdest = in(vsrc, expand_alpha_rev (*(__m64*)(&m)));
*dst = store8888(vdest);
}
else
@@ -1661,7 +1708,8 @@ fbCompositeSolidMask_nx8x0565mmx (pixman
FbStride dstStride, maskStride;
CARD16 w;
__m64 vsrc, vsrca;
- unsigned long long srcsrcsrcsrc, src16;
+ ullong srcsrcsrcsrc, src16;
+ __m64 vsrc16;
CHECKPOINT();
@@ -1677,7 +1725,8 @@ fbCompositeSolidMask_nx8x0565mmx (pixman
vsrc = load8888 (src);
vsrca = expand_alpha (vsrc);
- src16 = (ullong)pack565(vsrc, _mm_setzero_si64(), 0);
+ vsrc16 = pack565(vsrc, _mm_setzero_si64(), 0);
+ src16 = *(ullong*)(&vsrc16);
srcsrcsrcsrc = (ullong)src16 << 48 | (ullong)src16 << 32 |
(ullong)src16 << 16 | (ullong)src16;
@@ -1698,10 +1747,9 @@ fbCompositeSolidMask_nx8x0565mmx (pixman
if (m)
{
- ullong d = *dst;
- __m64 vd = (__m64)d;
- __m64 vdest = in_over(vsrc, vsrca, expand_alpha_rev ((__m64)m), expand565(vd, 0));
- *dst = (ullong)pack565(vdest, _mm_setzero_si64(), 0);
+ __m64 vd = _mm_cvtsi32_si64 (*dst);
+ __m64 vdest = in_over(vsrc, vsrca, expand_alpha_rev (*(__m64*)(&m)), expand565(vd, 0));
+ *dst = _mm_cvtsi64_si32 (pack565(vdest, _mm_setzero_si64(), 0));
}
w--;
@@ -1721,7 +1769,7 @@ fbCompositeSolidMask_nx8x0565mmx (pixman
if (srca == 0xff && (m0 & m1 & m2 & m3) == 0xff)
{
- *(unsigned long long *)dst = srcsrcsrcsrc;
+ *(ullong *)dst = srcsrcsrcsrc;
}
else if (m0 | m1 | m2 | m3)
{
@@ -1730,13 +1778,13 @@ fbCompositeSolidMask_nx8x0565mmx (pixman
vdest = *(__m64 *)dst;
- vm0 = (__m64)m0;
+ vm0 = *(__m64*)(&m0);
vdest = pack565(in_over(vsrc, vsrca, expand_alpha_rev(vm0), expand565(vdest, 0)), vdest, 0);
- vm1 = (__m64)m1;
+ vm1 = *(__m64*)(&m1);
vdest = pack565(in_over(vsrc, vsrca, expand_alpha_rev(vm1), expand565(vdest, 1)), vdest, 1);
- vm2 = (__m64)m2;
+ vm2 = *(__m64*)(&m2);
vdest = pack565(in_over(vsrc, vsrca, expand_alpha_rev(vm2), expand565(vdest, 2)), vdest, 2);
- vm3 = (__m64)m3;
+ vm3 = *(__m64*)(&m3);
vdest = pack565(in_over(vsrc, vsrca, expand_alpha_rev(vm3), expand565(vdest, 3)), vdest, 3);
*(__m64 *)dst = vdest;
@@ -1755,10 +1803,9 @@ fbCompositeSolidMask_nx8x0565mmx (pixman
if (m)
{
- ullong d = *dst;
- __m64 vd = (__m64)d;
- __m64 vdest = in_over(vsrc, vsrca, expand_alpha_rev ((__m64)m), expand565(vd, 0));
- *dst = (ullong)pack565(vdest, _mm_setzero_si64(), 0);
+ __m64 vd = _mm_cvtsi32_si64 (*dst);
+ __m64 vdest = in_over(vsrc, vsrca, expand_alpha_rev (*(__m64*)(&m)), expand565(vd, 0));
+ *dst = _mm_cvtsi64_si32 (pack565(vdest, _mm_setzero_si64(), 0));
}
w--;
@@ -1809,12 +1856,11 @@ fbCompositeSrc_8888RevNPx0565mmx (pixman
while (w && (unsigned long)dst & 7)
{
__m64 vsrc = load8888 (*src);
- ullong d = *dst;
- __m64 vdest = expand565 ((__m64)d, 0);
+ __m64 vdest = expand565 (_mm_cvtsi32_si64 (*dst), 0);
vdest = pack565(over_rev_non_pre(vsrc, vdest), vdest, 0);
- *dst = (ullong)vdest;
+ *dst = _mm_cvtsi64_si32 (vdest);
w--;
dst++;
@@ -1870,12 +1916,11 @@ fbCompositeSrc_8888RevNPx0565mmx (pixman
while (w)
{
__m64 vsrc = load8888 (*src);
- ullong d = *dst;
- __m64 vdest = expand565 ((__m64)d, 0);
+ __m64 vdest = expand565 (_mm_cvtsi32_si64 (*dst), 0);
vdest = pack565(over_rev_non_pre(vsrc, vdest), vdest, 0);
- *dst = (ullong)vdest;
+ *dst = _mm_cvtsi64_si32 (vdest);
w--;
dst++;
@@ -2030,10 +2075,9 @@ fbCompositeSolidMask_nx8888x0565Cmmx (pi
if (m)
{
- ullong d = *q;
- __m64 vdest = expand565 ((__m64)d, 0);
+ __m64 vdest = expand565 (_mm_cvtsi32_si64 (*q), 0);
vdest = pack565 (in_over (vsrc, vsrca, load8888 (m), vdest), vdest, 0);
- *q = (ullong)vdest;
+ *q = _mm_cvtsi64_si32 (vdest);
}
twidth--;
@@ -2073,10 +2117,9 @@ fbCompositeSolidMask_nx8888x0565Cmmx (pi
m = *(CARD32 *)p;
if (m)
{
- ullong d = *q;
- __m64 vdest = expand565((__m64)d, 0);
+ __m64 vdest = expand565(_mm_cvtsi32_si64 (*q), 0);
vdest = pack565 (in_over(vsrc, vsrca, load8888(m), vdest), vdest, 0);
- *q = (ullong)vdest;
+ *q = _mm_cvtsi64_si32 (vdest);
}
twidth--;
@@ -2206,7 +2249,7 @@ fbCompositeSrcAdd_8888x8888mmx (pixman_o
while (w >= 2)
{
- *(ullong*)dst = (ullong) _mm_adds_pu8(*(__m64*)src, *(__m64*)dst);
+ *(__m64*)dst = _mm_adds_pu8(*(__m64*)src, *(__m64*)dst);
dst += 2;
src += 2;
w -= 2;
@@ -2266,7 +2309,7 @@ fbSolidFillmmx (FbPixels *pDraw,
}
fill = ((ullong)xor << 32) | xor;
- vfill = (__m64)fill;
+ vfill = *(__m64*)&fill;
while (height--)
{
diff --git a/pixman/src/fbpict.c b/pixman/src/fbpict.c
index 675d1fb..0cdec3f 100644
--- a/pixman/src/fbpict.c
+++ b/pixman/src/fbpict.c
@@ -1922,8 +1922,13 @@ enum CPUFeatures {
static unsigned int detectCPUFeatures(void) {
unsigned int result, features;
char vendor[13];
+#ifdef _MSC_VER
+ int vendor0 = 0, vendor1, vendor2;
+#endif
vendor[0] = 0;
vendor[12] = 0;
+
+#ifdef __GNUC__
/* see p. 118 of amd64 instruction set manual Vol3 */
/* We need to be careful about the handling of %ebx and
* %esp here. We can't declare either one as clobbered
@@ -1965,6 +1970,41 @@ static unsigned int detectCPUFeatures(vo
:
: "%eax", "%ecx", "%edx"
);
+#elif defined (_MSC_VER)
+ _asm {
+ pushfd
+ pop eax
+ mov ecx, eax
+ xor eax, 00200000h
+ push eax
+ popfd
+ pushfd
+ pop eax
+ mov edx, 0
+ xor eax, ecx
+ jz nocpuid
+
+ mov eax, 0
+ push ebx
+ cpuid
+ mov eax, ebx
+ pop ebx
+ mov vendor0, eax
+ mov vendor1, edx
+ mov vendor2, ecx
+ mov eax, 1
+ push ebx
+ cpuid
+ pop ebx
+ nocpuid:
+ mov result, edx
+ }
+ memmove (vendor+0, &vendor0, 4);
+ memmove (vendor+4, &vendor1, 4);
+ memmove (vendor+8, &vendor2, 4);
+#else
+#error unsupported compiler
+#endif
features = 0;
if (result) {
@@ -1979,6 +2019,7 @@ static unsigned int detectCPUFeatures(vo
features |= SSE2;
if ((result & MMX) && !(result & SSE) && (strcmp(vendor, "AuthenticAMD") == 0)) {
/* check for AMD MMX extensions */
+#ifdef __GNUC__
unsigned int result;
__asm__("push %%ebx\n"
@@ -1996,6 +2037,22 @@ static unsigned int detectCPUFeatures(vo
:
: "%eax", "%ecx", "%edx"
);
+#endif
+#ifdef _MSC_VER
+ _asm {
+ push ebx
+ mov eax, 80000000h
+ cpuid
+ xor edx, edx
+ cmp eax, 1
+ jge notamd
+ mov eax, 80000001h
+ cpuid
+ notamd:
+ pop ebx
+ mov result, edx
+ }
+#endif
if (result & (1<<22))
features |= MMX_Extensions;
}
More information about the cairo-commit
mailing list