use pixman to implement BitBlt and StretchBlt

This commit is contained in:
Vincent Wei
2021-04-29 16:29:37 +08:00
parent cdf4ca3612
commit d07e797f92
11 changed files with 551 additions and 135 deletions

View File

@@ -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 <default=yes>],
build_adv2dapi=$enableval)
AC_ARG_ENABLE(pixman,
[ --enable-pixman use pixman to optimmize pixle operations <default=yes>],
use_pixman=$enableval)
AC_ARG_ENABLE(updateregion,
[ --enable-updateregion Use update region for cumulative updating surfaces <default=yes>],
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}

View File

@@ -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);
/**

View File

@@ -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;

View File

@@ -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 = {

View File

@@ -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

View File

@@ -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 <pixman.h>
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

View File

@@ -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;

View File

@@ -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 <pixman.h>
#include <math.h>
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 */

View File

@@ -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) {

View File

@@ -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

View File

@@ -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;