[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