Implementation of new API: SyncUpdateDC

This commit is contained in:
Vincent Wei
2018-11-29 12:22:01 +08:00
parent c04c44eefb
commit c643b10bbc
7 changed files with 208 additions and 27 deletions

View File

@@ -102,6 +102,7 @@ use_own_malloc="no"
use_own_pthread="no"
build_adv2dapi="yes"
build_syncupdate="no"
build_minimalgdi="no"
dnl Options for look and feel renderer
@@ -347,6 +348,10 @@ AC_ARG_ENABLE(adv2dapi,
[ --enable-adv2dapi include advanced 2D graphics APIs <default=yes>],
build_adv2dapi=$enableval)
AC_ARG_ENABLE(syncupdate,
[ --enable-syncupdate include implementation of SyncUpdateDC <default=yes>],
build_syncupdate=$enableval)
AC_ARG_ENABLE(minimalgdi,
[ --enable-minimalgdi build a minimal GDI library only <default=no>],
build_minimalgdi=$enableval)
@@ -1655,6 +1660,11 @@ if test "x$build_adv2dapi" = "xyes"; then
[Define if include advanced 2D graphics APIs])
fi
if test "x$build_syncupdate" = "xyes"; then
AC_DEFINE(_MGUSE_SYNC_UPDATE, 1,
[Define if include implementation of SyncUpdateDC])
fi
if test "x$fixed_math" = "xyes"; then
AC_DEFINE(_MGHAVE_FIXED_MATH, 1,
[Define if include fixed math routines])

View File

@@ -1983,6 +1983,20 @@ MG_EXPORT void GUIAPI ReleaseSecondaryDC (HWND hwnd, HDC hdc);
*/
MG_EXPORT void GUIAPI DeleteSecondaryDC (HWND hwnd);
/**
* \fn BOOL GUIAPI SyncUpdateDC (HDC hdc)
* \brief Synchronize the update rectangles of the surface corresponding to hdc to screen.
*
* \param hdc The handle to the DC.
*
* \return TRUE when there are rectangles to be synchronized and updated.
* FALSE when _MGUSE_SYNC_UPDATE is not defined, hdc is a memory DC,
* or it is not necessory to update.
*
* \note This function only works when _MGUSE_SYNC_UPDATE defined.
*/
MG_EXPORT BOOL GUIAPI SyncUpdateDC (HDC hdc);
/** @} end of dc_fns */
/**

View File

@@ -78,9 +78,9 @@ void screensaver_hide(void);
#define SIZE_QMSG_HEAP 16
#else
#define DEF_MSGQUEUE_LEN 16 /* default message queue length */
#define SIZE_CLIPRECTHEAP 128
#define SIZE_INVRECTHEAP 128
#define SIZE_QMSG_HEAP 8
#define SIZE_CLIPRECTHEAP 32
#define SIZE_INVRECTHEAP 64
#define SIZE_QMSG_HEAP 16
#endif
#endif

View File

@@ -45,10 +45,6 @@
#include "gdi.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define DISABLE_THREADS
#define GAL_mutex int
@@ -67,6 +63,20 @@ extern "C" {
#define GAL_ALPHA_OPAQUE 255
#define GAL_ALPHA_TRANSPARENT 0
#if defined (__NOUNIX__) || defined (__uClinux__)
#define SIZE_UPDATERECTHEAP 16
#else
#ifndef _MGRM_THREADS
#define SIZE_UPDATERECTHEAP 32
#else
#define SIZE_UPDATERECTHEAP 64
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/*
* Allocate a pixel format structure and fill it according to the given info.
*/
@@ -102,6 +112,11 @@ typedef struct GAL_Surface {
/* clipping information */
GAL_Rect clip_rect; /* Read-only */
#ifdef _MGUSE_SYNC_UPDATE
/* update region */
CLIPRGN update_region; /* Read-only */
#endif
/* info for fast blit mapping to other surfaces */
struct GAL_BlitMap *map; /* Private */
@@ -296,6 +311,11 @@ extern void GAL_UpdateRects
extern void GAL_UpdateRect
(GAL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h);
#ifdef _MGUSE_SYNC_UPDATE
extern BLOCKHEAP __mg_free_update_region_list;
extern BOOL GAL_SyncUpdate (GAL_Surface *screen);
#endif
#if 0
/*
* On hardware that supports double-buffering, this function sets up a flip

View File

@@ -126,6 +126,11 @@ GAL_Surface * GAL_CreateRGBSurface (Uint32 flags,
surface->format_version = 0;
GAL_SetClipRect(surface, NULL);
#ifdef _MGUSE_SYNC_UPDATE
/* Initialize update region */
InitClipRgn (&surface->update_region, &__mg_free_update_region_list);
#endif
/* Get the pixels */
if ( surface->w && surface->h ) {
if ( ((flags&GAL_HWSURFACE) == GAL_SWSURFACE) ||
@@ -1737,9 +1742,15 @@ void GAL_FreeSurface (GAL_Surface *surface)
(current_video && (surface == GAL_VideoSurface))) {
return;
}
if ( --surface->refcount > 0 ) {
if (--surface->refcount > 0) {
return;
}
#ifdef _MGUSE_SYNC_UPDATE
EmptyClipRgn (&surface->update_region);
#endif
if ( (surface->flags & GAL_RLEACCEL) == GAL_RLEACCEL ) {
GAL_UnRLESurface(surface, 0);
}

View File

@@ -149,6 +149,10 @@ static VideoBootStrap *bootstrap[] = {
GAL_VideoDevice *current_video = NULL;
#ifdef _MGUSE_SYNC_UPDATE
BLOCKHEAP __mg_free_update_region_list;
#endif
/* Various local functions */
int GAL_VideoInit(const char *driver_name, Uint32 flags);
void GAL_VideoQuit(void);
@@ -206,6 +210,10 @@ int GAL_VideoInit (const char *driver_name, Uint32 flags)
GAL_PixelFormat vformat;
Uint32 video_flags;
#ifdef _MGUSE_SYNC_UPDATE
InitFreeClipRectList (&__mg_free_update_region_list, SIZE_UPDATERECTHEAP);
#endif
/* Check to make sure we don't overwrite 'current_video' */
if ( current_video != NULL ) {
GAL_VideoQuit();
@@ -671,24 +679,24 @@ GAL_Surface *GAL_DisplayFormatAlpha(GAL_Surface *surface)
/*
* Update a specific portion of the physical screen
*/
void GAL_UpdateRect(GAL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
void GAL_UpdateRect (GAL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
{
GAL_VideoDevice *video = (GAL_VideoDevice *) screen->video;
GAL_VideoDevice *video = (GAL_VideoDevice *)screen->video;
if (!video)
return;
if ( screen && (video->UpdateRects ||video->UpdateSurfaceRects)) {
if (screen && (video->UpdateRects || video->UpdateSurfaceRects)) {
GAL_Rect rect;
/* Perform some checking */
if ( w == 0 )
if (w == 0)
w = screen->w;
if ( h == 0 )
if (h == 0)
h = screen->h;
if ( (int)(x+w) > screen->w )
if ((int)(x+w) > screen->w)
w = screen->w - x;
if ( (int)(y+h) > screen->h )
if ((int)(y+h) > screen->h)
h = screen->h - x;
/* Fill the rectangle */
@@ -696,25 +704,116 @@ void GAL_UpdateRect(GAL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h)
rect.y = y;
rect.w = w;
rect.h = h;
GAL_UpdateRects(screen, 1, &rect);
GAL_UpdateRects (screen, 1, &rect);
}
}
#ifdef _MGUSE_SYNC_UPDATE
void GAL_UpdateRects (GAL_Surface *screen, int numrects, GAL_Rect *rects)
{
GAL_VideoDevice *this =(GAL_VideoDevice *) screen->video;
int i;
GAL_VideoDevice *this = (GAL_VideoDevice *)screen->video;
if (this->info.mlt_surfaces == 0){
if (this && this->UpdateRects)
this->UpdateRects(this, numrects, rects);
if (this == NULL)
return;
if (this->info.mlt_surfaces == 0 && this->UpdateRects == NULL) {
return;
}
else{
if(this && this->UpdateSurfaceRects){
this->UpdateSurfaceRects(this, screen, numrects, rects);
else if (this->UpdateSurfaceRects) {
return;
}
for (i = 0; i < numrects; i++) {
RECT rc;
rc.left = rects[i].x;
rc.top = rects[i].y;
rc.right = rects[i].x + rects[i].w;
rc.bottom = rects[i].y + rects[i].h;
AddClipRect (&screen->update_region, &rc);
}
}
static int convert_region_to_rects (const CLIPRGN * rgn, GAL_Rect *rects, int max_nr)
{
int nr = 0;
PCLIPRECT clip_rect = rgn->head;
RECT left_rc;
while (clip_rect && ((nr + 1) < max_nr)) {
rects [nr].x = clip_rect->rc.left;
rects [nr].y = clip_rect->rc.top;
rects [nr].w = clip_rect->rc.right - clip_rect->rc.left;
rects [nr].h = clip_rect->rc.bottom - clip_rect->rc.top;
nr++;
clip_rect = clip_rect->next;
}
if (clip_rect == NULL) {
return nr;
}
SetRect (&left_rc, 0, 0, 0, 0);
while (clip_rect) {
UnionRect (&left_rc, &left_rc, &clip_rect->rc);
clip_rect = clip_rect->next;
}
rects [nr].x = left_rc.left;
rects [nr].y = left_rc.top;
rects [nr].w = left_rc.right - left_rc.left;
rects [nr].h = left_rc.bottom - left_rc.top;
nr++;
return nr;
}
BOOL GAL_SyncUpdate (GAL_Surface *screen)
{
GAL_VideoDevice *this = (GAL_VideoDevice *)screen->video;
GAL_Rect rects[8];
int numrects;
if (this == NULL)
return FALSE;
numrects = convert_region_to_rects (&screen->update_region, rects, 8);
if (numrects <= 0)
return FALSE;
if (this->info.mlt_surfaces == 0 && this->UpdateRects) {
this->UpdateRects (this, numrects, rects);
}
else if (this->UpdateSurfaceRects) {
this->UpdateSurfaceRects (this, screen, numrects, rects);
}
EmptyClipRgn (&screen->update_region);
return TRUE;
}
#else
void GAL_UpdateRects (GAL_Surface *screen, int numrects, GAL_Rect *rects)
{
GAL_VideoDevice *this = (GAL_VideoDevice *)screen->video;
if (this->info.mlt_surfaces == 0) {
if (this && this->UpdateRects)
this->UpdateRects (this, numrects, rects);
}
else {
if (this && this->UpdateSurfaceRects) {
this->UpdateSurfaceRects (this, screen, numrects, rects);
}
}
}
#endif /* _MGUSE_SYNC_UPDATE */
static void SetPalette_logical(GAL_Surface *screen, GAL_Color *colors,
int firstcolor, int ncolors)
{
@@ -878,9 +977,14 @@ void GAL_VideoQuit (void)
free(video->physpal);
video->physpal = NULL;
}
/* Finish cleaning up video subsystem */
video->free(this);
current_video = NULL;
#ifdef _MGUSE_SYNC_UPDATE
DestroyFreeClipRectList (&__mg_free_update_region_list);
#endif
}
return;
}
@@ -985,6 +1089,11 @@ static GAL_Surface *Slave_CreateSurface (GAL_VideoDevice *this,
surface->format_version = 0;
GAL_SetClipRect(surface, NULL);
#ifdef _MGUSE_SYNC_UPDATE
/* Initialize update region */
InitClipRgn (&surface->update_region, &__mg_free_update_region_list);
#endif
/* Allocate an empty mapping */
surface->map = GAL_AllocBlitMap();
if ( surface->map == NULL ) {
@@ -1185,7 +1294,7 @@ GAL_Surface *gal_SlaveVideoInit(const char* driver_name, const char* mode)
video = GAL_GetVideo(driver_name);
if (video == NULL) {
fprintf (stderr, "NEWGAL: Does not find the slave video engine: %s.\n",
_DBG_PRINTF ("NEWGAL: Does not find the slave video engine: %s.\n",
driver_name);
return NULL;
}
@@ -1194,7 +1303,7 @@ GAL_Surface *gal_SlaveVideoInit(const char* driver_name, const char* mode)
memset(&vformat, 0, sizeof(vformat));
if ( video->VideoInit(video, &vformat) < 0 ) {
fprintf (stderr, "NEWGAL: Can not init the slave video engine: %s.\n",
_DBG_PRINTF ("NEWGAL: Can not init the slave video engine: %s.\n",
driver_name);
gal_SlaveVideoQuit (video->screen);
return NULL;
@@ -1203,7 +1312,7 @@ GAL_Surface *gal_SlaveVideoInit(const char* driver_name, const char* mode)
surface = Slave_CreateSurface (video, 0, 0, vformat.BitsPerPixel,
vformat.Rmask, vformat.Gmask, vformat.Bmask, 0);
if (!surface) {
fprintf (stderr, "NEWGAL: Create slave video surface failure.\n");
_DBG_PRINTF ("NEWGAL: Create slave video surface failure.\n");
return NULL;
}
@@ -1214,8 +1323,9 @@ GAL_Surface *gal_SlaveVideoInit(const char* driver_name, const char* mode)
if (!(Slave_SetVideoMode(video, surface, w, h, depth, GAL_HWPALETTE))) {
gal_SlaveVideoQuit (video->screen);
fprintf (stderr, "NEWGAL: Set video mode failure.\n");
_DBG_PRINTF ("NEWGAL: Set video mode failure.\n");
return NULL;
}
return surface;
}

View File

@@ -3687,3 +3687,19 @@ MG_EXPORT int GUIAPI SetUserCompositionOps (HDC hdc, CB_COMP_SETPIXEL comp_setpi
return old_rop;
}
MG_EXPORT BOOL GUIAPI SyncUpdateDC (HDC hdc)
{
#ifdef _MGUSE_SYNC_UPDATE
BOOL rc;
PDC pdc = dc_HDC2PDC (hdc);
LOCK (&__mg_gdilock);
rc = GAL_SyncUpdate (pdc->surface);
UNLOCK (&__mg_gdilock);
return rc;
#else
return FALSE;
#endif
}