optimize __mg_composite_dirty_znodes

This commit is contained in:
Vincent Wei
2020-03-24 13:00:10 +08:00
parent f7cb85401c
commit a693fa7dc2
2 changed files with 232 additions and 99 deletions

View File

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

View File

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