Changeset 34872 in vbox for trunk/src/VBox
- Timestamp:
- Dec 9, 2010 11:00:13 AM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c
r34765 r34872 694 694 vboxLineLength(ScrnInfoPtr pScrn, int32_t cDisplayWidth) 695 695 { 696 uint64_t cbLine = ((uint64_t)cDisplayWidth * vboxBPP(pScrn) / 8 + 7) & ~7;696 uint64_t cbLine = ((uint64_t)cDisplayWidth * vboxBPP(pScrn) / 8 + 3) & ~3; 697 697 return cbLine < INT32_MAX ? cbLine : INT32_MAX; 698 698 } … … 1188 1188 } 1189 1189 1190 static void1191 vboxCalcDisplayDimensions(VBOXPtr pVBox, int32_t *pcWidth, int32_t *pcHeight)1192 {1193 int32_t cWidth = 0, cHeight = 0;1194 unsigned i;1195 for (i = 0; i < pVBox->cScreens; ++i)1196 {1197 int32_t cWidthScreen = pVBox->aScreenLocation[i].x1198 + pVBox->aScreenLocation[i].cx;1199 int32_t cHeightScreen = pVBox->aScreenLocation[i].y1200 + pVBox->aScreenLocation[i].cy;1201 if (cWidthScreen > cWidth)1202 cWidth = cWidthScreen;1203 if (cHeightScreen > cWidth)1204 cWidth = cWidthScreen;1205 }1206 *pcWidth = cWidth;1207 *pcHeight = cHeight;1208 }1209 1210 1190 static Bool 1211 1191 VBOXSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags) … … 1225 1205 rc = xf86SetSingleMode(pScrn, pMode, 0); 1226 1206 #else 1207 VBOXAdjustScreenPixmap(pScrn, pMode->HDisplay, pMode->VDisplay); 1227 1208 rc = VBOXSetMode(pScrn, 0, pMode->HDisplay, pMode->VDisplay, 1228 1209 pScrn->frameX0, pScrn->frameY0); 1229 {1230 int32_t cWidth, cHeight;1231 vboxCalcDisplayDimensions(pVBox, &cWidth, &cHeight);1232 VBOXAdjustScreenPixmap(pScrn, cWidth, cHeight);1233 }1234 1210 if (rc) 1235 1211 { … … 1247 1223 } 1248 1224 1249 /* Set a graphics mode. Poke the required values into registers, enable 1250 guest-host acceleration functions and tell the host we support advanced 1251 graphics functions. */ 1225 /** Get the index of the screen we will use as the primary one. This is in 1226 * fact the first screen located fully inside the virtual desktop, or zero 1227 * if none are. Screens which are not fully inside will be set up to be 1228 * identical to the primary one, so from the host's point of view the first 1229 * screen can always be treated as the primary. */ 1230 static uint32_t 1231 vboxGetPrimaryIndex(ScrnInfoPtr pScrn) 1232 { 1233 VBOXPtr pVBox = VBOXGetRec(pScrn); 1234 unsigned i; 1235 for (i = 0; i < pVBox->cScreens; ++i) 1236 if ( pVBox->aScreenLocation[i].x + pVBox->aScreenLocation[i].cx 1237 < pScrn->virtualX 1238 && pVBox->aScreenLocation[i].y + pVBox->aScreenLocation[i].cy 1239 < pScrn->virtualY) 1240 return i; 1241 return 0; /* This will probably look bad if it can happen. */ 1242 } 1243 1244 /** 1245 * This is a rather un-transparent workaround for the fact that HGSMI doesn't 1246 * let us disable screens. If a guest screen is not enabled we set it to 1247 * match the display on the primary screen. 1248 */ 1249 static uint32_t 1250 vboxGetRealLocationIndex(ScrnInfoPtr pScrn, unsigned i) 1251 { 1252 VBOXPtr pVBox = VBOXGetRec(pScrn); 1253 if ( pVBox->aScreenLocation[i].x + pVBox->aScreenLocation[i].cx 1254 <= pScrn->virtualX 1255 && pVBox->aScreenLocation[i].y + pVBox->aScreenLocation[i].cy 1256 <= pScrn->virtualY) 1257 return i; 1258 return vboxGetPrimaryIndex(pScrn); 1259 1260 } 1261 1262 /** Set a graphics mode. Poke any required values into registers, do an HGSMI 1263 * mode set and tell the host we support advanced graphics functions. This 1264 * procedure is complicated by three things. 1265 * - The first is that X.Org can implicitly disable a screen by resizing the 1266 * virtual framebuffer so that the screen is no longer inside it. We have 1267 * to spot and handle this. 1268 * - The second is that HGSMI doesn't actually let us disable a monitor. We 1269 * should add this at some point, but for now I want to implement the 1270 * protocol and not extend it, so I "disable" monitors by setting them to 1271 * show the same thing as the first enabled monitor (see @a 1272 * vboxGetPrimaryIndex). 1273 * - The third is that the code has to work around HGSMI's special handling of 1274 * the primary screen. X.Org doesn't have the same concept, and can move 1275 * the primary about the virtual desktop (not such an issue) and can also 1276 * disable the first screen. 1277 */ 1252 1278 static Bool 1253 1279 VBOXSetMode(ScrnInfoPtr pScrn, unsigned cDisplay, unsigned cWidth, … … 1256 1282 VBOXPtr pVBox = VBOXGetRec(pScrn); 1257 1283 Bool rc = TRUE; 1258 uint32_t xRel = cDisplay ? x - pVBox->aScreenLocation[0].x : 0; 1259 uint32_t yRel = cDisplay ? y - pVBox->aScreenLocation[0].y : 0; 1284 Bool fPrimaryMoved = FALSE; 1285 uint32_t cPrimary, cIndex; 1286 uint32_t cwReal, chReal; 1287 int32_t cxRel, cyRel, cxReal, cyReal; 1260 1288 1261 1289 TRACE_LOG("cDisplay=%u, cWidth=%u, cHeight=%u, x=%d, y=%d, displayWidth=%d\n", 1262 1290 cDisplay, cWidth, cHeight, x, y, pScrn->displayWidth); 1291 cPrimary = vboxGetPrimaryIndex(pScrn); 1292 cIndex = vboxGetRealLocationIndex(pScrn, cDisplay); 1293 if ( cDisplay == cPrimary 1294 && ( x != pVBox->aScreenLocation[cDisplay].x 1295 || y != pVBox->aScreenLocation[cDisplay].y)) 1296 fPrimaryMoved = TRUE; 1297 pVBox->aScreenLocation[cDisplay].cx = cWidth; 1298 pVBox->aScreenLocation[cDisplay].cy = cHeight; 1299 pVBox->aScreenLocation[cDisplay].x = x; 1300 pVBox->aScreenLocation[cDisplay].y = y; 1301 cwReal = pVBox->aScreenLocation[cIndex].cx; 1302 chReal = pVBox->aScreenLocation[cIndex].cy; 1303 cxReal = pVBox->aScreenLocation[cIndex].x; 1304 cyReal = pVBox->aScreenLocation[cIndex].y; 1305 cxRel = cxReal - pVBox->aScreenLocation[cPrimary].x; 1306 cyRel = cyReal - pVBox->aScreenLocation[cPrimary].y; 1263 1307 /* Don't fiddle with the hardware if we are switched 1264 1308 * to a virtual terminal. */ 1265 1309 if (!pVBox->vtSwitch) 1266 1310 { 1311 TRACE_LOG("setting mode. cWidth=%u, cHeight=%u, cwReal=%u, chReal=%u, pScrn->virtualX=%d, pScrn->virtualY=%d, vboxBPP(pScrn)=%d, x=%d, y=%d, cDisplay=%u, cPrimary=%u, cIndex=%u, cxRel=%d, cyRel=%d, cxReal=%d, cyReal=%d, pVBox->cbLine=%d\n", 1312 cWidth, cHeight, cwReal, chReal, pScrn->virtualX, 1313 pScrn->virtualY, vboxBPP(pScrn), x, y, cDisplay, cPrimary, 1314 cIndex, cxRel, cyRel, cxReal, cyReal, pVBox->cbLine); 1267 1315 if (cDisplay == 0) 1268 VBoxVideoSetModeRegisters(c Width, cHeight, pScrn->displayWidth,1269 vboxBPP(pScrn), x, y);1316 VBoxVideoSetModeRegisters(cwReal, chReal, pScrn->displayWidth, 1317 vboxBPP(pScrn), cxReal, cyReal); 1270 1318 /* Tell the host we support graphics */ 1271 1319 if (vbox_device_available(pVBox)) … … 1275 1323 && (pVBox->fHaveHGSMI) 1276 1324 && !pVBox->vtSwitch) 1277 VBoxHGSMIProcessDisplayInfo(&pVBox->guestCtx, cDisplay, xRel, yRel, 1278 pVBox->cbLine + x * vboxBPP(pScrn) / 8, 1325 VBoxHGSMIProcessDisplayInfo(&pVBox->guestCtx, cDisplay, cxRel, cyRel, 1326 cyReal * pVBox->cbLine 1327 + cxReal * vboxBPP(pScrn) / 8, 1279 1328 pVBox->cbLine, 1280 cWidth, cHeight, vboxBPP(pScrn)); 1281 pVBox->aScreenLocation[cDisplay].cx = cWidth; 1282 pVBox->aScreenLocation[cDisplay].cy = cHeight; 1283 pVBox->aScreenLocation[cDisplay].x = x; 1284 pVBox->aScreenLocation[cDisplay].y = y; 1329 cwReal, chReal, vboxBPP(pScrn)); 1330 /* The guest-host protocol says that first screen is always at offset 1331 * (0,0). Ergo, if the guest changes that offset we need to move all 1332 * other screens in the host to keep the relative positions right. */ 1333 if (fPrimaryMoved) 1334 { 1335 unsigned i; 1336 for (i = 1; i < pVBox->cScreens; ++i) 1337 if (i != cPrimary) 1338 VBOXSetMode(pScrn, i, pVBox->aScreenLocation[i].cx, 1339 pVBox->aScreenLocation[i].cy, 1340 pVBox->aScreenLocation[i].x, 1341 pVBox->aScreenLocation[i].y); 1342 } 1285 1343 TRACE_LOG("returning %s\n", rc ? "TRUE" : "FALSE"); 1286 1344 return rc; 1287 1345 } 1288 1346 1347 /** Resize the virtual framebuffer. After resizing we reset all modes 1348 * (X.Org 1.3+) to adjust them to the new framebuffer. 1349 */ 1289 1350 static Bool VBOXAdjustScreenPixmap(ScrnInfoPtr pScrn, int width, int height) 1290 1351 { … … 1320 1381 #ifdef VBOXVIDEO_13 1321 1382 /* Write the new values to the hardware */ 1322 xf86SetDesiredModes(pScrn); 1383 { 1384 unsigned i; 1385 for (i = 0; i < pVBox->cScreens; ++i) 1386 VBOXSetMode(pScrn, i, pVBox->aScreenLocation[i].cx, 1387 pVBox->aScreenLocation[i].cy, 1388 pVBox->aScreenLocation[i].x, 1389 pVBox->aScreenLocation[i].y); 1390 } 1323 1391 #endif 1324 1392 return TRUE;
Note:
See TracChangeset
for help on using the changeset viewer.