From d07e797f92dcff5109515ce2b17ac4087fc7d72a Mon Sep 17 00:00:00 2001 From: Vincent Wei Date: Thu, 29 Apr 2021 16:29:37 +0800 Subject: [PATCH] use pixman to implement BitBlt and StretchBlt --- configure.ac | 27 +++++ include/gdi.h | 135 +++++++++++------------ src/include/newgal.h | 32 ++++-- src/kernel/compsor-fallback.c | 42 ++++++-- src/newgal/Makefile.am | 2 +- src/newgal/blit.c | 194 ++++++++++++++++++++++++++++++++++ src/newgal/blit.h | 5 +- src/newgal/stretch.c | 194 +++++++++++++++++++++++++++++++++- src/newgal/surface.c | 10 +- src/newgdi/Makefile.am | 2 +- src/newgdi/bitmap.c | 43 +------- 11 files changed, 551 insertions(+), 135 deletions(-) diff --git a/configure.ac b/configure.ac index ac698995..d888efb3 100644 --- a/configure.ac +++ b/configure.ac @@ -109,6 +109,7 @@ use_own_stdio="no" use_own_malloc="no" use_own_pthread="no" build_adv2dapi="yes" +use_pixman="yes" build_updateregion="yes" build_minimalgdi="no" @@ -366,6 +367,10 @@ AC_ARG_ENABLE(adv2dapi, [ --enable-adv2dapi include advanced 2D graphics APIs ], build_adv2dapi=$enableval) +AC_ARG_ENABLE(pixman, +[ --enable-pixman use pixman to optimmize pixle operations ], +use_pixman=$enableval) + AC_ARG_ENABLE(updateregion, [ --enable-updateregion Use update region for cumulative updating surfaces ], build_updateregion=$enableval) @@ -2261,6 +2266,26 @@ if test "x$build_ttf_support" = "xyes"; then AC_SUBST(FT2_INC_DIR) fi +dnl Check Pixman lib +if test "x$use_pixman" = "xyes"; then + PKG_CHECK_MODULES([PIXMAN], [pixman-1 >= 0.34.0], [foo=bar], + [use_pixman="no; not found pixman."]) +fi + +if test "x$use_pixman" = "xyes"; then + AC_DEFINE(_MGUSE_PIXMAN, 1, + [Define if use libpixman for optimized pixel operations]) + AC_ARG_WITH(pixman_includes, +[ --with-pixman-includes=DIR where the libpixman includes are]) + + if test "x$with_pixman_includes" != "x"; then + PIXMAN_CFLAGS="-I$with_pixman_includes" + fi + + DEP_LIBS="$DEP_LIBS $PIXMAN_LIBS" + AC_SUBST(PIXMAN_CFLAGS) +fi + if test "x$build_bmpf_support" = "xyes"; then AC_DEFINE(_MGFONT_BMPF, 1, [Define if support Bitmap fonts]) @@ -2776,6 +2801,7 @@ AC_MSG_NOTICE([ * Target name: ${with_targetname} * Cursor: ${build_cursor_support} * Update Region: ${build_updateregion} + * Pixman: ${use_pixman} ## NEWGAL Engines: * dummy: ${enable_video_dummy} @@ -2811,6 +2837,7 @@ AC_MSG_NOTICE([ * CPP flags: ${CPPFLAGS} * CC flags: ${CFLAGS} * CXX flags: ${CXXFLAGS} + * Pixman includes: ${PIXMAN_CFLAGS} * FreeType2 includes: ${FT2_INC_DIR} * HarfBuzz includes: ${HB_INC_DIR} * Dep. libraries: ${DEP_LIBS} diff --git a/include/gdi.h b/include/gdi.h index 84699003..8d80c9f4 100644 --- a/include/gdi.h +++ b/include/gdi.h @@ -5165,131 +5165,139 @@ MG_EXPORT BOOL GUIAPI FillBitmapPartInBox (HDC hdc, int box_x, int box_y, * The color blend mothed. * * See [Compositing and Blending Level 1](https://www.w3.org/TR/compositing-1/) + * Note: we define the same values with Pixman. */ typedef enum { - /** Porter Duff rule: source over destination */ - COLOR_BLEND_PD_SRC_OVER = 0, - /** Porter Duff rule: destination over source */ - COLOR_BLEND_PD_DST_OVER, - /** Porter Duff rule: clear */ - COLOR_BLEND_PD_CLEAR, - /** Porter Duff rule: source */ - COLOR_BLEND_PD_SRC, - /** Porter Duff rule: destination */ - COLOR_BLEND_PD_DST, - /** Porter Duff rule: souorce in destination */ - COLOR_BLEND_PD_SRC_IN, - /** Porter Duff rule: destination in souorce */ - COLOR_BLEND_PD_DST_IN, - /** Porter Duff rule: source held out by destination */ - COLOR_BLEND_PD_SRC_OUT, - /** Porter Duff rule: destination held out by source */ - COLOR_BLEND_PD_DST_OUT, - /** Porter Duff rule: source atop destination */ - COLOR_BLEND_PD_SRC_ATOP, - /** Porter Duff rule: destination atop source */ - COLOR_BLEND_PD_DST_ATOP, - /** Porter Duff rule: source xor destination */ - COLOR_BLEND_PD_XOR, - /** Porter Duff rule: plus */ - COLOR_BLEND_PD_PLUS, - /** Porter Duff rule: modulate */ - COLOR_BLEND_PD_MODULATE, + COLOR_BLEND_LEGACY = 0, + COLOR_BLEND_FLAGS_MASK = 0xFF00, - COLOR_BLEND_PD_FIRST = COLOR_BLEND_PD_SRC_OVER, - COLOR_BLEND_PD_LAST = COLOR_BLEND_PD_MODULATE, + /** Porter Duff rule: clear */ + COLOR_BLEND_PD_CLEAR = 0x0100, // PIXMAN_OP_CLEAR = 0x00 + /** Porter Duff rule: source */ + COLOR_BLEND_PD_SRC = 0x0101, // PIXMAN_OP_SRC = 0x01 + /** Porter Duff rule: destination */ + COLOR_BLEND_PD_DST = 0x0102, // PIXMAN_OP_DST = 0x02 + /** Porter Duff rule: source over destination */ + COLOR_BLEND_PD_SRC_OVER = 0x0103, // PIXMAN_OP_OVER = 0x03 + /** Porter Duff rule: destination over source */ + COLOR_BLEND_PD_DST_OVER = 0x0104, // PIXMAN_OP_OVER_REVERSE = 0x04 + /** Porter Duff rule: souorce in destination */ + COLOR_BLEND_PD_SRC_IN = 0x0105, // PIXMAN_OP_IN = 0x05 + /** Porter Duff rule: destination in souorce */ + COLOR_BLEND_PD_DST_IN = 0x0106, // PIXMAN_OP_IN_REVERSE = 0x06 + /** Porter Duff rule: source held out by destination */ + COLOR_BLEND_PD_SRC_OUT = 0x0107, // PIXMAN_OP_OUT = 0x07 + /** Porter Duff rule: destination held out by source */ + COLOR_BLEND_PD_DST_OUT = 0x0108, // PIXMAN_OP_OUT_REVERSE = 0x08 + /** Porter Duff rule: source atop destination */ + COLOR_BLEND_PD_SRC_ATOP = 0x0109, // PIXMAN_OP_ATOP = 0x09 + /** Porter Duff rule: destination atop source */ + COLOR_BLEND_PD_DST_ATOP = 0x010a, // PIXMAN_OP_ATOP_REVERSE = 0x0a + /** Porter Duff rule: source xor destination */ + COLOR_BLEND_PD_XOR = 0x010b, // PIXMAN_OP_XOR = 0x0b + /** Porter Duff rule: plus */ + COLOR_BLEND_PD_PLUS = 0x010c, // PIXMAN_OP_ADD = 0x0c + /** Porter Duff rule: modulate */ + COLOR_BLEND_PD_MODULATE = 0x010d, // PIXMAN_OP_SATURATE = 0x0d + + COLOR_BLEND_PD_FLAG = 0x0100, + COLOR_BLEND_PD_FIRST = COLOR_BLEND_PD_CLEAR, + COLOR_BLEND_PD_LAST = COLOR_BLEND_PD_MODULATE, /** * Separable blend mode: normal * The blending formula simply selects the source color. */ - COLOR_BLEND_SP_NORMAL, + COLOR_BLEND_SP_NORMAL = 0x0801, /** * Separable blend mode: multiply * Darkens by multiplying colors: Sc·Dc. */ - COLOR_BLEND_SP_MULTIPLY, + COLOR_BLEND_SP_MULTIPLY = 0x0830, // PIXMAN_OP_MULTIPLY = 0x30 /** * Separable blend mode: screen * Complements product of complements: Sc + Dc - Sc·Dc. */ - COLOR_BLEND_SP_SCREEN, + COLOR_BLEND_SP_SCREEN = 0x0831, // PIXMAN_OP_SCREEN = 0x31 /** * Separable blend mode: overlay * Inverse of hard-light. */ - COLOR_BLEND_SP_OVERLAY, + COLOR_BLEND_SP_OVERLAY = 0x0832, // PIXMAN_OP_OVERLAY = 0x32 /** * Separable blend mode: darken * Minimum of colors: min(Sc, Dc). */ - COLOR_BLEND_SP_DARKEN, + COLOR_BLEND_SP_DARKEN = 0x0833, // PIXMAN_OP_DARKEN = 0x33 /** * Separable blend mode: lighten * Maximum of colors: max(Sc, Dc). */ - COLOR_BLEND_SP_LIGHTEN, + COLOR_BLEND_SP_LIGHTEN = 0x0834, // PIXMAN_OP_LIGHTEN = 0x34 /** * Separable blend mode: color-dodge * Brightens destination based on source. */ - COLOR_BLEND_SP_COLOR_DODGE, + COLOR_BLEND_SP_COLOR_DODGE = 0x0835, // PIXMAN_OP_COLOR_DODGE = 0x35, /** * Separable blend mode: color-burn * Darkens destination based on source. */ - COLOR_BLEND_SP_COLOR_BURN, + COLOR_BLEND_SP_COLOR_BURN = 0x0836, // PIXMAN_OP_COLOR_BURN = 0x36, /** * Separable blend mode: hard-light * Similar to effect of harsh spotlight. */ - COLOR_BLEND_SP_HARD_LIGHT, + COLOR_BLEND_SP_HARD_LIGHT = 0x0837, // PIXMAN_OP_HARD_LIGHT = 0x37, /** * Separable blend mode: soft-light * Similar to effect of soft spotlight. */ - COLOR_BLEND_SP_SOFT_LIGHT, + COLOR_BLEND_SP_SOFT_LIGHT = 0x0838, // PIXMAN_OP_SOFT_LIGHT = 0x38 /** * Separable blend mode: difference * Subtracts the darker from the lighter: Abs(Dc - Sc). */ - COLOR_BLEND_SP_DIFFERENCE, + COLOR_BLEND_SP_DIFFERENCE = 0x0839, // PIXMAN_OP_DIFFERENCE = 0x39 /** * Separable blend mode: exclusion * Similar to Difference but lower contrast. */ - COLOR_BLEND_SP_EXCLUSION, + COLOR_BLEND_SP_EXCLUSION = 0x083a, // PIXMAN_OP_EXCLUSION = 0x3a - COLOR_BLEND_SP_FIRST = COLOR_BLEND_SP_NORMAL, - COLOR_BLEND_SP_LAST = COLOR_BLEND_SP_EXCLUSION, + COLOR_BLEND_SP_FLAG = 0x0800, + COLOR_BLEND_SP_FIRST = COLOR_BLEND_SP_NORMAL, + COLOR_BLEND_SP_LAST = COLOR_BLEND_SP_EXCLUSION, /** * Non-Separable blend mode: hue * Creates a color with the hue of the source color and * the saturation and luminosity of the backdrop color. */ - COLOR_BLEND_NS_HUE, + COLOR_BLEND_NS_HUE = 0x103b, // PIXMAN_OP_HSL_HUE = 0x3b /** * Non-Separable blend mode: saturation * Creates a color with the saturation of the source color and * the hue and luminosity of the backdrop color. */ - COLOR_BLEND_NS_SATURATION, + COLOR_BLEND_NS_SATURATION = 0x103c, // PIXMAN_OP_HSL_SATURATION = 0x3c /** * Non-Separable blend mode: color * Creates a color with the hue and saturation of the source color * and the luminosity of the backdrop color. */ - COLOR_BLEND_NS_COLOR, + COLOR_BLEND_NS_COLOR = 0x103d, // PIXMAN_OP_HSL_COLOR = 0x3d + /** * Non-Separable blend mode: luminosity * Creates a color with the luminosity of the source color and * the hue and saturation of the backdrop color. */ - COLOR_BLEND_NS_LUMINOSITY, + COLOR_BLEND_NS_LUMINOSITY = 0x103e, // PIXMAN_OP_HSL_LUMINOSITY = 0x3e - COLOR_BLEND_NS_FIRST = COLOR_BLEND_NS_HUE, - COLOR_BLEND_NS_LAST = COLOR_BLEND_NS_LUMINOSITY, + COLOR_BLEND_NS_FLAG = 0x1000, + COLOR_BLEND_NS_FIRST = COLOR_BLEND_NS_HUE, + COLOR_BLEND_NS_LAST = COLOR_BLEND_NS_LUMINOSITY, } ColorBlendMethod; /** @@ -5341,10 +5349,10 @@ typedef enum { * in the destination DC. * \param dy The y coordinate of the upper-left corner of the rectangle * in the destination DC. - * \param dwRop The raster logical operation, see \a ColorLogicalOp. - * this argument is reserved for future use, currently ignored. - * - * \note The alpha and color key settings of the source DC will come into play. + * \param dwRop The color blending method, see \a ColorBlendMethod. + * this argument is only valid when Pixman is used, and + * the alpha and the color key settings of the source DC will be + * ignored if it is not \a COLOR_BLEND_LEGACY. * * \sa StretchBlt, SetMemDCAlpha, SetMemDCColorKey, ColorLogicalOp */ @@ -5377,24 +5385,19 @@ MG_EXPORT void GUIAPI BitBlt (HDC hsdc, int sx, int sy, int sw, int sh, * in the destination DC. * \param dw The width of the destination rectangle. * \param dh The height of the destination rectangle. - * \param dwRop The raster logical operation, see \a ColorLogicalOp. - * this argument is reserved for future use, currently ignored. - * - * \note The source rect should be contained in the device space entirely, - * and all coordinates should be in the device space. - * - * \note The source DC and dest DC must compatible, else will do nothing. - * - * \note The alpha and color key settings of the source DC will not come - * into play. + * \param dwRop The color blending method, see \a ColorBlendMethod. + * this argument is only valid when Pixman is used, and + * the alpha and the color key settings of the source DC will be + * ignored if it is not \a COLOR_BLEND_LEGACY. * * \sa BitBlt, SetMemDCAlpha, SetMemDCColorKey */ MG_EXPORT void GUIAPI StretchBlt (HDC hsdc, int sx, int sy, int sw, int sh, HDC hddc, int dx, int dy, int dw, int dh, DWORD dwRop); -// Test API: The implementation which uses hardware stretch function. -MG_EXPORT void GUIAPI StretchBltHW (HDC hsdc, int sx, int sy, int sw, int sh, + +/* Use this if you want to have the legacy manner of StretchBlt */ +MG_EXPORT void GUIAPI StretchBltLegacy (HDC hsdc, int sx, int sy, int sw, int sh, HDC hddc, int dx, int dy, int dw, int dh, DWORD dwRop); /** diff --git a/src/include/newgal.h b/src/include/newgal.h index ea0cbe3e..b1b73a9c 100644 --- a/src/include/newgal.h +++ b/src/include/newgal.h @@ -207,7 +207,10 @@ typedef struct GAL_Surface { unsigned int format_version; /* Private */ /* reference count -- used when freeing surface */ - int refcount; /* Read-mostly */ + unsigned int refcount; /* Read-mostly */ + + /* temp. data */ + uintptr_t tmp_data; /* Private */ #if IS_COMPOSITING_SCHEMA /* The pointer to GAL_SharedSurfaceHeader if the surface @@ -774,6 +777,10 @@ void GAL_GetClipRect (GAL_Surface *surface, GAL_Rect *rect); GAL_Surface *GAL_ConvertSurface (GAL_Surface *src, GAL_PixelFormat *fmt, Uint32 flags); +#ifdef _MGUSE_PIXMAN +int GAL_CheckPixmanFormat (struct GAL_Surface *src, struct GAL_Surface *dst); +#endif + /* * This performs a fast blit from the source surface to the destination * surface. It assumes that the source and destination rectangles are @@ -840,21 +847,26 @@ GAL_Surface *GAL_ConvertSurface * fullscreen application. The lock will also fail until you have access * to the video memory again. */ -/* You should call GAL_BlitSurface() unless you know exactly how GAL - blitting works internally and how to use the other blit functions. -*/ -#define GAL_BlitSurface GAL_UpperBlit - /* This is the public blit function, GAL_BlitSurface(), and it performs rectangle validation and clipping before passing it to GAL_LowerBlit() */ int GAL_UpperBlit (GAL_Surface *src, GAL_Rect *srcrect, - GAL_Surface *dst, GAL_Rect *dstrect); + GAL_Surface *dst, GAL_Rect *dstrect, DWORD op); + /* This is a semi-private blit function and it performs low-level surface blitting only. */ int GAL_LowerBlit (GAL_Surface *src, GAL_Rect *srcrect, - GAL_Surface *dst, GAL_Rect *dstrect); + GAL_Surface *dst, GAL_Rect *dstrect, DWORD op); + +/* You should call GAL_BlitSurface() unless you know exactly how GAL + blitting works internally and how to use the other blit functions. +*/ +static inline int GAL_BlitSurface (GAL_Surface *src, GAL_Rect *srcrect, + GAL_Surface *dst, GAL_Rect *dstrect) +{ + return GAL_UpperBlit (src, srcrect, dst, dstrect, 0); +} /* * This function performs a fast fill of the given rectangle with 'color' @@ -920,8 +932,8 @@ GAL_Surface * GAL_DisplayFormat (GAL_Surface *surface); */ GAL_Surface * GAL_DisplayFormatAlpha (GAL_Surface *surface); -int GAL_SoftStretch (GAL_Surface *src, GAL_Rect *srcrect, - GAL_Surface *dst, GAL_Rect *dstrect); +int GAL_StretchBlt (GAL_Surface *src, GAL_Rect *srcrect, + GAL_Surface *dst, GAL_Rect *dstrect, DWORD op); #ifdef _MGSCHEMA_COMPOSITING extern GAL_Surface* __gal_screen; diff --git a/src/kernel/compsor-fallback.c b/src/kernel/compsor-fallback.c index ce9dbc3e..6f294483 100644 --- a/src/kernel/compsor-fallback.c +++ b/src/kernel/compsor-fallback.c @@ -1095,6 +1095,8 @@ static void transit_to_layer (CompositorCtxt* ctxt, MG_Layer* to_layer) int idx_layer_0 = -1; int idx_layer_1 = -1; int i = 0, nr_layers = 0; + unsigned int total_time_ms = 0; + unsigned int total_times = 0; MG_Layer* layers[2]; @@ -1133,10 +1135,13 @@ static void transit_to_layer (CompositorCtxt* ctxt, MG_Layer* to_layer) _DBG_PRINTF ("cp.percent: %f, cp.scale: %f\n", cp.percent, cp.scale); t_ms = composite_layers (ctxt, layers, 2, &cp); - if (t_ms > 100) + if (t_ms > 50) _WRN_PRINTF ("Too slow to composite layers: %u\n", t_ms); - usleep (20 * 1000); + total_time_ms += t_ms; + total_times++; + + usleep (10 * 1000); cp.scale -= 0.02f; } @@ -1150,9 +1155,12 @@ static void transit_to_layer (CompositorCtxt* ctxt, MG_Layer* to_layer) _DBG_PRINTF ("cp.percent: %f, cp.scale: %f\n", cp.percent, cp.scale); t_ms = composite_layers (ctxt, layers, 2, &cp); - if (t_ms > 100) + if (t_ms > 50) _WRN_PRINTF ("Too slow to composite layers: %u\n", t_ms); + total_time_ms += t_ms; + total_times++; + usleep (20 * 1000); cp.percent -= 4.5f; } @@ -1167,10 +1175,13 @@ static void transit_to_layer (CompositorCtxt* ctxt, MG_Layer* to_layer) _DBG_PRINTF ("cp.percent: %f, cp.scale: %f\n", cp.percent, cp.scale); t_ms = composite_layers (ctxt, layers, 2, &cp); - if (t_ms > 100) + if (t_ms > 50) _WRN_PRINTF ("Too slow to composite layers: %u\n", t_ms); - usleep (20 * 1000); + total_time_ms += t_ms; + total_times++; + + usleep (10 * 1000); cp.scale += 0.02f; } } @@ -1187,10 +1198,13 @@ static void transit_to_layer (CompositorCtxt* ctxt, MG_Layer* to_layer) _DBG_PRINTF ("cp.percent: %f, cp.scale: %f\n", cp.percent, cp.scale); t_ms = composite_layers (ctxt, layers, 2, &cp); - if (t_ms > 100) + if (t_ms > 50) _WRN_PRINTF ("Too slow to composite layers: %u\n", t_ms); - usleep (20 * 1000); + total_time_ms += t_ms; + total_times++; + + usleep (10 * 1000); cp.scale -= 0.02f; } @@ -1203,9 +1217,12 @@ static void transit_to_layer (CompositorCtxt* ctxt, MG_Layer* to_layer) _DBG_PRINTF ("cp.percent: %f, cp.scale: %f\n", cp.percent, cp.scale); t_ms = composite_layers (ctxt, layers, 2, &cp); - if (t_ms > 100) + if (t_ms > 50) _WRN_PRINTF ("Too slow to composite layers: %u\n", t_ms); + total_time_ms += t_ms; + total_times++; + usleep (20 * 1000); cp.percent += 4.5f; } @@ -1220,13 +1237,18 @@ static void transit_to_layer (CompositorCtxt* ctxt, MG_Layer* to_layer) _DBG_PRINTF ("cp.percent: %f, cp.scale: %f\n", cp.percent, cp.scale); t_ms = composite_layers (ctxt, layers, 2, &cp); - if (t_ms > 100) + if (t_ms > 50) _WRN_PRINTF ("Too slow to composite layers: %u\n", t_ms); - usleep (20 * 1000); + total_time_ms += t_ms; + total_times++; + + usleep (10 * 1000); cp.scale += 0.02f; } } + + _DBG_PRINTF ("Average time to composite the layers: %u (times: %u)\n", total_time_ms / total_times, total_times); } CompositorOps __mg_fallback_compositor = { diff --git a/src/newgal/Makefile.am b/src/newgal/Makefile.am index 3dcb1729..20939d7c 100644 --- a/src/newgal/Makefile.am +++ b/src/newgal/Makefile.am @@ -1,6 +1,6 @@ ## Makefile.am for the NEWGAL library -AM_CPPFLAGS = -I$(abs_top_srcdir)/src/include -I$(abs_top_srcdir)/include +AM_CPPFLAGS = -I$(abs_top_srcdir)/src/include -I$(abs_top_srcdir)/include $(PIXMAN_CFLAGS) noinst_LTLIBRARIES = libnewgal.la diff --git a/src/newgal/blit.c b/src/newgal/blit.c index ec833efa..5e57b65a 100644 --- a/src/newgal/blit.c +++ b/src/newgal/blit.c @@ -162,6 +162,12 @@ static void GAL_BlitCopyOverlap(GAL_BlitInfo *info) } } +#ifdef _MGUSE_PIXMAN +BOOL GAL_CheckPixmanFormat (struct GAL_Surface *src, struct GAL_Surface *dst); +static int GAL_PixmanBlit (struct GAL_Surface *src, GAL_Rect *srcrect, + struct GAL_Surface *dst, GAL_Rect *dstrect); +#endif + /* Figure out which of many blit routines to set up on a surface */ int GAL_CalculateBlit(GAL_Surface *surface) { @@ -301,8 +307,196 @@ int GAL_CalculateBlit(GAL_Surface *surface) } if ( surface->map->sw_blit == NULL ) { +#ifdef _MGUSE_PIXMAN + if (blit_index & 1) { + // have colorkey + surface->map->sw_blit = GAL_SoftBlit; + } + else if (GAL_CheckPixmanFormat (surface, surface->map->dst)) { + surface->map->sw_blit = GAL_PixmanBlit; + } + else { + surface->map->sw_blit = GAL_SoftBlit; + } +#else surface->map->sw_blit = GAL_SoftBlit; +#endif } return(0); } +#ifdef _MGUSE_PIXMAN +#include + +struct rgbamasks_pixman_format_map { + uint32_t pixman_format; + Uint32 Rmask, Gmask, Bmask, Amask; +}; + +static struct rgbamasks_pixman_format_map _format_map_8bpp [] = { + { PIXMAN_r3g3b2, 0xE0, 0x1C, 0x03, 0x00 }, + { PIXMAN_b2g3r3, 0x0E, 0x38, 0xC0, 0x00 }, + { PIXMAN_a2r2g2b2, 0x30, 0x0C, 0x03, 0xC0 }, + { PIXMAN_a2b2g2r2, 0x03, 0x0C, 0x03, 0xC0 }, +}; + +static struct rgbamasks_pixman_format_map _format_map_16bpp [] = { + { PIXMAN_x4r4g4b4, 0x0F00, 0x00F0, 0x000F, 0x0000 }, + { PIXMAN_x4b4g4r4, 0x000F, 0x00F0, 0x0F00, 0x0000 }, + // { PIXMAN_r4g4b4x4, 0xF000, 0x0F00, 0x00F0, 0x0000 }, + // { PIXMAN_b4g4r4x4, 0x00F0, 0x0F00, 0xF000, 0x0000 }, + { PIXMAN_a4r4g4b4, 0x0F00, 0x00F0, 0x000F, 0xF000 }, + { PIXMAN_a4b4g4r4, 0x000F, 0x00F0, 0x0F00, 0xF000 }, + // { PIXMAN_r4g4b4a4, 0xF000, 0x0F00, 0x00F0, 0x000F }, + // { PIXMAN_b4g4r4a4, 0x00F0, 0x0F00, 0xF000, 0x000F }, + { PIXMAN_x1r5g5b5, 0x7C00, 0x03E0, 0x001F, 0x0000 }, + { PIXMAN_x1b5g5r5, 0x001F, 0x03E0, 0x7C00, 0x0000 }, + // { PIXMAN_r5g5b5x1, 0xF800, 0x07C0, 0x003E, 0x0000 }, + // { PIXMAN_b5g5r5x1, 0x003E, 0x07C0, 0xF800, 0x0000 }, + { PIXMAN_a1r5g5b5, 0x7C00, 0x03E0, 0x001F, 0x8000 }, + { PIXMAN_a1b5g5r5, 0x001F, 0x03E0, 0x7C00, 0x8000 }, + // { PIXMAN_r5g5b5a1, 0xF800, 0x07C0, 0x003E, 0x0001 }, + // { PIXMAN_b5g5r5a1, 0x003E, 0x07C0, 0xF800, 0x0001 }, + { PIXMAN_r5g6b5, 0xF800, 0x07E0, 0x001F, 0x0000 }, + { PIXMAN_b5g6r5, 0x001F, 0x07E0, 0xF800, 0x0000 }, +}; + +static struct rgbamasks_pixman_format_map _format_map_24bpp [] = { + { PIXMAN_r8g8b8, 0xFF0000, 0x00FF00, 0x0000FF, 0x000000 }, + { PIXMAN_b8g8r8, 0x0000FF, 0x00FF00, 0xFF0000, 0x000000 }, +}; + +static struct rgbamasks_pixman_format_map _format_map_32bpp [] = { + { PIXMAN_x8r8g8b8, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }, + { PIXMAN_x8b8g8r8, 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 }, + { PIXMAN_r8g8b8x8, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000 }, + { PIXMAN_b8g8r8x8, 0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000 }, + { PIXMAN_a8r8g8b8, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 }, + { PIXMAN_a8b8g8r8, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 }, + { PIXMAN_r8g8b8a8, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF }, + { PIXMAN_b8g8r8a8, 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF }, +}; + +static uint32_t translate_gal_format(const GAL_PixelFormat *gal_format) +{ + struct rgbamasks_pixman_format_map* map; + size_t i, n; + + switch (gal_format->BitsPerPixel) { + case 8: + map = _format_map_8bpp; + n = TABLESIZE(_format_map_8bpp); + break; + + case 16: + map = _format_map_16bpp; + n = TABLESIZE(_format_map_16bpp); + break; + + case 24: + map = _format_map_24bpp; + n = TABLESIZE(_format_map_24bpp); + break; + + case 32: + map = _format_map_32bpp; + n = TABLESIZE(_format_map_32bpp); + break; + + default: + return 0; + } + + for (i = 0; i < n; i++) { + if (gal_format->Rmask == map[i].Rmask && + gal_format->Gmask == map[i].Gmask && + gal_format->Bmask == map[i].Bmask && + gal_format->Amask == map[i].Amask) { + return map[i].pixman_format; + } + } + + return 0; +} + +BOOL GAL_CheckPixmanFormat (struct GAL_Surface *src, struct GAL_Surface *dst) +{ + src->tmp_data = translate_gal_format (src->format); + if (dst) { + dst->tmp_data = translate_gal_format (dst->format); + return src->tmp_data && dst->tmp_data; + } + + return src->tmp_data != 0; +} + +static int GAL_PixmanBlit (struct GAL_Surface *src, GAL_Rect *srcrect, + struct GAL_Surface *dst, GAL_Rect *dstrect) +{ + pixman_image_t *src_img = NULL, *dst_img = NULL, *msk_img = NULL; + pixman_op_t op; + uint32_t alpha_bits; + int retv = -1; + + assert (src->tmp_data); + assert (dst->tmp_data); + + if ((src->flags & GAL_SRCALPHA) && src->format->alpha != GAL_ALPHA_OPAQUE) { + memset (&alpha_bits, src->format->alpha, sizeof(alpha_bits)); + msk_img = pixman_image_create_bits_no_clear (PIXMAN_a8, 1, 1, &alpha_bits, 4); + if (msk_img) + pixman_image_set_repeat (msk_img, PIXMAN_REPEAT_NORMAL); + } + + if (src->map->cop == COLOR_BLEND_LEGACY) { + if ((src->flags & GAL_SRCPIXELALPHA) && src->format->Amask && src != dst) { + op = PIXMAN_OP_OVER; + } + else { + op = PIXMAN_OP_SRC; + } + } + else { + op = src->map->cop & ~COLOR_BLEND_FLAGS_MASK; + } + + src_img = pixman_image_create_bits_no_clear ((pixman_format_code_t)src->tmp_data, + src->w, src->h, + (uint32_t *)((char*)src->pixels + src->pixels_off), + src->pitch); + if (src_img == NULL) + goto out; + + if (dst != src) { + dst_img = pixman_image_create_bits_no_clear ((pixman_format_code_t)dst->tmp_data, + dst->w, dst->h, + (uint32_t *)((char*)dst->pixels + dst->pixels_off), + dst->pitch); + if (dst_img == NULL) + goto out; + } + else { + dst_img = src_img; + } + + retv = 0; + pixman_image_composite32 (op, src_img, msk_img, dst_img, + srcrect->x, srcrect->y, + 0, 0, + dstrect->x, dstrect->y, + srcrect->w, srcrect->h); + +out: + if (msk_img) + pixman_image_unref (msk_img); + + if (src_img) + pixman_image_unref (src_img); + + if (dst_img != src_img && dst_img) + pixman_image_unref (dst_img); + + return retv; +} +#endif // _MGUSE_PIXMAN + diff --git a/src/newgal/blit.h b/src/newgal/blit.h index b66daab2..decdbb00 100644 --- a/src/newgal/blit.h +++ b/src/newgal/blit.h @@ -77,16 +77,17 @@ struct private_swaccel { /* Blit mapping definition */ typedef struct GAL_BlitMap { GAL_Surface *dst; - int identity; Uint8 *table; GAL_blit hw_blit; GAL_blit sw_blit; struct private_hwaccel *hw_data; struct private_swaccel *sw_data; + DWORD cop; + int identity; /* the version count matches the destination; mismatch indicates an invalid mapping */ - unsigned int format_version; + unsigned int format_version; } GAL_BlitMap; diff --git a/src/newgal/stretch.c b/src/newgal/stretch.c index ed4ea291..555b2493 100644 --- a/src/newgal/stretch.c +++ b/src/newgal/stretch.c @@ -193,7 +193,7 @@ static void copy_row3(Uint8 *src, int src_w, Uint8 *dst, int dst_w) /* Perform a stretch blit between two surfaces of the same format. NOTE: This function is not safe to call from multiple threads! */ -int GAL_SoftStretch(GAL_Surface *src, GAL_Rect *srcrect, +static int GAL_SoftStretch(GAL_Surface *src, GAL_Rect *srcrect, GAL_Surface *dst, GAL_Rect *dstrect) { int pos, inc; @@ -232,7 +232,8 @@ int GAL_SoftStretch(GAL_Surface *src, GAL_Rect *srcrect, if ( (dstrect->x < 0) || (dstrect->y < 0) || ((dstrect->x+dstrect->w) > dst->w) || ((dstrect->y+dstrect->h) > dst->h) ) { - GAL_SetError("NEWGAL: Invalid destination blit rectangle.\n"); + GAL_SetError("NEWGAL: Invalid destination blit rectangle (%d, %d, %d x %d) to surface (%d x %d)\n", + dstrect->x, dstrect->y, dstrect->w, dstrect->h, dst->w, dst->h); return(-1); } } else { @@ -323,3 +324,192 @@ int GAL_SoftStretch(GAL_Surface *src, GAL_Rect *srcrect, return(0); } +static void GAL_SoftStretchHelper (GAL_Surface *src, GAL_Rect *srcrect, + GAL_Surface *dst, GAL_Rect *dstrect, DWORD op) +{ + GAL_Surface *new_surf; + GAL_Rect new_rc = { 0, 0, dstrect->w, dstrect->h }; + + new_surf = GAL_CreateRGBSurface (GAL_SWSURFACE, dstrect->w, dstrect->h, + GAL_BitsPerPixel(src), + GAL_RMask(src), GAL_GMask(src), GAL_BMask(src), GAL_AMask(src)); + if (new_surf == NULL) { + _WRN_PRINTF ("Failed to create a software surface\n"); + return; + } + + GAL_SoftStretch (src, srcrect, new_surf, &new_rc); + + if ((src->flags & GAL_SRCALPHA) == GAL_SRCALPHA) { + new_surf->flags |= GAL_SRCALPHA; + new_surf->format->alpha = src->format->alpha; + } + if ((src->flags & GAL_SRCPIXELALPHA) == GAL_SRCPIXELALPHA) { + new_surf->flags |= GAL_SRCPIXELALPHA; + } + if ((src->flags & GAL_SRCCOLORKEY) == GAL_SRCCOLORKEY) { + new_surf->flags |= GAL_SRCCOLORKEY; + new_surf->format->colorkey = src->format->colorkey; + } + GAL_UpperBlit (new_surf, &new_rc, dst, dstrect, op); + GAL_FreeSurface (new_surf); +} + +static int GAL_StretchBltLegacy (GAL_Surface *src, GAL_Rect *srcrect, + GAL_Surface *dst, GAL_Rect *dstrect, DWORD op) +{ + GAL_Rect clipped_srcrect, clipped_dstrect; + + if (GAL_RMask (src) != GAL_RMask (dst) + || GAL_GMask (src) != GAL_GMask (dst) + || GAL_BMask (src) != GAL_BMask (dst) + || GAL_AMask (src) != GAL_AMask (dst)) { + GAL_SoftStretchHelper (src, srcrect, dst, dstrect, op); + return 0; + } + + if (dstrect->x >= dst->clip_rect.x && + dstrect->y >= dst->clip_rect.y && + dstrect->x + dstrect->w <= dst->clip_rect.x + dst->clip_rect.w && + dstrect->y + dstrect->h <= dst->clip_rect.y + dst->clip_rect.h) { + clipped_srcrect = *srcrect; + clipped_dstrect = *dstrect; + } + else if (GAL_IntersectRect (dstrect, &dst->clip_rect, &clipped_dstrect)) { + float ratio_x = clipped_dstrect.w * 1.0f / dstrect->w; + float ratio_y = clipped_dstrect.h * 1.0f / dstrect->h; + + clipped_srcrect.w = (srcrect->w * ratio_x); + clipped_srcrect.h = (srcrect->h * ratio_y); + clipped_srcrect.x = srcrect->x + (clipped_dstrect.x - dstrect->x) * ratio_x; + clipped_srcrect.y = srcrect->y + (clipped_dstrect.y - dstrect->y) * ratio_y; + + if (clipped_srcrect.w <= 0 || clipped_srcrect.h <= 0 || + clipped_dstrect.w <= 0 || clipped_dstrect.h <= 0) + return -1; + } + else { + return -1; + } + + GAL_SoftStretch (src, &clipped_srcrect, dst, &clipped_dstrect); + return 0; +} + +#ifdef _MGUSE_PIXMAN +#include +#include + +int GAL_StretchBlt (GAL_Surface *src, GAL_Rect *srcrect, + GAL_Surface *dst, GAL_Rect *dstrect, DWORD cop) +{ + pixman_image_t *src_img = NULL, *dst_img = NULL, *msk_img = NULL; + pixman_op_t op; + uint32_t alpha_bits; + int retv = -1; + + if (!GAL_CheckPixmanFormat (src, dst) || (src->flags & GAL_SRCCOLORKEY)) + return GAL_StretchBltLegacy (src, srcrect, dst, dstrect, op); + + assert (src->tmp_data); + assert (dst->tmp_data); + + if ((src->flags & GAL_SRCALPHA) && src->format->alpha != GAL_ALPHA_OPAQUE) { + memset (&alpha_bits, src->format->alpha, sizeof(alpha_bits)); + msk_img = pixman_image_create_bits_no_clear (PIXMAN_a8, 1, 1, &alpha_bits, 4); + if (msk_img) + pixman_image_set_repeat (msk_img, PIXMAN_REPEAT_NORMAL); + } + + if (cop == COLOR_BLEND_LEGACY) { + if ((src->flags & GAL_SRCPIXELALPHA) && src->format->Amask && src != dst) { + op = PIXMAN_OP_OVER; + } + else { + op = PIXMAN_OP_SRC; + } + } + else { + op = cop & ~COLOR_BLEND_FLAGS_MASK; + } + + src_img = pixman_image_create_bits_no_clear ((pixman_format_code_t)src->tmp_data, + src->w, src->h, + (uint32_t *)((char*)src->pixels + src->pixels_off), + src->pitch); + if (src_img == NULL) + goto out; + + if (dst != src) { + dst_img = pixman_image_create_bits_no_clear ((pixman_format_code_t)dst->tmp_data, + dst->w, dst->h, + (uint32_t *)((char*)dst->pixels + dst->pixels_off), + dst->pitch); + if (dst_img == NULL) + goto out; + } + else { + dst_img = src_img; + } + + { + double fscale_x = srcrect->w * 1.0 / dstrect->w; + double fscale_y = srcrect->h * 1.0 / dstrect->h; + pixman_f_transform_t ftransform; + pixman_transform_t transform; + pixman_fixed_t *params; + int n_params; + pixman_region32_t clip_region; + + pixman_f_transform_init_identity (&ftransform); + pixman_f_transform_scale (&ftransform, NULL, fscale_x, fscale_y); + //pixman_f_transform_translate (&ftransform, NULL, - dstrect->w / 2.0f, - dstrect->h / 2.0); + pixman_transform_from_pixman_f_transform (&transform, &ftransform); + pixman_image_set_transform (src_img, &transform); + + params = pixman_filter_create_separable_convolution ( + &n_params, + pixman_double_to_fixed(fscale_x), + pixman_double_to_fixed(fscale_y), + PIXMAN_KERNEL_IMPULSE, + PIXMAN_KERNEL_IMPULSE, + PIXMAN_KERNEL_BOX, + PIXMAN_KERNEL_BOX, + 2, 2); + pixman_image_set_filter (src_img, PIXMAN_FILTER_SEPARABLE_CONVOLUTION, params, n_params); + free (params); + + pixman_region32_init_rect (&clip_region, + dst->clip_rect.x, dst->clip_rect.y, dst->clip_rect.w, dst->clip_rect.h); + pixman_image_set_clip_region32 (dst_img, &clip_region); + + retv = 0; + pixman_image_composite32 (op, src_img, msk_img, dst_img, + srcrect->x, srcrect->y, + 0, 0, + dstrect->x, dstrect->y, + srcrect->w, srcrect->h); + } + +out: + if (msk_img) + pixman_image_unref (msk_img); + + if (src_img) + pixman_image_unref (src_img); + + if (dst_img != src_img && dst_img) + pixman_image_unref (dst_img); + + return retv; +} + +#else /* defined _MGUSE_PIXMAN */ + +int GAL_StretchBlt (GAL_Surface *src, GAL_Rect *srcrect, + GAL_Surface *dst, GAL_Rect *dstrect, DWORD op) +{ + return GAL_StretchBltLegacy (src, srcrect, dst, dstrect, op); +} + +#endif /* not defined _MGUSE_PIXMAN */ diff --git a/src/newgal/surface.c b/src/newgal/surface.c index ebe1a35c..f7d6c693 100644 --- a/src/newgal/surface.c +++ b/src/newgal/surface.c @@ -501,11 +501,13 @@ static int own_overlapped_bitblit(GAL_blit real_blit, struct GAL_Surface *src, G * by calling the one(s) you need. */ int GAL_LowerBlit (GAL_Surface *src, GAL_Rect *srcrect, - GAL_Surface *dst, GAL_Rect *dstrect) + GAL_Surface *dst, GAL_Rect *dstrect, DWORD op) { GAL_blit do_blit; int ret; + src->map->cop = op; + /* Check to make sure the blit mapping is valid */ if ((src->map->dst != dst) || (src->map->dst->format_version != src->map->format_version)) { @@ -567,7 +569,7 @@ int GAL_LowerBlit (GAL_Surface *src, GAL_Rect *srcrect, int GAL_UpperBlit (GAL_Surface *src, GAL_Rect *srcrect, - GAL_Surface *dst, GAL_Rect *dstrect) + GAL_Surface *dst, GAL_Rect *dstrect, DWORD op) { GAL_Rect fulldst; int srcx, srcy, w, h; @@ -647,7 +649,7 @@ int GAL_UpperBlit (GAL_Surface *src, GAL_Rect *srcrect, sr.y = srcy; sr.w = dstrect->w = w; sr.h = dstrect->h = h; - return GAL_LowerBlit(src, &sr, dst, dstrect); + return GAL_LowerBlit(src, &sr, dst, dstrect, op); } dstrect->w = dstrect->h = 0; return 0; @@ -1665,7 +1667,7 @@ GAL_Surface * GAL_ConvertSurface (GAL_Surface *surface, bounds.y = 0; bounds.w = surface->w; bounds.h = surface->h; - GAL_LowerBlit(surface, &bounds, convert, &bounds); + GAL_LowerBlit(surface, &bounds, convert, &bounds, 0); /* Clean up the original surface, and update converted surface */ if (convert != NULL) { diff --git a/src/newgdi/Makefile.am b/src/newgdi/Makefile.am index 5a71b5cf..e261fbbe 100644 --- a/src/newgdi/Makefile.am +++ b/src/newgdi/Makefile.am @@ -1,4 +1,4 @@ -AM_CPPFLAGS = $(FT2_INC_DIR) $(HB_INC_DIR) +AM_CPPFLAGS = $(FT2_INC_DIR) $(HB_INC_DIR) $(PIXMAN_CFLAGS) AM_CPPFLAGS += -I$(abs_top_srcdir)/src/include -I$(abs_top_srcdir)/include noinst_LTLIBRARIES = libnewgdi.la diff --git a/src/newgdi/bitmap.c b/src/newgdi/bitmap.c index 60b73de1..a9a0c690 100644 --- a/src/newgdi/bitmap.c +++ b/src/newgdi/bitmap.c @@ -1362,12 +1362,12 @@ static void StretchBltSlow (HDC hsdc, int sx, int sy, int sw, int sh, return; } - StretchBlt (hsdc, sx, sy, sw, sh, newdc, 0, 0, dw, dh, dwRop); + StretchBltLegacy (hsdc, sx, sy, sw, sh, newdc, 0, 0, dw, dh, dwRop); BitBlt (newdc, 0, 0, dw, dh, hddc, dx, dy, dwRop); DeleteMemDC (newdc); } -void GUIAPI StretchBlt (HDC hsdc, int sx, int sy, int sw, int sh, +void GUIAPI StretchBltLegacy (HDC hsdc, int sx, int sy, int sw, int sh, HDC hddc, int dx, int dy, int dw, int dh, DWORD dwRop) { PDC psdc, pddc; @@ -1528,33 +1528,7 @@ error_ret: UNLOCK_GCRINFO (pddc); } -static void StretchBltSlowHW (HDC hsdc, int sx, int sy, int sw, int sh, - HDC hddc, int dx, int dy, int dw, int dh, DWORD dwRop) -{ - HDC newdc; - POINT pt1 = { dx, dy }; - POINT pt2 = { dx + dw, dy + dh }; - - LPtoDP (hddc, &pt1); - LPtoDP (hddc, &pt2); - dw = (pt2.x >= pt1.x) ? (pt2.x - pt1.x) : (pt1.x - pt2.x); - dh = (pt2.y >= pt1.y) ? (pt2.y - pt1.y) : (pt1.y - pt2.y); - - if (dw == 0 && dh == 0) - return; - - newdc = CreateCompatibleDCEx (hsdc, dw, dh); - if (newdc == HDC_INVALID) { - _WRN_PRINTF ("Failed to create a compatible memory DC\n"); - return; - } - - StretchBltHW (hsdc, sx, sy, sw, sh, newdc, 0, 0, dw, dh, dwRop); - BitBlt (newdc, 0, 0, dw, dh, hddc, dx, dy, dwRop); - DeleteMemDC (newdc); -} - -void GUIAPI StretchBltHW (HDC hsdc, int sx, int sy, int sw, int sh, +void GUIAPI StretchBlt (HDC hsdc, int sx, int sy, int sw, int sh, HDC hddc, int dx, int dy, int dw, int dh, DWORD dwRop) { PDC psdc, pddc; @@ -1564,15 +1538,6 @@ void GUIAPI StretchBltHW (HDC hsdc, int sx, int sy, int sw, int sh, RECT eff_rc; psdc = dc_HDC2PDC (hsdc); - pddc = dc_HDC2PDC (hddc); - if (GAL_RMask (psdc->surface) != GAL_RMask (pddc->surface) - || GAL_GMask (psdc->surface) != GAL_GMask (pddc->surface) - || GAL_BMask (psdc->surface) != GAL_BMask (pddc->surface) - || GAL_AMask (psdc->surface) != GAL_AMask (pddc->surface)) { - StretchBltSlowHW (hsdc, sx, sy, sw, sh, hddc, dx, dy, dw, dh, dwRop); - return; - } - if (!(pddc = __mg_check_ecrgn (hddc))) return; @@ -1671,7 +1636,7 @@ void GUIAPI StretchBltHW (HDC hsdc, int sx, int sy, int sw, int sh, src.x = sx; src.y = sy; src.w = sw; src.h = sh; dst.x = dx; dst.y = dy; dst.w = dw; dst.h = dh; - GAL_SoftStretch (psdc->surface, &src, pddc->surface, &dst); + GAL_StretchBlt (psdc->surface, &src, pddc->surface, &dst, dwRop); } cliprect = cliprect->next;