1 /* 2 * Copyright (C) 2010 Splitted-Desktop Systems. All Rights Reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the 6 * "Software"), to deal in the Software without restriction, including 7 * without limitation the rights to use, copy, modify, merge, publish, 8 * distribute, sub license, and/or sell copies of the Software, and to 9 * permit persons to whom the Software is furnished to do so, subject to 10 * the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the 13 * next paragraph) shall be included in all copies or substantial portions 14 * of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 19 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <dlfcn.h> 29 #include <X11/Xlib.h> 30 31 #define ADL_OK 0 32 #define ADL_MAX_PATH 256 33 34 /* 35 * Based on public AMD Display Library (ADL) SDK: 36 * <http://developer.amd.com/gpu/adlsdk/Pages/default.aspx> 37 */ 38 typedef struct AdapterInfo { 39 int iSize; 40 int iAdapterIndex; 41 char strUDID[ADL_MAX_PATH]; 42 int iBusNumber; 43 int iDeviceNumber; 44 int iFunctionNumber; 45 int iVendorID; 46 char strAdapterName[ADL_MAX_PATH]; 47 char strDisplayName[ADL_MAX_PATH]; 48 int iPresent; 49 int iXScreenNum; 50 int iDrvIndex; 51 char strXScreenConfigName[ADL_MAX_PATH]; 52 } AdapterInfo, *LPAdapterInfo; 53 54 typedef struct XScreenInfo { 55 int iXScreenNum; 56 char strXScreenConfigName[ADL_MAX_PATH]; 57 } XScreenInfo, *LPXScreenInfo; 58 59 typedef void *(*ADL_MAIN_MALLOC_CALLBACK)(int); 60 typedef int (*ADL_MAIN_CONTROL_CREATE)(ADL_MAIN_MALLOC_CALLBACK, int); 61 typedef int (*ADL_MAIN_CONTROL_DESTROY)(void); 62 typedef int (*ADL_ADAPTER_NUMBEROFADAPTERS_GET)(int *); 63 typedef int (*ADL_ADAPTER_ADAPTERINFO_GET)(LPAdapterInfo, int); 64 typedef int (*ADL_ADAPTER_XSCREENINFO_GET)(LPXScreenInfo, int); 65 66 static void *ADL_Main_Memory_Alloc(int iSize) 67 { 68 return malloc(iSize); 69 } 70 71 static void ADL_Main_Memory_Free(void *arg) 72 { 73 void ** const lpBuffer = arg; 74 75 if (lpBuffer && *lpBuffer) { 76 free(*lpBuffer); 77 *lpBuffer = NULL; 78 } 79 } 80 81 static int get_display_name_length(const char *name) 82 { 83 const char *m; 84 85 if (!name) 86 return 0; 87 88 /* Strip out screen number */ 89 m = strchr(name, ':'); 90 if (m) { 91 m = strchr(m, '.'); 92 if (m) 93 return m - name; 94 } 95 return strlen(name); 96 } 97 98 static int match_display_name(Display *x11_dpy, const char *display_name) 99 { 100 Display *test_dpy; 101 char *test_dpy_name, *x11_dpy_name; 102 int test_dpy_namelen, x11_dpy_namelen; 103 int m; 104 105 test_dpy = XOpenDisplay(display_name); 106 if (!test_dpy) 107 return 0; 108 109 test_dpy_name = XDisplayString(test_dpy); 110 test_dpy_namelen = get_display_name_length(test_dpy_name); 111 x11_dpy_name = XDisplayString(x11_dpy); 112 x11_dpy_namelen = get_display_name_length(x11_dpy_name); 113 114 m = (test_dpy_namelen == x11_dpy_namelen && 115 (test_dpy_namelen == 0 || 116 (test_dpy_namelen > 0 && 117 strncmp(test_dpy_name, x11_dpy_name, test_dpy_namelen) == 0))); 118 119 XCloseDisplay(test_dpy); 120 return m; 121 } 122 123 Bool VA_FGLRXGetClientDriverName( Display *dpy, int screen, 124 int *ddxDriverMajorVersion, int *ddxDriverMinorVersion, 125 int *ddxDriverPatchVersion, char **clientDriverName ) 126 { 127 ADL_MAIN_CONTROL_CREATE ADL_Main_Control_Create; 128 ADL_MAIN_CONTROL_DESTROY ADL_Main_Control_Destroy; 129 ADL_ADAPTER_NUMBEROFADAPTERS_GET ADL_Adapter_NumberOfAdapters_Get; 130 ADL_ADAPTER_ADAPTERINFO_GET ADL_Adapter_AdapterInfo_Get; 131 ADL_ADAPTER_XSCREENINFO_GET ADL_Adapter_XScreenInfo_Get; 132 133 LPAdapterInfo lpAdapterInfo = NULL; 134 LPXScreenInfo lpXScreenInfo = NULL; 135 void *libadl_handle = NULL; 136 Bool success = False; 137 int is_adl_initialized = 0; 138 int i, num_adapters, lpAdapterInfo_size, lpXScreenInfo_size; 139 140 if (ddxDriverMajorVersion) 141 *ddxDriverMajorVersion = 0; 142 if (ddxDriverMinorVersion) 143 *ddxDriverMinorVersion = 0; 144 if (ddxDriverPatchVersion) 145 *ddxDriverPatchVersion = 0; 146 if (clientDriverName) 147 *clientDriverName = NULL; 148 149 libadl_handle = dlopen("libatiadlxx.so", RTLD_LAZY|RTLD_GLOBAL); 150 if (!libadl_handle) 151 goto end; 152 153 dlerror(); 154 ADL_Main_Control_Create = (ADL_MAIN_CONTROL_CREATE) 155 dlsym(libadl_handle,"ADL_Main_Control_Create"); 156 if (dlerror() || !ADL_Main_Control_Create) 157 goto end; 158 159 ADL_Main_Control_Destroy = (ADL_MAIN_CONTROL_DESTROY) 160 dlsym(libadl_handle,"ADL_Main_Control_Destroy"); 161 if (dlerror() || !ADL_Main_Control_Destroy) 162 goto end; 163 164 ADL_Adapter_NumberOfAdapters_Get = (ADL_ADAPTER_NUMBEROFADAPTERS_GET) 165 dlsym(libadl_handle,"ADL_Adapter_NumberOfAdapters_Get"); 166 if (dlerror() || !ADL_Adapter_NumberOfAdapters_Get) 167 goto end; 168 169 ADL_Adapter_AdapterInfo_Get = (ADL_ADAPTER_ADAPTERINFO_GET) 170 dlsym(libadl_handle,"ADL_Adapter_AdapterInfo_Get"); 171 if (dlerror() || !ADL_Adapter_AdapterInfo_Get) 172 goto end; 173 174 ADL_Adapter_XScreenInfo_Get = (ADL_ADAPTER_XSCREENINFO_GET) 175 dlsym(libadl_handle,"ADL_Adapter_XScreenInfo_Get"); 176 if (dlerror() || !ADL_Adapter_XScreenInfo_Get) 177 goto end; 178 179 if (ADL_Main_Control_Create(ADL_Main_Memory_Alloc, 1) != ADL_OK) 180 goto end; 181 is_adl_initialized = 1; 182 183 if (ADL_Adapter_NumberOfAdapters_Get(&num_adapters) != ADL_OK) 184 goto end; 185 if (num_adapters <= 0) 186 goto end; 187 188 lpAdapterInfo_size = num_adapters * sizeof(*lpAdapterInfo); 189 lpAdapterInfo = ADL_Main_Memory_Alloc(lpAdapterInfo_size); 190 if (!lpAdapterInfo) 191 goto end; 192 memset(lpAdapterInfo, 0, lpAdapterInfo_size); 193 194 for (i = 0; i < num_adapters; i++) 195 lpAdapterInfo[i].iSize = sizeof(lpAdapterInfo[i]); 196 197 lpXScreenInfo_size = num_adapters * sizeof(*lpXScreenInfo); 198 lpXScreenInfo = ADL_Main_Memory_Alloc(lpXScreenInfo_size); 199 if (!lpXScreenInfo) 200 goto end; 201 memset(lpXScreenInfo, 0, lpXScreenInfo_size); 202 203 if (ADL_Adapter_AdapterInfo_Get(lpAdapterInfo, lpAdapterInfo_size) != ADL_OK) 204 goto end; 205 206 if (ADL_Adapter_XScreenInfo_Get(lpXScreenInfo, lpXScreenInfo_size) != ADL_OK) 207 goto end; 208 209 for (i = 0; i < num_adapters; i++) { 210 LPXScreenInfo const lpCurrXScreenInfo = &lpXScreenInfo[i]; 211 LPAdapterInfo const lpCurrAdapterInfo = &lpAdapterInfo[i]; 212 if (!lpCurrAdapterInfo->iPresent) 213 continue; 214 #if 0 215 printf("Adapter %d:\n", i); 216 printf(" iAdapterIndex: %d\n", lpCurrAdapterInfo->iAdapterIndex); 217 printf(" strUDID: '%s'\n", lpCurrAdapterInfo->strUDID); 218 printf(" iBusNumber: %d\n", lpCurrAdapterInfo->iBusNumber); 219 printf(" iDeviceNumber: %d\n", lpCurrAdapterInfo->iDeviceNumber); 220 printf(" iFunctionNumber: %d\n", lpCurrAdapterInfo->iFunctionNumber); 221 printf(" iVendorID: 0x%04x\n", lpCurrAdapterInfo->iVendorID); 222 printf(" strAdapterName: '%s'\n", lpCurrAdapterInfo->strAdapterName); 223 printf(" strDisplayName: '%s'\n", lpCurrAdapterInfo->strDisplayName); 224 printf(" iPresent: %d\n", lpCurrAdapterInfo->iPresent); 225 printf(" iXScreenNum: %d\n", lpCurrXScreenInfo->iXScreenNum); 226 #endif 227 if (screen == lpCurrXScreenInfo->iXScreenNum && 228 match_display_name(dpy, lpCurrAdapterInfo->strDisplayName)) { 229 if (clientDriverName) 230 *clientDriverName = strdup("fglrx"); 231 success = True; 232 break; 233 } 234 } 235 236 end: 237 if (lpXScreenInfo) 238 ADL_Main_Memory_Free(&lpXScreenInfo); 239 if (lpAdapterInfo) 240 ADL_Main_Memory_Free(&lpAdapterInfo); 241 if (is_adl_initialized) 242 ADL_Main_Control_Destroy(); 243 if (libadl_handle) 244 dlclose(libadl_handle); 245 return success; 246 } 247