OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright (c) 2008 NVIDIA, Corporation |
| 3 * |
| 4 * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 5 * of this software and associated documentation files (the "Software"), to deal |
| 6 * in the Software without restriction, including without limitation the rights |
| 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 8 * copies of the Software, and to permit persons to whom the Software is |
| 9 * furnished to do so, subject to the following conditions: |
| 10 * |
| 11 * The above copyright notice and this permission notice (including the next |
| 12 * paragraph) shall be included in all copies or substantial portions of the |
| 13 * Software. |
| 14 * |
| 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 21 * SOFTWARE. |
| 22 */ |
| 23 |
| 24 #define _GNU_SOURCE 1 |
| 25 #include <string.h> |
| 26 |
| 27 #define NEED_REPLIES |
| 28 #include <stdlib.h> |
| 29 #include <X11/Xlibint.h> |
| 30 #include <X11/Xutil.h> |
| 31 #include <X11/extensions/Xext.h> |
| 32 #include <X11/extensions/extutil.h> |
| 33 #include "va_nvctrl.h" |
| 34 |
| 35 #define NV_CONTROL_ERRORS 0 |
| 36 #define NV_CONTROL_EVENTS 5 |
| 37 #define NV_CONTROL_NAME "NV-CONTROL" |
| 38 |
| 39 #define NV_CTRL_TARGET_TYPE_X_SCREEN 0 |
| 40 #define NV_CTRL_TARGET_TYPE_GPU 1 |
| 41 #define NV_CTRL_TARGET_TYPE_FRAMELOCK 2 |
| 42 #define NV_CTRL_TARGET_TYPE_VCSC 3 /* Visual Computing System */ |
| 43 |
| 44 #define NV_CTRL_STRING_NVIDIA_DRIVER_VERSION 3 /* R--G */ |
| 45 |
| 46 #define X_nvCtrlQueryExtension 0 |
| 47 #define X_nvCtrlIsNv 1 |
| 48 #define X_nvCtrlQueryStringAttribute 4 |
| 49 |
| 50 typedef struct { |
| 51 CARD8 reqType; |
| 52 CARD8 nvReqType; |
| 53 CARD16 length B16; |
| 54 } xnvCtrlQueryExtensionReq; |
| 55 #define sz_xnvCtrlQueryExtensionReq 4 |
| 56 |
| 57 typedef struct { |
| 58 BYTE type; /* X_Reply */ |
| 59 CARD8 padb1; |
| 60 CARD16 sequenceNumber B16; |
| 61 CARD32 length B32; |
| 62 CARD16 major B16; |
| 63 CARD16 minor B16; |
| 64 CARD32 padl4 B32; |
| 65 CARD32 padl5 B32; |
| 66 CARD32 padl6 B32; |
| 67 CARD32 padl7 B32; |
| 68 CARD32 padl8 B32; |
| 69 } xnvCtrlQueryExtensionReply; |
| 70 #define sz_xnvCtrlQueryExtensionReply 32 |
| 71 |
| 72 typedef struct { |
| 73 CARD8 reqType; |
| 74 CARD8 nvReqType; |
| 75 CARD16 length B16; |
| 76 CARD32 screen B32; |
| 77 } xnvCtrlIsNvReq; |
| 78 #define sz_xnvCtrlIsNvReq 8 |
| 79 |
| 80 typedef struct { |
| 81 BYTE type; /* X_Reply */ |
| 82 CARD8 padb1; |
| 83 CARD16 sequenceNumber B16; |
| 84 CARD32 length B32; |
| 85 CARD32 isnv B32; |
| 86 CARD32 padl4 B32; |
| 87 CARD32 padl5 B32; |
| 88 CARD32 padl6 B32; |
| 89 CARD32 padl7 B32; |
| 90 CARD32 padl8 B32; |
| 91 } xnvCtrlIsNvReply; |
| 92 #define sz_xnvCtrlIsNvReply 32 |
| 93 |
| 94 typedef struct { |
| 95 CARD8 reqType; |
| 96 CARD8 nvReqType; |
| 97 CARD16 length B16; |
| 98 CARD16 target_id B16; /* X screen number or GPU number */ |
| 99 CARD16 target_type B16; /* X screen or GPU */ |
| 100 CARD32 display_mask B32; |
| 101 CARD32 attribute B32; |
| 102 } xnvCtrlQueryStringAttributeReq; |
| 103 #define sz_xnvCtrlQueryStringAttributeReq 16 |
| 104 |
| 105 typedef struct { |
| 106 BYTE type; |
| 107 BYTE pad0; |
| 108 CARD16 sequenceNumber B16; |
| 109 CARD32 length B32; |
| 110 CARD32 flags B32; |
| 111 CARD32 n B32; /* Length of string */ |
| 112 CARD32 pad4 B32; |
| 113 CARD32 pad5 B32; |
| 114 CARD32 pad6 B32; |
| 115 CARD32 pad7 B32; |
| 116 } xnvCtrlQueryStringAttributeReply; |
| 117 #define sz_xnvCtrlQueryStringAttributeReply 32 |
| 118 |
| 119 #define NVCTRL_EXT_NEED_CHECK (XPointer)(~0) |
| 120 #define NVCTRL_EXT_NEED_NOTHING (XPointer)(0) |
| 121 #define NVCTRL_EXT_NEED_TARGET_SWAP (XPointer)(1) |
| 122 |
| 123 static XExtensionInfo _nvctrl_ext_info_data; |
| 124 static XExtensionInfo *nvctrl_ext_info = &_nvctrl_ext_info_data; |
| 125 static /* const */ char *nvctrl_extension_name = NV_CONTROL_NAME; |
| 126 |
| 127 #define XNVCTRLCheckExtension(dpy,i,val) \ |
| 128 XextCheckExtension (dpy, i, nvctrl_extension_name, val) |
| 129 #define XNVCTRLSimpleCheckExtension(dpy,i) \ |
| 130 XextSimpleCheckExtension (dpy, i, nvctrl_extension_name) |
| 131 |
| 132 static int close_display(); |
| 133 static /* const */ XExtensionHooks nvctrl_extension_hooks = { |
| 134 NULL, /* create_gc */ |
| 135 NULL, /* copy_gc */ |
| 136 NULL, /* flush_gc */ |
| 137 NULL, /* free_gc */ |
| 138 NULL, /* create_font */ |
| 139 NULL, /* free_font */ |
| 140 close_display, /* close_display */ |
| 141 NULL, /* wire_to_event */ |
| 142 NULL, /* event_to_wire */ |
| 143 NULL, /* error */ |
| 144 NULL, /* error_string */ |
| 145 }; |
| 146 |
| 147 static XEXT_GENERATE_FIND_DISPLAY (find_display, nvctrl_ext_info, |
| 148 nvctrl_extension_name, |
| 149 &nvctrl_extension_hooks, |
| 150 NV_CONTROL_EVENTS, NVCTRL_EXT_NEED_CHECK) |
| 151 |
| 152 static XEXT_GENERATE_CLOSE_DISPLAY (close_display, nvctrl_ext_info) |
| 153 |
| 154 static Bool XNVCTRLQueryVersion (Display *dpy, int *major, int *minor); |
| 155 |
| 156 /* |
| 157 * NV-CONTROL versions 1.8 and 1.9 pack the target_type and target_id |
| 158 * fields in reversed order. In order to talk to one of these servers, |
| 159 * we need to swap these fields. |
| 160 */ |
| 161 static void XNVCTRLCheckTargetData(Display *dpy, XExtDisplayInfo *info, |
| 162 int *target_type, int *target_id) |
| 163 { |
| 164 /* Find out what the server's NV-CONTROL version is and |
| 165 * setup for swapping if we need to. |
| 166 */ |
| 167 if (info->data == NVCTRL_EXT_NEED_CHECK) { |
| 168 int major, minor; |
| 169 |
| 170 if (XNVCTRLQueryVersion(dpy, &major, &minor)) { |
| 171 if (major == 1 && |
| 172 (minor == 8 || minor == 9)) { |
| 173 info->data = NVCTRL_EXT_NEED_TARGET_SWAP; |
| 174 } else { |
| 175 info->data = NVCTRL_EXT_NEED_NOTHING; |
| 176 } |
| 177 } else { |
| 178 info->data = NVCTRL_EXT_NEED_NOTHING; |
| 179 } |
| 180 } |
| 181 |
| 182 /* We need to swap the target_type and target_id */ |
| 183 if (info->data == NVCTRL_EXT_NEED_TARGET_SWAP) { |
| 184 int tmp; |
| 185 tmp = *target_type; |
| 186 *target_type = *target_id; |
| 187 *target_id = tmp; |
| 188 } |
| 189 } |
| 190 |
| 191 |
| 192 static Bool XNVCTRLQueryExtension ( |
| 193 Display *dpy, |
| 194 int *event_basep, |
| 195 int *error_basep |
| 196 ){ |
| 197 XExtDisplayInfo *info = find_display (dpy); |
| 198 |
| 199 if (XextHasExtension(info)) { |
| 200 if (event_basep) *event_basep = info->codes->first_event; |
| 201 if (error_basep) *error_basep = info->codes->first_error; |
| 202 return True; |
| 203 } else { |
| 204 return False; |
| 205 } |
| 206 } |
| 207 |
| 208 |
| 209 static Bool XNVCTRLQueryVersion ( |
| 210 Display *dpy, |
| 211 int *major, |
| 212 int *minor |
| 213 ){ |
| 214 XExtDisplayInfo *info = find_display (dpy); |
| 215 xnvCtrlQueryExtensionReply rep; |
| 216 xnvCtrlQueryExtensionReq *req; |
| 217 |
| 218 if(!XextHasExtension(info)) |
| 219 return False; |
| 220 |
| 221 XNVCTRLCheckExtension (dpy, info, False); |
| 222 |
| 223 LockDisplay (dpy); |
| 224 GetReq (nvCtrlQueryExtension, req); |
| 225 req->reqType = info->codes->major_opcode; |
| 226 req->nvReqType = X_nvCtrlQueryExtension; |
| 227 if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { |
| 228 UnlockDisplay (dpy); |
| 229 SyncHandle (); |
| 230 return False; |
| 231 } |
| 232 if (major) *major = rep.major; |
| 233 if (minor) *minor = rep.minor; |
| 234 UnlockDisplay (dpy); |
| 235 SyncHandle (); |
| 236 return True; |
| 237 } |
| 238 |
| 239 |
| 240 static Bool XNVCTRLIsNvScreen ( |
| 241 Display *dpy, |
| 242 int screen |
| 243 ){ |
| 244 XExtDisplayInfo *info = find_display (dpy); |
| 245 xnvCtrlIsNvReply rep; |
| 246 xnvCtrlIsNvReq *req; |
| 247 Bool isnv; |
| 248 |
| 249 if(!XextHasExtension(info)) |
| 250 return False; |
| 251 |
| 252 XNVCTRLCheckExtension (dpy, info, False); |
| 253 |
| 254 LockDisplay (dpy); |
| 255 GetReq (nvCtrlIsNv, req); |
| 256 req->reqType = info->codes->major_opcode; |
| 257 req->nvReqType = X_nvCtrlIsNv; |
| 258 req->screen = screen; |
| 259 if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { |
| 260 UnlockDisplay (dpy); |
| 261 SyncHandle (); |
| 262 return False; |
| 263 } |
| 264 isnv = rep.isnv; |
| 265 UnlockDisplay (dpy); |
| 266 SyncHandle (); |
| 267 return isnv; |
| 268 } |
| 269 |
| 270 |
| 271 static Bool XNVCTRLQueryTargetStringAttribute ( |
| 272 Display *dpy, |
| 273 int target_type, |
| 274 int target_id, |
| 275 unsigned int display_mask, |
| 276 unsigned int attribute, |
| 277 char **ptr |
| 278 ){ |
| 279 XExtDisplayInfo *info = find_display (dpy); |
| 280 xnvCtrlQueryStringAttributeReply rep; |
| 281 xnvCtrlQueryStringAttributeReq *req; |
| 282 Bool exists; |
| 283 int length, numbytes, slop; |
| 284 |
| 285 if (!ptr) return False; |
| 286 |
| 287 if(!XextHasExtension(info)) |
| 288 return False; |
| 289 |
| 290 XNVCTRLCheckExtension (dpy, info, False); |
| 291 XNVCTRLCheckTargetData(dpy, info, &target_type, &target_id); |
| 292 |
| 293 LockDisplay (dpy); |
| 294 GetReq (nvCtrlQueryStringAttribute, req); |
| 295 req->reqType = info->codes->major_opcode; |
| 296 req->nvReqType = X_nvCtrlQueryStringAttribute; |
| 297 req->target_type = target_type; |
| 298 req->target_id = target_id; |
| 299 req->display_mask = display_mask; |
| 300 req->attribute = attribute; |
| 301 if (!_XReply (dpy, (xReply *) &rep, 0, False)) { |
| 302 UnlockDisplay (dpy); |
| 303 SyncHandle (); |
| 304 return False; |
| 305 } |
| 306 length = rep.length; |
| 307 numbytes = rep.n; |
| 308 slop = numbytes & 3; |
| 309 *ptr = (char *) Xmalloc(numbytes); |
| 310 if (! *ptr) { |
| 311 _XEatData(dpy, length); |
| 312 UnlockDisplay (dpy); |
| 313 SyncHandle (); |
| 314 return False; |
| 315 } else { |
| 316 _XRead(dpy, (char *) *ptr, numbytes); |
| 317 if (slop) _XEatData(dpy, 4-slop); |
| 318 } |
| 319 exists = rep.flags; |
| 320 UnlockDisplay (dpy); |
| 321 SyncHandle (); |
| 322 return exists; |
| 323 } |
| 324 |
| 325 static Bool XNVCTRLQueryStringAttribute ( |
| 326 Display *dpy, |
| 327 int screen, |
| 328 unsigned int display_mask, |
| 329 unsigned int attribute, |
| 330 char **ptr |
| 331 ){ |
| 332 return XNVCTRLQueryTargetStringAttribute(dpy, NV_CTRL_TARGET_TYPE_X_SCREEN, |
| 333 screen, display_mask, |
| 334 attribute, ptr); |
| 335 } |
| 336 |
| 337 |
| 338 Bool VA_NVCTRLQueryDirectRenderingCapable( Display *dpy, int screen, |
| 339 Bool *isCapable ) |
| 340 { |
| 341 int event_base; |
| 342 int error_base; |
| 343 |
| 344 if (isCapable) |
| 345 *isCapable = False; |
| 346 |
| 347 if (!XNVCTRLQueryExtension(dpy, &event_base, &error_base)) |
| 348 return False; |
| 349 |
| 350 if (isCapable && XNVCTRLIsNvScreen(dpy, screen)) |
| 351 *isCapable = True; |
| 352 |
| 353 return True; |
| 354 } |
| 355 |
| 356 Bool VA_NVCTRLGetClientDriverName( Display *dpy, int screen, |
| 357 int *ddxDriverMajorVersion, int *ddxDriverMinorVersion, |
| 358 int *ddxDriverPatchVersion, char **clientDriverName ) |
| 359 { |
| 360 if (ddxDriverMajorVersion) |
| 361 *ddxDriverMajorVersion = 0; |
| 362 if (ddxDriverMinorVersion) |
| 363 *ddxDriverMinorVersion = 0; |
| 364 if (ddxDriverPatchVersion) |
| 365 *ddxDriverPatchVersion = 0; |
| 366 if (clientDriverName) |
| 367 *clientDriverName = NULL; |
| 368 |
| 369 char *nvidia_driver_version = NULL; |
| 370 if (!XNVCTRLQueryStringAttribute(dpy, screen, 0, NV_CTRL_STRING_NVIDIA_DRIVE
R_VERSION, &nvidia_driver_version)) |
| 371 return False; |
| 372 |
| 373 char *end, *str = nvidia_driver_version; |
| 374 unsigned long v = strtoul(str, &end, 10); |
| 375 if (end && end != str) { |
| 376 if (ddxDriverMajorVersion) |
| 377 *ddxDriverMajorVersion = v; |
| 378 if (*(str = end) == '.') { |
| 379 v = strtoul(str + 1, &end, 10); |
| 380 if (end && end != str && (*end == '.' || *end == '\0')) { |
| 381 if (ddxDriverMinorVersion) |
| 382 *ddxDriverMinorVersion = v; |
| 383 if (*(str = end) == '.') { |
| 384 v = strtoul(str + 1, &end, 10); |
| 385 if (end && end != str && *end == '\0') { |
| 386 if (ddxDriverPatchVersion) |
| 387 *ddxDriverPatchVersion = v; |
| 388 } |
| 389 } |
| 390 } |
| 391 } |
| 392 } |
| 393 Xfree(nvidia_driver_version); |
| 394 |
| 395 if (clientDriverName) |
| 396 *clientDriverName = strdup("nvidia"); |
| 397 |
| 398 return True; |
| 399 } |
OLD | NEW |