From c643b10bbc339884ceb2fe3eeced5a87f00cd34a Mon Sep 17 00:00:00 2001 From: Vincent Wei Date: Thu, 29 Nov 2018 12:22:01 +0800 Subject: [PATCH] Implementation of new API: SyncUpdateDC --- configure.ac | 10 +++ include/gdi.h | 14 ++++ src/include/internals.h | 6 +- src/include/newgal.h | 28 ++++++-- src/newgal/surface.c | 13 +++- src/newgal/video.c | 148 ++++++++++++++++++++++++++++++++++------ src/newgdi/gdi.c | 16 +++++ 7 files changed, 208 insertions(+), 27 deletions(-) diff --git a/configure.ac b/configure.ac index 5ec0fa35..f3a5cd02 100644 --- a/configure.ac +++ b/configure.ac @@ -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 ], build_adv2dapi=$enableval) +AC_ARG_ENABLE(syncupdate, +[ --enable-syncupdate include implementation of SyncUpdateDC ], +build_syncupdate=$enableval) + AC_ARG_ENABLE(minimalgdi, [ --enable-minimalgdi build a minimal GDI library only ], 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]) diff --git a/include/gdi.h b/include/gdi.h index 7da1a512..fc0baf59 100644 --- a/include/gdi.h +++ b/include/gdi.h @@ -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 */ /** diff --git a/src/include/internals.h b/src/include/internals.h index 52672e1e..cb485e7e 100644 --- a/src/include/internals.h +++ b/src/include/internals.h @@ -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 diff --git a/src/include/newgal.h b/src/include/newgal.h index 3b2490bc..31f127f2 100644 --- a/src/include/newgal.h +++ b/src/include/newgal.h @@ -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 diff --git a/src/newgal/surface.c b/src/newgal/surface.c index 91fe169f..ec63ed4a 100644 --- a/src/newgal/surface.c +++ b/src/newgal/surface.c @@ -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); } diff --git a/src/newgal/video.c b/src/newgal/video.c index e8650d73..3909377d 100644 --- a/src/newgal/video.c +++ b/src/newgal/video.c @@ -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; } + diff --git a/src/newgdi/gdi.c b/src/newgdi/gdi.c index 1504db4f..989bbc41 100644 --- a/src/newgdi/gdi.c +++ b/src/newgdi/gdi.c @@ -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 +} +