add FCM_SCALE to the fallback compositor

This commit is contained in:
Vincent Wei
2021-04-15 10:04:46 +08:00
parent 182f195a57
commit a2183ed53a
2 changed files with 208 additions and 42 deletions

View File

@@ -1775,8 +1775,10 @@ typedef struct _CompositorOps {
} CompositorOps;
#define FCM_HORIZONTAL 0
#define FCM_VERTICAL 1
#define FCM_HORIZONTAL 0x0000
#define FCM_VERTICAL 0x0001
#define FCM_METHOD_MASK 0x00FF
#define FCM_SCALE 0x0100
/** The combining parameters for the callback compositor. */
typedef struct _CombParamsFallback {
@@ -1784,11 +1786,16 @@ typedef struct _CombParamsFallback {
* The combining method, can be one of the following values:
* - FCM_HORIZONTAL
* - FCM_VERTICAL
* and/or OR'd with the following value:
* - FCM_SCALE
*/
int method;
unsigned int method;
/** The percentage of the screen occupied by the first layer. */
int percent;
float percent;
/** The scale factor of non-global z-nodes. */
float scale;
} COMBPARAMS_FALLBACK;
/**

View File

@@ -84,6 +84,7 @@ struct _CompositorCtxt {
int offx; // the offset for the general znodes.
int offy;
BOOL scaled; // is scaled?
};
static CompositorCtxt* initialize (const char* name)
@@ -103,6 +104,7 @@ static CompositorCtxt* initialize (const char* name)
ctxt->layer = NULL;
ctxt->offx = 0;
ctxt->offy = 0;
ctxt->scaled = FALSE;
}
return ctxt;
@@ -297,24 +299,39 @@ static void composite_opaque_win_znode (CompositorCtxt* ctxt, int from)
if ((znode_hdr->flags & ZNIF_VISIBLE) &&
((znode_hdr->ct & CT_SYSTEM_MASK) == CT_OPAQUE) &&
IntersectRegion (&ctxt->inv_rgn, &ctxt->dirty_rgn, rgn)) {
BOOL offx, offy;
int offx, offy;
BOOL scaled;
if ((ctxt->offx || ctxt->offy) && !(znode_hdr->flags & ZOF_IF_SPECIAL)) {
if ((ctxt->offx || ctxt->offy || ctxt->scaled) &&
!(znode_hdr->flags & ZOF_IF_SPECIAL)) {
offx = ctxt->offx;
offy = ctxt->offy;
scaled = ctxt->scaled;
}
else {
offx = 0;
offy = 0;
scaled = FALSE;
}
SetMemDCColorKey (znode_hdr->mem_dc, 0, 0);
SetMemDCAlpha (znode_hdr->mem_dc, 0, 0);
SelectClipRegion (HDC_SCREEN_SYS, &ctxt->inv_rgn);
BitBlt (znode_hdr->mem_dc,
0, 0, RECTW(znode_hdr->rc), RECTH(znode_hdr->rc),
HDC_SCREEN_SYS,
znode_hdr->rc.left + offx, znode_hdr->rc.top + offy, 0);
if (scaled) {
StretchBlt (znode_hdr->mem_dc,
0, 0, RECTW(znode_hdr->rc), RECTH(znode_hdr->rc),
HDC_SCREEN_SYS,
rgn->rcBound.left, rgn->rcBound.top,
RECTW (rgn->rcBound), RECTH (rgn->rcBound),
0);
}
else {
BitBlt (znode_hdr->mem_dc,
0, 0, RECTW(znode_hdr->rc), RECTH(znode_hdr->rc),
HDC_SCREEN_SYS,
znode_hdr->rc.left + offx, znode_hdr->rc.top + offy, 0);
}
SelectClipRect (HDC_SCREEN_SYS, NULL);
SubtractRegion (&ctxt->dirty_rgn, &ctxt->dirty_rgn, &ctxt->inv_rgn);
@@ -341,14 +358,18 @@ static void composite_all_lucent_win_znodes_above (CompositorCtxt* ctxt,
(znode_hdr->ct & CT_SYSTEM_MASK) != CT_OPAQUE &&
IntersectRegion (&ctxt->inv_rgn, dirty_rgn, rgn)) {
int offx, offy;
BOOL scaled;
if ((ctxt->offx || ctxt->offy) && !(znode_hdr->flags & ZOF_IF_SPECIAL)) {
if ((ctxt->offx || ctxt->offy || ctxt->scaled) &&
!(znode_hdr->flags & ZOF_IF_SPECIAL)) {
offx = ctxt->offx;
offy = ctxt->offy;
scaled = ctxt->scaled;
}
else {
offx = 0;
offy = 0;
scaled = FALSE;
}
switch (znode_hdr->ct & CT_SYSTEM_MASK) {
@@ -385,10 +406,20 @@ static void composite_all_lucent_win_znodes_above (CompositorCtxt* ctxt,
}
SelectClipRegion (HDC_SCREEN_SYS, &ctxt->inv_rgn);
BitBlt (znode_hdr->mem_dc,
0, 0, RECTW(znode_hdr->rc), RECTH(znode_hdr->rc),
HDC_SCREEN_SYS,
znode_hdr->rc.left + offx, znode_hdr->rc.top + offy, 0);
if (scaled) {
StretchBlt (znode_hdr->mem_dc,
0, 0, RECTW(znode_hdr->rc), RECTH(znode_hdr->rc),
HDC_SCREEN_SYS,
rgn->rcBound.left, rgn->rcBound.top,
RECTW (rgn->rcBound), RECTH (rgn->rcBound),
0);
}
else {
BitBlt (znode_hdr->mem_dc,
0, 0, RECTW(znode_hdr->rc), RECTH(znode_hdr->rc),
HDC_SCREEN_SYS,
znode_hdr->rc.left + offx, znode_hdr->rc.top + offy, 0);
}
SelectClipRect (HDC_SCREEN_SYS, NULL);
}
@@ -885,7 +916,8 @@ static void on_layer_op (CompositorCtxt* ctxt, int layer_op,
}
}
static int offset_regions_of_general_znodes (MG_Layer* layer, int offx, int offy)
static int offset_regions_of_general_znodes (MG_Layer* layer,
int offx, int offy, float scale)
{
int nr = 0;
int next;
@@ -900,7 +932,57 @@ static int offset_regions_of_general_znodes (MG_Layer* layer, int offx, int offy
if ((znode_hdr->flags & ZNIF_VISIBLE) &&
!(znode_hdr->flags & ZOF_IF_SPECIAL)) {
OffsetRegion (rgn, offx, offy);
if (scale != 1.0f) {
RECT new_bound = rgn->rcBound;
int old_width = RECTW (rgn->rcBound);
int old_height = RECTH (rgn->rcBound);
int new_width = (int)(old_width * scale + 0.5f);
int new_height = (int)(old_height * scale + 0.5f);
int cx = (new_width - old_width) / 2;
int cy = (new_height - old_height) / 2;
InflateRect (&new_bound, cx, cy);
if (!EqualRect (&rgn->rcBound, &new_bound)) {
if (scale > 1.0f) {
assert (IsCovered (&rgn->rcBound, &new_bound));
AddClipRect (rgn, &new_bound);
}
else {
assert (IsCovered ( &new_bound, &rgn->rcBound));
IntersectClipRect (rgn, &new_bound);
}
}
}
nr++;
}
next = ServerGetNextZNode (layer, next, NULL);
}
return nr;
}
static int restore_regions_of_general_znodes (MG_Layer* layer)
{
int nr = 0;
int next;
next = ServerGetNextZNode (layer, 0, NULL);
while (next > 0) {
const ZNODEHEADER* znode_hdr;
CLIPRGN* rgn;
znode_hdr = ServerGetWinZNodeHeader (layer, next, (void**)&rgn, FALSE);
assert (znode_hdr);
if ((znode_hdr->flags & ZNIF_VISIBLE) &&
!(znode_hdr->flags & ZOF_IF_SPECIAL)) {
EmptyClipRgn (rgn);
ServerGetWinZNodeRegion (layer, next, RGN_OP_SET | RGN_OP_FLAG_ABS, rgn);
nr++;
}
@@ -919,21 +1001,24 @@ static unsigned int composite_layers (CompositorCtxt* ctxt, MG_Layer* layers[],
assert (nr_layers == 2);
if (cp->percent < 0 || cp->percent > 100) {
_WRN_PRINTF("Bad percent (%d).\n", cp->percent);
if (cp->percent < 0.0f || cp->percent > 100.0f) {
_WRN_PRINTF("Bad percent (%f).\n", cp->percent);
return 0;
}
clock_gettime (CLOCK_MONOTONIC, &ts_start);
if (!(cp->method & FCM_SCALE))
cp->scale = 1.0f;
rc0 = ctxt->rc_screen;
rc1 = ctxt->rc_screen;
if (cp->method == FCM_VERTICAL) {
rc0.bottom = cp->percent * RECTH (rc0) / 100;
if ((cp->method & FCM_METHOD_MASK) == FCM_VERTICAL) {
rc0.bottom = (int)(cp->percent * RECTH (rc0) / 100.0f + 0.5f);
rc1.top = rc0.bottom;
}
else {
rc0.right = cp->percent * RECTW (rc0) / 100;
rc0.right = (int)(cp->percent * RECTW (rc0) / 100.0f + 0.5f);
rc1.left = rc0.right;
}
@@ -945,18 +1030,21 @@ static unsigned int composite_layers (CompositorCtxt* ctxt, MG_Layer* layers[],
ctxt->layer = layers[0];
ctxt->offx = rc0.right - ctxt->rc_screen.right;
ctxt->offy = rc0.bottom - ctxt->rc_screen.bottom;
ctxt->scaled = (cp->scale != 1.0f);
if (ctxt->offx || ctxt->offy)
offset_regions_of_general_znodes (ctxt->layer, ctxt->offx, ctxt->offy);
if (ctxt->offx || ctxt->offy || ctxt->scaled)
offset_regions_of_general_znodes (ctxt->layer,
ctxt->offx, ctxt->offy, cp->scale);
composite_on_dirty_region (ctxt, 0);
if (ctxt->offx || ctxt->offy)
offset_regions_of_general_znodes (ctxt->layer, -ctxt->offx, -ctxt->offy);
if (ctxt->offx || ctxt->offy || ctxt->scaled)
restore_regions_of_general_znodes (ctxt->layer);
}
else {
// only composite the wallpaper
ctxt->layer = NULL;
ctxt->offx = 0;
ctxt->offy = 0;
ctxt->scaled = FALSE;
composite_wallpaper (ctxt);
}
@@ -968,18 +1056,21 @@ static unsigned int composite_layers (CompositorCtxt* ctxt, MG_Layer* layers[],
ctxt->layer = layers[1];
ctxt->offx = rc1.left;
ctxt->offy = rc1.top;
ctxt->scaled = (cp->scale != 1.0f);
if (ctxt->offx || ctxt->offy)
offset_regions_of_general_znodes (ctxt->layer, ctxt->offx, ctxt->offy);
if (ctxt->offx || ctxt->offy || ctxt->scaled)
offset_regions_of_general_znodes (ctxt->layer,
ctxt->offx, ctxt->offy, cp->scale);
composite_on_dirty_region (ctxt, 0);
if (ctxt->offx || ctxt->offy)
offset_regions_of_general_znodes (ctxt->layer, -ctxt->offx, -ctxt->offy);
if (ctxt->offx || ctxt->offy || ctxt->scaled)
restore_regions_of_general_znodes (ctxt->layer);
}
else {
// only composite the wallpaper
ctxt->layer = NULL;
ctxt->offx = 0;
ctxt->offy = 0;
ctxt->scaled = FALSE;
composite_wallpaper (ctxt);
}
@@ -994,6 +1085,7 @@ static unsigned int composite_layers (CompositorCtxt* ctxt, MG_Layer* layers[],
ctxt->layer = NULL;
ctxt->offx = 0;
ctxt->offy = 0;
ctxt->scaled = FALSE;
return (ts_end.tv_sec - ts_start.tv_sec) * 1000 +
(ts_end.tv_nsec - ts_start.tv_nsec) / 1000000;
@@ -1013,7 +1105,7 @@ static void transit_to_layer (CompositorCtxt* ctxt, MG_Layer* to_layer)
MG_Layer* layers[2];
COMBPARAMS_FALLBACK cp = { FCM_HORIZONTAL, 5 };
COMBPARAMS_FALLBACK cp = { FCM_HORIZONTAL | FCM_SCALE, 5.0f, 1.0f };
while (layer) {
if (layer == mgTopmostLayer)
@@ -1037,36 +1129,103 @@ static void transit_to_layer (CompositorCtxt* ctxt, MG_Layer* to_layer)
if (idx_layer_1 > idx_layer_0) {
/* to_layer is to the right of the topmost layer */
layers[0] = mgTopmostLayer;
layers[1] = to_layer;
cp.percent = 95;
while (cp.percent > 5) {
// Step 1) Zoom out the current topmost layer
layers[0] = mgTopmostLayer;
layers[1] = NULL;
cp.percent = 100.0f;
cp.scale = 0.98f;
while (cp.scale > 0.60f) {
unsigned int t_ms;
t_ms = composite_layers (ctxt, layers, 2, &cp);
if (t_ms > 100)
_WRN_PRINTF ("Two slow to composite layers: %u\n", t_ms);
_WRN_PRINTF ("Too slow to composite layers: %u\n", t_ms);
usleep (20 * 1000);
cp.percent -= 9;
cp.scale -= 0.02f;
}
// Step 2) Move to the new topmost layer
layers[0] = mgTopmostLayer;
layers[1] = to_layer;
cp.percent = 95.0f;
cp.scale = 0.60f;
while (cp.percent > 5.0f) {
unsigned int t_ms;
t_ms = composite_layers (ctxt, layers, 2, &cp);
if (t_ms > 100)
_WRN_PRINTF ("Too slow to composite layers: %u\n", t_ms);
usleep (20 * 1000);
cp.percent -= 4.5f;
}
// Step 3) Zoom in the new topmost layer
layers[0] = to_layer;
layers[1] = NULL;
cp.percent = 100.0f;
cp.scale = 0.60f;
while (cp.scale < 1.00f) {
unsigned int t_ms;
t_ms = composite_layers (ctxt, layers, 2, &cp);
if (t_ms > 100)
_WRN_PRINTF ("Too slow to composite layers: %u\n", t_ms);
usleep (20 * 1000);
cp.scale += 0.02f;
}
}
else {
/* to_layer is to the left of the topmost layer */
layers[0] = to_layer;
layers[1] = mgTopmostLayer;
cp.percent = 5;
while (cp.percent < 95) {
// Step 1) Zoom out the current topmost layer
layers[0] = mgTopmostLayer;
layers[1] = NULL;
cp.percent = 100.0f;
cp.scale = 0.98f;
while (cp.scale > 0.60f) {
unsigned int t_ms;
t_ms = composite_layers (ctxt, layers, 2, &cp);
if (t_ms > 100)
_WRN_PRINTF ("Two slow to composite layers: %u\n", t_ms);
_WRN_PRINTF ("Too slow to composite layers: %u\n", t_ms);
usleep (20 * 1000);
cp.percent += 9;
cp.scale -= 0.02f;
}
// Step 2) Move the current topmost layer
layers[0] = to_layer;
layers[1] = mgTopmostLayer;
cp.percent = 5.0f;
while (cp.percent < 95.0f) {
unsigned int t_ms;
t_ms = composite_layers (ctxt, layers, 2, &cp);
if (t_ms > 100)
_WRN_PRINTF ("Too slow to composite layers: %u\n", t_ms);
usleep (20 * 1000);
cp.percent += 4.5f;
}
// Step 3) Zoom in the new topmost layer
layers[0] = to_layer;
layers[1] = NULL;
cp.percent = 100.0f;
cp.scale = 0.60f;
while (cp.scale > 1.00f) {
unsigned int t_ms;
t_ms = composite_layers (ctxt, layers, 2, &cp);
if (t_ms > 100)
_WRN_PRINTF ("Too slow to composite layers: %u\n", t_ms);
usleep (20 * 1000);
cp.scale += 0.02f;
}
}
}