1b042e37fSmrg/* 2b042e37fSmrg * Copyright © 2006 Keith Packard 3b042e37fSmrg * 4b042e37fSmrg * Permission to use, copy, modify, distribute, and sell this software and its 5b042e37fSmrg * documentation for any purpose is hereby granted without fee, provided that 6b042e37fSmrg * the above copyright notice appear in all copies and that both that copyright 7b042e37fSmrg * notice and this permission notice appear in supporting documentation, and 8b042e37fSmrg * that the name of the copyright holders not be used in advertising or 9b042e37fSmrg * publicity pertaining to distribution of the software without specific, 10b042e37fSmrg * written prior permission. The copyright holders make no representations 11b042e37fSmrg * about the suitability of this software for any purpose. It is provided "as 12b042e37fSmrg * is" without express or implied warranty. 13b042e37fSmrg * 14b042e37fSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15b042e37fSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16b042e37fSmrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17b042e37fSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18b042e37fSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19b042e37fSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20b042e37fSmrg * OF THIS SOFTWARE. 21b042e37fSmrg */ 22b042e37fSmrg 23b042e37fSmrg#ifdef HAVE_CONFIG_H 24b042e37fSmrg#include <config.h> 25b042e37fSmrg#endif 26b042e37fSmrg 27b242714cSmrg#include <limits.h> 28b042e37fSmrg#include <stdio.h> 29b042e37fSmrg#include <X11/Xlib.h> 30b042e37fSmrg/* we need to be able to manipulate the Display structure on events */ 31b042e37fSmrg#include <X11/Xlibint.h> 32b042e37fSmrg#include <X11/extensions/render.h> 33b042e37fSmrg#include <X11/extensions/Xrender.h> 34b042e37fSmrg#include "Xrandrint.h" 35b042e37fSmrg 36b042e37fSmrgXRRCrtcInfo * 37b042e37fSmrgXRRGetCrtcInfo (Display *dpy, XRRScreenResources *resources, RRCrtc crtc) 38b042e37fSmrg{ 39b042e37fSmrg XExtDisplayInfo *info = XRRFindDisplay(dpy); 40b042e37fSmrg xRRGetCrtcInfoReply rep; 41b042e37fSmrg xRRGetCrtcInfoReq *req; 42b042e37fSmrg int nbytes, nbytesRead, rbytes; 43b042e37fSmrg XRRCrtcInfo *xci; 44b042e37fSmrg 458c4a8e55Smrg RRCheckExtension (dpy, info, NULL); 46b042e37fSmrg 47b042e37fSmrg LockDisplay (dpy); 48b042e37fSmrg GetReq (RRGetCrtcInfo, req); 49b042e37fSmrg req->reqType = info->codes->major_opcode; 50b042e37fSmrg req->randrReqType = X_RRGetCrtcInfo; 51b042e37fSmrg req->crtc = crtc; 52b042e37fSmrg req->configTimestamp = resources->configTimestamp; 53b042e37fSmrg 54b042e37fSmrg if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 55b042e37fSmrg { 56b042e37fSmrg UnlockDisplay (dpy); 57b042e37fSmrg SyncHandle (); 58b042e37fSmrg return NULL; 59b042e37fSmrg } 60b042e37fSmrg 61b242714cSmrg if (rep.length < INT_MAX >> 2) 62b242714cSmrg { 63b242714cSmrg nbytes = (long) rep.length << 2; 64b042e37fSmrg 65b242714cSmrg nbytesRead = (long) (rep.nOutput * 4 + 66b242714cSmrg rep.nPossibleOutput * 4); 67b042e37fSmrg 68b242714cSmrg /* 69b242714cSmrg * first we must compute how much space to allocate for 70b242714cSmrg * randr library's use; we'll allocate the structures in a single 71b242714cSmrg * allocation, on cleanlyness grounds. 72b242714cSmrg */ 73b042e37fSmrg 74b242714cSmrg rbytes = (sizeof (XRRCrtcInfo) + 75b242714cSmrg rep.nOutput * sizeof (RROutput) + 76b242714cSmrg rep.nPossibleOutput * sizeof (RROutput)); 77b242714cSmrg 788d0bc965Smrg xci = Xmalloc(rbytes); 79b242714cSmrg } 80b242714cSmrg else 81b242714cSmrg { 82b242714cSmrg nbytes = 0; 83b242714cSmrg nbytesRead = 0; 84b242714cSmrg rbytes = 0; 85b242714cSmrg xci = NULL; 86b242714cSmrg } 87b042e37fSmrg 88b042e37fSmrg if (xci == NULL) { 898bd17e5fSmrg _XEatDataWords (dpy, rep.length); 90b042e37fSmrg UnlockDisplay (dpy); 91b042e37fSmrg SyncHandle (); 92b042e37fSmrg return NULL; 93b042e37fSmrg } 94b042e37fSmrg 95b042e37fSmrg xci->timestamp = rep.timestamp; 96b042e37fSmrg xci->x = rep.x; 97b042e37fSmrg xci->y = rep.y; 98b042e37fSmrg xci->width = rep.width; 99b042e37fSmrg xci->height = rep.height; 100b042e37fSmrg xci->mode = rep.mode; 101b042e37fSmrg xci->rotation = rep.rotation; 102b042e37fSmrg xci->noutput = rep.nOutput; 103b042e37fSmrg xci->outputs = (RROutput *) (xci + 1); 104b042e37fSmrg xci->rotations = rep.rotations; 105b042e37fSmrg xci->npossible = rep.nPossibleOutput; 106b042e37fSmrg xci->possible = (RROutput *) (xci->outputs + rep.nOutput); 107b042e37fSmrg 10867594505Smrg _XRead32 (dpy, (long *) xci->outputs, rep.nOutput << 2); 10967594505Smrg _XRead32 (dpy, (long *) xci->possible, rep.nPossibleOutput << 2); 1100597fb56Smrg 111b042e37fSmrg /* 112b042e37fSmrg * Skip any extra data 113b042e37fSmrg */ 114b042e37fSmrg if (nbytes > nbytesRead) 115b042e37fSmrg _XEatData (dpy, (unsigned long) (nbytes - nbytesRead)); 1160597fb56Smrg 117b042e37fSmrg UnlockDisplay (dpy); 118b042e37fSmrg SyncHandle (); 119b042e37fSmrg return (XRRCrtcInfo *) xci; 120b042e37fSmrg} 121b042e37fSmrg 122b042e37fSmrgvoid 123b042e37fSmrgXRRFreeCrtcInfo (XRRCrtcInfo *crtcInfo) 124b042e37fSmrg{ 125b042e37fSmrg Xfree (crtcInfo); 126b042e37fSmrg} 127b042e37fSmrg 128b042e37fSmrgStatus 129b042e37fSmrgXRRSetCrtcConfig (Display *dpy, 130b042e37fSmrg XRRScreenResources *resources, 131b042e37fSmrg RRCrtc crtc, 132b042e37fSmrg Time timestamp, 133b042e37fSmrg int x, int y, 134b042e37fSmrg RRMode mode, 135b042e37fSmrg Rotation rotation, 136b042e37fSmrg RROutput *outputs, 137b042e37fSmrg int noutputs) 138b042e37fSmrg{ 139b042e37fSmrg XExtDisplayInfo *info = XRRFindDisplay(dpy); 140b042e37fSmrg xRRSetCrtcConfigReply rep; 141b042e37fSmrg xRRSetCrtcConfigReq *req; 142b042e37fSmrg 143b042e37fSmrg RRCheckExtension (dpy, info, 0); 144b042e37fSmrg 145b042e37fSmrg LockDisplay(dpy); 146b042e37fSmrg GetReq (RRSetCrtcConfig, req); 147b042e37fSmrg req->reqType = info->codes->major_opcode; 148b042e37fSmrg req->randrReqType = X_RRSetCrtcConfig; 149b042e37fSmrg req->length += noutputs; 150b042e37fSmrg req->crtc = crtc; 151b042e37fSmrg req->timestamp = timestamp; 152b042e37fSmrg req->configTimestamp = resources->configTimestamp; 153b042e37fSmrg req->x = x; 154b042e37fSmrg req->y = y; 155b042e37fSmrg req->mode = mode; 156b042e37fSmrg req->rotation = rotation; 157b042e37fSmrg Data32 (dpy, outputs, noutputs << 2); 158b042e37fSmrg 159b042e37fSmrg if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 160b042e37fSmrg rep.status = RRSetConfigFailed; 161b042e37fSmrg UnlockDisplay (dpy); 162b042e37fSmrg SyncHandle (); 163b042e37fSmrg return rep.status; 164b042e37fSmrg} 165b042e37fSmrg 166b042e37fSmrgint 167b042e37fSmrgXRRGetCrtcGammaSize (Display *dpy, RRCrtc crtc) 168b042e37fSmrg{ 169b042e37fSmrg XExtDisplayInfo *info = XRRFindDisplay(dpy); 170b042e37fSmrg xRRGetCrtcGammaSizeReply rep; 171b042e37fSmrg xRRGetCrtcGammaSizeReq *req; 172b042e37fSmrg 173b042e37fSmrg RRCheckExtension (dpy, info, 0); 174b042e37fSmrg 175b042e37fSmrg LockDisplay(dpy); 176b042e37fSmrg GetReq (RRGetCrtcGammaSize, req); 177b042e37fSmrg req->reqType = info->codes->major_opcode; 178b042e37fSmrg req->randrReqType = X_RRGetCrtcGammaSize; 179b042e37fSmrg req->crtc = crtc; 180b042e37fSmrg 181b042e37fSmrg if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 182706b6b52Smrg rep.size = 0; 183b042e37fSmrg UnlockDisplay (dpy); 184b042e37fSmrg SyncHandle (); 185b042e37fSmrg return rep.size; 186b042e37fSmrg} 187b042e37fSmrg 188b042e37fSmrgXRRCrtcGamma * 189b042e37fSmrgXRRGetCrtcGamma (Display *dpy, RRCrtc crtc) 190b042e37fSmrg{ 191b042e37fSmrg XExtDisplayInfo *info = XRRFindDisplay(dpy); 192b042e37fSmrg xRRGetCrtcGammaReply rep; 193b042e37fSmrg xRRGetCrtcGammaReq *req; 194706b6b52Smrg XRRCrtcGamma *crtc_gamma = NULL; 195b042e37fSmrg long nbytes; 196b042e37fSmrg long nbytesRead; 197b042e37fSmrg 1988c4a8e55Smrg RRCheckExtension (dpy, info, NULL); 199b042e37fSmrg 200b042e37fSmrg LockDisplay(dpy); 201b042e37fSmrg GetReq (RRGetCrtcGamma, req); 202b042e37fSmrg req->reqType = info->codes->major_opcode; 203b042e37fSmrg req->randrReqType = X_RRGetCrtcGamma; 204b042e37fSmrg req->crtc = crtc; 205b042e37fSmrg 206b042e37fSmrg if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 207706b6b52Smrg goto out; 208b042e37fSmrg 209b242714cSmrg if (rep.length < INT_MAX >> 2) 210b242714cSmrg { 211b242714cSmrg nbytes = (long) rep.length << 2; 2120597fb56Smrg 213b242714cSmrg /* three channels of CARD16 data */ 214b242714cSmrg nbytesRead = (rep.size * 2 * 3); 215b042e37fSmrg 216b242714cSmrg crtc_gamma = XRRAllocGamma (rep.size); 217b242714cSmrg } 218b242714cSmrg else 219b242714cSmrg { 220b242714cSmrg nbytes = 0; 221b242714cSmrg nbytesRead = 0; 222b242714cSmrg crtc_gamma = NULL; 223b242714cSmrg } 2240597fb56Smrg 225b042e37fSmrg if (!crtc_gamma) 226b042e37fSmrg { 2278bd17e5fSmrg _XEatDataWords (dpy, rep.length); 228706b6b52Smrg goto out; 229b042e37fSmrg } 230b042e37fSmrg _XRead16 (dpy, crtc_gamma->red, rep.size * 2); 231b042e37fSmrg _XRead16 (dpy, crtc_gamma->green, rep.size * 2); 232b042e37fSmrg _XRead16 (dpy, crtc_gamma->blue, rep.size * 2); 2330597fb56Smrg 234b042e37fSmrg if (nbytes > nbytesRead) 235b042e37fSmrg _XEatData (dpy, (unsigned long) (nbytes - nbytesRead)); 236706b6b52Smrg 237706b6b52Smrgout: 238b042e37fSmrg UnlockDisplay (dpy); 239b042e37fSmrg SyncHandle (); 240b042e37fSmrg return crtc_gamma; 241b042e37fSmrg} 242b042e37fSmrg 243b042e37fSmrgXRRCrtcGamma * 244b042e37fSmrgXRRAllocGamma (int size) 245b042e37fSmrg{ 246b042e37fSmrg XRRCrtcGamma *crtc_gamma; 247b042e37fSmrg 248b042e37fSmrg crtc_gamma = Xmalloc (sizeof (XRRCrtcGamma) + 249b042e37fSmrg sizeof (crtc_gamma->red[0]) * size * 3); 250b042e37fSmrg if (!crtc_gamma) 251b042e37fSmrg return NULL; 252b042e37fSmrg crtc_gamma->size = size; 253b042e37fSmrg crtc_gamma->red = (unsigned short *) (crtc_gamma + 1); 254b042e37fSmrg crtc_gamma->green = crtc_gamma->red + size; 255b042e37fSmrg crtc_gamma->blue = crtc_gamma->green + size; 256b042e37fSmrg return crtc_gamma; 257b042e37fSmrg} 258b042e37fSmrg 259b042e37fSmrgvoid 260b042e37fSmrgXRRSetCrtcGamma (Display *dpy, RRCrtc crtc, XRRCrtcGamma *crtc_gamma) 261b042e37fSmrg{ 262b042e37fSmrg XExtDisplayInfo *info = XRRFindDisplay(dpy); 263b042e37fSmrg xRRSetCrtcGammaReq *req; 264b042e37fSmrg 265b042e37fSmrg RRSimpleCheckExtension (dpy, info); 266b042e37fSmrg 267b042e37fSmrg LockDisplay(dpy); 268b042e37fSmrg GetReq (RRSetCrtcGamma, req); 269b042e37fSmrg req->reqType = info->codes->major_opcode; 270b042e37fSmrg req->randrReqType = X_RRSetCrtcGamma; 271b042e37fSmrg req->crtc = crtc; 272b042e37fSmrg req->size = crtc_gamma->size; 273b042e37fSmrg req->length += (crtc_gamma->size * 2 * 3 + 3) >> 2; 274b042e37fSmrg /* 275b042e37fSmrg * Note this assumes the structure was allocated with XRRAllocGamma, 276b042e37fSmrg * otherwise the channels might not be contiguous 277b042e37fSmrg */ 278b042e37fSmrg Data16 (dpy, crtc_gamma->red, crtc_gamma->size * 2 * 3); 2790597fb56Smrg 280b042e37fSmrg UnlockDisplay (dpy); 281b042e37fSmrg SyncHandle (); 282b042e37fSmrg} 283b042e37fSmrg 284b042e37fSmrgvoid 285b042e37fSmrgXRRFreeGamma (XRRCrtcGamma *crtc_gamma) 286b042e37fSmrg{ 287b042e37fSmrg Xfree (crtc_gamma); 288b042e37fSmrg} 2898c4a8e55Smrg 2908c4a8e55Smrg/* Version 1.3 additions */ 2918c4a8e55Smrg 2928c4a8e55Smrgstatic void 2938c4a8e55SmrgXTransform_from_xRenderTransform (XTransform *x, 2948c4a8e55Smrg xRenderTransform *render) 2958c4a8e55Smrg{ 2968c4a8e55Smrg x->matrix[0][0] = render->matrix11; 2978c4a8e55Smrg x->matrix[0][1] = render->matrix12; 2988c4a8e55Smrg x->matrix[0][2] = render->matrix13; 2998c4a8e55Smrg 3008c4a8e55Smrg x->matrix[1][0] = render->matrix21; 3018c4a8e55Smrg x->matrix[1][1] = render->matrix22; 3028c4a8e55Smrg x->matrix[1][2] = render->matrix23; 3038c4a8e55Smrg 3048c4a8e55Smrg x->matrix[2][0] = render->matrix31; 3058c4a8e55Smrg x->matrix[2][1] = render->matrix32; 3068c4a8e55Smrg x->matrix[2][2] = render->matrix33; 3078c4a8e55Smrg} 3088c4a8e55Smrg 3098c4a8e55Smrgstatic void 3108c4a8e55SmrgxRenderTransform_from_XTransform (xRenderTransform *render, 3118c4a8e55Smrg XTransform *x) 3128c4a8e55Smrg{ 3138c4a8e55Smrg render->matrix11 = x->matrix[0][0]; 3148c4a8e55Smrg render->matrix12 = x->matrix[0][1]; 3158c4a8e55Smrg render->matrix13 = x->matrix[0][2]; 3168c4a8e55Smrg 3178c4a8e55Smrg render->matrix21 = x->matrix[1][0]; 3188c4a8e55Smrg render->matrix22 = x->matrix[1][1]; 3198c4a8e55Smrg render->matrix23 = x->matrix[1][2]; 3208c4a8e55Smrg 3218c4a8e55Smrg render->matrix31 = x->matrix[2][0]; 3228c4a8e55Smrg render->matrix32 = x->matrix[2][1]; 3238c4a8e55Smrg render->matrix33 = x->matrix[2][2]; 3248c4a8e55Smrg} 3258c4a8e55Smrg 3268c4a8e55Smrgvoid 3278c4a8e55SmrgXRRSetCrtcTransform (Display *dpy, 3280597fb56Smrg RRCrtc crtc, 3298c4a8e55Smrg XTransform *transform, 3308bd17e5fSmrg _Xconst char *filter, 3318c4a8e55Smrg XFixed *params, 3328c4a8e55Smrg int nparams) 3338c4a8e55Smrg{ 3348c4a8e55Smrg XExtDisplayInfo *info = XRRFindDisplay(dpy); 3358c4a8e55Smrg xRRSetCrtcTransformReq *req; 3368c4a8e55Smrg int nbytes = strlen (filter); 3378c4a8e55Smrg 3388c4a8e55Smrg RRSimpleCheckExtension (dpy, info); 3398c4a8e55Smrg 3408c4a8e55Smrg LockDisplay(dpy); 3418c4a8e55Smrg GetReq (RRSetCrtcTransform, req); 3428c4a8e55Smrg req->reqType = info->codes->major_opcode; 3438c4a8e55Smrg req->randrReqType = X_RRSetCrtcTransform; 3448c4a8e55Smrg req->crtc = crtc; 3458c4a8e55Smrg 3468c4a8e55Smrg xRenderTransform_from_XTransform (&req->transform, transform); 3478c4a8e55Smrg 3488c4a8e55Smrg req->nbytesFilter = nbytes; 3498c4a8e55Smrg req->length += ((nbytes + 3) >> 2) + nparams; 3508c4a8e55Smrg Data (dpy, filter, nbytes); 3518c4a8e55Smrg Data32 (dpy, params, nparams << 2); 3528c4a8e55Smrg 3538c4a8e55Smrg UnlockDisplay (dpy); 3548c4a8e55Smrg SyncHandle (); 3558c4a8e55Smrg} 3568c4a8e55Smrg 3578c4a8e55Smrg#define CrtcTransformExtra (SIZEOF(xRRGetCrtcTransformReply) - 32) 3580597fb56Smrg 3598c4a8e55Smrgstatic const xRenderTransform identity = { 3608c4a8e55Smrg 0x10000, 0, 0, 3618c4a8e55Smrg 0, 0x10000, 0, 3628c4a8e55Smrg 0, 0, 0x10000, 3638c4a8e55Smrg}; 3648c4a8e55Smrg 3658c4a8e55Smrgstatic Bool 3668c4a8e55Smrg_XRRHasTransform (int major, int minor) 3678c4a8e55Smrg{ 3688c4a8e55Smrg return major > 1 || (major == 1 && minor >= 3); 3698c4a8e55Smrg} 3708c4a8e55Smrg 3718c4a8e55SmrgStatus 3728c4a8e55SmrgXRRGetCrtcTransform (Display *dpy, 3738c4a8e55Smrg RRCrtc crtc, 3748c4a8e55Smrg XRRCrtcTransformAttributes **attributes) 3758c4a8e55Smrg{ 3768c4a8e55Smrg XExtDisplayInfo *info = XRRFindDisplay(dpy); 3778c4a8e55Smrg xRRGetCrtcTransformReply rep; 3788c4a8e55Smrg int major_version, minor_version; 3798c4a8e55Smrg XRRCrtcTransformAttributes *attr; 380b242714cSmrg char *extra = NULL, *end = NULL, *e; 3818c4a8e55Smrg 3828c4a8e55Smrg *attributes = NULL; 3838c4a8e55Smrg 3848c4a8e55Smrg RRCheckExtension (dpy, info, False); 3858c4a8e55Smrg 3860597fb56Smrg if (!XRRQueryVersion (dpy, &major_version, &minor_version) || 3878c4a8e55Smrg !_XRRHasTransform (major_version, minor_version)) 3888c4a8e55Smrg { 3898c4a8e55Smrg /* For pre-1.3 servers, just report identity matrices everywhere */ 3908c4a8e55Smrg rep.pendingTransform = identity; 3918c4a8e55Smrg rep.pendingNbytesFilter = 0; 3928c4a8e55Smrg rep.pendingNparamsFilter = 0; 3938c4a8e55Smrg rep.currentTransform = identity; 3948c4a8e55Smrg rep.currentNbytesFilter = 0; 3958c4a8e55Smrg rep.currentNparamsFilter = 0; 3968c4a8e55Smrg } 3978c4a8e55Smrg else 3988c4a8e55Smrg { 3998d0bc965Smrg xRRGetCrtcTransformReq *req; 4008d0bc965Smrg 4018c4a8e55Smrg LockDisplay (dpy); 4028c4a8e55Smrg GetReq (RRGetCrtcTransform, req); 4038c4a8e55Smrg req->reqType = info->codes->major_opcode; 4048c4a8e55Smrg req->randrReqType = X_RRGetCrtcTransform; 4058c4a8e55Smrg req->crtc = crtc; 4060597fb56Smrg 4078c4a8e55Smrg if (!_XReply (dpy, (xReply *) &rep, CrtcTransformExtra >> 2, xFalse)) 4088c4a8e55Smrg { 4098c4a8e55Smrg rep.pendingTransform = identity; 4108c4a8e55Smrg rep.pendingNbytesFilter = 0; 4118c4a8e55Smrg rep.pendingNparamsFilter = 0; 4128c4a8e55Smrg rep.currentTransform = identity; 4138c4a8e55Smrg rep.currentNbytesFilter = 0; 4148c4a8e55Smrg rep.currentNparamsFilter = 0; 4158c4a8e55Smrg } 4168c4a8e55Smrg else 4178c4a8e55Smrg { 4188c4a8e55Smrg int extraBytes = rep.length * 4 - CrtcTransformExtra; 419b242714cSmrg if (rep.length < INT_MAX / 4 && 420b242714cSmrg rep.length * 4 >= CrtcTransformExtra) { 421b242714cSmrg extra = Xmalloc (extraBytes); 422b242714cSmrg end = extra + extraBytes; 423b242714cSmrg } else 424b242714cSmrg extra = NULL; 4258c4a8e55Smrg if (!extra) { 426b242714cSmrg if (rep.length > (CrtcTransformExtra >> 2)) 427b242714cSmrg _XEatDataWords (dpy, rep.length - (CrtcTransformExtra >> 2)); 428b242714cSmrg else 429b242714cSmrg _XEatDataWords (dpy, rep.length); 4308c4a8e55Smrg UnlockDisplay (dpy); 4318c4a8e55Smrg SyncHandle (); 4328c4a8e55Smrg return False; 4338c4a8e55Smrg } 4348c4a8e55Smrg _XRead (dpy, extra, extraBytes); 4358c4a8e55Smrg } 4368c4a8e55Smrg 4378c4a8e55Smrg UnlockDisplay (dpy); 4388c4a8e55Smrg SyncHandle (); 4398c4a8e55Smrg } 4408c4a8e55Smrg 4418c4a8e55Smrg attr = Xmalloc (sizeof (XRRCrtcTransformAttributes) + 4428c4a8e55Smrg rep.pendingNparamsFilter * sizeof (XFixed) + 4438c4a8e55Smrg rep.currentNparamsFilter * sizeof (XFixed) + 4448c4a8e55Smrg rep.pendingNbytesFilter + 1 + 4458c4a8e55Smrg rep.currentNbytesFilter + 1); 4468c4a8e55Smrg 4478c4a8e55Smrg if (!attr) { 4488c4a8e55Smrg XFree (extra); 4498c4a8e55Smrg return False; 4508c4a8e55Smrg } 4518c4a8e55Smrg XTransform_from_xRenderTransform (&attr->pendingTransform, &rep.pendingTransform); 4528c4a8e55Smrg XTransform_from_xRenderTransform (&attr->currentTransform, &rep.currentTransform); 4538c4a8e55Smrg 4548c4a8e55Smrg attr->pendingParams = (XFixed *) (attr + 1); 4558c4a8e55Smrg attr->currentParams = attr->pendingParams + rep.pendingNparamsFilter; 4568c4a8e55Smrg attr->pendingFilter = (char *) (attr->currentParams + rep.currentNparamsFilter); 4578c4a8e55Smrg attr->currentFilter = attr->pendingFilter + rep.pendingNbytesFilter + 1; 4588c4a8e55Smrg 4598c4a8e55Smrg e = extra; 4608c4a8e55Smrg 461b242714cSmrg if (e + rep.pendingNbytesFilter > end) { 4623169be4bSmrg XFree (attr); 463b242714cSmrg XFree (extra); 464b242714cSmrg return False; 465b242714cSmrg } 4668c4a8e55Smrg memcpy (attr->pendingFilter, e, rep.pendingNbytesFilter); 4678c4a8e55Smrg attr->pendingFilter[rep.pendingNbytesFilter] = '\0'; 4688c4a8e55Smrg e += (rep.pendingNbytesFilter + 3) & ~3; 4698d0bc965Smrg for (unsigned int p = 0; p < rep.pendingNparamsFilter; p++) { 4708c4a8e55Smrg INT32 f; 471b242714cSmrg if (e + 4 > end) { 4723169be4bSmrg XFree (attr); 473b242714cSmrg XFree (extra); 474b242714cSmrg return False; 475b242714cSmrg } 4768c4a8e55Smrg memcpy (&f, e, 4); 4778c4a8e55Smrg e += 4; 4788c4a8e55Smrg attr->pendingParams[p] = (XFixed) f; 4798c4a8e55Smrg } 4808c4a8e55Smrg attr->pendingNparams = rep.pendingNparamsFilter; 4818c4a8e55Smrg 482b242714cSmrg if (e + rep.currentNbytesFilter > end) { 4833169be4bSmrg XFree (attr); 484b242714cSmrg XFree (extra); 485b242714cSmrg return False; 486b242714cSmrg } 4878c4a8e55Smrg memcpy (attr->currentFilter, e, rep.currentNbytesFilter); 4888c4a8e55Smrg attr->currentFilter[rep.currentNbytesFilter] = '\0'; 4898c4a8e55Smrg e += (rep.currentNbytesFilter + 3) & ~3; 4908d0bc965Smrg for (unsigned int p = 0; p < rep.currentNparamsFilter; p++) { 4918c4a8e55Smrg INT32 f; 492b242714cSmrg if (e + 4 > end) { 4933169be4bSmrg XFree (attr); 494b242714cSmrg XFree (extra); 495b242714cSmrg return False; 496b242714cSmrg } 4978c4a8e55Smrg memcpy (&f, e, 4); 4988c4a8e55Smrg e += 4; 4998c4a8e55Smrg attr->currentParams[p] = (XFixed) f; 5008c4a8e55Smrg } 5018c4a8e55Smrg attr->currentNparams = rep.currentNparamsFilter; 5028c4a8e55Smrg 5038c4a8e55Smrg if (extra) 5048c4a8e55Smrg XFree (extra); 5058c4a8e55Smrg *attributes = attr; 5068c4a8e55Smrg 5078c4a8e55Smrg return True; 5088c4a8e55Smrg} 5098c4a8e55Smrg 5108c4a8e55SmrgXRRPanning * 5118c4a8e55SmrgXRRGetPanning (Display *dpy, XRRScreenResources *resources, RRCrtc crtc) 5128c4a8e55Smrg{ 5138c4a8e55Smrg XExtDisplayInfo *info = XRRFindDisplay(dpy); 5148c4a8e55Smrg xRRGetPanningReply rep; 5158c4a8e55Smrg xRRGetPanningReq *req; 5168c4a8e55Smrg XRRPanning *xp; 5178c4a8e55Smrg 5188c4a8e55Smrg RRCheckExtension (dpy, info, NULL); 5198c4a8e55Smrg 5208c4a8e55Smrg LockDisplay (dpy); 5218c4a8e55Smrg GetReq (RRGetPanning, req); 5228c4a8e55Smrg req->reqType = info->codes->major_opcode; 5238c4a8e55Smrg req->randrReqType = X_RRGetPanning; 5248c4a8e55Smrg req->crtc = crtc; 5258c4a8e55Smrg 5268c4a8e55Smrg if (!_XReply (dpy, (xReply *) &rep, 1, xFalse)) 5278c4a8e55Smrg { 5288c4a8e55Smrg UnlockDisplay (dpy); 5298c4a8e55Smrg SyncHandle (); 5308c4a8e55Smrg return NULL; 5318c4a8e55Smrg } 5328c4a8e55Smrg 5338d0bc965Smrg if (! (xp = Xmalloc(sizeof(XRRPanning))) ) { 5348c4a8e55Smrg _XEatData (dpy, sizeof(XRRPanning)); 5358c4a8e55Smrg UnlockDisplay (dpy); 5368c4a8e55Smrg SyncHandle (); 5378c4a8e55Smrg return NULL; 5388c4a8e55Smrg } 5398c4a8e55Smrg 5408c4a8e55Smrg xp->timestamp = rep.timestamp; 5418c4a8e55Smrg xp->left = rep.left; 5428c4a8e55Smrg xp->top = rep.top; 5438c4a8e55Smrg xp->width = rep.width; 5448c4a8e55Smrg xp->height = rep.height; 5458c4a8e55Smrg xp->track_left = rep.track_left; 5468c4a8e55Smrg xp->track_top = rep.track_top; 5478c4a8e55Smrg xp->track_width = rep.track_width; 5488c4a8e55Smrg xp->track_height = rep.track_height; 5498c4a8e55Smrg xp->border_left = rep.border_left; 5508c4a8e55Smrg xp->border_top = rep.border_top; 5518c4a8e55Smrg xp->border_right = rep.border_right; 5528c4a8e55Smrg xp->border_bottom = rep.border_bottom; 5538c4a8e55Smrg 5548c4a8e55Smrg UnlockDisplay (dpy); 5558c4a8e55Smrg SyncHandle (); 5568c4a8e55Smrg return (XRRPanning *) xp; 5578c4a8e55Smrg} 5588c4a8e55Smrg 5598c4a8e55Smrgvoid 5608c4a8e55SmrgXRRFreePanning (XRRPanning *panning) 5618c4a8e55Smrg{ 5628c4a8e55Smrg Xfree (panning); 5638c4a8e55Smrg} 5648c4a8e55Smrg 5658c4a8e55SmrgStatus 5668c4a8e55SmrgXRRSetPanning (Display *dpy, 5678c4a8e55Smrg XRRScreenResources *resources, 5688c4a8e55Smrg RRCrtc crtc, 5698c4a8e55Smrg XRRPanning *panning) 5708c4a8e55Smrg{ 5718c4a8e55Smrg XExtDisplayInfo *info = XRRFindDisplay(dpy); 5728c4a8e55Smrg xRRSetPanningReply rep; 5738c4a8e55Smrg xRRSetPanningReq *req; 5748c4a8e55Smrg 5758c4a8e55Smrg RRCheckExtension (dpy, info, 0); 5768c4a8e55Smrg 5778c4a8e55Smrg LockDisplay(dpy); 5788c4a8e55Smrg GetReq (RRSetPanning, req); 5798c4a8e55Smrg req->reqType = info->codes->major_opcode; 5808c4a8e55Smrg req->randrReqType = X_RRSetPanning; 5818c4a8e55Smrg req->crtc = crtc; 5828c4a8e55Smrg req->timestamp = panning->timestamp; 5838c4a8e55Smrg req->left = panning->left; 5848c4a8e55Smrg req->top = panning->top; 5858c4a8e55Smrg req->width = panning->width; 5868c4a8e55Smrg req->height = panning->height; 5878c4a8e55Smrg req->track_left = panning->track_left; 5888c4a8e55Smrg req->track_top = panning->track_top; 5898c4a8e55Smrg req->track_width = panning->track_width; 5908c4a8e55Smrg req->track_height = panning->track_height; 5918c4a8e55Smrg req->border_left = panning->border_left; 5928c4a8e55Smrg req->border_top = panning->border_top; 5938c4a8e55Smrg req->border_right = panning->border_right; 5948c4a8e55Smrg req->border_bottom = panning->border_bottom; 5958c4a8e55Smrg 5968c4a8e55Smrg if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 5978c4a8e55Smrg rep.status = RRSetConfigFailed; 5988c4a8e55Smrg UnlockDisplay (dpy); 5998c4a8e55Smrg SyncHandle (); 6008c4a8e55Smrg return rep.status; 6018c4a8e55Smrg} 6028c4a8e55Smrg 603