Changeset 34440 in vbox for trunk/src/VBox/Additions/WINNT/Graphics/Display/vbox.c
- Timestamp:
- Nov 28, 2010 10:12:07 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/Graphics/Display/vbox.c
r34438 r34440 5 5 6 6 /* 7 * Copyright (C) 2006-20 07Oracle Corporation7 * Copyright (C) 2006-2010 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 25 25 #include <iprt/asm-amd64-x86.h> 26 26 #include <iprt/assert.h> 27 28 /*29 * There is a hardware ring buffer in the VBox VMMDev PCI memory space.30 * All graphics commands go there serialized by VBoxVBVABufferBeginUpdate.31 * and vboxHwBufferEndUpdate.32 *33 * off32Free is writing position. off32Data is reading position.34 * off32Free == off32Data means buffer is empty.35 * There must be always gap between off32Data and off32Free when data36 * are in the buffer.37 * Guest only changes off32Free, host changes off32Data.38 */39 40 /* Forward declarations of internal functions. */41 static void vboxHwBufferFlush(PHGSMIGUESTCOMMANDCONTEXT pCtx);42 static void vboxHwBufferPlaceDataAt(PVBVABUFFERCONTEXT pCtx, const void *p,43 uint32_t cb, uint32_t offset);44 static bool vboxHwBufferWrite(PVBVABUFFERCONTEXT pCtx,45 PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,46 const void *p, uint32_t cb);47 48 49 static bool vboxVBVAInformHost(PVBVABUFFERCONTEXT pCtx,50 PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,51 bool bEnable)52 {53 bool bRc = false;54 55 #if 0 /* All callers check this */56 if (ppdev->bHGSMISupported)57 #endif58 {59 void *p = VBoxHGSMIBufferAlloc(pHGSMICtx,60 sizeof (VBVAENABLE),61 HGSMI_CH_VBVA,62 VBVA_ENABLE);63 if (!p)64 {65 LogFunc(("HGSMIHeapAlloc failed\n"));66 }67 else68 {69 VBVAENABLE *pEnable = (VBVAENABLE *)p;70 71 pEnable->u32Flags = bEnable? VBVA_F_ENABLE: VBVA_F_DISABLE;72 pEnable->u32Offset = pCtx->offVRAMBuffer;73 pEnable->i32Result = VERR_NOT_SUPPORTED;74 75 VBoxHGSMIBufferSubmit(pHGSMICtx, p);76 77 if (bEnable)78 {79 bRc = RT_SUCCESS(pEnable->i32Result);80 }81 else82 {83 bRc = true;84 }85 86 VBoxHGSMIBufferFree(pHGSMICtx, p);87 }88 }89 90 return bRc;91 }92 93 /*94 * Public hardware buffer methods.95 */96 RTDECL(bool) VBoxVBVAEnable(PVBVABUFFERCONTEXT pCtx,97 PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,98 VBVABUFFER *pVBVA)99 {100 bool bRc = false;101 102 LogFlowFunc(("pVBVA %p\n", pVBVA));103 104 #if 0 /* All callers check this */105 if (ppdev->bHGSMISupported)106 #endif107 {108 LogFunc(("pVBVA %p vbva off 0x%x\n", pVBVA, pCtx->offVRAMBuffer));109 110 pVBVA->hostFlags.u32HostEvents = 0;111 pVBVA->hostFlags.u32SupportedOrders = 0;112 pVBVA->off32Data = 0;113 pVBVA->off32Free = 0;114 memset(pVBVA->aRecords, 0, sizeof (pVBVA->aRecords));115 pVBVA->indexRecordFirst = 0;116 pVBVA->indexRecordFree = 0;117 pVBVA->cbPartialWriteThreshold = 256;118 pVBVA->cbData = pCtx->cbBuffer - sizeof (VBVABUFFER) + sizeof (pVBVA->au8Data);119 120 pCtx->fHwBufferOverflow = false;121 pCtx->pRecord = NULL;122 pCtx->pVBVA = pVBVA;123 124 bRc = vboxVBVAInformHost(pCtx, pHGSMICtx, true);125 }126 127 if (!bRc)128 {129 VBoxVBVADisable(pCtx, pHGSMICtx);130 }131 132 return bRc;133 }134 135 RTDECL(void) VBoxVBVADisable(PVBVABUFFERCONTEXT pCtx,136 PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx)137 {138 LogFlowFunc(("\n"));139 140 pCtx->fHwBufferOverflow = false;141 pCtx->pRecord = NULL;142 pCtx->pVBVA = NULL;143 144 vboxVBVAInformHost(pCtx, pHGSMICtx, false);145 146 return;147 }148 149 RTDECL(bool) VBoxVBVABufferBeginUpdate(PVBVABUFFERCONTEXT pCtx,150 PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx)151 {152 bool bRc = false;153 154 // LogFunc(("flags = 0x%08X\n", pCtx->pVBVA? pCtx->pVBVA->u32HostEvents: -1));155 156 if ( pCtx->pVBVA157 && (pCtx->pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_ENABLED))158 {159 uint32_t indexRecordNext;160 161 Assert(!pCtx->fHwBufferOverflow);162 Assert(pCtx->pRecord == NULL);163 164 indexRecordNext = (pCtx->pVBVA->indexRecordFree + 1) % VBVA_MAX_RECORDS;165 166 if (indexRecordNext == pCtx->pVBVA->indexRecordFirst)167 {168 /* All slots in the records queue are used. */169 vboxHwBufferFlush (pHGSMICtx);170 }171 172 if (indexRecordNext == pCtx->pVBVA->indexRecordFirst)173 {174 /* Even after flush there is no place. Fail the request. */175 LogFunc(("no space in the queue of records!!! first %d, last %d\n",176 pCtx->pVBVA->indexRecordFirst, pCtx->pVBVA->indexRecordFree));177 }178 else179 {180 /* Initialize the record. */181 VBVARECORD *pRecord = &pCtx->pVBVA->aRecords[pCtx->pVBVA->indexRecordFree];182 183 pRecord->cbRecord = VBVA_F_RECORD_PARTIAL;184 185 pCtx->pVBVA->indexRecordFree = indexRecordNext;186 187 // LogFunc(("indexRecordNext = %d\n", indexRecordNext));188 189 /* Remember which record we are using. */190 pCtx->pRecord = pRecord;191 192 bRc = true;193 }194 }195 196 return bRc;197 }198 199 RTDECL(void) VBoxVBVABufferEndUpdate(PVBVABUFFERCONTEXT pCtx)200 {201 VBVARECORD *pRecord;202 203 // LogFunc(("\n"));204 205 Assert(pCtx->pVBVA);206 207 pRecord = pCtx->pRecord;208 Assert(pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));209 210 /* Mark the record completed. */211 pRecord->cbRecord &= ~VBVA_F_RECORD_PARTIAL;212 213 pCtx->fHwBufferOverflow = false;214 pCtx->pRecord = NULL;215 216 return;217 }218 219 /*220 * Private operations.221 */222 static uint32_t vboxHwBufferAvail (const VBVABUFFER *pVBVA)223 {224 int32_t i32Diff = pVBVA->off32Data - pVBVA->off32Free;225 226 return i32Diff > 0? i32Diff: pVBVA->cbData + i32Diff;227 }228 229 static void vboxHwBufferFlush(PHGSMIGUESTCOMMANDCONTEXT pCtx)230 {231 /* Issue the flush command. */232 void *p = VBoxHGSMIBufferAlloc(pCtx,233 sizeof (VBVAFLUSH),234 HGSMI_CH_VBVA,235 VBVA_FLUSH);236 if (!p)237 {238 LogFunc(("HGSMIHeapAlloc failed\n"));239 }240 else241 {242 VBVAFLUSH *pFlush = (VBVAFLUSH *)p;243 244 pFlush->u32Reserved = 0;245 246 VBoxHGSMIBufferSubmit(pCtx, p);247 248 VBoxHGSMIBufferSubmit(pCtx, p);249 }250 251 return;252 }253 254 static void vboxHwBufferPlaceDataAt(PVBVABUFFERCONTEXT pCtx, const void *p,255 uint32_t cb, uint32_t offset)256 {257 VBVABUFFER *pVBVA = pCtx->pVBVA;258 uint32_t u32BytesTillBoundary = pVBVA->cbData - offset;259 uint8_t *dst = &pVBVA->au8Data[offset];260 int32_t i32Diff = cb - u32BytesTillBoundary;261 262 if (i32Diff <= 0)263 {264 /* Chunk will not cross buffer boundary. */265 memcpy (dst, p, cb);266 }267 else268 {269 /* Chunk crosses buffer boundary. */270 memcpy (dst, p, u32BytesTillBoundary);271 memcpy (&pVBVA->au8Data[0], (uint8_t *)p + u32BytesTillBoundary, i32Diff);272 }273 274 return;275 }276 277 static bool vboxHwBufferWrite(PVBVABUFFERCONTEXT pCtx,278 PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,279 const void *p, uint32_t cb)280 {281 VBVARECORD *pRecord;282 uint32_t cbHwBufferAvail;283 284 uint32_t cbWritten = 0;285 286 VBVABUFFER *pVBVA = pCtx->pVBVA;287 Assert(pVBVA);288 289 if (!pVBVA || pCtx->fHwBufferOverflow)290 {291 return false;292 }293 294 Assert(pVBVA->indexRecordFirst != pVBVA->indexRecordFree);295 296 pRecord = pCtx->pRecord;297 Assert(pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));298 299 LogFunc(("%d\n", cb));300 301 cbHwBufferAvail = vboxHwBufferAvail (pVBVA);302 303 while (cb > 0)304 {305 uint32_t cbChunk = cb;306 307 // LogFunc(("pVBVA->off32Free %d, pRecord->cbRecord 0x%08X, cbHwBufferAvail %d, cb %d, cbWritten %d\n",308 // pVBVA->off32Free, pRecord->cbRecord, cbHwBufferAvail, cb, cbWritten));309 310 if (cbChunk >= cbHwBufferAvail)311 {312 LogFunc(("1) avail %d, chunk %d\n", cbHwBufferAvail, cbChunk));313 314 vboxHwBufferFlush (pHGSMICtx);315 316 cbHwBufferAvail = vboxHwBufferAvail (pVBVA);317 318 if (cbChunk >= cbHwBufferAvail)319 {320 LogFunc(("no place for %d bytes. Only %d bytes available after flush. Going to partial writes.\n",321 cb, cbHwBufferAvail));322 323 if (cbHwBufferAvail <= pVBVA->cbPartialWriteThreshold)324 {325 LogFunc(("Buffer overflow!!!\n"));326 pCtx->fHwBufferOverflow = true;327 Assert(false);328 return false;329 }330 331 cbChunk = cbHwBufferAvail - pVBVA->cbPartialWriteThreshold;332 }333 }334 335 Assert(cbChunk <= cb);336 Assert(cbChunk <= vboxHwBufferAvail (pVBVA));337 338 vboxHwBufferPlaceDataAt (pCtx, (uint8_t *)p + cbWritten, cbChunk, pVBVA->off32Free);339 340 pVBVA->off32Free = (pVBVA->off32Free + cbChunk) % pVBVA->cbData;341 pRecord->cbRecord += cbChunk;342 cbHwBufferAvail -= cbChunk;343 344 cb -= cbChunk;345 cbWritten += cbChunk;346 }347 348 return true;349 }350 351 /*352 * Public writer to the hardware buffer.353 */354 RTDECL(bool) VBoxVBVAWrite(PVBVABUFFERCONTEXT pCtx,355 PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,356 const void *pv, uint32_t cb)357 {358 return vboxHwBufferWrite (pCtx, pHGSMICtx, pv, cb);359 }360 361 RTDECL(bool) VBoxVBVAOrderSupported(PVBVABUFFERCONTEXT pCtx, unsigned code)362 {363 VBVABUFFER *pVBVA = pCtx->pVBVA;364 365 if (!pVBVA)366 {367 return FALSE;368 }369 370 if (pVBVA->hostFlags.u32SupportedOrders & (1 << code))371 {372 return true;373 }374 375 return FALSE;376 }377 378 RTDECL(void) VBoxHGSMIProcessDisplayInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,379 uint32_t cDisplay,380 int32_t cOriginX,381 int32_t cOriginY,382 uint32_t offStart,383 uint32_t cbPitch,384 uint32_t cWidth,385 uint32_t cHeight,386 uint16_t cBPP)387 {388 /* Issue the screen info command. */389 void *p = VBoxHGSMIBufferAlloc(pCtx,390 sizeof (VBVAINFOSCREEN),391 HGSMI_CH_VBVA,392 VBVA_INFO_SCREEN);393 if (!p)394 {395 LogFunc(("HGSMIHeapAlloc failed\n"));396 }397 else398 {399 VBVAINFOSCREEN *pScreen = (VBVAINFOSCREEN *)p;400 401 pScreen->u32ViewIndex = cDisplay;402 pScreen->i32OriginX = cOriginX;403 pScreen->i32OriginY = cOriginY;404 pScreen->u32StartOffset = offStart;405 pScreen->u32LineSize = cbPitch;406 pScreen->u32Width = cWidth;407 pScreen->u32Height = cHeight;408 pScreen->u16BitsPerPixel = cBPP;409 pScreen->u16Flags = VBVA_SCREEN_F_ACTIVE;410 411 VBoxHGSMIBufferSubmit(pCtx, p);412 413 VBoxHGSMIBufferFree(pCtx, p);414 }415 }416 27 417 28 void VBoxProcessDisplayInfo (PPDEV ppdev)
Note:
See TracChangeset
for help on using the changeset viewer.