diff options
author | Keith Packard <keithp@keithp.com> | 2013-07-26 18:46:45 -0700 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2013-07-26 18:46:45 -0700 |
commit | 31cce6ec946c27fcad853cd0ce5ca5cbe6f510ab (patch) | |
tree | df660fd546f4e1e32d1e360bb9d049ed4c63818b /Eyes.c | |
parent | 717b348e12bdd1f3486709e9887b4cfcfa3fd6de (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.c | 138 |
1 files changed, 134 insertions, 4 deletions
@@ -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 |