Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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