2 * Copyright © 2006 Keith Packard
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
29 /* we need to be able to manipulate the Display structure on events */
30 #include <X11/Xlibint.h>
31 #include <X11/extensions/render.h>
32 #include <X11/extensions/Xrender.h>
33 #include "Xrandrint.h"
36 XRRGetCrtcInfo (Display *dpy, XRRScreenResources *resources, RRCrtc crtc)
38 XExtDisplayInfo *info = XRRFindDisplay(dpy);
39 xRRGetCrtcInfoReply rep;
40 xRRGetCrtcInfoReq *req;
41 int nbytes, nbytesRead, rbytes;
44 RRCheckExtension (dpy, info, NULL);
47 GetReq (RRGetCrtcInfo, req);
48 req->reqType = info->codes->major_opcode;
49 req->randrReqType = X_RRGetCrtcInfo;
51 req->configTimestamp = resources->configTimestamp;
53 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
60 nbytes = (long) rep.length << 2;
62 nbytesRead = (long) (rep.nOutput * 4 +
63 rep.nPossibleOutput * 4);
66 * first we must compute how much space to allocate for
67 * randr library's use; we'll allocate the structures in a single
68 * allocation, on cleanlyness grounds.
71 rbytes = (sizeof (XRRCrtcInfo) +
72 rep.nOutput * sizeof (RROutput) +
73 rep.nPossibleOutput * sizeof (RROutput));
75 xci = (XRRCrtcInfo *) Xmalloc(rbytes);
77 _XEatData (dpy, (unsigned long) nbytes);
83 xci->timestamp = rep.timestamp;
86 xci->width = rep.width;
87 xci->height = rep.height;
89 xci->rotation = rep.rotation;
90 xci->noutput = rep.nOutput;
91 xci->outputs = (RROutput *) (xci + 1);
92 xci->rotations = rep.rotations;
93 xci->npossible = rep.nPossibleOutput;
94 xci->possible = (RROutput *) (xci->outputs + rep.nOutput);
96 _XRead32 (dpy, xci->outputs, rep.nOutput << 2);
97 _XRead32 (dpy, xci->possible, rep.nPossibleOutput << 2);
100 * Skip any extra data
102 if (nbytes > nbytesRead)
103 _XEatData (dpy, (unsigned long) (nbytes - nbytesRead));
107 return (XRRCrtcInfo *) xci;
111 XRRFreeCrtcInfo (XRRCrtcInfo *crtcInfo)
117 XRRSetCrtcConfig (Display *dpy,
118 XRRScreenResources *resources,
127 XExtDisplayInfo *info = XRRFindDisplay(dpy);
128 xRRSetCrtcConfigReply rep;
129 xRRSetCrtcConfigReq *req;
131 RRCheckExtension (dpy, info, 0);
134 GetReq (RRSetCrtcConfig, req);
135 req->reqType = info->codes->major_opcode;
136 req->randrReqType = X_RRSetCrtcConfig;
137 req->length += noutputs;
139 req->timestamp = timestamp;
140 req->configTimestamp = resources->configTimestamp;
144 req->rotation = rotation;
145 Data32 (dpy, outputs, noutputs << 2);
147 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
148 rep.status = RRSetConfigFailed;
155 XRRGetCrtcGammaSize (Display *dpy, RRCrtc crtc)
157 XExtDisplayInfo *info = XRRFindDisplay(dpy);
158 xRRGetCrtcGammaSizeReply rep;
159 xRRGetCrtcGammaSizeReq *req;
161 RRCheckExtension (dpy, info, 0);
164 GetReq (RRGetCrtcGammaSize, req);
165 req->reqType = info->codes->major_opcode;
166 req->randrReqType = X_RRGetCrtcGammaSize;
169 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
177 XRRGetCrtcGamma (Display *dpy, RRCrtc crtc)
179 XExtDisplayInfo *info = XRRFindDisplay(dpy);
180 xRRGetCrtcGammaReply rep;
181 xRRGetCrtcGammaReq *req;
182 XRRCrtcGamma *crtc_gamma = NULL;
186 RRCheckExtension (dpy, info, NULL);
189 GetReq (RRGetCrtcGamma, req);
190 req->reqType = info->codes->major_opcode;
191 req->randrReqType = X_RRGetCrtcGamma;
194 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
197 nbytes = (long) rep.length << 2;
199 /* three channels of CARD16 data */
200 nbytesRead = (rep.size * 2 * 3);
202 crtc_gamma = XRRAllocGamma (rep.size);
206 _XEatData (dpy, (unsigned long) nbytes);
209 _XRead16 (dpy, crtc_gamma->red, rep.size * 2);
210 _XRead16 (dpy, crtc_gamma->green, rep.size * 2);
211 _XRead16 (dpy, crtc_gamma->blue, rep.size * 2);
213 if (nbytes > nbytesRead)
214 _XEatData (dpy, (unsigned long) (nbytes - nbytesRead));
223 XRRAllocGamma (int size)
225 XRRCrtcGamma *crtc_gamma;
227 crtc_gamma = Xmalloc (sizeof (XRRCrtcGamma) +
228 sizeof (crtc_gamma->red[0]) * size * 3);
231 crtc_gamma->size = size;
232 crtc_gamma->red = (unsigned short *) (crtc_gamma + 1);
233 crtc_gamma->green = crtc_gamma->red + size;
234 crtc_gamma->blue = crtc_gamma->green + size;
239 XRRSetCrtcGamma (Display *dpy, RRCrtc crtc, XRRCrtcGamma *crtc_gamma)
241 XExtDisplayInfo *info = XRRFindDisplay(dpy);
242 xRRSetCrtcGammaReq *req;
244 RRSimpleCheckExtension (dpy, info);
247 GetReq (RRSetCrtcGamma, req);
248 req->reqType = info->codes->major_opcode;
249 req->randrReqType = X_RRSetCrtcGamma;
251 req->size = crtc_gamma->size;
252 req->length += (crtc_gamma->size * 2 * 3 + 3) >> 2;
254 * Note this assumes the structure was allocated with XRRAllocGamma,
255 * otherwise the channels might not be contiguous
257 Data16 (dpy, crtc_gamma->red, crtc_gamma->size * 2 * 3);
264 XRRFreeGamma (XRRCrtcGamma *crtc_gamma)
269 /* Version 1.3 additions */
272 XTransform_from_xRenderTransform (XTransform *x,
273 xRenderTransform *render)
275 x->matrix[0][0] = render->matrix11;
276 x->matrix[0][1] = render->matrix12;
277 x->matrix[0][2] = render->matrix13;
279 x->matrix[1][0] = render->matrix21;
280 x->matrix[1][1] = render->matrix22;
281 x->matrix[1][2] = render->matrix23;
283 x->matrix[2][0] = render->matrix31;
284 x->matrix[2][1] = render->matrix32;
285 x->matrix[2][2] = render->matrix33;
289 xRenderTransform_from_XTransform (xRenderTransform *render,
292 render->matrix11 = x->matrix[0][0];
293 render->matrix12 = x->matrix[0][1];
294 render->matrix13 = x->matrix[0][2];
296 render->matrix21 = x->matrix[1][0];
297 render->matrix22 = x->matrix[1][1];
298 render->matrix23 = x->matrix[1][2];
300 render->matrix31 = x->matrix[2][0];
301 render->matrix32 = x->matrix[2][1];
302 render->matrix33 = x->matrix[2][2];
306 XRRSetCrtcTransform (Display *dpy,
308 XTransform *transform,
313 XExtDisplayInfo *info = XRRFindDisplay(dpy);
314 xRRSetCrtcTransformReq *req;
315 int nbytes = strlen (filter);
317 RRSimpleCheckExtension (dpy, info);
320 GetReq (RRSetCrtcTransform, req);
321 req->reqType = info->codes->major_opcode;
322 req->randrReqType = X_RRSetCrtcTransform;
325 xRenderTransform_from_XTransform (&req->transform, transform);
327 req->nbytesFilter = nbytes;
328 req->length += ((nbytes + 3) >> 2) + nparams;
329 Data (dpy, filter, nbytes);
330 Data32 (dpy, params, nparams << 2);
336 #define CrtcTransformExtra (SIZEOF(xRRGetCrtcTransformReply) - 32)
338 static const xRenderTransform identity = {
345 _XRRHasTransform (int major, int minor)
347 return major > 1 || (major == 1 && minor >= 3);
351 XRRGetCrtcTransform (Display *dpy,
353 XRRCrtcTransformAttributes **attributes)
355 XExtDisplayInfo *info = XRRFindDisplay(dpy);
356 xRRGetCrtcTransformReply rep;
357 xRRGetCrtcTransformReq *req;
358 int major_version, minor_version;
359 XRRCrtcTransformAttributes *attr;
360 char *extra = NULL, *e;
365 RRCheckExtension (dpy, info, False);
367 if (!XRRQueryVersion (dpy, &major_version, &minor_version) ||
368 !_XRRHasTransform (major_version, minor_version))
370 /* For pre-1.3 servers, just report identity matrices everywhere */
371 rep.pendingTransform = identity;
372 rep.pendingNbytesFilter = 0;
373 rep.pendingNparamsFilter = 0;
374 rep.currentTransform = identity;
375 rep.currentNbytesFilter = 0;
376 rep.currentNparamsFilter = 0;
381 GetReq (RRGetCrtcTransform, req);
382 req->reqType = info->codes->major_opcode;
383 req->randrReqType = X_RRGetCrtcTransform;
386 if (!_XReply (dpy, (xReply *) &rep, CrtcTransformExtra >> 2, xFalse))
388 rep.pendingTransform = identity;
389 rep.pendingNbytesFilter = 0;
390 rep.pendingNparamsFilter = 0;
391 rep.currentTransform = identity;
392 rep.currentNbytesFilter = 0;
393 rep.currentNparamsFilter = 0;
397 int extraBytes = rep.length * 4 - CrtcTransformExtra;
398 extra = Xmalloc (extraBytes);
400 _XEatData (dpy, extraBytes);
405 _XRead (dpy, extra, extraBytes);
412 attr = Xmalloc (sizeof (XRRCrtcTransformAttributes) +
413 rep.pendingNparamsFilter * sizeof (XFixed) +
414 rep.currentNparamsFilter * sizeof (XFixed) +
415 rep.pendingNbytesFilter + 1 +
416 rep.currentNbytesFilter + 1);
422 XTransform_from_xRenderTransform (&attr->pendingTransform, &rep.pendingTransform);
423 XTransform_from_xRenderTransform (&attr->currentTransform, &rep.currentTransform);
425 attr->pendingParams = (XFixed *) (attr + 1);
426 attr->currentParams = attr->pendingParams + rep.pendingNparamsFilter;
427 attr->pendingFilter = (char *) (attr->currentParams + rep.currentNparamsFilter);
428 attr->currentFilter = attr->pendingFilter + rep.pendingNbytesFilter + 1;
432 memcpy (attr->pendingFilter, e, rep.pendingNbytesFilter);
433 attr->pendingFilter[rep.pendingNbytesFilter] = '\0';
434 e += (rep.pendingNbytesFilter + 3) & ~3;
435 for (p = 0; p < rep.pendingNparamsFilter; p++) {
439 attr->pendingParams[p] = (XFixed) f;
441 attr->pendingNparams = rep.pendingNparamsFilter;
443 memcpy (attr->currentFilter, e, rep.currentNbytesFilter);
444 attr->currentFilter[rep.currentNbytesFilter] = '\0';
445 e += (rep.currentNbytesFilter + 3) & ~3;
446 for (p = 0; p < rep.currentNparamsFilter; p++) {
450 attr->currentParams[p] = (XFixed) f;
452 attr->currentNparams = rep.currentNparamsFilter;
462 XRRGetPanning (Display *dpy, XRRScreenResources *resources, RRCrtc crtc)
464 XExtDisplayInfo *info = XRRFindDisplay(dpy);
465 xRRGetPanningReply rep;
466 xRRGetPanningReq *req;
469 RRCheckExtension (dpy, info, NULL);
472 GetReq (RRGetPanning, req);
473 req->reqType = info->codes->major_opcode;
474 req->randrReqType = X_RRGetPanning;
477 if (!_XReply (dpy, (xReply *) &rep, 1, xFalse))
484 if (! (xp = (XRRPanning *) Xmalloc(sizeof(XRRPanning))) ) {
485 _XEatData (dpy, sizeof(XRRPanning));
491 xp->timestamp = rep.timestamp;
494 xp->width = rep.width;
495 xp->height = rep.height;
496 xp->track_left = rep.track_left;
497 xp->track_top = rep.track_top;
498 xp->track_width = rep.track_width;
499 xp->track_height = rep.track_height;
500 xp->border_left = rep.border_left;
501 xp->border_top = rep.border_top;
502 xp->border_right = rep.border_right;
503 xp->border_bottom = rep.border_bottom;
507 return (XRRPanning *) xp;
511 XRRFreePanning (XRRPanning *panning)
517 XRRSetPanning (Display *dpy,
518 XRRScreenResources *resources,
522 XExtDisplayInfo *info = XRRFindDisplay(dpy);
523 xRRSetPanningReply rep;
524 xRRSetPanningReq *req;
526 RRCheckExtension (dpy, info, 0);
529 GetReq (RRSetPanning, req);
530 req->reqType = info->codes->major_opcode;
531 req->randrReqType = X_RRSetPanning;
533 req->timestamp = panning->timestamp;
534 req->left = panning->left;
535 req->top = panning->top;
536 req->width = panning->width;
537 req->height = panning->height;
538 req->track_left = panning->track_left;
539 req->track_top = panning->track_top;
540 req->track_width = panning->track_width;
541 req->track_height = panning->track_height;
542 req->border_left = panning->border_left;
543 req->border_top = panning->border_top;
544 req->border_right = panning->border_right;
545 req->border_bottom = panning->border_bottom;
547 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
548 rep.status = RRSetConfigFailed;