mirror of
https://github.com/VincentWei/MiniGUI.git
synced 2026-02-07 02:52:42 +08:00
optimize __mg_composite_dirty_znodes
This commit is contained in:
@@ -67,12 +67,17 @@
|
||||
|
||||
#define SIZE_CLIPRC_HEAP 64
|
||||
|
||||
#define DIRTY_ZT_PPP 0x01
|
||||
#define DIRTY_ZT_WIN 0x02
|
||||
#define DIRTY_ZT_WPP 0x04
|
||||
|
||||
struct _CompositorCtxt {
|
||||
RECT rc_screen; // screen rect - avoid duplicated GetScreenRect calls
|
||||
BLOCKHEAP cliprc_heap;// heap for clipping rects
|
||||
CLIPRGN wins_rgn; // visible region for all windows (subtract popup menus)
|
||||
CLIPRGN dirty_rgn; // the dirty region
|
||||
CLIPRGN inv_rgn; // the invalid region for a specific znode
|
||||
//Uint32 dirty_types;// the dirty znode types.
|
||||
};
|
||||
|
||||
static CompositorCtxt* initialize (const char* name)
|
||||
@@ -256,30 +261,6 @@ static inline void tile_dirty_region_for_wallpaper (CompositorCtxt* ctxt)
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL generate_dirty_region (CompositorCtxt* ctxt,
|
||||
const ZNODEHEADER* znode_hdr, const CLIPRGN* znode_rgn)
|
||||
{
|
||||
EmptyClipRgn (&ctxt->dirty_rgn);
|
||||
if (znode_hdr && znode_hdr->dirty_rcs) {
|
||||
int i;
|
||||
for (i = 0; i < znode_hdr->nr_dirty_rcs; i++) {
|
||||
RECT rc;
|
||||
|
||||
// device coordinates to screen coordinates
|
||||
rc = znode_hdr->dirty_rcs [i];
|
||||
OffsetRect (&rc, znode_hdr->rc.left, znode_hdr->rc.top);
|
||||
AddClipRect (&ctxt->dirty_rgn, &rc);
|
||||
}
|
||||
|
||||
if (znode_rgn)
|
||||
IntersectRegion (&ctxt->dirty_rgn, &ctxt->dirty_rgn, znode_rgn);
|
||||
else
|
||||
IntersectClipRect (&ctxt->dirty_rgn, &ctxt->rc_screen);
|
||||
}
|
||||
|
||||
return !IsEmptyClipRgn (&ctxt->dirty_rgn);
|
||||
}
|
||||
|
||||
static void composite_wallpaper_rect (CompositorCtxt* ctxt,
|
||||
const RECT* dirty_rc)
|
||||
{
|
||||
@@ -530,63 +511,6 @@ static void composite_on_dirty_region (CompositorCtxt* ctxt, int from)
|
||||
SyncUpdateDC (HDC_SCREEN_SYS);
|
||||
}
|
||||
|
||||
static void on_dirty_win (CompositorCtxt* ctxt, MG_Layer* layer, int zidx)
|
||||
{
|
||||
const ZNODEHEADER* znode_hdr = NULL;
|
||||
CLIPRGN *rgn;
|
||||
|
||||
/* the fallback compositor only manages znodes on the topmost layer. */
|
||||
if (layer != mgTopmostLayer || zidx <= 0)
|
||||
return;
|
||||
|
||||
_DBG_PRINTF("called: %d\n", zidx);
|
||||
|
||||
/* generate the dirty region */
|
||||
znode_hdr = ServerGetWinZNodeHeader (NULL, zidx, (void**)&rgn, TRUE);
|
||||
assert (znode_hdr);
|
||||
|
||||
if (generate_dirty_region (ctxt, znode_hdr, rgn)) {
|
||||
if (znode_hdr->changes == 0) {
|
||||
/* It's the first exposure of the window. */
|
||||
_MG_PRINTF ("It is the first exposure of the window (%d): %u\n",
|
||||
zidx, znode_hdr->dirty_age);
|
||||
}
|
||||
|
||||
if (IsEmptyClipRgn (&ctxt->dirty_rgn)) {
|
||||
goto ret;
|
||||
}
|
||||
|
||||
composite_on_dirty_region (ctxt, zidx);
|
||||
}
|
||||
|
||||
ret:
|
||||
ServerReleaseWinZNodeHeader (NULL, zidx);
|
||||
}
|
||||
|
||||
static void on_dirty_wpp (CompositorCtxt* ctxt)
|
||||
{
|
||||
const ZNODEHEADER* znode_hdr;
|
||||
|
||||
//_DBG_PRINTF ("called\n");
|
||||
znode_hdr = ServerGetWinZNodeHeader (NULL, 0, NULL, TRUE);
|
||||
assert (znode_hdr);
|
||||
|
||||
if (generate_dirty_region (ctxt, znode_hdr, NULL)) {
|
||||
tile_dirty_region_for_wallpaper (ctxt);
|
||||
subtract_opaque_win_znodes_above (ctxt, 0);
|
||||
//subtract_opaque_ppp_znodes (ctxt);
|
||||
|
||||
if (IsEmptyClipRgn (&ctxt->dirty_rgn)) {
|
||||
goto ret;
|
||||
}
|
||||
|
||||
composite_on_dirty_region (ctxt, 0);
|
||||
}
|
||||
|
||||
ret:
|
||||
ServerReleaseWinZNodeHeader (NULL, 0);
|
||||
}
|
||||
|
||||
static void rebuild_wins_region (CompositorCtxt* ctxt)
|
||||
{
|
||||
int i, nr_ppps;
|
||||
@@ -683,29 +607,110 @@ static void on_showing_ppp (CompositorCtxt* ctxt, int zidx)
|
||||
SubtractRegion (&ctxt->wins_rgn, &ctxt->wins_rgn, rgn);
|
||||
}
|
||||
|
||||
static void on_dirty_ppp (CompositorCtxt* ctxt, int zidx)
|
||||
static BOOL reset_dirty_region (CompositorCtxt* ctxt, MG_Layer* layer)
|
||||
{
|
||||
if (layer != mgTopmostLayer)
|
||||
return FALSE;
|
||||
|
||||
//ctxt->dirty_types = 0;
|
||||
EmptyClipRgn (&ctxt->dirty_rgn);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL generate_dirty_region (CompositorCtxt* ctxt,
|
||||
const ZNODEHEADER* znode_hdr, const CLIPRGN* znode_rgn)
|
||||
{
|
||||
if (znode_hdr && znode_hdr->dirty_rcs) {
|
||||
int i;
|
||||
for (i = 0; i < znode_hdr->nr_dirty_rcs; i++) {
|
||||
RECT rc;
|
||||
|
||||
// device coordinates to screen coordinates
|
||||
rc = znode_hdr->dirty_rcs [i];
|
||||
OffsetRect (&rc, znode_hdr->rc.left, znode_hdr->rc.top);
|
||||
AddClipRect (&ctxt->dirty_rgn, &rc);
|
||||
}
|
||||
|
||||
if (znode_rgn)
|
||||
IntersectRegion (&ctxt->dirty_rgn, &ctxt->dirty_rgn, znode_rgn);
|
||||
else
|
||||
IntersectClipRect (&ctxt->dirty_rgn, &ctxt->rc_screen);
|
||||
}
|
||||
|
||||
return !IsEmptyClipRgn (&ctxt->dirty_rgn);
|
||||
}
|
||||
|
||||
static BOOL merge_dirty_ppp (CompositorCtxt* ctxt, MG_Layer* layer, int zidx)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
const ZNODEHEADER* znode_hdr;
|
||||
CLIPRGN* rgn;
|
||||
|
||||
_DBG_PRINTF ("called\n");
|
||||
_DBG_PRINTF("called: %d\n", zidx);
|
||||
|
||||
/* the fallback compositor only manages znodes on the topmost layer. */
|
||||
if (layer != mgTopmostLayer || zidx <= 0)
|
||||
return rc;
|
||||
|
||||
znode_hdr = ServerGetPopupMenuZNodeHeader (zidx, (void**)&rgn, TRUE);
|
||||
assert (znode_hdr);
|
||||
assert (rgn);
|
||||
|
||||
if (generate_dirty_region (ctxt, znode_hdr, rgn)) {
|
||||
SelectClipRegion (HDC_SCREEN_SYS, &ctxt->dirty_rgn);
|
||||
BitBlt (znode_hdr->mem_dc, 0, 0,
|
||||
RECTW (znode_hdr->rc), RECTH (znode_hdr->rc),
|
||||
HDC_SCREEN_SYS, znode_hdr->rc.left, znode_hdr->rc.top, 0);
|
||||
//ctxt->dirty_types |= DIRTY_ZT_PPP;
|
||||
rc = TRUE;
|
||||
}
|
||||
ServerReleasePopupMenuZNodeHeader (zidx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
SelectClipRect (HDC_SCREEN_SYS, &ctxt->rc_screen);
|
||||
EmptyClipRgn (&ctxt->dirty_rgn);
|
||||
static BOOL merge_dirty_win (CompositorCtxt* ctxt, MG_Layer* layer, int zidx)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
const ZNODEHEADER* znode_hdr = NULL;
|
||||
CLIPRGN *rgn;
|
||||
|
||||
/* the fallback compositor only manages znodes on the topmost layer. */
|
||||
if (layer != mgTopmostLayer || zidx <= 0)
|
||||
return rc;
|
||||
|
||||
_DBG_PRINTF("called: %d\n", zidx);
|
||||
|
||||
/* merge the dirty region */
|
||||
znode_hdr = ServerGetWinZNodeHeader (NULL, zidx, (void**)&rgn, TRUE);
|
||||
if (generate_dirty_region (ctxt, znode_hdr, rgn)) {
|
||||
//ctxt->dirty_types |= DIRTY_ZT_WIN;
|
||||
rc = TRUE;
|
||||
}
|
||||
ServerReleaseWinZNodeHeader (NULL, zidx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BOOL merge_dirty_wpp (CompositorCtxt* ctxt, MG_Layer* layer)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
const ZNODEHEADER* znode_hdr;
|
||||
|
||||
znode_hdr = ServerGetWinZNodeHeader (NULL, 0, NULL, TRUE);
|
||||
if (generate_dirty_region (ctxt, znode_hdr, NULL)) {
|
||||
tile_dirty_region_for_wallpaper (ctxt);
|
||||
//subtract_opaque_win_znodes_above (ctxt, 0);
|
||||
//ctxt->dirty_types |= DIRTY_ZT_WPP;
|
||||
rc = TRUE;
|
||||
}
|
||||
|
||||
ServerReleasePopupMenuZNodeHeader (zidx);
|
||||
ServerReleaseWinZNodeHeader (NULL, 0);
|
||||
return rc;
|
||||
}
|
||||
|
||||
SyncUpdateDC (HDC_SCREEN_SYS);
|
||||
BOOL refresh_dirty_region (CompositorCtxt* ctxt, MG_Layer* layer)
|
||||
{
|
||||
/* the fallback compositor only manages znodes on the topmost layer. */
|
||||
if (layer != mgTopmostLayer || IsEmptyClipRgn (&ctxt->dirty_rgn))
|
||||
return FALSE;
|
||||
|
||||
composite_ppp_znodes (ctxt);
|
||||
composite_on_dirty_region (ctxt, 0);
|
||||
|
||||
EmptyClipRgn (&ctxt->dirty_rgn);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void on_hiding_ppp (CompositorCtxt* ctxt, int zidx)
|
||||
@@ -907,9 +912,11 @@ CompositorOps __mg_fallback_compositor = {
|
||||
calc_mainwin_pos: calc_mainwin_pos,
|
||||
purge_ppp_data: purge_ppp_data,
|
||||
purge_win_data: purge_win_data,
|
||||
on_dirty_ppp: on_dirty_ppp,
|
||||
on_dirty_win: on_dirty_win,
|
||||
on_dirty_wpp: on_dirty_wpp,
|
||||
reset_dirty_region: reset_dirty_region,
|
||||
merge_dirty_ppp: merge_dirty_ppp,
|
||||
merge_dirty_win: merge_dirty_win,
|
||||
merge_dirty_wpp: merge_dirty_wpp,
|
||||
refresh_dirty_region: refresh_dirty_region,
|
||||
on_dirty_screen: on_dirty_screen,
|
||||
on_showing_ppp: on_showing_ppp,
|
||||
on_hiding_ppp: on_hiding_ppp,
|
||||
|
||||
@@ -88,8 +88,11 @@ static const CompositorOps* load_default_compositor (void)
|
||||
{
|
||||
const char* filename = NULL;
|
||||
char buff [LEN_SO_NAME + 1];
|
||||
const CompositorOps* (*ex_compsor_get) (const char*, const CompositorOps*);
|
||||
const CompositorOps* (*ex_compsor_get) (const char*,
|
||||
const CompositorOps*, int*);
|
||||
char* error;
|
||||
const CompositorOps* ops;
|
||||
int version = 0;
|
||||
|
||||
filename = getenv ("MG_DEF_COMPOSITOR_SO");
|
||||
if (filename == NULL) {
|
||||
@@ -117,7 +120,13 @@ static const CompositorOps* load_default_compositor (void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ex_compsor_get (COMPSOR_NAME_DEFAULT, &__mg_fallback_compositor);
|
||||
ops = ex_compsor_get (COMPSOR_NAME_DEFAULT,
|
||||
&__mg_fallback_compositor, &version);
|
||||
|
||||
if (ops == NULL || version != COMPSOR_OPS_VERSION)
|
||||
return NULL;
|
||||
|
||||
return ops;
|
||||
}
|
||||
|
||||
static void lock_znode_surface (PDC pdc, ZORDERNODE* node)
|
||||
@@ -151,6 +160,7 @@ static void unlock_znode_surface (PDC pdc, ZORDERNODE* node)
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 /* not optimized */
|
||||
void __mg_composite_dirty_znodes (void)
|
||||
{
|
||||
MG_Layer* layer;
|
||||
@@ -245,6 +255,122 @@ void __mg_composite_dirty_znodes (void)
|
||||
}
|
||||
}
|
||||
|
||||
#else /* not optimized */
|
||||
|
||||
static void composite_layer (MG_Layer* layer, CompositorCtxt* ctxt,
|
||||
const CompositorOps* ops)
|
||||
{
|
||||
ZORDERINFO* zi;
|
||||
ZORDERNODE* nodes;
|
||||
int i, next;
|
||||
unsigned int changes_in_dc;
|
||||
PDC pdc;
|
||||
zi = (ZORDERINFO*)layer->zorder_info;
|
||||
|
||||
if (!ops->reset_dirty_region (ctxt, layer))
|
||||
return;
|
||||
|
||||
/* travel menu znodes on the layer */
|
||||
if (zi->nr_popupmenus > 0) {
|
||||
nodes = GET_MENUNODE(zi);
|
||||
for (i = 0; i < zi->nr_popupmenus; i++) {
|
||||
pdc = dc_HDC2PDC (nodes[i].mem_dc);
|
||||
assert (pdc->surface->dirty_info);
|
||||
|
||||
lock_znode_surface (pdc, nodes + i);
|
||||
changes_in_dc = pdc->surface->dirty_info->dirty_age;
|
||||
if (changes_in_dc != nodes[i].changes) {
|
||||
ops->merge_dirty_ppp (ctxt, layer, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* travel win znodes on the layer */
|
||||
nodes = GET_ZORDERNODE(zi);
|
||||
next = 0;
|
||||
while ((next = __kernel_get_next_znode (zi, next)) > 0) {
|
||||
if (nodes [next].flags & ZOF_VISIBLE) {
|
||||
pdc = dc_HDC2PDC (nodes[next].mem_dc);
|
||||
assert (pdc->surface->dirty_info);
|
||||
|
||||
lock_znode_surface (pdc, nodes + next);
|
||||
changes_in_dc = pdc->surface->dirty_info->dirty_age;
|
||||
if (changes_in_dc != nodes[next].changes) {
|
||||
ops->merge_dirty_win (ctxt, layer, next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check wallpaper pattern */
|
||||
pdc = dc_HDC2PDC (HDC_SCREEN);
|
||||
if (pdc->surface->w > 0 && pdc->surface->h > 0) {
|
||||
assert (pdc->surface->dirty_info);
|
||||
lock_znode_surface (pdc, nodes);
|
||||
changes_in_dc = pdc->surface->dirty_info->dirty_age;
|
||||
if (changes_in_dc != nodes[0].changes) {
|
||||
ops->merge_dirty_wpp (ctxt, layer);
|
||||
}
|
||||
}
|
||||
|
||||
ops->refresh_dirty_region (ctxt, layer);
|
||||
|
||||
/* unlock the znode surfaces for popup menus */
|
||||
if (zi->nr_popupmenus > 0) {
|
||||
nodes = GET_MENUNODE(zi);
|
||||
for (i = 0; i < zi->nr_popupmenus; i++) {
|
||||
pdc = dc_HDC2PDC (nodes[i].mem_dc);
|
||||
|
||||
nodes[i].changes = pdc->surface->dirty_info->dirty_age;
|
||||
pdc->surface->dirty_info->nr_dirty_rcs = 0;
|
||||
unlock_znode_surface (pdc, nodes + i);
|
||||
}
|
||||
}
|
||||
|
||||
/* unlock the znode surfaces for windows */
|
||||
nodes = GET_ZORDERNODE(zi);
|
||||
next = 0;
|
||||
while ((next = __kernel_get_next_znode (zi, next)) > 0) {
|
||||
if (nodes [next].flags & ZOF_VISIBLE) {
|
||||
pdc = dc_HDC2PDC (nodes[next].mem_dc);
|
||||
nodes[next].changes = pdc->surface->dirty_info->dirty_age;
|
||||
pdc->surface->dirty_info->nr_dirty_rcs = 0;
|
||||
unlock_znode_surface (pdc, nodes + next);
|
||||
}
|
||||
}
|
||||
|
||||
/* unlock the znode surfaces for wallpaper patter */
|
||||
pdc = dc_HDC2PDC (HDC_SCREEN);
|
||||
if (pdc->surface->w > 0 && pdc->surface->h > 0) {
|
||||
nodes[0].changes = pdc->surface->dirty_info->dirty_age;
|
||||
pdc->surface->dirty_info->nr_dirty_rcs = 0;
|
||||
unlock_znode_surface (pdc, nodes);
|
||||
}
|
||||
}
|
||||
|
||||
void __mg_composite_dirty_znodes (void)
|
||||
{
|
||||
MG_Layer* layer;
|
||||
CompositorCtxt* ctxt;
|
||||
const CompositorOps* ops = ServerSelectCompositor (NULL, &ctxt);
|
||||
|
||||
assert (ops);
|
||||
|
||||
/* first handle the topmost layer */
|
||||
composite_layer (mgTopmostLayer, ctxt, ops);
|
||||
|
||||
/* then handle other layers */
|
||||
layer = mgLayers;
|
||||
while (layer) {
|
||||
if (layer != mgTopmostLayer) {
|
||||
composite_layer (layer, ctxt, ops);
|
||||
}
|
||||
|
||||
layer = layer->next;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* optimized */
|
||||
|
||||
static void purge_znodes_private_data_in_layer (const CompositorOps* ops,
|
||||
CompositorCtxt* ctxt, MG_Layer* layer)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user