10597fb56Smrg/* 20597fb56Smrg * Copyright © 2011 Dave Airlie 30597fb56Smrg * 40597fb56Smrg * Permission to use, copy, modify, distribute, and sell this software and its 50597fb56Smrg * documentation for any purpose is hereby granted without fee, provided that 60597fb56Smrg * the above copyright notice appear in all copies and that both that copyright 70597fb56Smrg * notice and this permission notice appear in supporting documentation, and 80597fb56Smrg * that the name of the copyright holders not be used in advertising or 90597fb56Smrg * publicity pertaining to distribution of the software without specific, 100597fb56Smrg * written prior permission. The copyright holders make no representations 110597fb56Smrg * about the suitability of this software for any purpose. It is provided "as 120597fb56Smrg * is" without express or implied warranty. 130597fb56Smrg * 140597fb56Smrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 150597fb56Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 160597fb56Smrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 170597fb56Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 180597fb56Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 190597fb56Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 200597fb56Smrg * OF THIS SOFTWARE. 210597fb56Smrg */ 220597fb56Smrg 230597fb56Smrg 240597fb56Smrg#ifdef HAVE_CONFIG_H 250597fb56Smrg#include <config.h> 260597fb56Smrg#endif 270597fb56Smrg 28f1c62215Smrg#include <limits.h> 290597fb56Smrg#include <stdio.h> 300597fb56Smrg#include <X11/Xlib.h> 310597fb56Smrg/* we need to be able to manipulate the Display structure on events */ 320597fb56Smrg#include <X11/Xlibint.h> 330597fb56Smrg#include <X11/extensions/render.h> 340597fb56Smrg#include <X11/extensions/Xrender.h> 350597fb56Smrg#include "Xrandrint.h" 360597fb56Smrg 370597fb56SmrgXRRProviderResources * 380597fb56SmrgXRRGetProviderResources(Display *dpy, Window window) 390597fb56Smrg{ 400597fb56Smrg XExtDisplayInfo *info = XRRFindDisplay(dpy); 410597fb56Smrg xRRGetProvidersReply rep; 420597fb56Smrg xRRGetProvidersReq *req; 430597fb56Smrg XRRProviderResources *xrpr; 440597fb56Smrg long nbytes, nbytesRead; 450597fb56Smrg int rbytes; 460597fb56Smrg 470597fb56Smrg RRCheckExtension (dpy, info, NULL); 480597fb56Smrg 490597fb56Smrg LockDisplay (dpy); 500597fb56Smrg 510597fb56Smrg GetReq(RRGetProviders, req); 520597fb56Smrg req->reqType = info->codes->major_opcode; 530597fb56Smrg req->randrReqType = X_RRGetProviders; 540597fb56Smrg req->window = window; 550597fb56Smrg 560597fb56Smrg if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 570597fb56Smrg { 580597fb56Smrg UnlockDisplay (dpy); 590597fb56Smrg SyncHandle (); 600597fb56Smrg return NULL; 610597fb56Smrg } 620597fb56Smrg 634b9d291aSchristos if (rep.length < (INT_MAX >> 2)) { 64f1c62215Smrg nbytes = (long) rep.length << 2; 650597fb56Smrg 66f1c62215Smrg nbytesRead = (long) (rep.nProviders * 4); 670597fb56Smrg 68f1c62215Smrg rbytes = (sizeof(XRRProviderResources) + rep.nProviders * 69f1c62215Smrg sizeof(RRProvider)); 708b1f82e3Smrg xrpr = Xmalloc(rbytes); 71f1c62215Smrg } else { 72f1c62215Smrg nbytes = 0; 73f1c62215Smrg nbytesRead = 0; 74f1c62215Smrg rbytes = 0; 75f1c62215Smrg xrpr = NULL; 76f1c62215Smrg } 770597fb56Smrg 780597fb56Smrg if (xrpr == NULL) { 79a0b5b4faSmrg _XEatDataWords (dpy, rep.length); 800597fb56Smrg UnlockDisplay (dpy); 810597fb56Smrg SyncHandle (); 820597fb56Smrg return NULL; 830597fb56Smrg } 840597fb56Smrg 850597fb56Smrg xrpr->timestamp = rep.timestamp; 860597fb56Smrg xrpr->nproviders = rep.nProviders; 870597fb56Smrg xrpr->providers = (RRProvider *)(xrpr + 1); 880597fb56Smrg 893366ab10Smrg _XRead32(dpy, (long *) xrpr->providers, rep.nProviders << 2); 900597fb56Smrg 910597fb56Smrg if (nbytes > nbytesRead) 920597fb56Smrg _XEatData (dpy, (unsigned long) (nbytes - nbytesRead)); 930597fb56Smrg 940597fb56Smrg 950597fb56Smrg UnlockDisplay (dpy); 960597fb56Smrg SyncHandle(); 970597fb56Smrg 980597fb56Smrg return (XRRProviderResources *) xrpr; 990597fb56Smrg} 1000597fb56Smrg 1010597fb56Smrgvoid 1020597fb56SmrgXRRFreeProviderResources(XRRProviderResources *provider_resources) 1030597fb56Smrg{ 1040597fb56Smrg free(provider_resources); 1050597fb56Smrg} 1060597fb56Smrg 1070597fb56SmrgXRRProviderInfo * 1080597fb56SmrgXRRGetProviderInfo(Display *dpy, XRRScreenResources *resources, RRProvider provider) 1090597fb56Smrg{ 1100597fb56Smrg XExtDisplayInfo *info = XRRFindDisplay(dpy); 1110597fb56Smrg xRRGetProviderInfoReply rep; 1120597fb56Smrg xRRGetProviderInfoReq *req; 1130597fb56Smrg int nbytes, nbytesRead, rbytes; 1140597fb56Smrg XRRProviderInfo *xpi; 1150597fb56Smrg 1160597fb56Smrg RRCheckExtension (dpy, info, NULL); 1170597fb56Smrg 1180597fb56Smrg LockDisplay (dpy); 1190597fb56Smrg GetReq (RRGetProviderInfo, req); 1200597fb56Smrg req->reqType = info->codes->major_opcode; 1210597fb56Smrg req->randrReqType = X_RRGetProviderInfo; 1220597fb56Smrg req->provider = provider; 1230597fb56Smrg req->configTimestamp = resources->configTimestamp; 1240597fb56Smrg 1258b1f82e3Smrg if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) 1260597fb56Smrg { 1270597fb56Smrg UnlockDisplay (dpy); 1280597fb56Smrg SyncHandle (); 1290597fb56Smrg return NULL; 1300597fb56Smrg } 1310597fb56Smrg 132a5bbb2f1Smrg if (rep.length > (INT_MAX >> 2)) 133f1c62215Smrg { 1348b1f82e3Smrg _XEatDataWords (dpy, rep.length); 135f1c62215Smrg UnlockDisplay (dpy); 136f1c62215Smrg SyncHandle (); 137f1c62215Smrg return NULL; 138f1c62215Smrg } 139f1c62215Smrg 1408b1f82e3Smrg nbytes = ((long) rep.length << 2); 1410597fb56Smrg 1420597fb56Smrg nbytesRead = (long)(rep.nCrtcs * 4 + 1430597fb56Smrg rep.nOutputs * 4 + 1440597fb56Smrg rep.nAssociatedProviders * 8 + 1450597fb56Smrg ((rep.nameLength + 3) & ~3)); 1460597fb56Smrg 1470597fb56Smrg rbytes = (sizeof(XRRProviderInfo) + 1480597fb56Smrg rep.nCrtcs * sizeof(RRCrtc) + 1490597fb56Smrg rep.nOutputs * sizeof(RROutput) + 1500597fb56Smrg rep.nAssociatedProviders * (sizeof(RRProvider) + sizeof(unsigned int))+ 1510597fb56Smrg rep.nameLength + 1); 1520597fb56Smrg 1538b1f82e3Smrg xpi = Xmalloc(rbytes); 1540597fb56Smrg if (xpi == NULL) { 1558b1f82e3Smrg _XEatDataWords (dpy, rep.length); 1560597fb56Smrg UnlockDisplay (dpy); 1570597fb56Smrg SyncHandle (); 1580597fb56Smrg return NULL; 1590597fb56Smrg } 1600597fb56Smrg 1610597fb56Smrg xpi->capabilities = rep.capabilities; 1620597fb56Smrg xpi->ncrtcs = rep.nCrtcs; 1630597fb56Smrg xpi->noutputs = rep.nOutputs; 1640597fb56Smrg xpi->nassociatedproviders = rep.nAssociatedProviders; 1650597fb56Smrg xpi->crtcs = (RRCrtc *)(xpi + 1); 1660597fb56Smrg xpi->outputs = (RROutput *)(xpi->crtcs + rep.nCrtcs); 1670597fb56Smrg xpi->associated_providers = (RRProvider *)(xpi->outputs + rep.nOutputs); 1680597fb56Smrg xpi->associated_capability = (unsigned int *)(xpi->associated_providers + rep.nAssociatedProviders); 1690597fb56Smrg xpi->name = (char *)(xpi->associated_capability + rep.nAssociatedProviders); 1700597fb56Smrg 1713366ab10Smrg _XRead32(dpy, (long *) xpi->crtcs, rep.nCrtcs << 2); 1723366ab10Smrg _XRead32(dpy, (long *) xpi->outputs, rep.nOutputs << 2); 1730597fb56Smrg 1743366ab10Smrg _XRead32(dpy, (long *) xpi->associated_providers, rep.nAssociatedProviders << 2); 1759de3b32fSwiz 1769de3b32fSwiz /* 1779de3b32fSwiz * _XRead32 reads a series of 32-bit values from the protocol and writes 1789de3b32fSwiz * them out as a series of "long int" values, but associated_capability 1799de3b32fSwiz * is defined as unsigned int *, so that won't work for this array. 1809de3b32fSwiz * Instead we assume for now that "unsigned int" is also 32-bits, so 1819de3b32fSwiz * the values can be read without any conversion. 1829de3b32fSwiz */ 1839de3b32fSwiz _XRead(dpy, (char *) xpi->associated_capability, 1849de3b32fSwiz rep.nAssociatedProviders << 2); 1850597fb56Smrg 1860597fb56Smrg _XReadPad(dpy, xpi->name, rep.nameLength); 1870597fb56Smrg xpi->name[rep.nameLength] = '\0'; 1880597fb56Smrg 1890597fb56Smrg /* 1900597fb56Smrg * Skip any extra data 1910597fb56Smrg */ 1920597fb56Smrg if (nbytes > nbytesRead) 1930597fb56Smrg _XEatData (dpy, (unsigned long) (nbytes - nbytesRead)); 1940597fb56Smrg 1950597fb56Smrg UnlockDisplay (dpy); 1960597fb56Smrg SyncHandle (); 1970597fb56Smrg return (XRRProviderInfo *) xpi; 1980597fb56Smrg} 1990597fb56Smrg 2000597fb56Smrgvoid 2010597fb56SmrgXRRFreeProviderInfo(XRRProviderInfo *provider) 2020597fb56Smrg{ 2030597fb56Smrg free(provider); 2040597fb56Smrg} 2050597fb56Smrg 2060597fb56Smrgint 2070597fb56SmrgXRRSetProviderOutputSource(Display *dpy, XID provider, 2080597fb56Smrg XID source_provider) 2090597fb56Smrg{ 2100597fb56Smrg XExtDisplayInfo *info = XRRFindDisplay(dpy); 2110597fb56Smrg xRRSetProviderOutputSourceReq *req; 2120597fb56Smrg 2130597fb56Smrg RRCheckExtension (dpy, info, 0); 2140597fb56Smrg LockDisplay (dpy); 2150597fb56Smrg GetReq (RRSetProviderOutputSource, req); 2160597fb56Smrg req->reqType = info->codes->major_opcode; 2170597fb56Smrg req->randrReqType = X_RRSetProviderOutputSource; 2180597fb56Smrg req->provider = provider; 2190597fb56Smrg req->source_provider = source_provider; 2200597fb56Smrg UnlockDisplay (dpy); 2210597fb56Smrg SyncHandle (); 2220597fb56Smrg return 0; 2230597fb56Smrg} 2240597fb56Smrg 2250597fb56Smrgint 2260597fb56SmrgXRRSetProviderOffloadSink(Display *dpy, XID provider, 2270597fb56Smrg XID sink_provider) 2280597fb56Smrg{ 2290597fb56Smrg XExtDisplayInfo *info = XRRFindDisplay(dpy); 2300597fb56Smrg xRRSetProviderOffloadSinkReq *req; 2310597fb56Smrg 2320597fb56Smrg RRCheckExtension (dpy, info, 0); 2330597fb56Smrg LockDisplay (dpy); 2340597fb56Smrg GetReq (RRSetProviderOffloadSink, req); 2350597fb56Smrg req->reqType = info->codes->major_opcode; 2360597fb56Smrg req->randrReqType = X_RRSetProviderOffloadSink; 2370597fb56Smrg req->provider = provider; 2380597fb56Smrg req->sink_provider = sink_provider; 2390597fb56Smrg UnlockDisplay (dpy); 2400597fb56Smrg SyncHandle (); 2410597fb56Smrg return 0; 2420597fb56Smrg} 243