[Xfce4-commits] <xfce4-settings:xrandr-display-settings> Make xfce4-settings-helper less query-intensive for CRTCs
Jérôme Guelfucci
noreply at xfce.org
Thu Jun 17 23:30:02 CEST 2010
Updating branch refs/heads/xrandr-display-settings
to 49f2d9a21d009622748afd559f2fe473d28f2c7d (commit)
from 76a9181aebc87179d5ef9a9d7039688d5ecf4b0a (commit)
commit 49f2d9a21d009622748afd559f2fe473d28f2c7d
Author: Lionel Le Folgoc <mrpouit at gmail.com>
Date: Thu Jun 17 22:56:12 2010 +0200
Make xfce4-settings-helper less query-intensive for CRTCs
xfce4-settings-helper/displays.c | 324 +++++++++++++++++++++++++-------------
1 files changed, 216 insertions(+), 108 deletions(-)
diff --git a/xfce4-settings-helper/displays.c b/xfce4-settings-helper/displays.c
index 656abb9..883e208 100644
--- a/xfce4-settings-helper/displays.c
+++ b/xfce4-settings-helper/displays.c
@@ -75,6 +75,25 @@ struct _XfceDisplaysHelper
#endif
};
+#ifdef HAS_RANDR_ONE_POINT_TWO
+/* wrapper to avoid querying too often */
+typedef struct _XfceRRCrtc XfceRRCrtc;
+struct _XfceRRCrtc
+{
+ RRCrtc id;
+ RRMode mode;
+ Rotation rotation;
+ Rotation rotations;
+ gint x;
+ gint y;
+ gint noutput;
+ RROutput *outputs;
+ gint npossible;
+ RROutput *possible;
+ gint processed;
+};
+#endif
+
G_DEFINE_TYPE (XfceDisplaysHelper, xfce_displays_helper, G_TYPE_OBJECT);
@@ -192,40 +211,100 @@ xfce_displays_helper_process_screen_size (gint mode_width,
-static RRCrtc
-xfce_displays_helper_find_clone (Display *xdisplay,
- XRRScreenResources *resources,
- GArray *activated_crtcs,
- RROutput current_output,
- gint pos_x,
- gint pos_y,
- RRMode mode,
- Rotation rot)
+static XfceRRCrtc *
+xfce_displays_helper_list_crtcs (Display *xdisplay,
+ XRRScreenResources *resources)
{
+ XfceRRCrtc *crtcs;
XRRCrtcInfo *crtc_info;
- RRCrtc crtc;
- guint i;
- gint n, candidate;
+ gint n, m;
+
+ g_return_val_if_fail (xdisplay != NULL, NULL);
+ g_return_val_if_fail (resources != NULL, NULL);
+
+ /* get all existing CRTCs */
+ crtcs = g_new0 (XfceRRCrtc, resources->ncrtc);
+ for (n = 0; n < resources->ncrtc; ++n)
+ {
+ crtcs[n].id = resources->crtcs[n];
+ crtc_info = XRRGetCrtcInfo (xdisplay, resources, resources->crtcs[n]);
+ crtcs[n].mode = crtc_info->mode;
+ crtcs[n].rotation = crtc_info->rotation;
+ crtcs[n].rotations = crtc_info->rotations;
+ crtcs[n].x = crtc_info->x;
+ crtcs[n].y = crtc_info->y;
+ crtcs[n].noutput = crtc_info->noutput;
+ crtcs[n].outputs = NULL;
+ if (crtc_info->noutput > 0)
+ {
+ crtcs[n].outputs = g_new0 (RROutput, crtc_info->noutput);
+ for (m = 0; m < crtc_info->noutput; ++m)
+ crtcs[n].outputs[m] = crtc_info->outputs[m];
+ }
+ crtcs[n].npossible = crtc_info->npossible;
+ crtcs[n].possible = NULL;
+ if (crtc_info->npossible > 0)
+ {
+ crtcs[n].possible = g_new0 (RROutput, crtc_info->npossible);
+ for (m = 0; m < crtc_info->npossible; ++m)
+ crtcs[n].possible[m] = crtc_info->possible[m];
+ }
+ crtcs[n].processed = FALSE;
+ XRRFreeCrtcInfo (crtc_info);
+ }
+
+ return crtcs;
+}
- g_return_val_if_fail (xdisplay != NULL, None);
- g_return_val_if_fail (resources != NULL, None);
- g_return_val_if_fail (activated_crtcs != NULL, None);
- for (i = 0; i < activated_crtcs->len; ++i)
+
+static XfceRRCrtc *
+xfce_displays_helper_find_crtc_by_id (XRRScreenResources *resources,
+ XfceRRCrtc *crtcs,
+ RRCrtc id)
+{
+ gint n;
+
+ g_return_val_if_fail (resources != NULL, NULL);
+ g_return_val_if_fail (crtcs != NULL, NULL);
+
+ for (n = 0; n < resources->ncrtc; ++n)
{
- crtc = g_array_index (activated_crtcs, RRCrtc, i);
- crtc_info = XRRGetCrtcInfo (xdisplay, resources, crtc);
+ if (crtcs[n].id == id)
+ return &crtcs[n];
+ }
+
+ return NULL;
+}
+
+
+
+static XfceRRCrtc *
+xfce_displays_helper_find_clonable_crtc (XRRScreenResources *resources,
+ XfceRRCrtc *crtcs,
+ RROutput current_output,
+ gint pos_x,
+ gint pos_y,
+ RRMode mode,
+ Rotation rot)
+{
+ gint m, n, candidate;
+
+ g_return_val_if_fail (resources != NULL, NULL);
+ g_return_val_if_fail (crtcs != NULL, NULL);
- if (crtc_info->x == pos_x && crtc_info->y == pos_y
- && crtc_info->mode == mode && crtc_info->rotation == rot)
+ for (n = 0; n < resources->ncrtc; ++n)
+ {
+ if (crtcs[n].processed && crtcs[n].x == pos_x && crtcs[n].y == pos_y
+ && crtcs[n].mode == mode && crtcs[n].rotation == rot)
{
/* we found a CRTC already enabled with the exact values
=> might be suitable for a clone, check that it can be
connected to the new output */
candidate = FALSE;
- for (n = 0; n < crtc_info->npossible; ++n)
+ for (m = 0; m < crtcs[n].npossible; ++m)
{
- if (crtc_info->possible[n] == current_output)
+ if (crtcs[n].possible[m] == current_output)
{
candidate = TRUE;
break;
@@ -234,71 +313,93 @@ xfce_displays_helper_find_clone (Display *xdisplay,
/* definitely suitable for a clone */
if (candidate)
- {
- XRRFreeCrtcInfo (crtc_info);
- return crtc;
- }
+ return &crtcs[n];
}
-
- XRRFreeCrtcInfo (crtc_info);
}
- return None;
+ return NULL;
}
-static RRCrtc
-xfce_displays_helper_find_crtc (Display *xdisplay,
- XRRScreenResources *resources,
- XRROutputInfo *current_output)
+static XfceRRCrtc *
+xfce_displays_helper_find_usable_crtc (XRRScreenResources *resources,
+ XfceRRCrtc *crtcs,
+ XRROutputInfo *output_info,
+ RROutput output)
{
- XRROutputInfo *output_info;
- gint m, n, candidate;
+ gint m, n;
- g_return_val_if_fail (current_output != NULL, None);
+ g_return_val_if_fail (resources != NULL, NULL);
+ g_return_val_if_fail (crtcs != NULL, NULL);
+ g_return_val_if_fail (output_info != NULL, NULL);
/* if there is one already active, return it */
- if (current_output->crtc != None)
- return current_output->crtc;
-
- g_return_val_if_fail (xdisplay != NULL, None);
- g_return_val_if_fail (resources != NULL, None);
+ if (output_info->crtc != None)
+ return xfce_displays_helper_find_crtc_by_id (resources, crtcs,
+ output_info->crtc);
/* try to find one that is not already used by another output */
- for (n = 0; n < current_output->ncrtc; ++n)
+ for (n = 0; n < resources->ncrtc; ++n)
{
- candidate = TRUE;
- for (m = 0; m < resources->noutput; ++m)
+ if (crtcs[n].noutput > 0)
+ continue;
+
+ for (m = 0; m < crtcs[n].npossible; ++m)
{
- output_info = XRRGetOutputInfo (xdisplay, resources, resources->outputs[m]);
+ if (crtcs[n].possible[m] == output)
+ return &crtcs[n];
+ }
+ }
- /* go to the next output directly */
- if (output_info->connection != RR_Connected
- || g_strcmp0 (output_info->name, current_output->name) == 0)
- {
- XRRFreeOutputInfo (output_info);
- continue;
- }
+ /* none available */
+ g_warning ("No CRTC found for %s.", output_info->name);
+ return NULL;
+}
- /* crtc already used */
- if (output_info->crtc == current_output->crtcs[n])
- {
- candidate = FALSE;
- XRRFreeOutputInfo (output_info);
- break;
- }
- XRRFreeOutputInfo (output_info);
- }
- if (candidate)
- return current_output->crtcs[n];
+static Status
+xfce_displays_helper_apply_crtc (Display *xdisplay,
+ XRRScreenResources *resources,
+ XfceRRCrtc *crtc,
+ RRMode mode,
+ Rotation rot,
+ gint pos_x,
+ gint pos_y,
+ gint noutput,
+ RROutput *outputs)
+{
+ Status ret;
+ gint n;
+
+ g_return_val_if_fail (xdisplay != NULL, RRSetConfigSuccess);
+ g_return_val_if_fail (resources != NULL, RRSetConfigSuccess);
+ g_return_val_if_fail (crtc != NULL, RRSetConfigSuccess);
+
+ ret = XRRSetCrtcConfig (xdisplay, resources, crtc->id, CurrentTime, pos_x,
+ pos_y, mode, rot, outputs, noutput);
+
+ /* update our view */
+ if (ret == RRSetConfigSuccess)
+ {
+ crtc->mode = mode;
+ crtc->rotation = rot;
+ crtc->x = pos_x;
+ crtc->y = pos_y;
+ crtc->noutput = noutput;
+ g_free (crtc->outputs);
+ crtc->outputs = NULL;
+ if (noutput > 0)
+ {
+ crtc->outputs = g_new0 (RROutput, noutput);
+ for (n = 0; n < noutput; ++n)
+ crtc->outputs[n] = outputs[n];
+ }
+ crtc->processed = TRUE;
}
- /* none available */
- g_warning ("No CRTC found for %s.", current_output->name);
- return None;
+ return ret;
}
@@ -306,29 +407,29 @@ xfce_displays_helper_find_crtc (Display *xdisplay,
static Status
xfce_displays_helper_disable_crtc (Display *xdisplay,
XRRScreenResources *resources,
- RRCrtc crtc)
+ XfceRRCrtc *crtc)
{
g_return_val_if_fail (xdisplay != NULL, RRSetConfigSuccess);
g_return_val_if_fail (resources != NULL, RRSetConfigSuccess);
/* already disabled */
- if (crtc == None)
+ if (!crtc)
return RRSetConfigSuccess;
- return XRRSetCrtcConfig (xdisplay, resources, crtc, CurrentTime,
- 0, 0, None, RR_Rotate_0, NULL, 0);
+ return xfce_displays_helper_apply_crtc (xdisplay, resources, crtc, None,
+ RR_Rotate_0, 0, 0, 0, NULL);
}
static void
-xfce_displays_helper_set_outputs (XRRCrtcInfo *crtc_info,
- RROutput current_output,
- gint *noutput,
- RROutput **outputs)
+xfce_displays_helper_set_outputs (XfceRRCrtc *crtc,
+ RROutput current_output,
+ gint *noutput,
+ RROutput **outputs)
{
- gint m, n, found;
+ gint n, found;
- if (crtc_info->noutput == 0)
+ if (crtc->noutput == 0)
{
/* no output connected, easy, put the current one */
*noutput = 1;
@@ -339,23 +440,23 @@ xfce_displays_helper_set_outputs (XRRCrtcInfo *crtc_info,
found = FALSE;
/* some outputs are already connected, check if the current one is present */
- for (n = 0; n < crtc_info->noutput; ++n)
+ for (n = 0; n < crtc->noutput; ++n)
{
- if (crtc_info->outputs[n] == current_output)
+ if (crtc->outputs[n] == current_output)
{
found = TRUE;
break;
}
}
- *noutput = found ? crtc_info->noutput : crtc_info->noutput + 1;
+ *noutput = found ? crtc->noutput : crtc->noutput + 1;
*outputs = g_new0 (RROutput, *noutput);
/* readd the existing ones */
- for (m = n = 0; n < crtc_info->noutput; ++n)
- *outputs[m++] = crtc_info->outputs[n];
+ for (n = 0; n < crtc->noutput; ++n)
+ *outputs[n] = crtc->outputs[n];
/* add the current one if needed */
if (!found)
- *outputs[m] = current_output;
+ *outputs[++n] = current_output;
return;
}
@@ -369,8 +470,8 @@ xfce_displays_helper_channel_apply (XfceDisplaysHelper *helper,
GdkDisplay *display;
Display *xdisplay;
GdkWindow *root_window;
- GArray *activated_crtcs;
XRRScreenResources *resources;
+ XfceRRCrtc *crtcs, *crtc;
gchar property[512];
gint min_width, min_height, max_width, max_height;
gint mm_width, mm_height, width, height;
@@ -382,11 +483,9 @@ xfce_displays_helper_channel_apply (XfceDisplaysHelper *helper,
gchar *output_name, *output_res, *output_ref;
gdouble output_rate;
XRROutputInfo *output_info;
- XRRCrtcInfo *crtc_info;
XRRModeInfo *mode_info;
gdouble rate;
RRMode mode;
- RRCrtc crtc;
Rotation rot;
RROutput *outputs;
@@ -413,8 +512,10 @@ xfce_displays_helper_channel_apply (XfceDisplaysHelper *helper,
return;
}
+ /* get all existing CRTCs */
+ crtcs = xfce_displays_helper_list_crtcs (xdisplay, resources);
+
/* init them before starting */
- activated_crtcs = g_array_new (FALSE, FALSE, sizeof (RRCrtc));
mm_width = mm_height = width = height = 0;
/* get the number of outputs */
@@ -485,8 +586,9 @@ xfce_displays_helper_channel_apply (XfceDisplaysHelper *helper,
/* outputs that have to be disabled are stored without resolution */
if (output_res == NULL)
{
- if (xfce_displays_helper_disable_crtc (xdisplay, resources,
- output_info->crtc) != RRSetConfigSuccess)
+ crtc = xfce_displays_helper_find_crtc_by_id (resources, crtcs,
+ output_info->crtc);
+ if (xfce_displays_helper_disable_crtc (xdisplay, resources, crtc) != RRSetConfigSuccess)
g_warning ("Failed to disable CRTC for output %s.", output_info->name);
XRRFreeOutputInfo (output_info);
@@ -532,27 +634,25 @@ xfce_displays_helper_channel_apply (XfceDisplaysHelper *helper,
}
/* first, search for a possible clone */
- crtc = xfce_displays_helper_find_clone (xdisplay, resources, activated_crtcs,
- resources->outputs[m], pos_x, pos_y,
- mode, rot);
+ crtc = xfce_displays_helper_find_clonable_crtc (resources, crtcs,
+ resources->outputs[m],
+ pos_x, pos_y, mode, rot);
/* if it failed, forget about it and pick a free one */
- if (crtc == None)
- crtc = xfce_displays_helper_find_crtc (xdisplay, resources, output_info);
+ if (!crtc)
+ crtc = xfce_displays_helper_find_usable_crtc (resources, crtcs,
+ output_info, resources->outputs[m]);
- if (crtc != None)
+ if (crtc)
{
- crtc_info = XRRGetCrtcInfo (xdisplay, resources, crtc);
-
/* unsupported rotation, abort for this output */
- if ((crtc_info->rotations & rot) == 0)
+ if ((crtc->rotations & rot) == 0)
{
- XRRFreeCrtcInfo (crtc_info);
XRRFreeOutputInfo (output_info);
break;
}
noutput = 0;
- xfce_displays_helper_set_outputs (crtc_info, resources->outputs[m],
+ xfce_displays_helper_set_outputs (crtc, resources->outputs[m],
&noutput, &outputs);
/* get the sizes of the mode to enforce */
@@ -568,18 +668,20 @@ xfce_displays_helper_channel_apply (XfceDisplaysHelper *helper,
&mm_width, &mm_height);
/* check if we really need to do something */
- if (crtc_info->mode != mode || crtc_info->rotation != rot
- || crtc_info->x != pos_x || crtc_info->y != pos_y)
+ if (crtc->mode != mode || crtc->rotation != rot
+ || crtc->x != pos_x || crtc->y != pos_y
+ || crtc->noutput != noutput)
{
- if (XRRSetCrtcConfig (xdisplay, resources, crtc, crtc_info->timestamp,
- pos_x, pos_y, mode, rot, outputs, noutput) == RRSetConfigSuccess)
- g_array_append_val (activated_crtcs, crtc);
- else
+ if (xfce_displays_helper_apply_crtc (xdisplay, resources, crtc,
+ mode, rot, pos_x, pos_y,
+ noutput, outputs) != RRSetConfigSuccess)
+ {
+ /* failure */
g_warning ("Failed to configure %s.", output_info->name);
+ }
}
g_free (outputs);
- XRRFreeCrtcInfo (crtc_info);
}
XRRFreeOutputInfo (output_info);
@@ -596,8 +698,6 @@ xfce_displays_helper_channel_apply (XfceDisplaysHelper *helper,
g_free (output_name);
}
- g_array_free (activated_crtcs, TRUE);
-
/* set the screen size only if it's really needed and valid */
if (width >= min_width && width <= max_width
&& height >= min_height && height <= max_height
@@ -608,6 +708,14 @@ xfce_displays_helper_channel_apply (XfceDisplaysHelper *helper,
XRRSetScreenSize (xdisplay, GDK_WINDOW_XID (root_window),
width, height, mm_width, mm_height);
+ /* cleanup our CRTC view */
+ for (n = 0; n < resources->ncrtc; ++n)
+ {
+ g_free (crtcs[n].outputs);
+ g_free (crtcs[n].possible);
+ }
+ g_free (crtcs);
+
/* free the screen resources */
XRRFreeScreenResources (resources);
More information about the Xfce4-commits
mailing list