XrrProvider.c revision 4b9d291a
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));
70f1c62215Smrg	xrpr = (XRRProviderResources *) 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
1070597fb56Smrg#define ProviderInfoExtra	(SIZEOF(xRRGetProviderInfoReply) - 32)
1080597fb56SmrgXRRProviderInfo *
1090597fb56SmrgXRRGetProviderInfo(Display *dpy, XRRScreenResources *resources, RRProvider provider)
1100597fb56Smrg{
1110597fb56Smrg    XExtDisplayInfo	    *info = XRRFindDisplay(dpy);
1120597fb56Smrg    xRRGetProviderInfoReply rep;
1130597fb56Smrg    xRRGetProviderInfoReq *req;
1140597fb56Smrg    int nbytes, nbytesRead, rbytes;
1150597fb56Smrg    XRRProviderInfo *xpi;
1160597fb56Smrg
1170597fb56Smrg    RRCheckExtension (dpy, info, NULL);
1180597fb56Smrg
1190597fb56Smrg    LockDisplay (dpy);
1200597fb56Smrg    GetReq (RRGetProviderInfo, req);
1210597fb56Smrg    req->reqType = info->codes->major_opcode;
1220597fb56Smrg    req->randrReqType = X_RRGetProviderInfo;
1230597fb56Smrg    req->provider = provider;
1240597fb56Smrg    req->configTimestamp = resources->configTimestamp;
1250597fb56Smrg
1260597fb56Smrg    if (!_XReply (dpy, (xReply *) &rep, ProviderInfoExtra >> 2, xFalse))
1270597fb56Smrg    {
1280597fb56Smrg	UnlockDisplay (dpy);
1290597fb56Smrg	SyncHandle ();
1300597fb56Smrg	return NULL;
1310597fb56Smrg    }
1320597fb56Smrg
1334b9d291aSchristos    if (rep.length > (INT_MAX >> 2) || rep.length < (ProviderInfoExtra >> 2))
134f1c62215Smrg    {
1354b9d291aSchristos	if (rep.length < (ProviderInfoExtra >> 2))
136f1c62215Smrg	    _XEatDataWords (dpy, rep.length);
137f1c62215Smrg	else
138f1c62215Smrg	    _XEatDataWords (dpy, rep.length - (ProviderInfoExtra >> 2));
139f1c62215Smrg	UnlockDisplay (dpy);
140f1c62215Smrg	SyncHandle ();
141f1c62215Smrg	return NULL;
142f1c62215Smrg    }
143f1c62215Smrg
1440597fb56Smrg    nbytes = ((long) rep.length << 2) - ProviderInfoExtra;
1450597fb56Smrg
1460597fb56Smrg    nbytesRead = (long)(rep.nCrtcs * 4 +
1470597fb56Smrg			rep.nOutputs * 4 +
1480597fb56Smrg			rep.nAssociatedProviders * 8 +
1490597fb56Smrg			((rep.nameLength + 3) & ~3));
1500597fb56Smrg
1510597fb56Smrg    rbytes = (sizeof(XRRProviderInfo) +
1520597fb56Smrg	      rep.nCrtcs * sizeof(RRCrtc) +
1530597fb56Smrg	      rep.nOutputs * sizeof(RROutput) +
1540597fb56Smrg	      rep.nAssociatedProviders * (sizeof(RRProvider) + sizeof(unsigned int))+
1550597fb56Smrg	      rep.nameLength + 1);
1560597fb56Smrg
1570597fb56Smrg    xpi = (XRRProviderInfo *)Xmalloc(rbytes);
1580597fb56Smrg    if (xpi == NULL) {
159a0b5b4faSmrg	_XEatDataWords (dpy, rep.length - (ProviderInfoExtra >> 2));
1600597fb56Smrg	UnlockDisplay (dpy);
1610597fb56Smrg	SyncHandle ();
1620597fb56Smrg	return NULL;
1630597fb56Smrg    }
1640597fb56Smrg
1650597fb56Smrg    xpi->capabilities = rep.capabilities;
1660597fb56Smrg    xpi->ncrtcs = rep.nCrtcs;
1670597fb56Smrg    xpi->noutputs = rep.nOutputs;
1680597fb56Smrg    xpi->nassociatedproviders = rep.nAssociatedProviders;
1690597fb56Smrg    xpi->crtcs = (RRCrtc *)(xpi + 1);
1700597fb56Smrg    xpi->outputs = (RROutput *)(xpi->crtcs + rep.nCrtcs);
1710597fb56Smrg    xpi->associated_providers = (RRProvider *)(xpi->outputs + rep.nOutputs);
1720597fb56Smrg    xpi->associated_capability = (unsigned int *)(xpi->associated_providers + rep.nAssociatedProviders);
1730597fb56Smrg    xpi->name = (char *)(xpi->associated_capability + rep.nAssociatedProviders);
1740597fb56Smrg
1753366ab10Smrg    _XRead32(dpy, (long *) xpi->crtcs, rep.nCrtcs << 2);
1763366ab10Smrg    _XRead32(dpy, (long *) xpi->outputs, rep.nOutputs << 2);
1770597fb56Smrg
1783366ab10Smrg    _XRead32(dpy, (long *) xpi->associated_providers, rep.nAssociatedProviders << 2);
1799de3b32fSwiz
1809de3b32fSwiz    /*
1819de3b32fSwiz     * _XRead32 reads a series of 32-bit values from the protocol and writes
1829de3b32fSwiz     * them out as a series of "long int" values, but associated_capability
1839de3b32fSwiz     * is defined as unsigned int *, so that won't work for this array.
1849de3b32fSwiz     * Instead we assume for now that "unsigned int" is also 32-bits, so
1859de3b32fSwiz     * the values can be read without any conversion.
1869de3b32fSwiz     */
1879de3b32fSwiz    _XRead(dpy, (char *) xpi->associated_capability,
1889de3b32fSwiz           rep.nAssociatedProviders << 2);
1890597fb56Smrg
1900597fb56Smrg    _XReadPad(dpy, xpi->name, rep.nameLength);
1910597fb56Smrg    xpi->name[rep.nameLength] = '\0';
1920597fb56Smrg
1930597fb56Smrg    /*
1940597fb56Smrg     * Skip any extra data
1950597fb56Smrg     */
1960597fb56Smrg    if (nbytes > nbytesRead)
1970597fb56Smrg	_XEatData (dpy, (unsigned long) (nbytes - nbytesRead));
1980597fb56Smrg
1990597fb56Smrg    UnlockDisplay (dpy);
2000597fb56Smrg    SyncHandle ();
2010597fb56Smrg    return (XRRProviderInfo *) xpi;
2020597fb56Smrg}
2030597fb56Smrg
2040597fb56Smrgvoid
2050597fb56SmrgXRRFreeProviderInfo(XRRProviderInfo *provider)
2060597fb56Smrg{
2070597fb56Smrg    free(provider);
2080597fb56Smrg}
2090597fb56Smrg
2100597fb56Smrgint
2110597fb56SmrgXRRSetProviderOutputSource(Display *dpy, XID provider,
2120597fb56Smrg			   XID source_provider)
2130597fb56Smrg{
2140597fb56Smrg    XExtDisplayInfo	    *info = XRRFindDisplay(dpy);
2150597fb56Smrg    xRRSetProviderOutputSourceReq *req;
2160597fb56Smrg
2170597fb56Smrg    RRCheckExtension (dpy, info, 0);
2180597fb56Smrg    LockDisplay (dpy);
2190597fb56Smrg    GetReq (RRSetProviderOutputSource, req);
2200597fb56Smrg    req->reqType = info->codes->major_opcode;
2210597fb56Smrg    req->randrReqType = X_RRSetProviderOutputSource;
2220597fb56Smrg    req->provider = provider;
2230597fb56Smrg    req->source_provider = source_provider;
2240597fb56Smrg    UnlockDisplay (dpy);
2250597fb56Smrg    SyncHandle ();
2260597fb56Smrg    return 0;
2270597fb56Smrg}
2280597fb56Smrg
2290597fb56Smrgint
2300597fb56SmrgXRRSetProviderOffloadSink(Display *dpy, XID provider,
2310597fb56Smrg			  XID sink_provider)
2320597fb56Smrg{
2330597fb56Smrg    XExtDisplayInfo	    *info = XRRFindDisplay(dpy);
2340597fb56Smrg    xRRSetProviderOffloadSinkReq *req;
2350597fb56Smrg
2360597fb56Smrg    RRCheckExtension (dpy, info, 0);
2370597fb56Smrg    LockDisplay (dpy);
2380597fb56Smrg    GetReq (RRSetProviderOffloadSink, req);
2390597fb56Smrg    req->reqType = info->codes->major_opcode;
2400597fb56Smrg    req->randrReqType = X_RRSetProviderOffloadSink;
2410597fb56Smrg    req->provider = provider;
2420597fb56Smrg    req->sink_provider = sink_provider;
2430597fb56Smrg    UnlockDisplay (dpy);
2440597fb56Smrg    SyncHandle ();
2450597fb56Smrg    return 0;
2460597fb56Smrg}
247