Changeset 35843 in vbox
- Timestamp:
- Feb 3, 2011 4:25:37 PM (14 years ago)
- Location:
- trunk/src/VBox/Additions/x11/vboxvideo
- Files:
-
- 2 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/x11/vboxvideo/Makefile.kmk
r35840 r35843 72 72 vboxvideo_drv_INCS += $(PATH_ROOT)/src/VBox/Runtime/include 73 73 vboxvideo_drv_SOURCES = \ 74 pointer.c \ 74 75 vboxutils.c \ 75 76 vboxvideo.c \ -
trunk/src/VBox/Additions/x11/vboxvideo/pointer.c
r35775 r35843 172 172 } 173 173 174 /**175 * Callback function called by the X server to tell us about dirty176 * rectangles in the video buffer.177 *178 * @param pScreen pointer to the information structure for the current179 * screen180 * @param iRects Number of dirty rectangles to update181 * @param aRects Array of structures containing the coordinates of the182 * rectangles183 */184 static void185 vboxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects)186 {187 VBVACMDHDR cmdHdr;188 VBOXPtr pVBox;189 int i;190 unsigned j;191 192 pVBox = pScrn->driverPrivate;193 if (pVBox->fHaveHGSMI == FALSE || pVBox->vtSwitch)194 return;195 196 for (i = 0; i < iRects; ++i)197 for (j = 0; j < pVBox->cScreens; ++j)198 {199 /* Just continue quietly if VBVA is not currently active. */200 struct VBVABUFFER *pVBVA = pVBox->aVbvaCtx[j].pVBVA;201 if ( !pVBVA202 || !(pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_ENABLED))203 continue;204 if ( aRects[i].x1 > pVBox->aScreenLocation[j].x205 + pVBox->aScreenLocation[j].cx206 || aRects[i].y1 > pVBox->aScreenLocation[j].y207 + pVBox->aScreenLocation[j].cy208 || aRects[i].x2 < pVBox->aScreenLocation[j].x209 || aRects[i].y2 < pVBox->aScreenLocation[j].y)210 continue;211 cmdHdr.x = (int16_t)aRects[i].x1;212 cmdHdr.y = (int16_t)aRects[i].y1;213 cmdHdr.w = (uint16_t)(aRects[i].x2 - aRects[i].x1);214 cmdHdr.h = (uint16_t)(aRects[i].y2 - aRects[i].y1);215 216 #if 0217 TRACE_LOG("display=%u, x=%d, y=%d, w=%d, h=%d\n",218 j, cmdHdr.x, cmdHdr.y, cmdHdr.w, cmdHdr.h);219 #endif220 221 if (VBoxVBVABufferBeginUpdate(&pVBox->aVbvaCtx[j],222 &pVBox->guestCtx))223 {224 VBoxVBVAWrite(&pVBox->aVbvaCtx[j], &pVBox->guestCtx, &cmdHdr,225 sizeof(cmdHdr));226 VBoxVBVABufferEndUpdate(&pVBox->aVbvaCtx[j]);227 }228 }229 }230 231 /** Callback to fill in the view structures */232 static int233 vboxFillViewInfo(void *pvVBox, struct VBVAINFOVIEW *pViews, uint32_t cViews)234 {235 VBOXPtr pVBox = (VBOXPtr)pvVBox;236 unsigned i;237 for (i = 0; i < cViews; ++i)238 {239 pViews[i].u32ViewIndex = i;240 pViews[i].u32ViewOffset = 0;241 pViews[i].u32ViewSize = pVBox->cbView;242 pViews[i].u32MaxScreenSize = pVBox->cbFBMax;243 }244 return VINF_SUCCESS;245 }246 247 /**248 * Initialise VirtualBox's accelerated video extensions.249 *250 * @returns TRUE on success, FALSE on failure251 */252 static Bool253 vboxInitVbva(int scrnIndex, ScreenPtr pScreen, VBOXPtr pVBox)254 {255 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];256 int rc = VINF_SUCCESS;257 258 pVBox->cScreens = 1;259 if (!VBoxHGSMIIsSupported())260 {261 xf86DrvMsg(scrnIndex, X_ERROR, "The graphics device does not seem to support HGSMI. Disableing video acceleration.\n");262 return FALSE;263 }264 265 /* Set up the dirty rectangle handler. It will be added into a function266 * chain and gets removed when the screen is cleaned up. */267 if (ShadowFBInit2(pScreen, NULL, vboxHandleDirtyRect) != TRUE)268 {269 xf86DrvMsg(scrnIndex, X_ERROR,270 "Unable to install dirty rectangle handler for VirtualBox graphics acceleration.\n");271 return FALSE;272 }273 return TRUE;274 }275 276 /**277 * Initialise VirtualBox's accelerated video extensions.278 *279 * @returns TRUE on success, FALSE on failure280 */281 static Bool282 vboxSetupVRAMVbva(ScrnInfoPtr pScrn, VBOXPtr pVBox)283 {284 int rc = VINF_SUCCESS;285 unsigned i;286 uint32_t offVRAMBaseMapping, offGuestHeapMemory, cbGuestHeapMemory;287 void *pvGuestHeapMemory;288 289 if (!pVBox->fHaveHGSMI)290 return FALSE;291 VBoxHGSMIGetBaseMappingInfo(pScrn->videoRam * 1024, &offVRAMBaseMapping,292 NULL, &offGuestHeapMemory, &cbGuestHeapMemory,293 NULL);294 pvGuestHeapMemory = ((uint8_t *)pVBox->base) + offVRAMBaseMapping295 + offGuestHeapMemory;296 TRACE_LOG("video RAM: %u KB, guest heap offset: 0x%x, cbGuestHeapMemory: %u\n",297 pScrn->videoRam, offVRAMBaseMapping + offGuestHeapMemory,298 cbGuestHeapMemory);299 rc = VBoxHGSMISetupGuestContext(&pVBox->guestCtx, pvGuestHeapMemory,300 cbGuestHeapMemory,301 offVRAMBaseMapping + offGuestHeapMemory);302 if (RT_FAILURE(rc))303 {304 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set up the guest-to-host communication context, rc=%d\n", rc);305 return FALSE;306 }307 pVBox->cbView = pVBox->cbFBMax = offVRAMBaseMapping;308 pVBox->cScreens = VBoxHGSMIGetMonitorCount(&pVBox->guestCtx);309 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested monitor count: %u\n",310 pVBox->cScreens);311 for (i = 0; i < pVBox->cScreens; ++i)312 {313 pVBox->cbFBMax -= VBVA_MIN_BUFFER_SIZE;314 pVBox->aoffVBVABuffer[i] = pVBox->cbFBMax;315 TRACE_LOG("VBVA buffer offset for screen %u: 0x%lx\n", i,316 (unsigned long) pVBox->cbFBMax);317 VBoxVBVASetupBufferContext(&pVBox->aVbvaCtx[i],318 pVBox->aoffVBVABuffer[i],319 VBVA_MIN_BUFFER_SIZE);320 }321 TRACE_LOG("Maximum framebuffer size: %lu (0x%lx)\n",322 (unsigned long) pVBox->cbFBMax,323 (unsigned long) pVBox->cbFBMax);324 rc = VBoxHGSMISendViewInfo(&pVBox->guestCtx, pVBox->cScreens,325 vboxFillViewInfo, (void *)pVBox);326 if (RT_FAILURE(rc))327 {328 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to send the view information to the host, rc=%d\n", rc);329 return FALSE;330 }331 return TRUE;332 }333 334 174 Bool 335 175 vbox_init(int scrnIndex, VBOXPtr pVBox) … … 357 197 | VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR); 358 198 return rc; 359 }360 361 Bool362 vbox_open(ScrnInfoPtr pScrn, ScreenPtr pScreen, VBOXPtr pVBox)363 {364 TRACE_ENTRY();365 366 pVBox->fHaveHGSMI = vboxInitVbva(pScrn->scrnIndex, pScreen, pVBox);367 return pVBox->fHaveHGSMI;368 }369 370 Bool371 vbox_device_available(VBOXPtr pVBox)372 {373 return pVBox->useDevice;374 199 } 375 200 … … 765 590 return rc; 766 591 } 767 768 /**769 * Inform VBox that we will supply it with dirty rectangle information770 * and install the dirty rectangle handler.771 *772 * @returns TRUE for success, FALSE for failure773 * @param pScrn Pointer to a structure describing the X screen in use774 */775 Bool776 vboxEnableVbva(ScrnInfoPtr pScrn)777 {778 bool rc = TRUE;779 int scrnIndex = pScrn->scrnIndex;780 unsigned i;781 VBOXPtr pVBox = pScrn->driverPrivate;782 783 TRACE_ENTRY();784 if (!vboxSetupVRAMVbva(pScrn, pVBox))785 return FALSE;786 for (i = 0; i < pVBox->cScreens; ++i)787 {788 struct VBVABUFFER *pVBVA;789 790 pVBVA = (struct VBVABUFFER *) ( ((uint8_t *)pVBox->base)791 + pVBox->aoffVBVABuffer[i]);792 if (!VBoxVBVAEnable(&pVBox->aVbvaCtx[i], &pVBox->guestCtx, pVBVA, i))793 rc = FALSE;794 }795 if (!rc)796 {797 /* Request not accepted - disable for old hosts. */798 xf86DrvMsg(scrnIndex, X_ERROR,799 "Failed to enable screen update reporting for at least one virtual monitor.\n");800 vboxDisableVbva(pScrn);801 }802 return rc;803 }804 805 /**806 * Inform VBox that we will stop supplying it with dirty rectangle807 * information. This function is intended to be called when an X808 * virtual terminal is disabled, or the X server is terminated.809 *810 * @returns TRUE for success, FALSE for failure811 * @param pScrn Pointer to a structure describing the X screen in use812 */813 void814 vboxDisableVbva(ScrnInfoPtr pScrn)815 {816 int rc;817 int scrnIndex = pScrn->scrnIndex;818 unsigned i;819 VBOXPtr pVBox = pScrn->driverPrivate;820 821 TRACE_ENTRY();822 if (!pVBox->fHaveHGSMI) /* Ths function should not have been called */823 return;824 for (i = 0; i < pVBox->cScreens; ++i)825 VBoxVBVADisable(&pVBox->aVbvaCtx[i], &pVBox->guestCtx, i);826 }827 828 /**829 * Inform VBox that we are aware of advanced graphics functions830 * (i.e. dynamic resizing, seamless).831 *832 * @returns TRUE for success, FALSE for failure833 */834 Bool835 vboxEnableGraphicsCap(VBOXPtr pVBox)836 {837 TRACE_ENTRY();838 if (!pVBox->useDevice)839 return FALSE;840 return RT_SUCCESS(VbglR3SetGuestCaps(VMMDEV_GUEST_SUPPORTS_GRAPHICS, 0));841 }842 843 /**844 * Inform VBox that we are no longer aware of advanced graphics functions845 * (i.e. dynamic resizing, seamless).846 *847 * @returns TRUE for success, FALSE for failure848 */849 Bool850 vboxDisableGraphicsCap(VBOXPtr pVBox)851 {852 TRACE_ENTRY();853 if (!pVBox->useDevice)854 return FALSE;855 return RT_SUCCESS(VbglR3SetGuestCaps(0, VMMDEV_GUEST_SUPPORTS_GRAPHICS));856 }857 858 /**859 * Query the last display change request.860 *861 * @returns boolean success indicator.862 * @param pScrn Pointer to the X screen info structure.863 * @param pcx Where to store the horizontal pixel resolution (0 = do not change).864 * @param pcy Where to store the vertical pixel resolution (0 = do not change).865 * @param pcBits Where to store the bits per pixel (0 = do not change).866 * @param iDisplay Where to store the display number the request was for - 0 for the867 * primary display, 1 for the first secondary, etc.868 */869 Bool870 vboxGetDisplayChangeRequest(ScrnInfoPtr pScrn, uint32_t *pcx, uint32_t *pcy,871 uint32_t *pcBits, uint32_t *piDisplay)872 {873 VBOXPtr pVBox = pScrn->driverPrivate;874 TRACE_ENTRY();875 if (!pVBox->useDevice)876 return FALSE;877 int rc = VbglR3GetDisplayChangeRequest(pcx, pcy, pcBits, piDisplay, false);878 if (RT_SUCCESS(rc))879 return TRUE;880 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to obtain the last resolution requested by the guest, rc=%d.\n", rc);881 return FALSE;882 }883 884 885 /**886 * Query the host as to whether it likes a specific video mode.887 *888 * @returns the result of the query889 * @param cx the width of the mode being queried890 * @param cy the height of the mode being queried891 * @param cBits the bpp of the mode being queried892 */893 Bool894 vboxHostLikesVideoMode(ScrnInfoPtr pScrn, uint32_t cx, uint32_t cy, uint32_t cBits)895 {896 VBOXPtr pVBox = pScrn->driverPrivate;897 TRACE_ENTRY();898 if (!pVBox->useDevice)899 return TRUE; /* If we can't ask the host then we like everything. */900 return VbglR3HostLikesVideoMode(cx, cy, cBits);901 }902 903 /**904 * Check if any seamless mode is enabled.905 * Seamless is only relevant for the newer Xorg modules.906 *907 * @returns the result of the query908 * (true = seamless enabled, false = seamless not enabled)909 * @param pScrn Screen info pointer.910 */911 Bool912 vboxGuestIsSeamless(ScrnInfoPtr pScrn)913 {914 VMMDevSeamlessMode mode;915 VBOXPtr pVBox = pScrn->driverPrivate;916 TRACE_ENTRY();917 if (!pVBox->useDevice)918 return FALSE;919 if (RT_FAILURE(VbglR3SeamlessGetLastEvent(&mode)))920 return FALSE;921 return (mode != VMMDev_Seamless_Disabled);922 }923 924 /**925 * Save video mode parameters to the registry.926 *927 * @returns iprt status value928 * @param pszName the name to save the mode parameters under929 * @param cx mode width930 * @param cy mode height931 * @param cBits bits per pixel for the mode932 */933 Bool934 vboxSaveVideoMode(ScrnInfoPtr pScrn, uint32_t cx, uint32_t cy, uint32_t cBits)935 {936 VBOXPtr pVBox = pScrn->driverPrivate;937 TRACE_ENTRY();938 if (!pVBox->useDevice)939 return FALSE;940 return RT_SUCCESS(VbglR3SaveVideoMode("SavedMode", cx, cy, cBits));941 }942 943 /**944 * Retrieve video mode parameters from the registry.945 *946 * @returns iprt status value947 * @param pszName the name under which the mode parameters are saved948 * @param pcx where to store the mode width949 * @param pcy where to store the mode height950 * @param pcBits where to store the bits per pixel for the mode951 */952 Bool953 vboxRetrieveVideoMode(ScrnInfoPtr pScrn, uint32_t *pcx, uint32_t *pcy, uint32_t *pcBits)954 {955 VBOXPtr pVBox = pScrn->driverPrivate;956 TRACE_ENTRY();957 if (!pVBox->useDevice)958 return FALSE;959 int rc = VbglR3RetrieveVideoMode("SavedMode", pcx, pcy, pcBits);960 if (RT_SUCCESS(rc))961 TRACE_LOG("Retrieved a video mode of %dx%dx%d\n", *pcx, *pcy, *pcBits);962 else963 TRACE_LOG("Failed to retrieve video mode, error %d\n", rc);964 return (RT_SUCCESS(rc));965 }966 967 /**968 * Fills a display mode M with a built-in mode of name pszName and dimensions969 * cx and cy.970 */971 static void vboxFillDisplayMode(ScrnInfoPtr pScrn, DisplayModePtr m,972 const char *pszName, unsigned cx, unsigned cy)973 {974 VBOXPtr pVBox = pScrn->driverPrivate;975 TRACE_LOG("pszName=%s, cx=%u, cy=%u\n", pszName, cx, cy);976 m->status = MODE_OK;977 m->type = M_T_BUILTIN;978 /* Older versions of VBox only support screen widths which are a multiple979 * of 8 */980 if (pVBox->fAnyX)981 m->HDisplay = cx;982 else983 m->HDisplay = cx & ~7;984 m->HSyncStart = m->HDisplay + 2;985 m->HSyncEnd = m->HDisplay + 4;986 m->HTotal = m->HDisplay + 6;987 m->VDisplay = cy;988 m->VSyncStart = m->VDisplay + 2;989 m->VSyncEnd = m->VDisplay + 4;990 m->VTotal = m->VDisplay + 6;991 m->Clock = m->HTotal * m->VTotal * 60 / 1000; /* kHz */992 if (pszName)993 {994 if (m->name)995 free(m->name);996 m->name = xnfstrdup(pszName);997 }998 }999 1000 /** vboxvideo's list of standard video modes */1001 struct1002 {1003 /** mode width */1004 uint32_t cx;1005 /** mode height */1006 uint32_t cy;1007 } vboxStandardModes[] =1008 {1009 { 1600, 1200 },1010 { 1440, 1050 },1011 { 1280, 960 },1012 { 1024, 768 },1013 { 800, 600 },1014 { 640, 480 },1015 { 0, 0 }1016 };1017 enum1018 {1019 vboxNumStdModes = sizeof(vboxStandardModes) / sizeof(vboxStandardModes[0])1020 };1021 1022 /**1023 * Returns a standard mode which the host likes. Can be called multiple1024 * times with the index returned by the previous call to get a list of modes.1025 * @returns the index of the mode in the list, or 0 if no more modes are1026 * available1027 * @param pScrn the screen information structure1028 * @param pScrn->bitsPerPixel1029 * if this is non-null, only modes with this BPP will be1030 * returned1031 * @param cIndex the index of the last mode queried, or 0 to query the1032 * first mode available. Note: the first index is 11033 * @param pcx where to store the mode's width1034 * @param pcy where to store the mode's height1035 * @param pcBits where to store the mode's BPP1036 */1037 unsigned vboxNextStandardMode(ScrnInfoPtr pScrn, unsigned cIndex,1038 uint32_t *pcx, uint32_t *pcy,1039 uint32_t *pcBits)1040 {1041 XF86ASSERT(cIndex < vboxNumStdModes,1042 ("cIndex = %d, vboxNumStdModes = %d\n", cIndex,1043 vboxNumStdModes));1044 for (unsigned i = cIndex; i < vboxNumStdModes - 1; ++i)1045 {1046 uint32_t cBits = pScrn->bitsPerPixel;1047 uint32_t cx = vboxStandardModes[i].cx;1048 uint32_t cy = vboxStandardModes[i].cy;1049 1050 if (cBits != 0 && !vboxHostLikesVideoMode(pScrn, cx, cy, cBits))1051 continue;1052 if (vboxHostLikesVideoMode(pScrn, cx, cy, 32))1053 cBits = 32;1054 else if (vboxHostLikesVideoMode(pScrn, cx, cy, 16))1055 cBits = 16;1056 else1057 continue;1058 if (pcx)1059 *pcx = cx;1060 if (pcy)1061 *pcy = cy;1062 if (pcBits)1063 *pcBits = cBits;1064 return i + 1;1065 }1066 return 0;1067 }1068 1069 /**1070 * Returns the preferred video mode. The current order of preference is1071 * (from highest to least preferred):1072 * - The mode corresponding to the last size hint from the host1073 * - The video mode saved from the last session1074 * - The largest standard mode which the host likes, falling back to1075 * 640x480x32 as a worst case1076 * - If the host can't be contacted at all, we return 1024x768x321077 *1078 * The return type is void as we guarantee we will return some mode.1079 */1080 void vboxGetPreferredMode(ScrnInfoPtr pScrn, uint32_t iScreen, uint32_t *pcx,1081 uint32_t *pcy, uint32_t *pcBits)1082 {1083 /* Query the host for the preferred resolution and colour depth */1084 uint32_t cx = 0, cy = 0, iScreenIn = iScreen, cBits = 32;1085 VBOXPtr pVBox = pScrn->driverPrivate;1086 1087 TRACE_LOG("iScreen=%u\n", iScreen);1088 bool found = false;1089 if ( pVBox->aPreferredSize[iScreen].cx1090 && pVBox->aPreferredSize[iScreen].cy)1091 {1092 cx = pVBox->aPreferredSize[iScreen].cx;1093 cy = pVBox->aPreferredSize[iScreen].cy;1094 found = true;1095 }1096 if (pVBox->useDevice)1097 {1098 if (!found)1099 found = vboxGetDisplayChangeRequest(pScrn, &cx, &cy, &cBits,1100 &iScreenIn);1101 if ((cx == 0) || (cy == 0) || iScreenIn != iScreen)1102 found = false;1103 if (!found)1104 found = vboxRetrieveVideoMode(pScrn, &cx, &cy, &cBits);1105 if ((cx == 0) || (cy == 0))1106 found = false;1107 if (!found)1108 found = (vboxNextStandardMode(pScrn, 0, &cx, &cy, &cBits) != 0);1109 if (!found)1110 {1111 /* Last resort */1112 cx = 640;1113 cy = 480;1114 cBits = 32;1115 }1116 }1117 else1118 {1119 cx = 1024;1120 cy = 768;1121 }1122 if (pcx)1123 *pcx = cx;1124 if (pcy)1125 *pcy = cy;1126 if (pcBits)1127 *pcBits = cBits;1128 TRACE_LOG("cx=%u, cy=%u, cBits=%u\n", cx, cy, cBits);1129 }1130 1131 /* Move a screen mode found to the end of the list, so that RandR will give1132 * it the highest priority when a mode switch is requested. Returns the mode1133 * that was previously before the mode in the list in order to allow the1134 * caller to continue walking the list. */1135 static DisplayModePtr vboxMoveModeToFront(ScrnInfoPtr pScrn,1136 DisplayModePtr pMode)1137 {1138 DisplayModePtr pPrev = pMode->prev;1139 if (pMode != pScrn->modes)1140 {1141 pMode->prev->next = pMode->next;1142 pMode->next->prev = pMode->prev;1143 pMode->next = pScrn->modes;1144 pMode->prev = pScrn->modes->prev;1145 pMode->next->prev = pMode;1146 pMode->prev->next = pMode;1147 pScrn->modes = pMode;1148 }1149 return pPrev;1150 }1151 1152 /**1153 * Rewrites the first dynamic mode found which is not the current screen mode1154 * to contain the host's currently preferred screen size, then moves that1155 * mode to the front of the screen information structure's mode list.1156 * Additionally, if the current mode is not dynamic, the second dynamic mode1157 * will be set to match the current mode and also added to the front. This1158 * ensures that the user can always reset the current size to kick the driver1159 * to update its mode list.1160 */1161 void vboxWriteHostModes(ScrnInfoPtr pScrn, DisplayModePtr pCurrent)1162 {1163 uint32_t cx = 0, cy = 0, iDisplay = 0, cBits = 0;1164 DisplayModePtr pMode;1165 bool found = false;1166 1167 TRACE_ENTRY();1168 vboxGetPreferredMode(pScrn, 0, &cx, &cy, &cBits);1169 #ifdef DEBUG1170 /* Count the number of modes for sanity */1171 unsigned cModes = 1, cMode = 0;1172 DisplayModePtr pCount;1173 for (pCount = pScrn->modes; ; pCount = pCount->next, ++cModes)1174 if (pCount->next == pScrn->modes)1175 break;1176 #endif1177 for (pMode = pScrn->modes; ; pMode = pMode->next)1178 {1179 #ifdef DEBUG1180 XF86ASSERT (cMode++ < cModes, (NULL));1181 #endif1182 if ( pMode != pCurrent1183 && !strcmp(pMode->name, "VBoxDynamicMode"))1184 {1185 if (!found)1186 vboxFillDisplayMode(pScrn, pMode, NULL, cx, cy);1187 else if (pCurrent)1188 vboxFillDisplayMode(pScrn, pMode, NULL, pCurrent->HDisplay,1189 pCurrent->VDisplay);1190 found = true;1191 pMode = vboxMoveModeToFront(pScrn, pMode);1192 }1193 if (pMode->next == pScrn->modes)1194 break;1195 }1196 XF86ASSERT (found,1197 ("vboxvideo: no free dynamic mode found. Exiting.\n"));1198 XF86ASSERT ( (pScrn->modes->HDisplay == (long) cx)1199 || ( (pScrn->modes->HDisplay == pCurrent->HDisplay)1200 && (pScrn->modes->next->HDisplay == (long) cx)),1201 ("pScrn->modes->HDisplay=%u, pScrn->modes->next->HDisplay=%u\n",1202 pScrn->modes->HDisplay, pScrn->modes->next->HDisplay));1203 XF86ASSERT ( (pScrn->modes->VDisplay == (long) cy)1204 || ( (pScrn->modes->VDisplay == pCurrent->VDisplay)1205 && (pScrn->modes->next->VDisplay == (long) cy)),1206 ("pScrn->modes->VDisplay=%u, pScrn->modes->next->VDisplay=%u\n",1207 pScrn->modes->VDisplay, pScrn->modes->next->VDisplay));1208 }1209 1210 /**1211 * Allocates an empty display mode and links it into the doubly linked list of1212 * modes pointed to by pScrn->modes. Returns a pointer to the newly allocated1213 * memory.1214 */1215 static DisplayModePtr vboxAddEmptyScreenMode(ScrnInfoPtr pScrn)1216 {1217 DisplayModePtr pMode = xnfcalloc(sizeof(DisplayModeRec), 1);1218 1219 TRACE_ENTRY();1220 if (!pScrn->modes)1221 {1222 pScrn->modes = pMode;1223 pMode->next = pMode;1224 pMode->prev = pMode;1225 }1226 else1227 {1228 pMode->next = pScrn->modes;1229 pMode->prev = pScrn->modes->prev;1230 pMode->next->prev = pMode;1231 pMode->prev->next = pMode;1232 }1233 return pMode;1234 }1235 1236 /**1237 * Create display mode entries in the screen information structure for each1238 * of the initial graphics modes that we wish to support. This includes:1239 * - An initial mode, of the size requested by the caller1240 * - Two dynamic modes, one of which will be updated to match the last size1241 * hint from the host on each mode switch, but initially also of the1242 * requested size1243 * - Several standard modes, if possible ones that the host likes1244 * - Any modes that the user requested in xorg.conf/XFree86Config1245 */1246 void vboxAddModes(ScrnInfoPtr pScrn, uint32_t cxInit, uint32_t cyInit)1247 {1248 unsigned cx = 0, cy = 0, cIndex = 0;1249 /* For reasons related to the way RandR 1.1 is implemented, we need to1250 * make sure that the initial mode (more precisely, a mode equal to the1251 * initial virtual resolution) is always present in the mode list. RandR1252 * has the assumption build in that there will either be a mode of that1253 * size present at all times, or that the first mode in the list will1254 * always be smaller than the initial virtual resolution. Since our1255 * approach to dynamic resizing isn't quite the way RandR was intended to1256 * be, and breaks the second assumption, we guarantee the first. */1257 DisplayModePtr pMode = vboxAddEmptyScreenMode(pScrn);1258 vboxFillDisplayMode(pScrn, pMode, "VBoxInitialMode", cxInit, cyInit);1259 /* Create our two dynamic modes. */1260 pMode = vboxAddEmptyScreenMode(pScrn);1261 vboxFillDisplayMode(pScrn, pMode, "VBoxDynamicMode", cxInit, cyInit);1262 pMode = vboxAddEmptyScreenMode(pScrn);1263 vboxFillDisplayMode(pScrn, pMode, "VBoxDynamicMode", cxInit, cyInit);1264 /* Add standard modes supported by the host */1265 for ( ; ; )1266 {1267 char szName[256];1268 cIndex = vboxNextStandardMode(pScrn, cIndex, &cx, &cy, NULL);1269 if (cIndex == 0)1270 break;1271 sprintf(szName, "VBox-%ux%u", cx, cy);1272 pMode = vboxAddEmptyScreenMode(pScrn);1273 vboxFillDisplayMode(pScrn, pMode, szName, cx, cy);1274 }1275 /* And finally any modes specified by the user. We assume here that1276 * the mode names reflect the mode sizes. */1277 for (unsigned i = 0; pScrn->display->modes != NULL1278 && pScrn->display->modes[i] != NULL; i++)1279 {1280 if (sscanf(pScrn->display->modes[i], "%ux%u", &cx, &cy) == 2)1281 {1282 pMode = vboxAddEmptyScreenMode(pScrn);1283 vboxFillDisplayMode(pScrn, pMode, pScrn->display->modes[i], cx, cy);1284 }1285 }1286 } -
trunk/src/VBox/Additions/x11/vboxvideo/vboxutils.c
r35775 r35843 27 27 #include <iprt/string.h> 28 28 #include "compiler.h" 29 #include "cursorstr.h"30 29 31 30 #include "vboxvideo.h" 32 33 #define VBOX_MAX_CURSOR_WIDTH 6434 #define VBOX_MAX_CURSOR_HEIGHT 6435 36 /**************************************************************************37 * Debugging functions and macros *38 **************************************************************************/39 40 /* #define DEBUG_POINTER */41 42 #ifdef DEBUG43 # define PUT_PIXEL(c) ErrorF ("%c", c)44 #else /* DEBUG_VIDEO not defined */45 # define PUT_PIXEL(c) do { } while(0)46 #endif /* DEBUG_VIDEO not defined */47 48 /** Macro to printf an error message and return from a function */49 #define RETERROR(scrnIndex, RetVal, ...) \50 do \51 { \52 xf86DrvMsg(scrnIndex, X_ERROR, __VA_ARGS__); \53 return RetVal; \54 } \55 while (0)56 57 /** Structure to pass cursor image data between realise_cursor() and58 * load_cursor_image(). The members match the parameters to59 * @a VBoxHGSMIUpdatePointerShape(). */60 struct vboxCursorImage61 {62 uint32_t fFlags;63 uint32_t cHotX;64 uint32_t cHotY;65 uint32_t cWidth;66 uint32_t cHeight;67 uint8_t *pPixels;68 uint32_t cbLength;69 };70 71 #ifdef DEBUG_POINTER72 static void73 vbox_show_shape(unsigned short w, unsigned short h, CARD32 bg, unsigned char *image)74 {75 size_t x, y;76 unsigned short pitch;77 CARD32 *color;78 unsigned char *mask;79 size_t sizeMask;80 81 image += sizeof(struct vboxCursorImage);82 mask = image;83 pitch = (w + 7) / 8;84 sizeMask = (pitch * h + 3) & ~3;85 color = (CARD32 *)(image + sizeMask);86 87 TRACE_ENTRY();88 for (y = 0; y < h; ++y, mask += pitch, color += w)89 {90 for (x = 0; x < w; ++x)91 {92 if (mask[x / 8] & (1 << (7 - (x % 8))))93 ErrorF (" ");94 else95 {96 CARD32 c = color[x];97 if (c == bg)98 ErrorF("Y");99 else100 ErrorF("X");101 }102 }103 ErrorF("\n");104 }105 }106 #endif107 108 /**************************************************************************109 * Helper functions and macros *110 **************************************************************************/111 112 /* This is called by the X server every time it loads a new cursor to see113 * whether our "cursor hardware" can handle the cursor. This provides us with114 * a mechanism (the only one!) to switch back from a software to a hardware115 * cursor. */116 static Bool117 vbox_host_uses_hwcursor(ScrnInfoPtr pScrn)118 {119 Bool rc = TRUE;120 uint32_t fFeatures = 0;121 VBOXPtr pVBox = pScrn->driverPrivate;122 123 /* We may want to force the use of a software cursor. Currently this is124 * needed if the guest uses a large virtual resolution, as in this case125 * the host and guest tend to disagree about the pointer location. */126 if (pVBox->forceSWCursor)127 rc = FALSE;128 /* Query information about mouse integration from the host. */129 if (rc) {130 int vrc = VbglR3GetMouseStatus(&fFeatures, NULL, NULL);131 if (RT_FAILURE(vrc)) {132 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,133 "Unable to determine whether the virtual machine supports mouse pointer integration - request initialization failed with return code %d\n", vrc);134 rc = FALSE;135 }136 }137 /* If we got the information from the host then make sure the host wants138 * to draw the pointer. */139 if (rc)140 {141 if ( (fFeatures & VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE)142 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5143 /* As of this version (server 1.6) all major Linux releases144 * are known to handle USB tablets correctly. */145 || (fFeatures & VMMDEV_MOUSE_HOST_HAS_ABS_DEV)146 #endif147 )148 /* Assume this will never be unloaded as long as the X session is149 * running. */150 pVBox->guestCanAbsolute = TRUE;151 if ( (fFeatures & VMMDEV_MOUSE_HOST_CANNOT_HWPOINTER)152 || !pVBox->guestCanAbsolute153 || !(fFeatures & VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE)154 )155 rc = FALSE;156 }157 return rc;158 }159 31 160 32 /************************************************************************** 161 33 * Main functions * 162 34 **************************************************************************/ 163 164 void165 vbox_close(ScrnInfoPtr pScrn, VBOXPtr pVBox)166 {167 TRACE_ENTRY();168 169 xf86DestroyCursorInfoRec(pVBox->pCurs);170 pVBox->pCurs = NULL;171 TRACE_EXIT();172 }173 35 174 36 /** … … 333 195 334 196 Bool 335 vbox_init(int scrnIndex, VBOXPtr pVBox)336 {337 Bool rc = TRUE;338 int vrc;339 uint32_t fMouseFeatures = 0;340 341 TRACE_ENTRY();342 vrc = VbglR3Init();343 if (RT_FAILURE(vrc))344 {345 xf86DrvMsg(scrnIndex, X_ERROR,346 "Failed to initialize the VirtualBox device (rc=%d) - make sure that the VirtualBox guest additions are properly installed. If you are not sure, try reinstalling them. The X Window graphics drivers will run in compatibility mode.\n",347 vrc);348 rc = FALSE;349 }350 pVBox->useDevice = rc;351 /* We can't switch to a software cursor at will without help from352 * VBoxClient. So tell that to the host and wait for VBoxClient to353 * change this. */354 vrc = VbglR3GetMouseStatus(&fMouseFeatures, NULL, NULL);355 if (RT_SUCCESS(vrc))356 VbglR3SetMouseStatus( fMouseFeatures357 | VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR);358 return rc;359 }360 361 Bool362 197 vbox_open(ScrnInfoPtr pScrn, ScreenPtr pScreen, VBOXPtr pVBox) 363 198 { … … 372 207 { 373 208 return pVBox->useDevice; 374 }375 376 static void377 vbox_vmm_hide_cursor(ScrnInfoPtr pScrn, VBOXPtr pVBox)378 {379 int rc;380 381 rc = VBoxHGSMIUpdatePointerShape(&pVBox->guestCtx, 0, 0, 0, 0, 0, NULL, 0);382 if (RT_FAILURE(rc))383 {384 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not hide the virtual mouse pointer, VBox error %d.\n", rc);385 /* Play safe, and disable the hardware cursor until the next mode386 * switch, since obviously something happened that we didn't387 * anticipate. */388 pVBox->forceSWCursor = TRUE;389 }390 }391 392 static void393 vbox_vmm_show_cursor(ScrnInfoPtr pScrn, VBOXPtr pVBox)394 {395 int rc;396 397 if (!vbox_host_uses_hwcursor(pScrn))398 return;399 rc = VBoxHGSMIUpdatePointerShape(&pVBox->guestCtx, VBOX_MOUSE_POINTER_VISIBLE,400 0, 0, 0, 0, NULL, 0);401 if (RT_FAILURE(rc)) {402 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not unhide the virtual mouse pointer.\n");403 /* Play safe, and disable the hardware cursor until the next mode404 * switch, since obviously something happened that we didn't405 * anticipate. */406 pVBox->forceSWCursor = TRUE;407 }408 }409 410 static void411 vbox_vmm_load_cursor_image(ScrnInfoPtr pScrn, VBOXPtr pVBox,412 unsigned char *pvImage)413 {414 int rc;415 struct vboxCursorImage *pImage;416 pImage = (struct vboxCursorImage *)pvImage;417 418 #ifdef DEBUG_POINTER419 vbox_show_shape(pImage->cWidth, pImage->cHeight, 0, pvImage);420 #endif421 422 rc = VBoxHGSMIUpdatePointerShape(&pVBox->guestCtx, pImage->fFlags,423 pImage->cHotX, pImage->cHotY, pImage->cWidth, pImage->cHeight,424 pImage->pPixels, pImage->cbLength);425 if (RT_FAILURE(rc)) {426 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to set the virtual mouse pointer image.\n");427 /* Play safe, and disable the hardware cursor until the next mode428 * switch, since obviously something happened that we didn't429 * anticipate. */430 pVBox->forceSWCursor = TRUE;431 }432 }433 434 static void435 vbox_set_cursor_colors(ScrnInfoPtr pScrn, int bg, int fg)436 {437 NOREF(pScrn);438 NOREF(bg);439 NOREF(fg);440 /* ErrorF("vbox_set_cursor_colors NOT IMPLEMENTED\n"); */441 }442 443 444 static void445 vbox_set_cursor_position(ScrnInfoPtr pScrn, int x, int y)446 {447 /* Nothing to do here, as we are telling the guest where the mouse is,448 * not vice versa. */449 NOREF(pScrn);450 NOREF(x);451 NOREF(y);452 }453 454 static void455 vbox_hide_cursor(ScrnInfoPtr pScrn)456 {457 VBOXPtr pVBox = pScrn->driverPrivate;458 459 vbox_vmm_hide_cursor(pScrn, pVBox);460 }461 462 static void463 vbox_show_cursor(ScrnInfoPtr pScrn)464 {465 VBOXPtr pVBox = pScrn->driverPrivate;466 467 vbox_vmm_show_cursor(pScrn, pVBox);468 }469 470 static void471 vbox_load_cursor_image(ScrnInfoPtr pScrn, unsigned char *image)472 {473 VBOXPtr pVBox = pScrn->driverPrivate;474 475 vbox_vmm_load_cursor_image(pScrn, pVBox, image);476 }477 478 static Bool479 vbox_use_hw_cursor(ScreenPtr pScreen, CursorPtr pCurs)480 {481 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];482 return vbox_host_uses_hwcursor(pScrn);483 }484 485 static unsigned char486 color_to_byte(unsigned c)487 {488 return (c >> 8) & 0xff;489 }490 491 static unsigned char *492 vbox_realize_cursor(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)493 {494 VBOXPtr pVBox;495 CursorBitsPtr bitsp;496 unsigned short w, h, x, y;497 unsigned char *c, *p, *pm, *ps, *m;498 size_t sizeRequest, sizeRgba, sizeMask, srcPitch, dstPitch;499 CARD32 fc, bc, *cp;500 int rc, scrnIndex = infoPtr->pScrn->scrnIndex;501 struct vboxCursorImage *pImage;502 503 pVBox = infoPtr->pScrn->driverPrivate;504 bitsp = pCurs->bits;505 w = bitsp->width;506 h = bitsp->height;507 508 if (!w || !h || w > VBOX_MAX_CURSOR_WIDTH || h > VBOX_MAX_CURSOR_HEIGHT)509 RETERROR(scrnIndex, NULL,510 "Error invalid cursor dimensions %dx%d\n", w, h);511 512 if ((bitsp->xhot > w) || (bitsp->yhot > h))513 RETERROR(scrnIndex, NULL,514 "Error invalid cursor hotspot location %dx%d (max %dx%d)\n",515 bitsp->xhot, bitsp->yhot, w, h);516 517 srcPitch = PixmapBytePad (bitsp->width, 1);518 dstPitch = (w + 7) / 8;519 sizeMask = ((dstPitch * h) + 3) & (size_t) ~3;520 sizeRgba = w * h * 4;521 sizeRequest = sizeMask + sizeRgba + sizeof(*pImage);522 523 p = c = calloc (1, sizeRequest);524 if (!c)525 RETERROR(scrnIndex, NULL,526 "Error failed to alloc %lu bytes for cursor\n",527 (unsigned long) sizeRequest);528 529 pImage = (struct vboxCursorImage *)p;530 pImage->pPixels = m = p + sizeof(*pImage);531 cp = (CARD32 *)(m + sizeMask);532 533 TRACE_LOG ("w=%d h=%d sm=%d sr=%d p=%d\n",534 w, h, (int) sizeMask, (int) sizeRgba, (int) dstPitch);535 TRACE_LOG ("m=%p c=%p cp=%p\n", m, c, (void *)cp);536 537 fc = color_to_byte (pCurs->foreBlue)538 | (color_to_byte (pCurs->foreGreen) << 8)539 | (color_to_byte (pCurs->foreRed) << 16);540 541 bc = color_to_byte (pCurs->backBlue)542 | (color_to_byte (pCurs->backGreen) << 8)543 | (color_to_byte (pCurs->backRed) << 16);544 545 /*546 * Convert the Xorg source/mask bits to the and/xor bits VBox needs.547 * Xorg:548 * The mask is a bitmap indicating which parts of the cursor are549 * transparent and which parts are drawn. The source is a bitmap550 * indicating which parts of the non-transparent portion of the551 * the cursor should be painted in the foreground color and which552 * should be painted in the background color. By default, set bits553 * indicate the opaque part of the mask bitmap and clear bits554 * indicate the transparent part.555 * VBox:556 * The color data is the XOR mask. The AND mask bits determine557 * which pixels of the color data (XOR mask) will replace (overwrite)558 * the screen pixels (AND mask bit = 0) and which ones will be XORed559 * with existing screen pixels (AND mask bit = 1).560 * For example when you have the AND mask all 0, then you see the561 * correct mouse pointer image surrounded by black square.562 */563 for (pm = bitsp->mask, ps = bitsp->source, y = 0;564 y < h;565 ++y, pm += srcPitch, ps += srcPitch, m += dstPitch)566 {567 for (x = 0; x < w; ++x)568 {569 if (pm[x / 8] & (1 << (x % 8)))570 {571 /* opaque, leave AND mask bit at 0 */572 if (ps[x / 8] & (1 << (x % 8)))573 {574 *cp++ = fc;575 PUT_PIXEL('X');576 }577 else578 {579 *cp++ = bc;580 PUT_PIXEL('*');581 }582 }583 else584 {585 /* transparent, set AND mask bit */586 m[x / 8] |= 1 << (7 - (x % 8));587 /* don't change the screen pixel */588 *cp++ = 0;589 PUT_PIXEL(' ');590 }591 }592 PUT_PIXEL('\n');593 }594 595 pImage->cWidth = w;596 pImage->cHeight = h;597 pImage->cHotX = bitsp->xhot;598 pImage->cHotY = bitsp->yhot;599 pImage->fFlags = VBOX_MOUSE_POINTER_VISIBLE | VBOX_MOUSE_POINTER_SHAPE;600 pImage->cbLength = sizeRequest - sizeof(*pImage);601 602 #ifdef DEBUG_POINTER603 ErrorF("shape = %p\n", p);604 vbox_show_shape(w, h, bc, c);605 #endif606 607 return p;608 }609 610 #ifdef ARGB_CURSOR611 static Bool612 vbox_use_hw_cursor_argb(ScreenPtr pScreen, CursorPtr pCurs)613 {614 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];615 Bool rc = TRUE;616 617 if (!vbox_host_uses_hwcursor(pScrn))618 rc = FALSE;619 if ( rc620 && ( (pCurs->bits->height > VBOX_MAX_CURSOR_HEIGHT)621 || (pCurs->bits->width > VBOX_MAX_CURSOR_WIDTH)622 || (pScrn->bitsPerPixel <= 8)623 )624 )625 rc = FALSE;626 #ifndef VBOXVIDEO_13627 /* Evil hack - we use this as another way of poking the driver to update628 * our list of video modes. */629 vboxWriteHostModes(pScrn, pScrn->currentMode);630 #endif631 return rc;632 }633 634 635 static void636 vbox_load_cursor_argb(ScrnInfoPtr pScrn, CursorPtr pCurs)637 {638 VBOXPtr pVBox;639 VMMDevReqMousePointer *reqp;640 CursorBitsPtr bitsp;641 unsigned short w, h;642 unsigned short cx, cy;643 unsigned char *pm;644 CARD32 *pc;645 size_t sizeData, sizeMask;646 CARD8 *p;647 int scrnIndex;648 uint32_t fFlags = VBOX_MOUSE_POINTER_VISIBLE | VBOX_MOUSE_POINTER_SHAPE649 | VBOX_MOUSE_POINTER_ALPHA;650 int rc;651 652 pVBox = pScrn->driverPrivate;653 bitsp = pCurs->bits;654 w = bitsp->width;655 h = bitsp->height;656 scrnIndex = pScrn->scrnIndex;657 658 /* Mask must be generated for alpha cursors, that is required by VBox. */659 /* note: (michael) the next struct must be 32bit aligned. */660 sizeMask = ((w + 7) / 8 * h + 3) & ~3;661 662 if (!w || !h || w > VBOX_MAX_CURSOR_WIDTH || h > VBOX_MAX_CURSOR_HEIGHT)663 RETERROR(scrnIndex, ,664 "Error invalid cursor dimensions %dx%d\n", w, h);665 666 if ((bitsp->xhot > w) || (bitsp->yhot > h))667 RETERROR(scrnIndex, ,668 "Error invalid cursor hotspot location %dx%d (max %dx%d)\n",669 bitsp->xhot, bitsp->yhot, w, h);670 671 sizeData = w * h * 4 + sizeMask;672 p = calloc(1, sizeData);673 if (!p)674 RETERROR(scrnIndex, ,675 "Error failed to alloc %lu bytes for cursor\n",676 (unsigned long)sizeData);677 678 memcpy(p + sizeMask, bitsp->argb, w * h * 4);679 680 /* Emulate the AND mask. */681 pm = p;682 pc = bitsp->argb;683 684 /* Init AND mask to 1 */685 memset(pm, 0xFF, sizeMask);686 687 /*688 * The additions driver must provide the AND mask for alpha cursors. The host frontend689 * which can handle alpha channel, will ignore the AND mask and draw an alpha cursor.690 * But if the host does not support ARGB, then it simply uses the AND mask and the color691 * data to draw a normal color cursor.692 */693 for (cy = 0; cy < h; cy++)694 {695 unsigned char bitmask = 0x80;696 697 for (cx = 0; cx < w; cx++, bitmask >>= 1)698 {699 if (bitmask == 0)700 bitmask = 0x80;701 702 if (pc[cx] >= 0xF0000000)703 pm[cx / 8] &= ~bitmask;704 }705 706 /* Point to next source and dest scans */707 pc += w;708 pm += (w + 7) / 8;709 }710 711 rc = VBoxHGSMIUpdatePointerShape(&pVBox->guestCtx, fFlags, bitsp->xhot,712 bitsp->yhot, w, h, p, sizeData);713 free(p);714 }715 #endif716 717 Bool718 vbox_cursor_init(ScreenPtr pScreen)719 {720 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];721 VBOXPtr pVBox = pScrn->driverPrivate;722 xf86CursorInfoPtr pCurs = NULL;723 Bool rc = TRUE;724 725 TRACE_ENTRY();726 if (!pVBox->fHaveHGSMI)727 return FALSE;728 pVBox->pCurs = pCurs = xf86CreateCursorInfoRec();729 if (!pCurs) {730 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,731 "Failed to create X Window cursor information structures for virtual mouse.\n");732 rc = FALSE;733 }734 if (rc) {735 pCurs->MaxWidth = VBOX_MAX_CURSOR_WIDTH;736 pCurs->MaxHeight = VBOX_MAX_CURSOR_HEIGHT;737 pCurs->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP738 | HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1739 | HARDWARE_CURSOR_BIT_ORDER_MSBFIRST;740 741 pCurs->SetCursorColors = vbox_set_cursor_colors;742 pCurs->SetCursorPosition = vbox_set_cursor_position;743 pCurs->LoadCursorImage = vbox_load_cursor_image;744 pCurs->HideCursor = vbox_hide_cursor;745 pCurs->ShowCursor = vbox_show_cursor;746 pCurs->UseHWCursor = vbox_use_hw_cursor;747 pCurs->RealizeCursor = vbox_realize_cursor;748 749 #ifdef ARGB_CURSOR750 pCurs->UseHWCursorARGB = vbox_use_hw_cursor_argb;751 pCurs->LoadCursorARGB = vbox_load_cursor_argb;752 #endif753 754 /* Hide the host cursor before we initialise if we wish to use a755 * software cursor. */756 if (pVBox->forceSWCursor)757 vbox_vmm_hide_cursor(pScrn, pVBox);758 rc = xf86InitCursor(pScreen, pCurs);759 }760 if (!rc)761 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,762 "Failed to enable mouse pointer integration.\n");763 if (!rc && (pCurs != NULL))764 xf86DestroyCursorInfoRec(pCurs);765 return rc;766 209 } 767 210
Note:
See TracChangeset
for help on using the changeset viewer.