summaryrefslogtreecommitdiff
path: root/Eyes.c
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2013-07-26 18:46:45 -0700
committerKeith Packard <keithp@keithp.com>2013-07-26 18:46:45 -0700
commit31cce6ec946c27fcad853cd0ce5ca5cbe6f510ab (patch)
treedf660fd546f4e1e32d1e360bb9d049ed4c63818b /Eyes.c
parent717b348e12bdd1f3486709e9887b4cfcfa3fd6de (diff)
Add support for the 'Present' extension.
This makes updating the eyes nicely vblank synchronized. Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'Eyes.c')
-rw-r--r--Eyes.c138
1 files changed, 134 insertions, 4 deletions
diff --git a/Eyes.c b/Eyes.c
index a9f2618..70e833d 100644
--- a/Eyes.c
+++ b/Eyes.c
@@ -63,6 +63,9 @@ static XtResource resources[] = {
goffset(height), XtRImmediate, (XtPointer) 100},
{XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
offset(pixel[PART_PUPIL]), XtRString, XtDefaultForeground},
+ {XtNbackgroundPixmap, XtCPixmap, XtRPixmap, sizeof(Pixmap),
+ XtOffsetOf(CoreRec,core.background_pixmap),
+ XtRImmediate, (XtPointer)None},
{XtNoutline, XtCForeground, XtRPixel, sizeof(Pixel),
offset(pixel[PART_OUTLINE]), XtRString, XtDefaultForeground},
{XtNcenterColor, XtCBackground, XtRPixel, sizeof (Pixel),
@@ -77,6 +80,10 @@ static XtResource resources[] = {
{XtNrender, XtCBoolean, XtRBoolean, sizeof(Boolean),
offset(render), XtRImmediate, (XtPointer) TRUE },
#endif
+#ifdef PRESENT
+ {XtNpresent, XtCBoolean, XtRBoolean, sizeof(Boolean),
+ offset(present), XtRImmediate, (XtPointer) TRUE },
+#endif
{XtNdistance, XtCBoolean, XtRBoolean, sizeof(Boolean),
offset(distance), XtRImmediate, (XtPointer) FALSE },
};
@@ -113,6 +120,99 @@ static void ClassInitialize(void)
WidgetClass eyesWidgetClass = (WidgetClass) &eyesClassRec;
+#ifdef PRESENT
+static void CheckPresent(EyesWidget w) {
+ xcb_xfixes_query_version_cookie_t xfixes_cookie;
+ xcb_xfixes_query_version_reply_t *xfixes_reply;
+ xcb_damage_query_version_cookie_t damage_cookie;
+ xcb_damage_query_version_reply_t *damage_reply;
+ xcb_present_query_version_cookie_t present_cookie;
+ xcb_present_query_version_reply_t *present_reply;
+
+ if (!w->eyes.present)
+ return;
+
+ xfixes_cookie = xcb_xfixes_query_version(xt_xcb(w),
+ XCB_XFIXES_MAJOR_VERSION,
+ XCB_XFIXES_MINOR_VERSION);
+
+ damage_cookie = xcb_damage_query_version(xt_xcb(w),
+ XCB_DAMAGE_MAJOR_VERSION,
+ XCB_DAMAGE_MINOR_VERSION);
+
+ present_cookie = xcb_present_query_version(xt_xcb(w),
+ XCB_PRESENT_MAJOR_VERSION,
+ XCB_PRESENT_MINOR_VERSION);
+
+ xfixes_reply = xcb_xfixes_query_version_reply(xt_xcb(w),
+ xfixes_cookie,
+ NULL);
+ free(xfixes_reply);
+
+ damage_reply = xcb_damage_query_version_reply(xt_xcb(w),
+ damage_cookie,
+ NULL);
+ free(damage_reply);
+
+ present_reply = xcb_present_query_version_reply(xt_xcb(w),
+ present_cookie,
+ NULL);
+ if (xfixes_reply && damage_reply && present_reply)
+ printf ("Using present extension\n");
+ else
+ w->eyes.present = FALSE;
+}
+
+static void MakePresentData(EyesWidget w) {
+ xcb_generic_event_t *ev;
+
+ if (!w->eyes.present)
+ return;
+
+ if (!w->eyes.back_buffer) {
+ xcb_create_pixmap(xt_xcb(w),
+ w->core.depth,
+ w->eyes.back_buffer = xcb_generate_id(xt_xcb(w)),
+ XtWindow(w),
+ w->core.width,
+ w->core.height);
+ }
+ if (!w->eyes.back_damage) {
+ xcb_damage_create(xt_xcb(w),
+ w->eyes.back_damage = xcb_generate_id(xt_xcb(w)),
+ w->eyes.back_buffer,
+ XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY);
+ xcb_xfixes_create_region(xt_xcb(w),
+ w->eyes.back_region = xcb_generate_id(xt_xcb(w)),
+ 0, NULL);
+ }
+}
+
+static void UpdatePresent(EyesWidget w) {
+ if (w->eyes.back_buffer) {
+ xcb_damage_subtract(xt_xcb(w),
+ w->eyes.back_damage,
+ None,
+ w->eyes.back_region);
+ xcb_present_region(xt_xcb(w),
+ XtWindow(w),
+ w->eyes.back_buffer,
+ 0,
+ None,
+ w->eyes.back_region,
+ 0, 0,
+ None, 0, 1, 0);
+ }
+}
+
+#endif
+
+#ifdef PRESENT
+#define EyesDrawable(w) (w->eyes.back_buffer ? w->eyes.back_buffer : XtWindow(w))
+#else
+#define EyesDrawable(w) XtWindow(w)
+#endif
+
/* ARGSUSED */
static void Initialize (
Widget greq,
@@ -197,6 +297,11 @@ static void Initialize (
w->eyes.fill[i] = XRenderCreateSolidFill(XtDisplay (w), &rc);
}
#endif
+#ifdef PRESENT
+ w->eyes.back_buffer = None;
+ w->eyes.back_damage = None;
+ CheckPresent(w);
+#endif
}
static void
@@ -213,7 +318,7 @@ drawEllipse(EyesWidget w, enum EyesPart part,
Trectangle(&w->eyes.t, &tpos, &pos);
if (part == PART_CLEAR) {
- XFillRectangle(XtDisplay(w), XtWindow(w),
+ XFillRectangle(XtDisplay(w), EyesDrawable(w),
w->eyes.gc[PART_CENTER],
(int)pos.x, (int)pos.y,
(int)pos.width+2, (int)pos.height+2);
@@ -275,7 +380,7 @@ drawEllipse(EyesWidget w, enum EyesPart part,
TPOINT_NONE, TPOINT_NONE, diam);
XFillArc(XtDisplay(w),
- part == PART_SHAPE ? w->eyes.shape_mask : XtWindow(w),
+ part == PART_SHAPE ? w->eyes.shape_mask : EyesDrawable(w),
w->eyes.gc[part],
(int)(pos.x + 0.5), (int)(pos.y + 0.5),
(int)(pos.width + 0.0), (int)(pos.height + 0.0),
@@ -406,11 +511,17 @@ eyeBall(EyesWidget w,
static void repaint_window (EyesWidget w)
{
if (XtIsRealized ((Widget) w)) {
+#ifdef PRESENT
+ MakePresentData(w);
+#endif
eyeLiner (w, TRUE, 0);
eyeLiner (w, TRUE, 1);
computePupils (w, w->eyes.mouse, w->eyes.pupil);
eyeBall (w, TRUE, NULL, 0);
eyeBall (w, TRUE, NULL, 1);
+#ifdef PRESENT
+ UpdatePresent(w);
+#endif
}
}
@@ -440,6 +551,9 @@ drawEyes(EyesWidget w, TPoint mouse)
TPoint newpupil[2];
int num;
+#ifdef PRESENT
+ MakePresentData(w);
+#endif
if (TPointEqual (mouse, w->eyes.mouse)) {
if (delays[w->eyes.update + 1] != 0)
++w->eyes.update;
@@ -452,6 +566,9 @@ drawEyes(EyesWidget w, TPoint mouse)
w->eyes.mouse = mouse;
w->eyes.update = 0;
+#ifdef PRESENT
+ UpdatePresent(w);
+#endif
}
static void draw_it_core(EyesWidget w)
@@ -497,12 +614,25 @@ static void Resize (Widget gw)
if (XtIsRealized (gw))
{
- XClearWindow (dpy, XtWindow (w));
SetTransform (&w->eyes.t,
0, w->core.width,
w->core.height, 0,
W_MIN_X, W_MAX_X,
W_MIN_Y, W_MAX_Y);
+#ifdef PRESENT
+ if (w->eyes.back_buffer) {
+ xcb_free_pixmap(xt_xcb(w),
+ w->eyes.back_buffer);
+ w->eyes.back_buffer = None;
+ xcb_damage_destroy(xt_xcb(w),
+ w->eyes.back_damage);
+ w->eyes.back_damage = None;
+ }
+ MakePresentData(w);
+#endif
+ if (EyesDrawable(w) == XtWindow(w))
+ XClearWindow (dpy, XtWindow (w));
+
#ifdef XRENDER
if (w->eyes.picture) {
XRenderFreePicture(dpy, w->eyes.picture);
@@ -537,7 +667,7 @@ static void Resize (Widget gw)
pf = XRenderFindVisualFormat(dpy,
DefaultVisualOfScreen(w->core.screen));
if (pf)
- w->eyes.picture = XRenderCreatePicture(dpy, XtWindow (w),
+ w->eyes.picture = XRenderCreatePicture(dpy, EyesDrawable (w),
pf, 0, &pa);
}
#endif