forked from KolibriOS/kolibrios
400 lines
12 KiB
C
400 lines
12 KiB
C
|
/*
|
||
|
* Copyright (c) 2008 NVIDIA, Corporation
|
||
|
*
|
||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
|
* of this software and associated documentation files (the "Software"), to deal
|
||
|
* in the Software without restriction, including without limitation the rights
|
||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
|
* copies of the Software, and to permit persons to whom the Software is
|
||
|
* furnished to do so, subject to the following conditions:
|
||
|
*
|
||
|
* The above copyright notice and this permission notice (including the next
|
||
|
* paragraph) shall be included in all copies or substantial portions of the
|
||
|
* Software.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||
|
* SOFTWARE.
|
||
|
*/
|
||
|
|
||
|
#define _GNU_SOURCE 1
|
||
|
#include <string.h>
|
||
|
|
||
|
#define NEED_REPLIES
|
||
|
#include <stdlib.h>
|
||
|
#include <X11/Xlibint.h>
|
||
|
#include <X11/Xutil.h>
|
||
|
#include <X11/extensions/Xext.h>
|
||
|
#include <X11/extensions/extutil.h>
|
||
|
#include "va_nvctrl.h"
|
||
|
|
||
|
#define NV_CONTROL_ERRORS 0
|
||
|
#define NV_CONTROL_EVENTS 5
|
||
|
#define NV_CONTROL_NAME "NV-CONTROL"
|
||
|
|
||
|
#define NV_CTRL_TARGET_TYPE_X_SCREEN 0
|
||
|
#define NV_CTRL_TARGET_TYPE_GPU 1
|
||
|
#define NV_CTRL_TARGET_TYPE_FRAMELOCK 2
|
||
|
#define NV_CTRL_TARGET_TYPE_VCSC 3 /* Visual Computing System */
|
||
|
|
||
|
#define NV_CTRL_STRING_NVIDIA_DRIVER_VERSION 3 /* R--G */
|
||
|
|
||
|
#define X_nvCtrlQueryExtension 0
|
||
|
#define X_nvCtrlIsNv 1
|
||
|
#define X_nvCtrlQueryStringAttribute 4
|
||
|
|
||
|
typedef struct {
|
||
|
CARD8 reqType;
|
||
|
CARD8 nvReqType;
|
||
|
CARD16 length B16;
|
||
|
} xnvCtrlQueryExtensionReq;
|
||
|
#define sz_xnvCtrlQueryExtensionReq 4
|
||
|
|
||
|
typedef struct {
|
||
|
BYTE type; /* X_Reply */
|
||
|
CARD8 padb1;
|
||
|
CARD16 sequenceNumber B16;
|
||
|
CARD32 length B32;
|
||
|
CARD16 major B16;
|
||
|
CARD16 minor B16;
|
||
|
CARD32 padl4 B32;
|
||
|
CARD32 padl5 B32;
|
||
|
CARD32 padl6 B32;
|
||
|
CARD32 padl7 B32;
|
||
|
CARD32 padl8 B32;
|
||
|
} xnvCtrlQueryExtensionReply;
|
||
|
#define sz_xnvCtrlQueryExtensionReply 32
|
||
|
|
||
|
typedef struct {
|
||
|
CARD8 reqType;
|
||
|
CARD8 nvReqType;
|
||
|
CARD16 length B16;
|
||
|
CARD32 screen B32;
|
||
|
} xnvCtrlIsNvReq;
|
||
|
#define sz_xnvCtrlIsNvReq 8
|
||
|
|
||
|
typedef struct {
|
||
|
BYTE type; /* X_Reply */
|
||
|
CARD8 padb1;
|
||
|
CARD16 sequenceNumber B16;
|
||
|
CARD32 length B32;
|
||
|
CARD32 isnv B32;
|
||
|
CARD32 padl4 B32;
|
||
|
CARD32 padl5 B32;
|
||
|
CARD32 padl6 B32;
|
||
|
CARD32 padl7 B32;
|
||
|
CARD32 padl8 B32;
|
||
|
} xnvCtrlIsNvReply;
|
||
|
#define sz_xnvCtrlIsNvReply 32
|
||
|
|
||
|
typedef struct {
|
||
|
CARD8 reqType;
|
||
|
CARD8 nvReqType;
|
||
|
CARD16 length B16;
|
||
|
CARD16 target_id B16; /* X screen number or GPU number */
|
||
|
CARD16 target_type B16; /* X screen or GPU */
|
||
|
CARD32 display_mask B32;
|
||
|
CARD32 attribute B32;
|
||
|
} xnvCtrlQueryStringAttributeReq;
|
||
|
#define sz_xnvCtrlQueryStringAttributeReq 16
|
||
|
|
||
|
typedef struct {
|
||
|
BYTE type;
|
||
|
BYTE pad0;
|
||
|
CARD16 sequenceNumber B16;
|
||
|
CARD32 length B32;
|
||
|
CARD32 flags B32;
|
||
|
CARD32 n B32; /* Length of string */
|
||
|
CARD32 pad4 B32;
|
||
|
CARD32 pad5 B32;
|
||
|
CARD32 pad6 B32;
|
||
|
CARD32 pad7 B32;
|
||
|
} xnvCtrlQueryStringAttributeReply;
|
||
|
#define sz_xnvCtrlQueryStringAttributeReply 32
|
||
|
|
||
|
#define NVCTRL_EXT_NEED_CHECK (XPointer)(~0)
|
||
|
#define NVCTRL_EXT_NEED_NOTHING (XPointer)(0)
|
||
|
#define NVCTRL_EXT_NEED_TARGET_SWAP (XPointer)(1)
|
||
|
|
||
|
static XExtensionInfo _nvctrl_ext_info_data;
|
||
|
static XExtensionInfo *nvctrl_ext_info = &_nvctrl_ext_info_data;
|
||
|
static /* const */ char *nvctrl_extension_name = NV_CONTROL_NAME;
|
||
|
|
||
|
#define XNVCTRLCheckExtension(dpy,i,val) \
|
||
|
XextCheckExtension (dpy, i, nvctrl_extension_name, val)
|
||
|
#define XNVCTRLSimpleCheckExtension(dpy,i) \
|
||
|
XextSimpleCheckExtension (dpy, i, nvctrl_extension_name)
|
||
|
|
||
|
static int close_display();
|
||
|
static /* const */ XExtensionHooks nvctrl_extension_hooks = {
|
||
|
NULL, /* create_gc */
|
||
|
NULL, /* copy_gc */
|
||
|
NULL, /* flush_gc */
|
||
|
NULL, /* free_gc */
|
||
|
NULL, /* create_font */
|
||
|
NULL, /* free_font */
|
||
|
close_display, /* close_display */
|
||
|
NULL, /* wire_to_event */
|
||
|
NULL, /* event_to_wire */
|
||
|
NULL, /* error */
|
||
|
NULL, /* error_string */
|
||
|
};
|
||
|
|
||
|
static XEXT_GENERATE_FIND_DISPLAY (find_display, nvctrl_ext_info,
|
||
|
nvctrl_extension_name,
|
||
|
&nvctrl_extension_hooks,
|
||
|
NV_CONTROL_EVENTS, NVCTRL_EXT_NEED_CHECK)
|
||
|
|
||
|
static XEXT_GENERATE_CLOSE_DISPLAY (close_display, nvctrl_ext_info)
|
||
|
|
||
|
static Bool XNVCTRLQueryVersion (Display *dpy, int *major, int *minor);
|
||
|
|
||
|
/*
|
||
|
* NV-CONTROL versions 1.8 and 1.9 pack the target_type and target_id
|
||
|
* fields in reversed order. In order to talk to one of these servers,
|
||
|
* we need to swap these fields.
|
||
|
*/
|
||
|
static void XNVCTRLCheckTargetData(Display *dpy, XExtDisplayInfo *info,
|
||
|
int *target_type, int *target_id)
|
||
|
{
|
||
|
/* Find out what the server's NV-CONTROL version is and
|
||
|
* setup for swapping if we need to.
|
||
|
*/
|
||
|
if (info->data == NVCTRL_EXT_NEED_CHECK) {
|
||
|
int major, minor;
|
||
|
|
||
|
if (XNVCTRLQueryVersion(dpy, &major, &minor)) {
|
||
|
if (major == 1 &&
|
||
|
(minor == 8 || minor == 9)) {
|
||
|
info->data = NVCTRL_EXT_NEED_TARGET_SWAP;
|
||
|
} else {
|
||
|
info->data = NVCTRL_EXT_NEED_NOTHING;
|
||
|
}
|
||
|
} else {
|
||
|
info->data = NVCTRL_EXT_NEED_NOTHING;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* We need to swap the target_type and target_id */
|
||
|
if (info->data == NVCTRL_EXT_NEED_TARGET_SWAP) {
|
||
|
int tmp;
|
||
|
tmp = *target_type;
|
||
|
*target_type = *target_id;
|
||
|
*target_id = tmp;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
static Bool XNVCTRLQueryExtension (
|
||
|
Display *dpy,
|
||
|
int *event_basep,
|
||
|
int *error_basep
|
||
|
){
|
||
|
XExtDisplayInfo *info = find_display (dpy);
|
||
|
|
||
|
if (XextHasExtension(info)) {
|
||
|
if (event_basep) *event_basep = info->codes->first_event;
|
||
|
if (error_basep) *error_basep = info->codes->first_error;
|
||
|
return True;
|
||
|
} else {
|
||
|
return False;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
static Bool XNVCTRLQueryVersion (
|
||
|
Display *dpy,
|
||
|
int *major,
|
||
|
int *minor
|
||
|
){
|
||
|
XExtDisplayInfo *info = find_display (dpy);
|
||
|
xnvCtrlQueryExtensionReply rep;
|
||
|
xnvCtrlQueryExtensionReq *req;
|
||
|
|
||
|
if(!XextHasExtension(info))
|
||
|
return False;
|
||
|
|
||
|
XNVCTRLCheckExtension (dpy, info, False);
|
||
|
|
||
|
LockDisplay (dpy);
|
||
|
GetReq (nvCtrlQueryExtension, req);
|
||
|
req->reqType = info->codes->major_opcode;
|
||
|
req->nvReqType = X_nvCtrlQueryExtension;
|
||
|
if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
|
||
|
UnlockDisplay (dpy);
|
||
|
SyncHandle ();
|
||
|
return False;
|
||
|
}
|
||
|
if (major) *major = rep.major;
|
||
|
if (minor) *minor = rep.minor;
|
||
|
UnlockDisplay (dpy);
|
||
|
SyncHandle ();
|
||
|
return True;
|
||
|
}
|
||
|
|
||
|
|
||
|
static Bool XNVCTRLIsNvScreen (
|
||
|
Display *dpy,
|
||
|
int screen
|
||
|
){
|
||
|
XExtDisplayInfo *info = find_display (dpy);
|
||
|
xnvCtrlIsNvReply rep;
|
||
|
xnvCtrlIsNvReq *req;
|
||
|
Bool isnv;
|
||
|
|
||
|
if(!XextHasExtension(info))
|
||
|
return False;
|
||
|
|
||
|
XNVCTRLCheckExtension (dpy, info, False);
|
||
|
|
||
|
LockDisplay (dpy);
|
||
|
GetReq (nvCtrlIsNv, req);
|
||
|
req->reqType = info->codes->major_opcode;
|
||
|
req->nvReqType = X_nvCtrlIsNv;
|
||
|
req->screen = screen;
|
||
|
if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) {
|
||
|
UnlockDisplay (dpy);
|
||
|
SyncHandle ();
|
||
|
return False;
|
||
|
}
|
||
|
isnv = rep.isnv;
|
||
|
UnlockDisplay (dpy);
|
||
|
SyncHandle ();
|
||
|
return isnv;
|
||
|
}
|
||
|
|
||
|
|
||
|
static Bool XNVCTRLQueryTargetStringAttribute (
|
||
|
Display *dpy,
|
||
|
int target_type,
|
||
|
int target_id,
|
||
|
unsigned int display_mask,
|
||
|
unsigned int attribute,
|
||
|
char **ptr
|
||
|
){
|
||
|
XExtDisplayInfo *info = find_display (dpy);
|
||
|
xnvCtrlQueryStringAttributeReply rep;
|
||
|
xnvCtrlQueryStringAttributeReq *req;
|
||
|
Bool exists;
|
||
|
int length, numbytes, slop;
|
||
|
|
||
|
if (!ptr) return False;
|
||
|
|
||
|
if(!XextHasExtension(info))
|
||
|
return False;
|
||
|
|
||
|
XNVCTRLCheckExtension (dpy, info, False);
|
||
|
XNVCTRLCheckTargetData(dpy, info, &target_type, &target_id);
|
||
|
|
||
|
LockDisplay (dpy);
|
||
|
GetReq (nvCtrlQueryStringAttribute, req);
|
||
|
req->reqType = info->codes->major_opcode;
|
||
|
req->nvReqType = X_nvCtrlQueryStringAttribute;
|
||
|
req->target_type = target_type;
|
||
|
req->target_id = target_id;
|
||
|
req->display_mask = display_mask;
|
||
|
req->attribute = attribute;
|
||
|
if (!_XReply (dpy, (xReply *) &rep, 0, False)) {
|
||
|
UnlockDisplay (dpy);
|
||
|
SyncHandle ();
|
||
|
return False;
|
||
|
}
|
||
|
length = rep.length;
|
||
|
numbytes = rep.n;
|
||
|
slop = numbytes & 3;
|
||
|
*ptr = (char *) Xmalloc(numbytes);
|
||
|
if (! *ptr) {
|
||
|
_XEatData(dpy, length);
|
||
|
UnlockDisplay (dpy);
|
||
|
SyncHandle ();
|
||
|
return False;
|
||
|
} else {
|
||
|
_XRead(dpy, (char *) *ptr, numbytes);
|
||
|
if (slop) _XEatData(dpy, 4-slop);
|
||
|
}
|
||
|
exists = rep.flags;
|
||
|
UnlockDisplay (dpy);
|
||
|
SyncHandle ();
|
||
|
return exists;
|
||
|
}
|
||
|
|
||
|
static Bool XNVCTRLQueryStringAttribute (
|
||
|
Display *dpy,
|
||
|
int screen,
|
||
|
unsigned int display_mask,
|
||
|
unsigned int attribute,
|
||
|
char **ptr
|
||
|
){
|
||
|
return XNVCTRLQueryTargetStringAttribute(dpy, NV_CTRL_TARGET_TYPE_X_SCREEN,
|
||
|
screen, display_mask,
|
||
|
attribute, ptr);
|
||
|
}
|
||
|
|
||
|
|
||
|
Bool VA_NVCTRLQueryDirectRenderingCapable( Display *dpy, int screen,
|
||
|
Bool *isCapable )
|
||
|
{
|
||
|
int event_base;
|
||
|
int error_base;
|
||
|
|
||
|
if (isCapable)
|
||
|
*isCapable = False;
|
||
|
|
||
|
if (!XNVCTRLQueryExtension(dpy, &event_base, &error_base))
|
||
|
return False;
|
||
|
|
||
|
if (isCapable && XNVCTRLIsNvScreen(dpy, screen))
|
||
|
*isCapable = True;
|
||
|
|
||
|
return True;
|
||
|
}
|
||
|
|
||
|
Bool VA_NVCTRLGetClientDriverName( Display *dpy, int screen,
|
||
|
int *ddxDriverMajorVersion, int *ddxDriverMinorVersion,
|
||
|
int *ddxDriverPatchVersion, char **clientDriverName )
|
||
|
{
|
||
|
if (ddxDriverMajorVersion)
|
||
|
*ddxDriverMajorVersion = 0;
|
||
|
if (ddxDriverMinorVersion)
|
||
|
*ddxDriverMinorVersion = 0;
|
||
|
if (ddxDriverPatchVersion)
|
||
|
*ddxDriverPatchVersion = 0;
|
||
|
if (clientDriverName)
|
||
|
*clientDriverName = NULL;
|
||
|
|
||
|
char *nvidia_driver_version = NULL;
|
||
|
if (!XNVCTRLQueryStringAttribute(dpy, screen, 0, NV_CTRL_STRING_NVIDIA_DRIVER_VERSION, &nvidia_driver_version))
|
||
|
return False;
|
||
|
|
||
|
char *end, *str = nvidia_driver_version;
|
||
|
unsigned long v = strtoul(str, &end, 10);
|
||
|
if (end && end != str) {
|
||
|
if (ddxDriverMajorVersion)
|
||
|
*ddxDriverMajorVersion = v;
|
||
|
if (*(str = end) == '.') {
|
||
|
v = strtoul(str + 1, &end, 10);
|
||
|
if (end && end != str && (*end == '.' || *end == '\0')) {
|
||
|
if (ddxDriverMinorVersion)
|
||
|
*ddxDriverMinorVersion = v;
|
||
|
if (*(str = end) == '.') {
|
||
|
v = strtoul(str + 1, &end, 10);
|
||
|
if (end && end != str && *end == '\0') {
|
||
|
if (ddxDriverPatchVersion)
|
||
|
*ddxDriverPatchVersion = v;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
Xfree(nvidia_driver_version);
|
||
|
|
||
|
if (clientDriverName)
|
||
|
*clientDriverName = strdup("nvidia");
|
||
|
|
||
|
return True;
|
||
|
}
|