Changeset 92370 in vbox for trunk/src/VBox/Additions/x11/VBoxClient/display-drm.cpp
- Timestamp:
- Nov 11, 2021 2:07:41 PM (3 years ago)
- svn:sync-xref-src-repo-rev:
- 148224
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/x11/VBoxClient/display-drm.cpp
r92215 r92370 50 50 #include <unistd.h> 51 51 #include <stdio.h> 52 53 54 /** Maximum number of supported screens. DRM and X11 both limit this to 32. */ 55 /** @todo if this ever changes, dynamically allocate resizeable arrays in the 56 * context structure. */ 57 #define VMW_MAX_HEADS 32 58 59 /* VMWare kernel driver control parts definitions. */ 52 #include <limits.h> 60 53 61 54 #ifdef RT_OS_LINUX … … 65 58 #endif 66 59 60 /** Ioctl command to query vmwgfx version information. */ 61 #define DRM_IOCTL_VERSION _IOWR('d', 0x00, struct DRMVERSION) 62 /** Ioctl command to set new screen layout. */ 63 #define DRM_IOCTL_VMW_UPDATE_LAYOUT _IOW('d', 0x40 + 20, struct DRMVMWUPDATELAYOUT) 64 /** A driver name which identifies VMWare driver. */ 67 65 #define DRM_DRIVER_NAME "vmwgfx" 68 69 /** Counter of how often our daemon has been respawned. */ 70 unsigned g_cRespawn = 0; 71 /** Logging verbosity level. */ 72 unsigned g_cVerbosity = 0; 66 /** VMWare driver compatible version number. On previous versions resizing does not seem work. */ 67 #define DRM_DRIVER_VERSION_MAJOR_MIN (2) 68 #define DRM_DRIVER_VERSION_MINOR_MIN (10) 69 70 /** VMWare char device driver minor numbers range. */ 71 #define VMW_CONTROL_DEVICE_MINOR_START (64) 72 #define VMW_RENDER_DEVICE_MINOR_START (128) 73 #define VMW_RENDER_DEVICE_MINOR_END (192) 74 75 /** Maximum number of supported screens. DRM and X11 both limit this to 32. */ 76 /** @todo if this ever changes, dynamically allocate resizeable arrays in the 77 * context structure. */ 78 #define VMW_MAX_HEADS (32) 73 79 74 80 /** DRM version structure. */ … … 90 96 struct DRMVMWRECT 91 97 { 92 93 94 95 98 int32_t x; 99 int32_t y; 100 uint32_t w; 101 uint32_t h; 96 102 }; 97 103 AssertCompileSize(struct DRMVMWRECT, 16); 98 104 99 #define DRM_IOCTL_VERSION _IOWR('d', 0x00, struct DRMVERSION)100 101 struct DRMCONTEXT102 {103 RTFILE hDevice;104 };105 106 static void drmConnect(struct DRMCONTEXT *pContext)107 {108 unsigned i;109 RTFILE hDevice;110 111 if (pContext->hDevice != NIL_RTFILE)112 VBClLogFatalError("%s called with bad argument\n", __func__);113 /* Try to open the SVGA DRM device. */114 for (i = 0; i < 128; ++i)115 {116 char szPath[64];117 struct DRMVERSION version;118 char szName[sizeof(DRM_DRIVER_NAME)];119 int rc;120 121 /* Control devices for drm graphics driver control devices go from122 * controlD64 to controlD127. Render node devices go from renderD128123 * to renderD192. The driver takes resize hints via the control device124 * on pre-4.10 kernels and on the render device on newer ones. Try125 * both types. */126 if (i % 2 == 0)127 rc = RTStrPrintf(szPath, sizeof(szPath), "/dev/dri/renderD%u", i / 2 + 128);128 else129 rc = RTStrPrintf(szPath, sizeof(szPath), "/dev/dri/controlD%u", i / 2 + 64);130 if (RT_FAILURE(rc))131 VBClLogFatalError("RTStrPrintf of device path failed, rc=%Rrc\n", rc);132 rc = RTFileOpen(&hDevice, szPath, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);133 if (RT_FAILURE(rc))134 continue;135 RT_ZERO(version);136 version.cbName = sizeof(szName);137 version.pszName = szName;138 rc = RTFileIoCtl(hDevice, DRM_IOCTL_VERSION, &version, sizeof(version), NULL);139 if ( RT_SUCCESS(rc)140 && !strncmp(szName, DRM_DRIVER_NAME, sizeof(DRM_DRIVER_NAME) - 1)141 && ( version.cMajor > 2142 || (version.cMajor == 2 && version.cMinor > 9)))143 break;144 hDevice = NIL_RTFILE;145 }146 pContext->hDevice = hDevice;147 }148 149 105 /** Preferred screen layout information for DRM_VMW_UPDATE_LAYOUT IoCtl. The 150 106 * rects argument is a cast pointer to an array of drm_vmw_rect. */ 151 struct DRMVMWUPDATELAYOUT { 152 uint32_t cOutputs; 153 uint32_t u32Pad; 154 uint64_t ptrRects; 107 struct DRMVMWUPDATELAYOUT 108 { 109 uint32_t cOutputs; 110 uint32_t u32Pad; 111 uint64_t ptrRects; 155 112 }; 156 113 AssertCompileSize(struct DRMVMWUPDATELAYOUT, 16); 157 114 158 #define DRM_IOCTL_VMW_UPDATE_LAYOUT \ 159 _IOW('d', 0x40 + 20, struct DRMVMWUPDATELAYOUT) 160 161 static void drmSendHints(struct DRMCONTEXT *pContext, struct DRMVMWRECT *paRects, 162 unsigned cHeads) 115 /** These two parameters are mostly unused. Defined here in order to satisfy linking requirements. */ 116 unsigned g_cRespawn = 0; 117 unsigned g_cVerbosity = 0; 118 119 /** 120 * Attempts to open DRM device by given path and check if it is 121 * compatible for screen resize. 122 * 123 * @return DRM device handle on success or NIL_RTFILE otherwise. 124 * @param szPathPattern Path name pattern to the DRM device. 125 * @param uInstance Driver / device instance. 126 */ 127 static RTFILE drmTryDevice(const char *szPathPattern, uint8_t uInstance) 128 { 129 int rc = VERR_NOT_FOUND; 130 char szPath[PATH_MAX]; 131 struct DRMVERSION vmwgfxVersion; 132 RTFILE hDevice = NIL_RTFILE; 133 134 RT_ZERO(szPath); 135 RT_ZERO(vmwgfxVersion); 136 137 rc = RTStrPrintf(szPath, sizeof(szPath), szPathPattern, uInstance); 138 if (RT_SUCCESS(rc)) 139 { 140 rc = RTFileOpen(&hDevice, szPath, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); 141 if (RT_SUCCESS(rc)) 142 { 143 char szVmwgfxDriverName[sizeof(DRM_DRIVER_NAME)]; 144 RT_ZERO(szVmwgfxDriverName); 145 146 vmwgfxVersion.cbName = sizeof(szVmwgfxDriverName); 147 vmwgfxVersion.pszName = szVmwgfxDriverName; 148 149 /* Query driver version information and check if it can be used for screen resizing. */ 150 rc = RTFileIoCtl(hDevice, DRM_IOCTL_VERSION, &vmwgfxVersion, sizeof(vmwgfxVersion), NULL); 151 if ( RT_SUCCESS(rc) 152 && strncmp(szVmwgfxDriverName, DRM_DRIVER_NAME, sizeof(DRM_DRIVER_NAME) - 1) == 0 153 && ( vmwgfxVersion.cMajor >= DRM_DRIVER_VERSION_MAJOR_MIN 154 || ( vmwgfxVersion.cMajor == DRM_DRIVER_VERSION_MAJOR_MIN 155 && vmwgfxVersion.cMinor >= DRM_DRIVER_VERSION_MINOR_MIN))) 156 { 157 VBClLogInfo("VBoxDRMClient: found compatible device: %s\n", szPath); 158 } 159 else 160 { 161 RTFileClose(hDevice); 162 hDevice = NIL_RTFILE; 163 rc = VERR_NOT_FOUND; 164 } 165 } 166 } 167 else 168 { 169 VBClLogError("VBoxDRMClient: unable to construct path to DRM device: %Rrc\n", rc); 170 } 171 172 return RT_SUCCESS(rc) ? hDevice : NIL_RTFILE; 173 } 174 175 /** 176 * Attempts to find and open DRM device to be used for screen resize. 177 * 178 * @return DRM device handle on success or NIL_RTFILE otherwise. 179 */ 180 static RTFILE drmOpenVmwgfx(void) 181 { 182 /* Control devices for drm graphics driver control devices go from 183 * controlD64 to controlD127. Render node devices go from renderD128 184 * to renderD192. The driver takes resize hints via the control device 185 * on pre-4.10 (???) kernels and on the render device on newer ones. 186 * At first, try to find control device and render one if not found. 187 */ 188 uint8_t i; 189 RTFILE hDevice = NIL_RTFILE; 190 191 /* Lookup control device. */ 192 for (i = VMW_CONTROL_DEVICE_MINOR_START; i < VMW_RENDER_DEVICE_MINOR_START; i++) 193 { 194 hDevice = drmTryDevice("/dev/dri/controlD%u", i); 195 if (hDevice != NIL_RTFILE) 196 return hDevice; 197 } 198 199 /* Lookup render device. */ 200 for (i = VMW_RENDER_DEVICE_MINOR_START; i <= VMW_RENDER_DEVICE_MINOR_END; i++) 201 { 202 hDevice = drmTryDevice("/dev/dri/renderD%u", i); 203 if (hDevice != NIL_RTFILE) 204 return hDevice; 205 } 206 207 VBClLogError("VBoxDRMClient: unable to find DRM device\n"); 208 209 return hDevice; 210 } 211 212 static void drmSendHints(RTFILE hDevice, struct DRMVMWRECT *paRects, unsigned cHeads) 163 213 { 164 214 uid_t curuid = getuid(); … … 168 218 struct DRMVMWUPDATELAYOUT ioctlLayout; 169 219 170 if (pContext->hDevice == NIL_RTFILE)171 VBClLogFatalError("%s bad device argument\n", __func__);172 220 ioctlLayout.cOutputs = cHeads; 173 221 ioctlLayout.ptrRects = (uint64_t)paRects; 174 rc = RTFileIoCtl( pContext->hDevice, DRM_IOCTL_VMW_UPDATE_LAYOUT,222 rc = RTFileIoCtl(hDevice, DRM_IOCTL_VMW_UPDATE_LAYOUT, 175 223 &ioctlLayout, sizeof(ioctlLayout), NULL); 176 224 if (RT_FAILURE(rc) && rc != VERR_INVALID_PARAMETER) … … 182 230 int main(int argc, char *argv[]) 183 231 { 184 int rc = RTR3InitExe(argc, &argv, 0); 185 if (RT_FAILURE(rc)) 186 return RTMsgInitFailure(rc); 187 rc = VbglR3InitUser(); 188 if (RT_FAILURE(rc)) 189 VBClLogFatalError("VbglR3InitUser failed: %Rrc", rc); 190 191 struct DRMCONTEXT drmContext = { NIL_RTFILE }; 232 RTFILE hDevice = NIL_RTFILE; 192 233 static struct VMMDevDisplayDef aMonitors[VMW_MAX_HEADS]; 193 194 234 unsigned cEnabledMonitors; 195 235 /* Do not acknowledge the first event we query for to pick up old events, … … 201 241 RTFILE hPidFile; 202 242 243 int rc = RTR3InitExe(argc, &argv, 0); 244 if (RT_FAILURE(rc)) 245 return RTMsgInitFailure(rc); 246 247 rc = VbglR3InitUser(); 248 if (RT_FAILURE(rc)) 249 VBClLogFatalError("VbglR3InitUser failed: %Rrc", rc); 250 203 251 /* Check PID file before attempting to initialize anything. */ 204 252 rc = VbglR3PidFile(szPidFile, &hPidFile); … … 214 262 } 215 263 216 drmConnect(&drmContext);217 if ( drmContext.hDevice == NIL_RTFILE)264 hDevice = drmOpenVmwgfx(); 265 if (hDevice == NIL_RTFILE) 218 266 return VERR_OPEN_FAILED; 267 219 268 rc = VbglR3CtlFilterMask(VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST, 0); 220 269 if (RT_FAILURE(rc)) … … 288 337 printf("Monitor %u: %dx%d, (%d, %d)\n", i, (int)aEnabledMonitors[i].w, (int)aEnabledMonitors[i].h, 289 338 (int)aEnabledMonitors[i].x, (int)aEnabledMonitors[i].y); 290 drmSendHints( &drmContext, aEnabledMonitors, cEnabledMonitors);339 drmSendHints(hDevice, aEnabledMonitors, cEnabledMonitors); 291 340 } 292 341 do … … 300 349 /** @todo this code never executed since we do not have yet a clean way to exit 301 350 * main event loop above. */ 351 352 RTFileClose(hDevice); 353 302 354 VBClLogInfo("VBoxDRMClient: releasing PID file lock\n"); 303 355 VbglR3ClosePidFile(szPidFile, hPidFile);
Note:
See TracChangeset
for help on using the changeset viewer.