diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c index 4573f626b..3fccaeaa6 100644 --- a/hw/xfree86/modes/xf86Crtc.c +++ b/hw/xfree86/modes/xf86Crtc.c @@ -106,12 +106,17 @@ xf86CrtcCreate (ScrnInfoPtr scrn, pixman_transform_init_identity (&crtc->crtc_to_framebuffer); pixman_f_transform_init_identity (&crtc->f_crtc_to_framebuffer); pixman_f_transform_init_identity (&crtc->f_framebuffer_to_crtc); + pixman_f_transform_init_identity (&crtc->f_screen_to_crtc); + pixman_f_transform_init_identity (&crtc->user_sprite_position_transform); + pixman_f_transform_init_identity (&crtc->f_crtc_to_cursor); + pixman_f_transform_init_identity (&crtc->user_sprite_image_transform); crtc->filter = NULL; crtc->params = NULL; crtc->nparams = 0; crtc->filter_width = 0; crtc->filter_height = 0; crtc->transform_in_use = FALSE; + crtc->sprite_transform_in_use = FALSE; crtc->transformPresent = FALSE; crtc->desiredTransformPresent = FALSE; memset (&crtc->bounds, '\0', sizeof (crtc->bounds)); diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h index f43e0a7e9..8b42efc2f 100644 --- a/hw/xfree86/modes/xf86Crtc.h +++ b/hw/xfree86/modes/xf86Crtc.h @@ -345,6 +345,7 @@ struct _xf86Crtc { int filter_width; /* ABI 2 */ int filter_height; /* ABI 2 */ Bool transform_in_use; + Bool sprite_transform_in_use; RRTransformRec transform; /* ABI 2 */ Bool transformPresent; /* ABI 2 */ RRTransformRec desiredTransform; /* ABI 2 */ @@ -384,6 +385,22 @@ struct _xf86Crtc { * Clear the shadow */ Bool shadowClear; + + /** + * Sprite position transforms + */ + + /* Transform a screen coordinate to a crtc coordinate */ + struct pixman_f_transform f_screen_to_crtc; + + /* The user-specified portion of the screen to crtc conversion */ + struct pixman_f_transform user_sprite_position_transform; + + /* Transform a hardware cursor coordinate to a cursor coordinate */ + struct pixman_f_transform f_crtc_to_cursor; + + /* The user-specified portion of the cursor to hardware transform */ + struct pixman_f_transform user_sprite_image_transform; }; typedef struct _xf86OutputFuncs { @@ -777,6 +794,14 @@ xf86CrtcSetOrigin (xf86CrtcPtr crtc, int x, int y); extern _X_EXPORT Bool xf86CrtcRotate (xf86CrtcPtr crtc); + +/* + * Update cursor transform matrices after user changes + * This is just the cursor subset of xf86CrtcRotate + */ +extern _X_EXPORT void +xf86CrtcRotateCursor (xf86CrtcPtr crtc); + /* * Clean up any rotation data, used when a crtc is turned off * as well as when rotation is disabled. diff --git a/hw/xfree86/modes/xf86Cursors.c b/hw/xfree86/modes/xf86Cursors.c index 066744744..7b43bcb7f 100644 --- a/hw/xfree86/modes/xf86Cursors.c +++ b/hw/xfree86/modes/xf86Cursors.c @@ -338,7 +338,7 @@ xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y) /* * Transform position of cursor on screen */ - if (crtc->transform_in_use) + if (crtc->sprite_transform_in_use) { ScreenPtr screen = scrn->pScreen; xf86CursorScreenPtr ScreenPriv = @@ -349,7 +349,7 @@ xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y) v.v[0] = (x + ScreenPriv->HotX) + 0.5; v.v[1] = (y + ScreenPriv->HotY) + 0.5; v.v[2] = 1; - pixman_f_transform_point (&crtc->f_framebuffer_to_crtc, &v); + pixman_f_transform_point (&crtc->f_screen_to_crtc, &v); /* cursor will have 0.5 added to it already so floor is sufficent */ x = floor (v.v[0]); y = floor (v.v[1]); diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c index d60ee3c58..bbf28cdb4 100644 --- a/hw/xfree86/modes/xf86RandR12.c +++ b/hw/xfree86/modes/xf86RandR12.c @@ -180,14 +180,14 @@ xf86RandR13VerifyPanningArea (xf86CrtcPtr crtc, int screenWidth, int screenHeigh */ static void -xf86ComputeCrtcPan (Bool transform_in_use, +xf86ComputeCrtcPan (Bool sprite_transform_in_use, struct pixman_f_transform *m, double screen_x, double screen_y, double crtc_x, double crtc_y, int old_pan_x, int old_pan_y, int *new_pan_x, int *new_pan_y) { - if (transform_in_use) { + if (sprite_transform_in_use) { /* * Given the current transform, M, the current position * on the Screen, S, and the desired position on the CRTC, @@ -374,8 +374,8 @@ xf86RandR13Pan (xf86CrtcPtr crtc, int x, int y) c.v[0] = x; c.v[1] = y; c.v[2] = 1.0; - if (crtc->transform_in_use) { - pixman_f_transform_point(&crtc->f_framebuffer_to_crtc, &c); + if (crtc->sprite_transform_in_use) { + pixman_f_transform_point(&crtc->f_screen_to_crtc, &c); } else { c.v[0] -= crtc->x; c.v[1] -= crtc->y; @@ -402,8 +402,8 @@ xf86RandR13Pan (xf86CrtcPtr crtc, int x, int y) } } if (panned) - xf86ComputeCrtcPan (crtc->transform_in_use, - &crtc->f_framebuffer_to_crtc, + xf86ComputeCrtcPan (crtc->sprite_transform_in_use, + &crtc->f_screen_to_crtc, x, y, c.v[0], c.v[1], newX, newY, &newX, &newY); } @@ -414,7 +414,7 @@ xf86RandR13Pan (xf86CrtcPtr crtc, int x, int y) * XXX This computation only works when we do not have a transform * in use. */ - if (!crtc->transform_in_use) + if (!crtc->sprite_transform_in_use) { /* Validate against [xy]1 after [xy]2, to be sure that results are > 0 for [xy]1 > 0 */ if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) { @@ -1732,6 +1732,20 @@ xf86RandR12ChangeGamma(int scrnIndex, Gamma gamma) return Success; } +static void +xf86RandR14SetCrtcSpriteTransform(ScreenPtr pScreen, + RRCrtcPtr randr_crtc, + struct pixman_f_transform *f_position_transform, + struct pixman_f_transform *f_image_transform) +{ + xf86CrtcPtr crtc = randr_crtc->devPrivate; + + crtc->user_sprite_position_transform = *f_position_transform; + crtc->user_sprite_image_transform = *f_image_transform; + xf86CrtcRotateCursor(crtc); + xf86_reload_cursors(pScreen); +} + static Bool xf86RandR12EnterVT (int screen_index, int flags) { @@ -1740,6 +1754,7 @@ xf86RandR12EnterVT (int screen_index, int flags) XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); rrScrPrivPtr rp = rrGetScrPriv(pScreen); Bool ret; + int i; if (randrp->orig_EnterVT) { pScrn->EnterVT = randrp->orig_EnterVT; @@ -1751,7 +1766,6 @@ xf86RandR12EnterVT (int screen_index, int flags) } /* reload gamma */ - int i; for (i = 0; i < rp->numCrtcs; i++) xf86RandR12CrtcSetGamma(pScreen, rp->crtcs[i]); @@ -1782,6 +1796,7 @@ xf86RandR12Init12 (ScreenPtr pScreen) rp->rrSetConfig = NULL; pScrn->PointerMoved = xf86RandR12PointerMoved; pScrn->ChangeGamma = xf86RandR12ChangeGamma; + rp->rrSetCrtcSpriteTransform = xf86RandR14SetCrtcSpriteTransform; randrp->orig_EnterVT = pScrn->EnterVT; pScrn->EnterVT = xf86RandR12EnterVT; diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c index 57c3499ac..ddc6d4cb9 100644 --- a/hw/xfree86/modes/xf86Rotate.c +++ b/hw/xfree86/modes/xf86Rotate.c @@ -369,6 +369,39 @@ xf86CrtcFitsScreen (xf86CrtcPtr crtc, struct pict_f_transform *crtc_to_fb) 0 <= b.y1 && b.y2 <= pScrn->virtualY); } +/* + * A subset of xf86CrtcRotate that just deals with + * cursor image/position transforms. Used when changing + * the cursor transform + */ +void +xf86CrtcRotateCursor (xf86CrtcPtr crtc) +{ + /* if this is called during ScreenInit() we don't have pScrn->pScreen yet */ + RRTransformPtr transform = NULL; + PictTransform crtc_to_fb; + struct pict_f_transform f_crtc_to_fb, f_fb_to_crtc, f_screen_to_crtc, f_crtc_to_cursor; + + if (crtc->transformPresent) + transform = &crtc->transform; + + (void) RRTransformCompute (crtc->x, crtc->y, + crtc->mode.HDisplay, crtc->mode.VDisplay, + crtc->rotation, + transform, + &crtc->user_sprite_position_transform, + &crtc->user_sprite_image_transform, + + &crtc_to_fb, + &f_crtc_to_fb, + &f_fb_to_crtc, + &f_screen_to_crtc, + &f_crtc_to_cursor, + &crtc->sprite_transform_in_use); + crtc->f_screen_to_crtc = f_screen_to_crtc; + crtc->f_crtc_to_cursor = f_crtc_to_cursor; +} + Bool xf86CrtcRotate (xf86CrtcPtr crtc) { @@ -377,7 +410,7 @@ xf86CrtcRotate (xf86CrtcPtr crtc) /* if this is called during ScreenInit() we don't have pScrn->pScreen yet */ ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; PictTransform crtc_to_fb; - struct pict_f_transform f_crtc_to_fb, f_fb_to_crtc; + struct pict_f_transform f_crtc_to_fb, f_fb_to_crtc, f_screen_to_crtc, f_crtc_to_cursor; xFixed *new_params = NULL; int new_nparams = 0; PictFilterPtr new_filter = NULL; @@ -393,10 +426,15 @@ xf86CrtcRotate (xf86CrtcPtr crtc) crtc->mode.HDisplay, crtc->mode.VDisplay, crtc->rotation, transform, + &crtc->user_sprite_position_transform, + &crtc->user_sprite_image_transform, &crtc_to_fb, &f_crtc_to_fb, - &f_fb_to_crtc) && + &f_fb_to_crtc, + &f_screen_to_crtc, + &f_crtc_to_cursor, + &crtc->sprite_transform_in_use) && xf86CrtcFitsScreen (crtc, &f_crtc_to_fb)) { /* @@ -505,6 +543,8 @@ xf86CrtcRotate (xf86CrtcPtr crtc) crtc->crtc_to_framebuffer = crtc_to_fb; crtc->f_crtc_to_framebuffer = f_crtc_to_fb; crtc->f_framebuffer_to_crtc = f_fb_to_crtc; + crtc->f_screen_to_crtc = f_screen_to_crtc; + crtc->f_crtc_to_cursor = f_crtc_to_cursor; free(crtc->params); crtc->params = new_params; crtc->nparams = new_nparams; diff --git a/randr/Makefile.am b/randr/Makefile.am index de338b972..4b38e524b 100644 --- a/randr/Makefile.am +++ b/randr/Makefile.am @@ -20,6 +20,7 @@ librandr_la_SOURCES = \ rrproperty.c \ rrscreen.c \ rrsdispatch.c \ + rrsprite.c \ rrtransform.h \ rrtransform.c diff --git a/randr/randrstr.h b/randr/randrstr.h index 7ea608003..5e2a3518c 100644 --- a/randr/randrstr.h +++ b/randr/randrstr.h @@ -55,9 +55,10 @@ #define RANDR_10_INTERFACE 1 #define RANDR_12_INTERFACE 1 #define RANDR_13_INTERFACE 1 /* requires RANDR_12_INTERFACE */ +#define RANDR_14_INTERFACE 1 /* requires RANDR_13_INTERFACE */ #define RANDR_GET_CRTC_INTERFACE 1 -#define RANDR_INTERFACE_VERSION 0x0103 +#define RANDR_INTERFACE_VERSION 0x0104 typedef XID RRMode; typedef XID RROutput; @@ -122,9 +123,16 @@ struct _rrCrtc { Bool transforms; RRTransformRec client_pending_transform; RRTransformRec client_current_transform; + PictTransform client_sprite_position_transform; + PictTransform client_sprite_image_transform; + struct pict_f_transform client_sprite_f_position_transform; + struct pict_f_transform client_sprite_f_image_transform; + PictTransform transform; struct pict_f_transform f_transform; struct pict_f_transform f_inverse; + struct pict_f_transform f_sprite_position; /* crtc from screen */ + struct pict_f_transform f_sprite_image_inverse; /* image from crtc */ }; struct _rrOutput { @@ -233,6 +241,16 @@ typedef Bool (*RRSetConfigProcPtr) (ScreenPtr pScreen, #endif +typedef void (*RRSetCrtcSpriteTransformPtr) (ScreenPtr pScreen, + RRCrtcPtr randr_crtc, + struct pict_f_transform *position_transform, + struct pict_f_transform *image_transform); + +typedef void (*RRGetCrtcSpriteTransformPtr) (ScreenPtr pScreen, + RRCrtcPtr randr_crtc, + struct pict_f_transform *position_transform, + struct pict_f_transform *image_transform); + typedef struct _rrScrPriv { /* * 'public' part of the structure; DDXen fill this in @@ -256,7 +274,9 @@ typedef struct _rrScrPriv { RRGetPanningProcPtr rrGetPanning; RRSetPanningProcPtr rrSetPanning; #endif - + RRSetCrtcSpriteTransformPtr rrSetCrtcSpriteTransform; + RRGetCrtcSpriteTransformPtr rrGetCrtcSpriteTransform; + /* * Private part of the structure; not considered part of the ABI */ @@ -605,25 +625,6 @@ RRCrtcGammaSetSize (RRCrtcPtr crtc, extern _X_EXPORT void RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height); -/* - * Compute the complete transformation matrix including - * client-specified transform, rotation/reflection values and the crtc - * offset. - * - * Return TRUE if the resulting transform is not a simple translation. - */ -extern _X_EXPORT Bool -RRTransformCompute (int x, - int y, - int width, - int height, - Rotation rotation, - RRTransformPtr rr_transform, - - PictTransformPtr transform, - struct pict_f_transform *f_transform, - struct pict_f_transform *f_inverse); - /* * Return crtc transform */ @@ -700,6 +701,19 @@ ProcRRGetPanning (ClientPtr client); int ProcRRSetPanning (ClientPtr client); +void +RRCrtcSpriteTransformSet(RRCrtcPtr crtc, + PictTransform *position_transform, + PictTransform *image_transform, + struct pict_f_transform *f_position_transform, + struct pict_f_transform *f_image_transform); + +int +ProcRRSetCrtcSpriteTransform (ClientPtr client); + +int +ProcRRGetCrtcSpriteTransform (ClientPtr client); + /* rrdispatch.c */ extern _X_EXPORT Bool RRClientKnowsRates (ClientPtr pClient); @@ -889,6 +903,13 @@ ProcRRConfigureOutputProperty (ClientPtr client); extern _X_EXPORT int ProcRRDeleteOutputProperty (ClientPtr client); +/* rrsprite.c */ +extern _X_EXPORT int +ProcRRSetCrtcSpriteTransform (ClientPtr client); + +extern _X_EXPORT int +ProcRRGetCrtcSpriteTransform (ClientPtr client); + /* rrxinerama.c */ #ifdef XINERAMA extern _X_EXPORT void diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c index 98206a2b9..c2f696332 100644 --- a/randr/rrcrtc.c +++ b/randr/rrcrtc.c @@ -93,6 +93,8 @@ RRCrtcCreate (ScreenPtr pScreen, void *devPrivate) pixman_transform_init_identity (&crtc->transform); pixman_f_transform_init_identity (&crtc->f_transform); pixman_f_transform_init_identity (&crtc->f_inverse); + pixman_f_transform_init_identity (&crtc->f_sprite_position); + pixman_f_transform_init_identity (&crtc->f_sprite_image_inverse); if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc)) return NULL; @@ -231,15 +233,21 @@ RRCrtcNotify (RRCrtcPtr crtc, RRTransformCopy (&crtc->client_current_transform, transform); RRCrtcChanged (crtc, TRUE); } + if (crtc->changed && mode) { RRTransformCompute (x, y, mode->mode.width, mode->mode.height, rotation, &crtc->client_current_transform, + &crtc->client_sprite_f_position_transform, + &crtc->client_sprite_f_image_transform, &crtc->transform, &crtc->f_transform, - &crtc->f_inverse); + &crtc->f_inverse, &crtc->f_sprite_position, + &crtc->f_sprite_image_inverse, + NULL); } + return TRUE; } @@ -511,7 +519,7 @@ RRCrtcGammaNotify (RRCrtcPtr crtc) } static void -RRModeGetScanoutSize (RRModePtr mode, PictTransformPtr transform, +RRModeGetScanoutSize (RRModePtr mode, struct pixman_f_transform *transform, int *width, int *height) { BoxRec box; @@ -527,7 +535,7 @@ RRModeGetScanoutSize (RRModePtr mode, PictTransformPtr transform, box.x2 = mode->mode.width; box.y2 = mode->mode.height; - pixman_transform_bounds (transform, &box); + pixman_f_transform_bounds (transform, &box); *width = box.x2 - box.x1; *height = box.y2 - box.y1; } @@ -538,7 +546,7 @@ RRModeGetScanoutSize (RRModePtr mode, PictTransformPtr transform, void RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height) { - return RRModeGetScanoutSize (crtc->mode, &crtc->transform, width, height); + RRModeGetScanoutSize (crtc->mode, &crtc->f_transform, width, height); } /* @@ -924,9 +932,12 @@ ProcRRSetCrtcConfig (ClientPtr client) mode->mode.width, mode->mode.height, rotation, &crtc->client_pending_transform, - &transform, &f_transform, &f_inverse); + &crtc->client_sprite_f_position_transform, + &crtc->client_sprite_f_image_transform, + &transform, &f_transform, &f_inverse, NULL, NULL, NULL); - RRModeGetScanoutSize (mode, &transform, &source_width, &source_height); + RRModeGetScanoutSize (mode, &f_transform, + &source_width, &source_height); if (stuff->x + source_width > pScreen->width) { client->errorValue = stuff->x; diff --git a/randr/rrsprite.c b/randr/rrsprite.c new file mode 100644 index 000000000..5bf312ca9 --- /dev/null +++ b/randr/rrsprite.c @@ -0,0 +1,104 @@ +/* + * Copyright © 2010 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "randrstr.h" +#include "swaprep.h" + +void +RRCrtcSpriteTransformSet(RRCrtcPtr crtc, + PictTransform *position_transform, + PictTransform *image_transform, + struct pict_f_transform *f_position_transform, + struct pict_f_transform *f_image_transform) +{ + ScreenPtr pScreen; + rrScrPrivPtr pScrPriv; + + pScreen = crtc->pScreen; + pScrPriv = rrGetScrPriv(pScreen); + crtc->client_sprite_position_transform = *position_transform; + crtc->client_sprite_image_transform = *image_transform; + crtc->client_sprite_f_position_transform = *f_position_transform; + crtc->client_sprite_f_image_transform = *f_image_transform; + if (pScrPriv->rrSetCrtcSpriteTransform) + (*pScrPriv->rrSetCrtcSpriteTransform) (pScreen, crtc, + &crtc->client_sprite_f_position_transform, + &crtc->client_sprite_f_image_transform); +} + +int +ProcRRSetCrtcSpriteTransform (ClientPtr client) +{ + REQUEST(xRRSetCrtcSpriteTransformReq); + RRCrtcPtr crtc; + PictTransform position_transform, image_transform; + struct pixman_f_transform f_position_transform, f_image_transform; + + REQUEST_AT_LEAST_SIZE(xRRSetCrtcSpriteTransformReq); + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + PictTransform_from_xRenderTransform (&position_transform, &stuff->positionTransform); + PictTransform_from_xRenderTransform (&image_transform, &stuff->imageTransform); + pixman_f_transform_from_pixman_transform (&f_position_transform, &position_transform); + pixman_f_transform_from_pixman_transform (&f_image_transform, &image_transform); + + RRCrtcSpriteTransformSet (crtc, &position_transform, &image_transform, + &f_position_transform, &f_image_transform); + return Success; +} + +#define CrtcSpriteTransformExtra (SIZEOF(xRRGetCrtcSpriteTransformReply) - 32) + +int +ProcRRGetCrtcSpriteTransform (ClientPtr client) +{ + REQUEST(xRRGetCrtcSpriteTransformReq); + xRRGetCrtcSpriteTransformReply *reply; + RRCrtcPtr crtc; + int n; + char *extra; + + REQUEST_SIZE_MATCH (xRRGetCrtcSpriteTransformReq); + VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + + reply = malloc(sizeof (xRRGetCrtcSpriteTransformReply)); + if (!reply) + return BadAlloc; + + extra = (char *) (reply + 1); + reply->type = X_Reply; + reply->sequenceNumber = client->sequence; + reply->length = bytes_to_int32(CrtcSpriteTransformExtra); + + xRenderTransform_from_PictTransform(&reply->positionTransform, &crtc->client_sprite_position_transform); + xRenderTransform_from_PictTransform(&reply->imageTransform, &crtc->client_sprite_image_transform); + + if (client->swapped) { + swaps (&reply->sequenceNumber, n); + swapl (&reply->length, n); + SwapLongs((CARD32 *) &reply->positionTransform, bytes_to_int32(sizeof(xRenderTransform))); + SwapLongs((CARD32 *) &reply->imageTransform, bytes_to_int32(sizeof(xRenderTransform))); + } + WriteToClient (client, sizeof (xRRGetCrtcSpriteTransformReply), (char *) reply); + free(reply); + return Success; +} diff --git a/randr/rrtransform.c b/randr/rrtransform.c index e1620498b..3eda5f3cd 100644 --- a/randr/rrtransform.c +++ b/randr/rrtransform.c @@ -134,6 +134,24 @@ RRTransformRescale(struct pixman_f_transform *f_transform, double limit) f_transform->m[j][i] *= scale; } +#define EPSILON (1e-20) +#define IS_F_SAME(a,b) (fabs((a)-(b)) < EPSILON) +#define IS_F_ZERO(a) (fabs(a) < EPSILON) + +static Bool +pict_f_transform_is_identity (const struct pixman_f_transform *t) +{ + return (IS_F_SAME (t->m[0][0], t->m[1][1]) && + IS_F_SAME (t->m[0][0], t->m[2][2]) && + !IS_F_ZERO (t->m[0][0]) && + IS_F_ZERO (t->m[0][1]) && + IS_F_ZERO (t->m[0][2]) && + IS_F_ZERO (t->m[1][0]) && + IS_F_ZERO (t->m[1][2]) && + IS_F_ZERO (t->m[2][0]) && + IS_F_ZERO (t->m[2][1])); +} + /* * Compute the complete transformation matrix including * client-specified transform, rotation/reflection values and the crtc @@ -148,23 +166,39 @@ RRTransformCompute (int x, int height, Rotation rotation, RRTransformPtr rr_transform, + struct pixman_f_transform *sprite_position_transform, + struct pixman_f_transform *sprite_image_transform, PictTransformPtr transform, struct pixman_f_transform *f_transform, - struct pixman_f_transform *f_inverse) + struct pixman_f_transform *f_inverse, + struct pixman_f_transform *f_fb_to_sprite, + struct pixman_f_transform *f_sprite_to_image, + Bool *sprite_transform_in_use) { PictTransform t_transform, inverse; struct pixman_f_transform tf_transform, tf_inverse; + struct pixman_f_transform sf_position_transform, sf_image_transform; + struct pixman_f_transform f_image_to_sprite; Bool overflow = FALSE; + Bool ret = TRUE; if (!transform) transform = &t_transform; if (!f_transform) f_transform = &tf_transform; if (!f_inverse) f_inverse = &tf_inverse; + if (!f_fb_to_sprite) f_fb_to_sprite = &sf_position_transform; + if (!f_sprite_to_image) f_sprite_to_image = &sf_image_transform; + + /* invert the sprite image transform to have it go from dest to source */ + if (!pixman_f_transform_invert (&f_image_to_sprite, f_sprite_to_image)) + pixman_f_transform_init_identity(&f_image_to_sprite); pixman_transform_init_identity (transform); pixman_transform_init_identity (&inverse); pixman_f_transform_init_identity (f_transform); pixman_f_transform_init_identity (f_inverse); + pixman_f_transform_init_identity (f_fb_to_sprite); + pixman_f_transform_init_identity (f_sprite_to_image); if (rotation != RR_Rotate_0) { double f_rot_cos, f_rot_sin, f_rot_dx, f_rot_dy; @@ -246,7 +280,14 @@ RRTransformCompute (int x, pixman_f_transform_translate (f_transform, f_inverse, f_scale_dx, f_scale_dy); } -#ifdef RANDR_12_INTERFACE + /* + * Sprite position is affected by the transform matrix, + * but the image is not + */ + pixman_f_transform_multiply(f_sprite_to_image, + f_transform, + &f_image_to_sprite); + if (rr_transform) { if (!pixman_transform_multiply (transform, &rr_transform->transform, transform)) @@ -254,7 +295,7 @@ RRTransformCompute (int x, pixman_f_transform_multiply (f_transform, &rr_transform->f_transform, f_transform); pixman_f_transform_multiply (f_inverse, f_inverse, &rr_transform->f_inverse); } -#endif + /* * Compute the class of the resulting transform */ @@ -264,7 +305,7 @@ RRTransformCompute (int x, pixman_f_transform_init_translate (f_transform, x, y); pixman_f_transform_init_translate (f_inverse, -x, -y); - return FALSE; + ret = FALSE; } else { @@ -278,6 +319,19 @@ RRTransformCompute (int x, RRTransformRescale(&f_scaled, 16384.0); pixman_transform_from_pixman_f_transform(transform, &f_scaled); } - return TRUE; + ret = TRUE; } + + /* + * Sprite position is affected by the transform matrix, + * but the image is not + */ + pixman_f_transform_multiply(f_fb_to_sprite, + f_inverse, + sprite_position_transform); + if (sprite_transform_in_use) + *sprite_transform_in_use = ret || !pict_f_transform_is_identity(f_fb_to_sprite); + return ret; } + + diff --git a/randr/rrtransform.h b/randr/rrtransform.h index 561762dfe..5cfcf8d65 100644 --- a/randr/rrtransform.h +++ b/randr/rrtransform.h @@ -59,6 +59,13 @@ RRTransformSetFilter (RRTransformPtr dst, extern _X_EXPORT Bool RRTransformCopy (RRTransformPtr dst, RRTransformPtr src); +/* + * Compute the complete transformation matrix including + * client-specified transform, rotation/reflection values and the crtc + * offset. + * + * Return TRUE if the resulting transform is not a simple translation. + */ extern _X_EXPORT Bool RRTransformCompute (int x, int y, @@ -66,10 +73,14 @@ RRTransformCompute (int x, int height, Rotation rotation, RRTransformPtr rr_transform, + struct pict_f_transform *sprite_position_transform, + struct pict_f_transform *sprite_image_transform, PictTransformPtr transform, struct pict_f_transform *f_transform, - struct pict_f_transform *f_inverse); - + struct pict_f_transform *f_inverse, + struct pict_f_transform *f_fb_to_sprite, + struct pict_f_transform *f_sprite_to_image, + Bool *sprite_transform_in_use); #endif /* _RRTRANSFORM_H_ */