VirtualBox

Ignore:
Timestamp:
Apr 12, 2010 10:54:53 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
59968
Message:

wddm: avoid DMA transactions on GDI rendering (for preformance)

Location:
trunk/src/VBox/Additions/WINNT/Graphics/Miniport
Files:
2 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/Graphics/Miniport/Makefile.kmk

    r27164 r28228  
    8787  VBoxVideoWddm_DEFS      += VBOX_WITH_VIDEOHWACCEL
    8888 endif
     89 ifdef VBOXWDDM_WITH_VBVA
     90  VBoxVideoWddm_DEFS      += VBOXWDDM_WITH_VBVA
     91  ifdef VBOXVDMA_WITH_VBVA
     92   VBoxVideoWddm_DEFS     += VBOXVDMA_WITH_VBVA
     93  endif
     94 endif
    8995 VBoxVideoWddm_DEFS       += LOG_ENABLED
    9096 #VBoxVideoWddm_DEFS       += LOG_TO_BACKDOOR
     
    101107        wddm/VBoxVideoShgsmi.cpp \
    102108        wddm/VBoxVideoWddm.rc
     109 ifdef VBOXWDDM_WITH_VBVA
     110  VBoxVideoWddm_SOURCES   += \
     111    wddm/VBoxVideoVbva.cpp
     112 endif
    103113 VBoxVideoWddm_LIBS.x86   = \
    104114        $(PATH_SDK_WINDDKWLH_LIB)/bufferoverflowk.lib
  • trunk/src/VBox/Additions/WINNT/Graphics/Miniport/VBoxVideo.cpp

    r28031 r28228  
    349349#else
    350350    ULONG vramSize = vboxWddmVramCpuVisibleSegmentSize(DeviceExtension);
    351 #ifndef VBOXWDDM_WITH_FAKE_SEGMENT
     351#ifndef VBOXWDDM_RENDER_FROM_SHADOW
    352352    /* at least two surfaces will be needed: primary & shadow */
    353353    vramSize /= 2;
     
    925925        if (DeviceExtension->CurrentMode == 0)
    926926#else
    927         if (!DeviceExtension->cSources || !DeviceExtension->aSources[0].pAllocation)
     927        if (!DeviceExtension->cSources || !DeviceExtension->aSources[0].pPrimaryAllocation)
    928928#endif
    929929        {
     
    965965        }
    966966#else
    967         if (DeviceExtension->cSources && DeviceExtension->aSources[0].pAllocation)
     967        if (DeviceExtension->cSources && DeviceExtension->aSources[0].pPrimaryAllocation)
    968968        {
    969969            if (!xres)
    970                 xres = DeviceExtension->aSources[0].pAllocation->u.SurfInfo.width;
     970                xres = DeviceExtension->aSources[0].pPrimaryAllocation->u.SurfInfo.width;
    971971            if (!yres)
    972                 yres = DeviceExtension->aSources[0].pAllocation->u.SurfInfo.height;
     972                yres = DeviceExtension->aSources[0].pPrimaryAllocation->u.SurfInfo.height;
    973973            if (!bpp)
    974                 bpp  = DeviceExtension->aSources[0].pAllocation->u.SurfInfo.bpp;
     974                bpp  = DeviceExtension->aSources[0].pPrimaryAllocation->u.SurfInfo.bpp;
    975975        }
    976976#endif
     
    10201020                if (DeviceExtension->CurrentMode != 0)
    10211021#else
    1022                 if (DeviceExtension->cSources && DeviceExtension->aSources[0].pAllocation)
     1022                if (DeviceExtension->cSources && DeviceExtension->aSources[0].pPrimaryAllocation)
    10231023#endif
    10241024#ifndef VBOX_WITH_MULTIMONITOR_FIX
     
    11261126                if (DeviceExtension->CurrentMode == 0)
    11271127#else
    1128                 if (!DeviceExtension->cSources || !DeviceExtension->aSources[0].pAllocation)
     1128                if (!DeviceExtension->cSources || !DeviceExtension->aSources[0].pPrimaryAllocation)
    11291129#endif
    11301130                {
     
    14071407            &VideoRamBase /*OUT PVOID *VirtualAddress*/
    14081408            );
     1409    Assert(ntStatus == STATUS_SUCCESS);
    14091410    Status = ntStatus == STATUS_SUCCESS ? NO_ERROR : ERROR_INVALID_PARAMETER; /*<- this is what VideoPortMapMemory returns according to the docs */
    14101411#endif
  • trunk/src/VBox/Additions/WINNT/Graphics/Miniport/VBoxVideo.h

    r28031 r28228  
    117117#else
    118118#include <VBox/VBoxVideo.h>
     119#include "wddm/VBoxVideoWddm.h"
    119120#include "wddm/VBoxVideoShgsmi.h"
    120121#include "wddm/VBoxVideoVdma.h"
    121122#include "wddm/VBoxVideoVidPn.h"
    122 #include "wddm/VBoxVideoWddm.h"
     123#ifdef VBOXWDDM_WITH_VBVA
     124# include "wddm/VBoxVideoVbva.h"
     125#endif
     126
    123127
    124128typedef KSPIN_LOCK VBOXVCMNSPIN_LOCK, *PVBOXVCMNSPIN_LOCK;
     
    148152typedef struct VBOXWDDM_SOURCE
    149153{
    150     struct VBOXWDDM_ALLOCATION * pAllocation;
     154    struct VBOXWDDM_ALLOCATION * pPrimaryAllocation;
     155#ifdef VBOXWDDM_RENDER_FROM_SHADOW
     156    struct VBOXWDDM_ALLOCATION * pShadowAllocation;
     157    VBOXVIDEOOFFSET offVram;
     158    VBOXWDDM_SURFACE_DESC SurfInfo;
     159    VBOXVBVAINFO Vbva;
     160#endif
    151161    VBOXWDDM_POINTER_INFO PointerInfo;
    152162} VBOXWDDM_SOURCE, *PVBOXWDDM_SOURCE;
     
    199209#ifdef VBOXWDDM
    200210           VBOXVDMAINFO Vdma;
     211# ifdef VBOXVDMA_WITH_VBVA
     212           VBOXVBVAINFO Vbva;
     213# endif
    201214#endif
    202215
     
    609622DECLINLINE(ULONG) vboxWddmVramCpuVisibleSize(PDEVICE_EXTENSION pDevExt)
    610623{
     624#ifdef VBOXWDDM_RENDER_FROM_SHADOW
     625    /* all memory layout info should be initialized */
     626    Assert(pDevExt->aSources[0].Vbva.offVBVA);
     627    /* page aligned */
     628    Assert(!(pDevExt->aSources[0].Vbva.offVBVA & 0xfff));
     629
     630    return (ULONG)(pDevExt->aSources[0].Vbva.offVBVA & ~0xfffULL);
     631#else
    611632    /* all memory layout info should be initialized */
    612633    Assert(pDevExt->u.primary.Vdma.CmdHeap.area.offBase);
    613634    /* page aligned */
    614635    Assert(!(pDevExt->u.primary.Vdma.CmdHeap.area.offBase & 0xfff));
     636
    615637    return pDevExt->u.primary.Vdma.CmdHeap.area.offBase & ~0xfffUL;
     638#endif
    616639}
    617640
     
    621644}
    622645
    623 #ifdef VBOXWDDM_WITH_FAKE_SEGMENT
     646#ifdef VBOXWDDM_RENDER_FROM_SHADOW
    624647DECLINLINE(ULONG) vboxWddmVramCpuInvisibleSegmentSize(PDEVICE_EXTENSION pDevExt)
    625648{
    626649    return vboxWddmVramCpuVisibleSegmentSize(pDevExt);
    627650}
     651
     652DECLINLINE(bool) vboxWddmCmpSurfDescs(VBOXWDDM_SURFACE_DESC *pDesc1, VBOXWDDM_SURFACE_DESC *pDesc2)
     653{
     654    if (pDesc1->width != pDesc2->width)
     655        return false;
     656    if (pDesc1->height != pDesc2->height)
     657        return false;
     658    if (pDesc1->format != pDesc2->format)
     659        return false;
     660    if (pDesc1->bpp != pDesc2->bpp)
     661        return false;
     662    if (pDesc1->pitch != pDesc2->pitch)
     663        return false;
     664    return true;
     665}
     666
     667DECLINLINE(void) vboxWddmAssignShadow(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_SOURCE pSource, PVBOXWDDM_ALLOCATION pAllocation, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId)
     668{
     669    if (pSource->pShadowAllocation == pAllocation)
     670        return;
     671
     672    if (pSource->pShadowAllocation)
     673    {
     674        PVBOXWDDM_ALLOCATION pOldAlloc = pSource->pShadowAllocation;
     675        PVBOXWDDM_ALLOCATION_SHADOWSURFACE pOldShadowInfo = VBOXWDDM_ALLOCATION_BODY(pOldAlloc, VBOXWDDM_ALLOCATION_SHADOWSURFACE);
     676        /* clear the visibility info fo the current primary */
     677        pOldShadowInfo->bVisible = FALSE;
     678        pOldShadowInfo->bAssigned = FALSE;
     679        Assert(pOldShadowInfo->VidPnSourceId == srcId);
     680        /* release the shadow surface */
     681        pOldShadowInfo->VidPnSourceId = D3DDDI_ID_UNINITIALIZED;
     682    }
     683
     684    if (pAllocation)
     685    {
     686        PVBOXWDDM_ALLOCATION_SHADOWSURFACE pShadowInfo = VBOXWDDM_ALLOCATION_BODY(pAllocation, VBOXWDDM_ALLOCATION_SHADOWSURFACE);
     687        pShadowInfo->bVisible = FALSE;
     688        /* this check ensures the shadow is not used for other source simultaneously */
     689        Assert(pShadowInfo->VidPnSourceId == D3DDDI_ID_UNINITIALIZED);
     690        pShadowInfo->VidPnSourceId = srcId;
     691        pShadowInfo->bAssigned = TRUE;
     692        if (!vboxWddmCmpSurfDescs(&pSource->SurfInfo, &pAllocation->u.SurfInfo))
     693            pSource->offVram = VBOXVIDEOOFFSET_VOID; /* force guest->host notification */
     694        pSource->SurfInfo = pAllocation->u.SurfInfo;
     695    }
     696
     697    pSource->pShadowAllocation = pAllocation;
     698}
    628699#endif
    629700
    630701DECLINLINE(VOID) vboxWddmAssignPrimary(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_SOURCE pSource, PVBOXWDDM_ALLOCATION pAllocation, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId)
    631702{
    632     if (pSource->pAllocation == pAllocation)
     703    if (pSource->pPrimaryAllocation == pAllocation)
    633704        return;
    634705
    635     if (pSource->pAllocation)
     706    if (pSource->pPrimaryAllocation)
    636707    {
    637         PVBOXWDDM_ALLOCATION pOldAlloc = pSource->pAllocation;
     708        PVBOXWDDM_ALLOCATION pOldAlloc = pSource->pPrimaryAllocation;
    638709        PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE pOldPrimaryInfo = VBOXWDDM_ALLOCATION_BODY(pOldAlloc, VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE);
    639710        /* clear the visibility info fo the current primary */
     
    652723    }
    653724
    654     pSource->pAllocation = pAllocation;
     725    pSource->pPrimaryAllocation = pAllocation;
    655726}
    656727
  • trunk/src/VBox/Additions/WINNT/Graphics/Miniport/VBoxVideoHGSMI.cpp

    r28031 r28228  
    956956                vboxVdmaDestroy(PrimaryExtension, &PrimaryExtension->u.primary.Vdma);
    957957        }
     958
     959#ifdef VBOXWDDM_RENDER_FROM_SHADOW
     960        if (RT_SUCCESS(rc))
     961        {
     962            ulAvailable = offset;
     963            ulSize = ulAvailable / 2;
     964            ulSize /= PrimaryExtension->cSources;
     965            Assert(ulSize > VBVA_MIN_BUFFER_SIZE);
     966            if (ulSize > VBVA_MIN_BUFFER_SIZE)
     967            {
     968                ULONG ulRatio = ulSize/VBVA_MIN_BUFFER_SIZE;
     969                ulRatio >>= 4; /* /= 16; */
     970                if (ulRatio)
     971                    ulSize = VBVA_MIN_BUFFER_SIZE * ulRatio;
     972                else
     973                    ulSize = VBVA_MIN_BUFFER_SIZE;
     974            }
     975            else
     976            {
     977                /* todo: ?? */
     978            }
     979
     980            ulSize &= ~0xFFF;
     981            Assert(ulSize);
     982
     983            Assert(ulSize * PrimaryExtension->cSources < ulAvailable);
     984
     985            for (int i = PrimaryExtension->cSources-1; i >= 0; --i)
     986            {
     987                offset -= ulSize;
     988                rc = vboxVbvaCreate(PrimaryExtension, &PrimaryExtension->aSources[i].Vbva, offset, ulSize, i);
     989                AssertRC(rc);
     990                if (RT_SUCCESS(rc))
     991                {
     992                    rc = vboxVbvaEnable(PrimaryExtension, &PrimaryExtension->aSources[i].Vbva);
     993                    AssertRC(rc);
     994                    if (RT_FAILURE(rc))
     995                    {
     996                        /* @todo: de-initialize */
     997                    }
     998                }
     999            }
     1000        }
     1001#endif
    9581002
    9591003        if (RT_FAILURE(rc))
  • trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoShgsmi.cpp

    r27307 r28228  
    5656}
    5757
    58 
    59 DECLINLINE(void) vboxSHGSMICommandDoSubmit(struct _HGSMIHEAP * pHeap, PVBOXSHGSMIHEADER pHeader)
    60 {
    61     /* Initialize the buffer and get the offset for port IO. */
    62     HGSMIOFFSET offBuffer = HGSMIHeapBufferOffset (pHeap, pHeader);
    63 
    64     /* Submit the buffer to the host. */
    65     vboxSHGSMICbCommandWrite(pHeap, offBuffer);
    66 }
    67 
    6858/* do not wait for completion */
    69 DECLINLINE(void) vboxSHGSMICommandSubmitAsynch (struct _HGSMIHEAP * pHeap, PVBOXSHGSMIHEADER pHeader)
     59DECLINLINE(const VBOXSHGSMIHEADER*) vboxSHGSMICommandPrepAsynch (struct _HGSMIHEAP * pHeap, PVBOXSHGSMIHEADER pHeader)
    7060{
    7161    /* ensure the command is not removed until we're processing it */
    7262    vboxSHGSMICommandRetain(pHeader);
    73 
    74     vboxSHGSMICommandDoSubmit(pHeap, pHeader);
    75 
     63    return pHeader;
     64}
     65
     66DECLINLINE(void) vboxSHGSMICommandDoneAsynch (struct _HGSMIHEAP * pHeap, const VBOXSHGSMIHEADER* pHeader)
     67{
    7668    if(!(ASMAtomicReadU32((volatile uint32_t *)&pHeader->fFlags) & VBOXSHGSMI_FLAG_HG_ASYNCH))
    7769    {
     
    8072    }
    8173
    82     vboxSHGSMICommandRelease(pHeap, pHeader);
    83 
    84 }
    85 
    86 void VBoxSHGSMICommandSubmitAsynchEvent (struct _HGSMIHEAP * pHeap, PVOID pvBuff, RTSEMEVENT hEventSem)
     74    vboxSHGSMICommandRelease(pHeap, (PVBOXSHGSMIHEADER)pHeader);
     75}
     76
     77const VBOXSHGSMIHEADER* VBoxSHGSMICommandPrepAsynchEvent (struct _HGSMIHEAP * pHeap, PVOID pvBuff, RTSEMEVENT hEventSem)
    8778{
    8879    PVBOXSHGSMIHEADER pHeader = VBoxSHGSMIBufferHeader (pvBuff);
     
    9182    pHeader->fFlags   = VBOXSHGSMI_FLAG_GH_ASYNCH_IRQ;
    9283
    93     vboxSHGSMICommandSubmitAsynch (pHeap, pHeader);
    94 }
    95 
    96 int VBoxSHGSMICommandSubmitSynch (struct _HGSMIHEAP * pHeap, PVOID pCmd)
     84    return vboxSHGSMICommandPrepAsynch (pHeap, pHeader);
     85}
     86
     87const VBOXSHGSMIHEADER* VBoxSHGSMICommandPrepSynch (struct _HGSMIHEAP * pHeap, PVOID pCmd)
    9788{
    9889    RTSEMEVENT hEventSem;
     
    10192    if (RT_SUCCESS(rc))
    10293    {
    103         VBoxSHGSMICommandSubmitAsynchEvent (pHeap, pCmd, hEventSem);
    104 
    105         rc = RTSemEventWait(hEventSem, RT_INDEFINITE_WAIT);
    106         Assert(RT_SUCCESS(rc));
    107         if (RT_SUCCESS(rc))
    108             RTSemEventDestroy(hEventSem);
    109     }
     94        return VBoxSHGSMICommandPrepAsynchEvent (pHeap, pCmd, hEventSem);
     95    }
     96    return NULL;
     97}
     98
     99void VBoxSHGSMICommandDoneAsynch (struct _HGSMIHEAP * pHeap, const VBOXSHGSMIHEADER * pHeader)
     100{
     101    vboxSHGSMICommandDoneAsynch(pHeap, pHeader);
     102}
     103
     104int VBoxSHGSMICommandDoneSynch (struct _HGSMIHEAP * pHeap, const VBOXSHGSMIHEADER* pHeader)
     105{
     106    VBoxSHGSMICommandDoneAsynch (pHeap, pHeader);
     107    RTSEMEVENT hEventSem = (RTSEMEVENT)pHeader->u64Info2;
     108    int rc = RTSemEventWait(hEventSem, RT_INDEFINITE_WAIT);
     109    AssertRC(rc);
     110    if (RT_SUCCESS(rc))
     111        RTSemEventDestroy(hEventSem);
    110112    return rc;
    111113}
    112114
    113 void VBoxSHGSMICommandSubmitAsynch (struct _HGSMIHEAP * pHeap, PVOID pvBuff, PFNVBOXSHGSMICMDCOMPLETION pfnCompletion, PVOID pvCompletion, uint32_t fFlags)
     115void VBoxSHGSMICommandCancelAsynch (struct _HGSMIHEAP * pHeap, const VBOXSHGSMIHEADER* pHeader)
     116{
     117    vboxSHGSMICommandRelease(pHeap, (PVBOXSHGSMIHEADER)pHeader);
     118}
     119
     120void VBoxSHGSMICommandCancelSynch (struct _HGSMIHEAP * pHeap, const VBOXSHGSMIHEADER* pHeader)
     121{
     122    VBoxSHGSMICommandCancelAsynch (pHeap, pHeader);
     123    RTSEMEVENT hEventSem = (RTSEMEVENT)pHeader->u64Info2;
     124    RTSemEventDestroy(hEventSem);
     125}
     126
     127const VBOXSHGSMIHEADER* VBoxSHGSMICommandPrepAsynch (struct _HGSMIHEAP * pHeap, PVOID pvBuff, PFNVBOXSHGSMICMDCOMPLETION pfnCompletion, PVOID pvCompletion, uint32_t fFlags)
    114128{
    115129    fFlags &= ~VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ;
     
    119133    pHeader->fFlags = fFlags;
    120134
    121     vboxSHGSMICommandSubmitAsynch (pHeap, pHeader);
    122 }
    123 
    124 void VBoxSHGSMICommandSubmitAsynchIrq (struct _HGSMIHEAP * pHeap, PVOID pvBuff, PFNVBOXSHGSMICMDCOMPLETION_IRQ pfnCompletion, PVOID pvCompletion, uint32_t fFlags)
     135    return vboxSHGSMICommandPrepAsynch (pHeap, pHeader);
     136}
     137
     138const VBOXSHGSMIHEADER* VBoxSHGSMICommandPrepAsynchIrq (struct _HGSMIHEAP * pHeap, PVOID pvBuff, PFNVBOXSHGSMICMDCOMPLETION_IRQ pfnCompletion, PVOID pvCompletion, uint32_t fFlags)
    125139{
    126140    fFlags |= VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ | VBOXSHGSMI_FLAG_GH_ASYNCH_IRQ;
     
    131145    pHeader->fFlags = fFlags;
    132146
    133     vboxSHGSMICommandSubmitAsynch (pHeap, pHeader);
     147    return vboxSHGSMICommandPrepAsynch (pHeap, pHeader);
    134148}
    135149
  • trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoShgsmi.h

    r28031 r28228  
    8888}
    8989
    90 void VBoxSHGSMICommandSubmitAsynch (struct _HGSMIHEAP *pHeap, PVOID pvBuff, FNVBOXSHGSMICMDCOMPLETION pfnCompletion, PVOID pvCompletion, uint32_t fFlags);
    91 void VBoxSHGSMICommandSubmitAsynchIrq (struct _HGSMIHEAP * pHeap, PVOID pvBuff, PFNVBOXSHGSMICMDCOMPLETION_IRQ pfnCompletion, PVOID pvCompletion, uint32_t fFlags);
    92 void VBoxSHGSMICommandSubmitAsynchEvent (struct _HGSMIHEAP * pHeap, PVOID pvBuff, RTSEMEVENT hEventSem);
    93 int VBoxSHGSMICommandSubmitSynch (struct _HGSMIHEAP * pHeap, PVOID pCmd);
    94 int VBoxSHGSMICommandSubmitSynchCompletion (struct _HGSMIHEAP * pHeap, PVOID pCmd);
    95 void* VBoxSHGSMICommandAlloc (struct _HGSMIHEAP * pHeap, HGSMISIZE cbData, uint8_t u8Channel, uint16_t u16ChannelInfo);
    96 void VBoxSHGSMICommandFree (struct _HGSMIHEAP * pHeap, void *pvBuffer);
    97 int VBoxSHGSMICommandProcessCompletion (struct _HGSMIHEAP * pHeap, HGSMIOFFSET offCmd, bool bIrq, PVBOXSHGSMILIST pPostProcessList);
    98 int VBoxSHGSMICommandPostprocessCompletion (struct _HGSMIHEAP * pHeap, PVBOXSHGSMILIST pPostProcessList);
    9990
    100 void vboxSHGSMICbCommandWrite(struct _HGSMIHEAP * pHeap, HGSMIOFFSET data);
     91const VBOXSHGSMIHEADER* VBoxSHGSMICommandPrepAsynchEvent(struct _HGSMIHEAP * pHeap, PVOID pvBuff, RTSEMEVENT hEventSem);
     92const VBOXSHGSMIHEADER* VBoxSHGSMICommandPrepSynch(struct _HGSMIHEAP * pHeap, PVOID pCmd);
     93const VBOXSHGSMIHEADER* VBoxSHGSMICommandPrepAsynch(struct _HGSMIHEAP * pHeap, PVOID pvBuff, PFNVBOXSHGSMICMDCOMPLETION pfnCompletion, PVOID pvCompletion, uint32_t fFlags);
     94const VBOXSHGSMIHEADER* VBoxSHGSMICommandPrepAsynchIrq(struct _HGSMIHEAP * pHeap, PVOID pvBuff, PFNVBOXSHGSMICMDCOMPLETION_IRQ pfnCompletion, PVOID pvCompletion, uint32_t fFlags);
     95
     96void VBoxSHGSMICommandDoneAsynch(struct _HGSMIHEAP * pHeap, const VBOXSHGSMIHEADER* pHeader);
     97int VBoxSHGSMICommandDoneSynch(struct _HGSMIHEAP * pHeap, const VBOXSHGSMIHEADER* pHeader);
     98void VBoxSHGSMICommandCancelAsynch(struct _HGSMIHEAP * pHeap, const VBOXSHGSMIHEADER* pHeader);
     99void VBoxSHGSMICommandCancelSynch(struct _HGSMIHEAP * pHeap, const VBOXSHGSMIHEADER* pHeader);
     100
     101DECLINLINE(HGSMIOFFSET) VBoxSHGSMICommandOffset(struct _HGSMIHEAP * pHeap, const VBOXSHGSMIHEADER* pHeader)
     102{
     103    return HGSMIHeapBufferOffset(pHeap, (void*)pHeader);
     104}
     105
     106void* VBoxSHGSMICommandAlloc(struct _HGSMIHEAP * pHeap, HGSMISIZE cbData, uint8_t u8Channel, uint16_t u16ChannelInfo);
     107void VBoxSHGSMICommandFree(struct _HGSMIHEAP * pHeap, void *pvBuffer);
     108int VBoxSHGSMICommandProcessCompletion(struct _HGSMIHEAP * pHeap, HGSMIOFFSET offCmd, bool bIrq, PVBOXSHGSMILIST pPostProcessList);
     109int VBoxSHGSMICommandPostprocessCompletion(struct _HGSMIHEAP * pHeap, PVBOXSHGSMILIST pPostProcessList);
    101110
    102111#endif /* #ifndef ___VBoxVideoShgsmi_h___ */
  • trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoVdma.cpp

    r27383 r28228  
    2929 */
    3030
     31#ifdef VBOXVDMA_WITH_VBVA
     32static int vboxWddmVdmaSubmitVbva(struct _DEVICE_EXTENSION* pDevExt, PVBOXVDMAINFO pInfo, HGSMIOFFSET offDr)
     33{
     34    return vboxVbvaReportCmdOffset(pDevExt, &pDevExt->u.primary.Vbva, offDr);
     35}
     36#define vboxWddmVdmaSubmit vboxWddmVdmaSubmitVbva
     37#else
     38static int vboxWddmVdmaSubmitHgsmi(struct _DEVICE_EXTENSION* pDevExt, PVBOXVDMAINFO pInfo, HGSMIOFFSET offDr)
     39{
     40    VBoxHGSMIGuestWrite(pDevExt, offDr);
     41    return VINF_SUCCESS;
     42}
     43#define vboxWddmVdmaSubmit vboxWddmVdmaSubmitHgsmi
     44#endif
    3145
    3246static int vboxVdmaInformHost (PDEVICE_EXTENSION pDevExt, PVBOXVDMAINFO pInfo, VBOXVDMA_CTL_TYPE enmCtl)
     
    3448    int rc = VINF_SUCCESS;
    3549
    36     PVBOXVDMA_CTL pCmd = (PVBOXVDMA_CTL)VBoxSHGSMICommandAlloc (&pDevExt->u.primary.hgsmiAdapterHeap, sizeof (VBOXVDMA_CTL), HGSMI_CH_VBVA, VBVA_VDMA_CTL);
     50    PVBOXVDMA_CTL pCmd = (PVBOXVDMA_CTL)VBoxSHGSMICommandAlloc(&pDevExt->u.primary.hgsmiAdapterHeap, sizeof (VBOXVDMA_CTL), HGSMI_CH_VBVA, VBVA_VDMA_CTL);
    3751    if (pCmd)
    3852    {
     
    4155        pCmd->i32Result = VERR_NOT_SUPPORTED;
    4256
    43         VBoxSHGSMICommandSubmitSynch (&pDevExt->u.primary.hgsmiAdapterHeap, pCmd);
    44 
    45         rc = pCmd->i32Result;
    46         AssertRC(rc);
     57        const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepSynch(&pDevExt->u.primary.hgsmiAdapterHeap, pCmd);
     58        Assert(pHdr);
     59        if (pHdr)
     60        {
     61            do
     62            {
     63                HGSMIOFFSET offCmd = VBoxSHGSMICommandOffset(&pDevExt->u.primary.hgsmiAdapterHeap, pHdr);
     64                Assert(offCmd != HGSMIOFFSET_VOID);
     65                if (offCmd != HGSMIOFFSET_VOID)
     66                {
     67                    rc = vboxWddmVdmaSubmit(pDevExt, pInfo, offCmd);
     68                    AssertRC(rc);
     69                    if (RT_SUCCESS(rc))
     70                    {
     71                        rc = VBoxSHGSMICommandDoneSynch(&pDevExt->u.primary.hgsmiAdapterHeap, pHdr);
     72                        AssertRC(rc);
     73                        if (RT_SUCCESS(rc))
     74                        {
     75                            rc = pCmd->i32Result;
     76                            AssertRC(rc);
     77                        }
     78                        break;
     79                    }
     80                }
     81                else
     82                    rc = VERR_INVALID_PARAMETER;
     83                /* fail to submit, cancel it */
     84                VBoxSHGSMICommandCancelSynch(&pDevExt->u.primary.hgsmiAdapterHeap, pHdr);
     85            } while (0);
     86        }
    4787
    4888        VBoxSHGSMICommandFree (&pDevExt->u.primary.hgsmiAdapterHeap, pCmd);
     
    248288}
    249289
    250 void vboxVdmaCBufDrSubmit (PDEVICE_EXTENSION pDevExt, PVBOXVDMAINFO pInfo, PVBOXVDMACBUF_DR pDr)
    251 {
    252     VBoxSHGSMICommandSubmitAsynchIrq (&pInfo->CmdHeap, pDr, vboxVdmaCBufDrCompletionIrq, pDevExt, VBOXSHGSMI_FLAG_GH_ASYNCH_FORCE);
    253 }
     290int vboxVdmaCBufDrSubmit(PDEVICE_EXTENSION pDevExt, PVBOXVDMAINFO pInfo, PVBOXVDMACBUF_DR pDr)
     291{
     292    const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepAsynchIrq (&pInfo->CmdHeap, pDr, vboxVdmaCBufDrCompletionIrq, pDevExt, VBOXSHGSMI_FLAG_GH_ASYNCH_FORCE);
     293    Assert(pHdr);
     294    int rc = VERR_GENERAL_FAILURE;
     295    if (pHdr)
     296    {
     297        do
     298        {
     299            HGSMIOFFSET offCmd = VBoxSHGSMICommandOffset(&pInfo->CmdHeap, pHdr);
     300            Assert(offCmd != HGSMIOFFSET_VOID);
     301            if (offCmd != HGSMIOFFSET_VOID)
     302            {
     303                rc = vboxWddmVdmaSubmit(pDevExt, pInfo, offCmd);
     304                AssertRC(rc);
     305                if (RT_SUCCESS(rc))
     306                {
     307                    VBoxSHGSMICommandDoneAsynch(&pInfo->CmdHeap, pHdr);
     308                    AssertRC(rc);
     309                    break;
     310                }
     311            }
     312            else
     313                rc = VERR_INVALID_PARAMETER;
     314            /* fail to submit, cancel it */
     315            VBoxSHGSMICommandCancelAsynch(&pInfo->CmdHeap, pHdr);
     316        } while (0);
     317    }
     318    else
     319        rc = VERR_INVALID_PARAMETER;
     320    return rc;
     321}
  • trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoVdma.h

    r28031 r28228  
    2121#include "../VBoxVideo.h"
    2222
     23#if 0
     24typedef DECLCALLBACK(int) FNVBOXVDMASUBMIT(struct _DEVICE_EXTENSION* pDevExt, struct VBOXVDMAINFO * pInfo, HGSMIOFFSET offDr, PVOID pvContext);
     25typedef FNVBOXVDMASUBMIT *PFNVBOXVDMASUBMIT;
     26
     27typedef struct VBOXVDMASUBMIT
     28{
     29    PFNVBOXVDMASUBMIT pfnSubmit;
     30    PVOID pvContext;
     31} VBOXVDMASUBMIT, *PVBOXVDMASUBMIT;
     32#endif
     33
    2334/* DMA commands are currently submitted over HGSMI */
    2435typedef struct VBOXVDMAINFO
     
    2738    UINT      uLastCompletedPagingBufferCmdFenceId;
    2839    BOOL      fEnabled;
     40#if 0
     41    VBOXVDMASUBMIT Submitter;
     42#endif
    2943} VBOXVDMAINFO, *PVBOXVDMAINFO;
    3044
    31 int vboxVdmaCreate (struct _DEVICE_EXTENSION* pDevExt, VBOXVDMAINFO *pInfo, ULONG offBuffer, ULONG cbBuffer);
     45int vboxVdmaCreate (struct _DEVICE_EXTENSION* pDevExt, VBOXVDMAINFO *pInfo, ULONG offBuffer, ULONG cbBuffer
     46#if 0
     47        , PFNVBOXVDMASUBMIT pfnSubmit, PVOID pvContext
     48#endif
     49        );
    3250int vboxVdmaDisable (struct _DEVICE_EXTENSION* pDevExt, PVBOXVDMAINFO pInfo);
    3351int vboxVdmaEnable (struct _DEVICE_EXTENSION* pDevExt, PVBOXVDMAINFO pInfo);
    3452int vboxVdmaFlush (struct _DEVICE_EXTENSION* pDevExt, PVBOXVDMAINFO pInfo);
    3553int vboxVdmaDestroy (struct _DEVICE_EXTENSION* pDevExt, PVBOXVDMAINFO pInfo);
    36 void vboxVdmaCBufDrSubmit (struct _DEVICE_EXTENSION* pDevExt, PVBOXVDMAINFO pInfo, PVBOXVDMACBUF_DR pDr);
     54int vboxVdmaCBufDrSubmit (struct _DEVICE_EXTENSION* pDevExt, PVBOXVDMAINFO pInfo, PVBOXVDMACBUF_DR pDr);
    3755struct VBOXVDMACBUF_DR* vboxVdmaCBufDrCreate (PVBOXVDMAINFO pInfo, uint32_t cbTrailingData);
    3856void vboxVdmaCBufDrFree (PVBOXVDMAINFO pInfo, struct VBOXVDMACBUF_DR* pDr);
  • trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoWddm.cpp

    r28031 r28228  
    4242}
    4343
    44 void vboxSHGSMICbCommandWrite(struct _HGSMIHEAP * pHeap, HGSMIOFFSET data)
    45 {
    46     /* @todo: this should be taken from PDEVICE_EXTENSION */
    47     //VBoxHGSMIGuestWrite(pDevExt, data);
    48     VBoxVideoCmnPortWriteUlong((PULONG)VGA_PORT_HGSMI_GUEST, data);
    49 }
    50 
    5144//VBOXVIDEOOFFSET vboxWddmVRAMAddressToOffset(PDEVICE_EXTENSION pDevExt, PHYSICAL_ADDRESS phAddress)
    5245//{
     
    8780}
    8881
    89 NTSTATUS vboxWddmGhDisplayPostInfoScreen (PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
     82NTSTATUS vboxWddmGhDisplayPostInfoScreen (PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pAllocation, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
    9083{
    9184    VBOXVIDEOOFFSET offVram = pAllocation->offVram;
     
    9487        return STATUS_INVALID_PARAMETER;
    9588
    96     PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE pPrimaryInfo = VBOXWDDM_ALLOCATION_BODY(pAllocation, VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE);
     89//    PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE pPrimaryInfo = VBOXWDDM_ALLOCATION_BODY(pAllocation, VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE);
    9790    /* Issue the screen info command. */
    9891    void *p = vboxHGSMIBufferAlloc (pDevExt,
     
    10598        VBVAINFOSCREEN *pScreen = (VBVAINFOSCREEN *)p;
    10699
    107         pScreen->u32ViewIndex    = pPrimaryInfo->VidPnSourceId;
     100        pScreen->u32ViewIndex    = /*pPrimaryInfo->*/VidPnSourceId;
    108101        pScreen->i32OriginX      = 0;
    109102        pScreen->i32OriginY      = 0;
     
    123116}
    124117
    125 NTSTATUS vboxWddmGhDisplayPostInfoView (PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
    126 {
    127     VBOXVIDEOOFFSET offVram = pAllocation->offVram;
    128     Assert(offVram != VBOXVIDEOOFFSET_VOID);
    129     if (offVram == VBOXVIDEOOFFSET_VOID)
    130         return STATUS_INVALID_PARAMETER;
    131 
    132     PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE pPrimaryInfo = VBOXWDDM_ALLOCATION_BODY(pAllocation, VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE);
     118/* all views have a zero offset */
     119NTSTATUS vboxWddmGhDisplayPostInfoView (PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pAllocation, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
     120{
     121//    VBOXVIDEOOFFSET offVram = pAllocation->offVram;
     122//    Assert(offVram != VBOXVIDEOOFFSET_VOID);
     123//    if (offVram == VBOXVIDEOOFFSET_VOID)
     124//        return STATUS_INVALID_PARAMETER;
     125
     126//    PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE pPrimaryInfo = VBOXWDDM_ALLOCATION_BODY(pAllocation, VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE);
    133127    /* Issue the screen info command. */
    134128    void *p = vboxHGSMIBufferAlloc (pDevExt,
     
    141135        VBVAINFOVIEW *pView = (VBVAINFOVIEW *)p;
    142136
    143         pView->u32ViewIndex     = pPrimaryInfo->VidPnSourceId;
    144         pView->u32ViewOffset    = (uint32_t)offVram;
     137        pView->u32ViewIndex     = /*pPrimaryInfo->*/VidPnSourceId;
     138        pView->u32ViewOffset    = 0;//(uint32_t)offVram;
    145139        pView->u32ViewSize      = vboxWddmVramCpuVisibleSegmentSize(pDevExt)/pDevExt->cSources;
    146140
     
    155149}
    156150
    157 NTSTATUS vboxWddmGhDisplaySetMode (PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
    158 {
    159     PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE pPrimaryInfo = VBOXWDDM_ALLOCATION_BODY(pAllocation, VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE);
    160     if (pPrimaryInfo->VidPnSourceId)
     151NTSTATUS vboxWddmGhDisplaySetMode (PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pAllocation, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
     152{
     153//    PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE pPrimaryInfo = VBOXWDDM_ALLOCATION_BODY(pAllocation, VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE);
     154    if (/*pPrimaryInfo->*/VidPnSourceId)
    161155        return STATUS_SUCCESS;
    162156
     
    173167NTSTATUS vboxWddmGhDisplaySetInfo(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_SOURCE pSource)
    174168{
    175     PVBOXWDDM_ALLOCATION pAllocation = pSource->pAllocation;
     169
     170#ifndef VBOXWDDM_RENDER_FROM_SHADOW
     171    PVBOXWDDM_ALLOCATION pAllocation = pSource->pPrimaryAllocation;
     172    PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE pPrimaryInfo = VBOXWDDM_ALLOCATION_BODY(pAllocation, VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE);
     173#else
     174    PVBOXWDDM_ALLOCATION pAllocation = pSource->pShadowAllocation;
     175    PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE pPrimaryInfo = VBOXWDDM_ALLOCATION_BODY(pSource->pPrimaryAllocation, VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE);
     176#endif
    176177    VBOXVIDEOOFFSET offVram = vboxWddmValidatePrimary(pAllocation);
    177178    Assert(offVram != VBOXVIDEOOFFSET_VOID);
     
    182183     * Set the current mode into the hardware.
    183184     */
    184     NTSTATUS Status = vboxWddmGhDisplaySetMode (pDevExt, pAllocation);
     185    NTSTATUS Status = vboxWddmGhDisplaySetMode (pDevExt, pAllocation, pPrimaryInfo->VidPnSourceId);
    185186    Assert(Status == STATUS_SUCCESS);
    186187    if (Status == STATUS_SUCCESS)
    187188    {
    188         Status = vboxWddmGhDisplayPostInfoView (pDevExt, pAllocation);
     189        Status = vboxWddmGhDisplayPostInfoView (pDevExt, pAllocation, pPrimaryInfo->VidPnSourceId);
    189190        Assert(Status == STATUS_SUCCESS);
    190191        if (Status == STATUS_SUCCESS)
    191192        {
    192             Status = vboxWddmGhDisplayPostInfoScreen (pDevExt, pAllocation);
     193            Status = vboxWddmGhDisplayPostInfoScreen (pDevExt, pAllocation, pPrimaryInfo->VidPnSourceId);
    193194            Assert(Status == STATUS_SUCCESS);
    194195            if (Status != STATUS_SUCCESS)
     
    203204    return Status;
    204205}
     206
     207#ifdef VBOXWDDM_RENDER_FROM_SHADOW
     208bool vboxWddmCheckUpdateShadowAddress(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_SOURCE pSource, UINT SegmentId, VBOXVIDEOOFFSET offVram)
     209{
     210    if (pSource->offVram == offVram)
     211        return false;
     212    pSource->offVram = offVram;
     213    pSource->pShadowAllocation->SegmentId = SegmentId;
     214    pSource->pShadowAllocation->offVram = offVram;
     215
     216    NTSTATUS Status = vboxWddmGhDisplaySetInfo(pDevExt, pSource);
     217    Assert(Status == STATUS_SUCCESS);
     218    if (Status != STATUS_SUCCESS)
     219        drprintf((__FUNCTION__": vboxWddmGhDisplaySetInfo failed, Status (0x%x)\n", Status));
     220
     221    return true;
     222}
     223
     224bool vboxWddmRectIsEmpty(RECTL * pRect)
     225{
     226    return pRect->left == pRect->right-1 && pRect->top == pRect->bottom-1;
     227}
     228
     229bool vboxWddmRectIntersect(RECTL * pRect1, RECTL * pRect2)
     230{
     231    return !((pRect1->left < pRect2->left && pRect1->right < pRect2->left)
     232            || (pRect2->left < pRect1->left && pRect2->right < pRect1->left)
     233            || (pRect1->top < pRect2->top && pRect1->bottom < pRect2->top)
     234            || (pRect2->top < pRect1->top && pRect2->bottom < pRect1->top));
     235}
     236
     237bool vboxWddmRectInclude(RECTL * pRect1, RECTL * pRect2)
     238{
     239    return ((pRect1->left <= pRect2->left && pRect1->right >= pRect2->right)
     240            && (pRect1->top <= pRect2->top && pRect1->bottom >= pRect2->bottom));
     241}
     242
     243void vboxWddmRectUnited(RECT * pDst, const RECT * pRect1, const RECT * pRect2)
     244{
     245    pDst->left = RT_MIN(pRect1->left, pRect2->left);
     246    pDst->top = RT_MIN(pRect1->top, pRect2->top);
     247    pDst->right = RT_MAX(pRect1->right, pRect2->right);
     248    pDst->bottom = RT_MAX(pRect1->bottom, pRect2->bottom);
     249}
     250
     251void vboxWddmRectTranslate(RECTL * pRect, int x, int y)
     252{
     253    pRect->left   += x;
     254    pRect->top    += y;
     255    pRect->right  += x;
     256    pRect->bottom += y;
     257}
     258#endif
    205259
    206260HGSMIHEAP* vboxWddmHgsmiGetHeapFromCmdOffset(PDEVICE_EXTENSION pDevExt, HGSMIOFFSET offCmd)
     
    385439        case D3DDDIFMT_A16B16G16R16:
    386440            return 64;
     441        case D3DDDIFMT_A8P8:
     442            return 16;
     443        case D3DDDIFMT_P8:
     444            return 8;
    387445        default:
    388446            AssertBreakpoint();
     
    561619        pContext->pPDO = PhysicalDeviceObject;
    562620        *MiniportDeviceContext = pContext;
     621#ifdef VBOXWDDM_RENDER_FROM_SHADOW
     622        for (int i = 0; i < RT_ELEMENTS(pContext->aSources); ++i)
     623        {
     624            pContext->aSources[i].offVram = VBOXVIDEOOFFSET_VOID;
     625        }
     626#endif
    563627    }
    564628    else
     
    11691233             * DXGK_QUERYSEGMENTIN *pQsIn = (DXGK_QUERYSEGMENTIN*)pQueryAdapterInfo->pInputData; */
    11701234            DXGK_QUERYSEGMENTOUT *pQsOut = (DXGK_QUERYSEGMENTOUT*)pQueryAdapterInfo->pOutputData;
    1171 #ifdef VBOXWDDM_WITH_FAKE_SEGMENT
     1235#ifdef VBOXWDDM_RENDER_FROM_SHADOW
    11721236# define VBOXWDDM_SEGMENTS_COUNT 2
    11731237#else
     
    11991263                pDr->Flags.Value = 0;
    12001264                pDr->Flags.CpuVisible = 1;
    1201 #ifdef VBOXWDDM_WITH_FAKE_SEGMENT
     1265#ifdef VBOXWDDM_RENDER_FROM_SHADOW
    12021266                ++pDr;
    12031267                /* create cpu-invisible segment of the same size */
     
    12861350            break;
    12871351        }
     1352#ifdef VBOXWDDM_RENDER_FROM_SHADOW
     1353        case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
     1354        {
     1355            PVBOXWDDM_ALLOCATION_SHADOWSURFACE pAlloc = VBOXWDDM_ALLOCATION_BODY(pAllocation, VBOXWDDM_ALLOCATION_SHADOWSURFACE);
     1356            if (pAlloc->bAssigned)
     1357            {
     1358                Assert(pAlloc->VidPnSourceId != D3DDDI_ID_UNINITIALIZED);
     1359                /* @todo: do we need to notify host? */
     1360                vboxWddmAssignShadow(pDevExt, &pDevExt->aSources[pAlloc->VidPnSourceId], NULL, pAlloc->VidPnSourceId);
     1361            }
     1362            break;
     1363        }
     1364#endif
    12881365        default:
    12891366            break;
     
    13331410                            pAllocationInfo->HintedBank.Value = 0;
    13341411                            pAllocationInfo->PreferredSegment.Value = 0;
     1412#if 1 //defined(VBOXWDDM_RENDER_FROM_SHADOW)
    13351413                            pAllocationInfo->SupportedReadSegmentSet = 1;
    13361414                            pAllocationInfo->SupportedWriteSegmentSet = 1;
     1415#else
     1416                            pAllocationInfo->SupportedReadSegmentSet = 2;
     1417                            pAllocationInfo->SupportedWriteSegmentSet = 2;
     1418#endif
    13371419                            pAllocationInfo->EvictionSegmentSet = 0;
    13381420                            pAllocationInfo->MaximumRenamingListLength = 0;
    13391421                            pAllocationInfo->hAllocation = pAllocation;
    13401422                            pAllocationInfo->Flags.Value = 0;
     1423#ifndef VBOXWDDM_RENDER_FROM_SHADOW
    13411424                            pAllocationInfo->Flags.CpuVisible = 1;
     1425#endif
    13421426                            pAllocationInfo->pAllocationUsageHint = NULL;
    13431427                            pAllocationInfo->AllocationPriority = D3DDDI_ALLOCATIONPRIORITY_NORMAL;
     
    13631447            }
    13641448            case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
     1449#ifdef VBOXWDDM_RENDER_FROM_SHADOW
     1450            {
     1451                Assert(pAllocationInfo->PrivateDriverDataSize >= VBOXWDDM_ALLOCINFO_HEADSIZE());
     1452                if (pAllocationInfo->PrivateDriverDataSize >= VBOXWDDM_ALLOCINFO_HEADSIZE())
     1453                {
     1454                    PVBOXWDDM_ALLOCATION pAllocation = (PVBOXWDDM_ALLOCATION)vboxWddmMemAllocZero(VBOXWDDM_ALLOCATION_SIZE(VBOXWDDM_ALLOCATION_SHADOWSURFACE));
     1455                    Assert(pAllocation);
     1456                    if (pAllocation)
     1457                    {
     1458                        pAllocation->enmType = pAllocInfo->enmType;
     1459                        pAllocation->offVram = VBOXVIDEOOFFSET_VOID;
     1460                        pAllocation->u.SurfInfo = pAllocInfo->u.SurfInfo;
     1461
     1462                        pAllocationInfo->pPrivateDriverData = NULL;
     1463                        pAllocationInfo->PrivateDriverDataSize = 0;
     1464                        pAllocationInfo->Alignment = 0;
     1465                        pAllocationInfo->Size = pAllocInfo->u.SurfInfo.pitch * pAllocInfo->u.SurfInfo.height;
     1466                        pAllocationInfo->PitchAlignedSize = 0;
     1467                        pAllocationInfo->HintedBank.Value = 0;
     1468                        pAllocationInfo->PreferredSegment.Value = 0;
     1469                        pAllocationInfo->SupportedReadSegmentSet = 1;
     1470                        pAllocationInfo->SupportedWriteSegmentSet = 1;
     1471                        pAllocationInfo->EvictionSegmentSet = 0;
     1472                        pAllocationInfo->MaximumRenamingListLength = 0;
     1473                        pAllocationInfo->hAllocation = pAllocation;
     1474                        pAllocationInfo->Flags.Value = 0;
     1475                        pAllocationInfo->Flags.CpuVisible = 1;
     1476                        pAllocationInfo->pAllocationUsageHint = NULL;
     1477                        pAllocationInfo->AllocationPriority = D3DDDI_ALLOCATIONPRIORITY_NORMAL;
     1478                        PVBOXWDDM_ALLOCATION_SHADOWSURFACE pAlloc = VBOXWDDM_ALLOCATION_BODY(pAllocation, VBOXWDDM_ALLOCATION_SHADOWSURFACE);
     1479                        pAlloc->VidPnSourceId = D3DDDI_ID_UNINITIALIZED;
     1480//                        pAlloc->bVisible = FALSE;
     1481//                        pAlloc->bAssigned = FALSE;
     1482                    }
     1483                    else
     1484                    {
     1485                        drprintf((__FUNCTION__ ": ERROR: failed to create allocation description\n"));
     1486                        Status = STATUS_NO_MEMORY;
     1487                    }
     1488                }
     1489                else
     1490                {
     1491                    drprintf((__FUNCTION__ ": ERROR: PrivateDriverDataSize(%d) less than cmd size(%d)\n", pAllocationInfo->PrivateDriverDataSize, VBOXWDDM_ALLOCINFO_HEADSIZE()));
     1492                    Status = STATUS_INVALID_PARAMETER;
     1493                }
     1494                break;
     1495            }
     1496#endif
    13651497            case VBOXWDDM_ALLOC_TYPE_STD_STAGINGSURFACE:
    13661498            {
     
    16621794    dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
    16631795
    1664     vboxVDbgBreakFv();
     1796    vboxVDbgBreakF();
    16651797
    16661798    /* Value == 2 is Present
     
    16681800     * we do not expect any other flags to be set here */
    16691801//    Assert(pPatch->Flags.Value == 2 || pPatch->Flags.Value == 4);
    1670 
     1802#ifdef VBOXWDDM_RENDER_FROM_SHADOW
     1803    Assert(pPatch->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATE_DATA));
     1804    Assert(pPatch->DmaBufferPrivateDataSubmissionEndOffset - pPatch->DmaBufferPrivateDataSubmissionStartOffset >= sizeof (VBOXWDDM_DMA_PRIVATE_DATA));
     1805    if (pPatch->DmaBufferPrivateDataSubmissionEndOffset - pPatch->DmaBufferPrivateDataSubmissionStartOffset >= sizeof (VBOXWDDM_DMA_PRIVATE_DATA))
     1806    {
     1807        PVBOXWDDM_DMA_PRIVATE_DATA pPrivateData = (PVBOXWDDM_DMA_PRIVATE_DATA)((uint8_t*)pPatch->pDmaBufferPrivateData + pPatch->DmaBufferPrivateDataSubmissionStartOffset);
     1808        const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[0];
     1809        Assert(pPatchList->AllocationIndex == DXGK_PRESENT_SOURCE_INDEX);
     1810        Assert(pPatchList->PatchOffset == 0);
     1811        const DXGK_ALLOCATIONLIST *pAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
     1812        Assert(pAllocationList->SegmentId);
     1813        pPrivateData->segmentIdShadow = pAllocationList->SegmentId;
     1814        pPrivateData->offShadow = (VBOXVIDEOOFFSET)pAllocationList->PhysicalAddress.QuadPart;
     1815    }
     1816    else
     1817    {
     1818        drprintf((__FUNCTION__": DmaBufferPrivateDataSubmissionEndOffset (%d) - DmaBufferPrivateDataSubmissionStartOffset (%d) < sizeof (VBOXWDDM_DMA_PRIVATE_DATA) (%d)\n",
     1819                pPatch->DmaBufferPrivateDataSubmissionEndOffset,
     1820                pPatch->DmaBufferPrivateDataSubmissionStartOffset,
     1821                sizeof (VBOXWDDM_DMA_PRIVATE_DATA)));
     1822        return STATUS_INVALID_PARAMETER;
     1823    }
     1824#else
    16711825    uint8_t *pBuf = ((uint8_t *)pPatch->pDmaBuffer) + pPatch->DmaBufferSubmissionStartOffset;
    16721826    for (UINT i = pPatch->PatchLocationListSubmissionStart; i < pPatch->PatchLocationListSubmissionLength; ++i)
     
    16871841        }
    16881842    }
     1843#endif
    16891844
    16901845    dfprintf(("<== "__FUNCTION__ ", context(0x%x)\n", hAdapter));
     
    16921847    return Status;
    16931848}
     1849
     1850#ifdef VBOXWDDM_RENDER_FROM_SHADOW
     1851typedef struct VBOXWDDM_SHADOW_UPDATE_COMPLETION
     1852{
     1853    PDEVICE_EXTENSION pDevExt;
     1854    PVBOXWDDM_DMA_PRIVATE_DATA pTransactionData;
     1855    UINT SubmissionFenceId;
     1856} VBOXWDDM_SHADOW_UPDATE_COMPLETION, *PVBOXWDDM_SHADOW_UPDATE_COMPLETION;
     1857
     1858BOOLEAN vboxWddmNotifyShadowUpdateCompletion(PVOID Context)
     1859{
     1860    PVBOXWDDM_SHADOW_UPDATE_COMPLETION pdc = (PVBOXWDDM_SHADOW_UPDATE_COMPLETION)Context;
     1861    PDEVICE_EXTENSION pDevExt = pdc->pDevExt;
     1862    DXGKARGCB_NOTIFY_INTERRUPT_DATA notify;
     1863    memset(&notify, 0, sizeof(DXGKARGCB_NOTIFY_INTERRUPT_DATA));
     1864
     1865    notify.InterruptType = DXGK_INTERRUPT_DMA_COMPLETED;
     1866    notify.DmaCompleted.SubmissionFenceId = pdc->SubmissionFenceId;
     1867    notify.DmaCompleted.NodeOrdinal = pdc->pTransactionData->pContext->NodeOrdinal;
     1868    notify.DmaCompleted.EngineOrdinal = 0;
     1869    pdc->pTransactionData->pContext->uLastCompletedCmdFenceId = pdc->SubmissionFenceId;
     1870
     1871    pDevExt->u.primary.DxgkInterface.DxgkCbNotifyInterrupt(pDevExt->u.primary.DxgkInterface.DeviceHandle, &notify);
     1872
     1873    pDevExt->bNotifyDxDpc = TRUE;
     1874    BOOLEAN bDpcQueued = pDevExt->u.primary.DxgkInterface.DxgkCbQueueDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
     1875    Assert(bDpcQueued);
     1876
     1877    return bDpcQueued;
     1878}
     1879#endif
     1880
    16941881
    16951882NTSTATUS
     
    17041891//    dfprintf(("==> "__FUNCTION__ ", context(0x%x)\n", hAdapter));
    17051892
    1706     vboxVDbgBreakFv();
     1893    vboxVDbgBreakF();
    17071894
    17081895    PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)hAdapter;
    1709 
    17101896    Assert(!pSubmitCommand->DmaBufferSegmentId);
    17111897
     
    17241910    PVBOXWDDM_DMA_PRIVATE_DATA pPrivateData = (PVBOXWDDM_DMA_PRIVATE_DATA)((uint8_t*)pSubmitCommand->pDmaBufferPrivateData + pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset);
    17251911    Assert(pPrivateData);
     1912#ifdef VBOXWDDM_RENDER_FROM_SHADOW
     1913    VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pPrivateData->srcId];
     1914    BOOLEAN bRet;
     1915    vboxWddmCheckUpdateShadowAddress(pDevExt, pSource, pPrivateData->segmentIdShadow, pPrivateData->offShadow);
     1916    VBOXVBVA_OP(ReportDirtyRect, pDevExt, &pSource->Vbva, &pPrivateData->rect);
     1917    /* get DPC data at IRQL */
     1918
     1919    VBOXWDDM_SHADOW_UPDATE_COMPLETION context;
     1920    context.pDevExt = pDevExt;
     1921    context.pTransactionData = pPrivateData;
     1922    context.SubmissionFenceId = pSubmitCommand->SubmissionFenceId;
     1923    Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
     1924            pDevExt->u.primary.DxgkInterface.DeviceHandle,
     1925            vboxWddmNotifyShadowUpdateCompletion,
     1926            &context,
     1927            0, /* IN ULONG MessageNumber */
     1928            &bRet);
     1929#else
    17261930    PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate (&pDevExt->u.primary.Vdma, 0);
    17271931    if (!pDr)
     
    17431947
    17441948    vboxVdmaCBufDrSubmit (pDevExt, &pDevExt->u.primary.Vdma, pDr);
    1745 
     1949#endif
    17461950//    dfprintf(("<== "__FUNCTION__ ", context(0x%x)\n", hAdapter));
    17471951
     
    21642368}
    21652369
     2370
     2371/* the lpRgnData->Buffer comes to us as RECT
     2372 * to avoid extra memcpy we cast it to PRTRECT assuming
     2373 * they are identical */
     2374AssertCompile(sizeof(RECT) == sizeof(RTRECT));
     2375AssertCompile(RT_OFFSETOF(RECT, left) == RT_OFFSETOF(RTRECT, xLeft));
     2376AssertCompile(RT_OFFSETOF(RECT, bottom) == RT_OFFSETOF(RTRECT, yBottom));
     2377AssertCompile(RT_OFFSETOF(RECT, right) == RT_OFFSETOF(RTRECT, xRight));
     2378AssertCompile(RT_OFFSETOF(RECT, top) == RT_OFFSETOF(RTRECT, yTop));
     2379
    21662380NTSTATUS
    21672381APIENTRY
     
    21882402                /* the lpRgnData->Buffer comes to us as RECT
    21892403                 * to avoid extra memcpy we cast it to PRTRECT assuming
    2190                  * they are identical */
    2191                 AssertCompile(sizeof(RECT) == sizeof(RTRECT));
    2192                 AssertCompile(RT_OFFSETOF(RECT, left) == RT_OFFSETOF(RTRECT, xLeft));
    2193                 AssertCompile(RT_OFFSETOF(RECT, bottom) == RT_OFFSETOF(RTRECT, yBottom));
    2194                 AssertCompile(RT_OFFSETOF(RECT, right) == RT_OFFSETOF(RTRECT, xRight));
    2195                 AssertCompile(RT_OFFSETOF(RECT, top) == RT_OFFSETOF(RTRECT, yTop));
     2404                 * they are identical
     2405                 * see AssertCompile's above */
     2406
    21962407                RTRECT   *pRect = (RTRECT *)&lpRgnData->Buffer;
    21972408
     
    25922803        PVBOXWDDM_ALLOCATION pAllocation;
    25932804        Assert(pSetVidPnSourceAddress->hAllocation);
    2594         Assert(pSetVidPnSourceAddress->hAllocation || pSource->pAllocation);
     2805        Assert(pSetVidPnSourceAddress->hAllocation || pSource->pPrimaryAllocation);
    25952806        Assert (pSetVidPnSourceAddress->Flags.Value < 2); /* i.e. 0 or 1 (ModeChange) */
    25962807        if (pSetVidPnSourceAddress->hAllocation)
     
    26002811        }
    26012812        else
    2602             pAllocation = pSource->pAllocation;
     2813            pAllocation = pSource->pPrimaryAllocation;
    26032814
    26042815        Assert(pAllocation);
     
    26112822            Assert (pAllocation->SegmentId);
    26122823            Assert (!pPrimary->bVisible);
     2824#ifndef VBOXWDDM_RENDER_FROM_SHADOW
    26132825            if (pPrimary->bVisible)
    26142826            {
     
    26192831                    drprintf((__FUNCTION__": vboxWddmGhDisplaySetInfo failed, Status (0x%x)\n", Status));
    26202832            }
     2833#endif
    26212834        }
    26222835        else
     
    26572870    {
    26582871        PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pSetVidPnSourceVisibility->VidPnSourceId];
    2659         PVBOXWDDM_ALLOCATION pAllocation = pSource->pAllocation;
     2872        PVBOXWDDM_ALLOCATION pAllocation = pSource->pPrimaryAllocation;
    26602873        PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE pPrimary = VBOXWDDM_ALLOCATION_BODY(pAllocation, VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE);
    26612874
     
    26642877        {
    26652878            pPrimary->bVisible = pSetVidPnSourceVisibility->Visible;
     2879#ifndef VBOXWDDM_RENDER_FROM_SHADOW
    26662880            if (pPrimary->bVisible)
    26672881            {
     
    26752889                vboxVdmaFlush (pDevExt, &pDevExt->u.primary.Vdma);
    26762890            }
     2891#endif
    26772892        }
    26782893    }
     
    30713286
    30723287    PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[id];
    3073     if (pSource->pAllocation != pAllocation)
     3288    if (pSource->pPrimaryAllocation != pAllocation)
    30743289        return NULL;
    30753290
     
    31113326    {
    31123327        Assert(pPresent->Flags.Value == 1); /* only Blt is set, we do not support anything else for now */
     3328#ifndef VBOXWDDM_RENDER_FROM_SHADOW
    31133329        UINT cbCmd = pPresent->DmaSize;
    31143330
     
    31983414            Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
    31993415        }
    3200 
     3416#else
     3417        DXGK_ALLOCATIONLIST *pSrc =  &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
     3418        DXGK_ALLOCATIONLIST *pDst =  &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
     3419        PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pSrc);
     3420        Assert(pSrcAlloc);
     3421        if (pSrcAlloc)
     3422        {
     3423            PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
     3424            Assert(pDstAlloc);
     3425            if (pDstAlloc)
     3426            {
     3427                Assert (pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE);
     3428                Assert (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE);
     3429                if (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE)
     3430                {
     3431                    PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE pPrimaryInfo = VBOXWDDM_ALLOCATION_BODY(pDstAlloc, VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE);
     3432                    Assert(pPrimaryInfo->bAssigned);
     3433                    Assert(pPrimaryInfo->bVisible);
     3434                    if (pPrimaryInfo->bAssigned
     3435                            && pPrimaryInfo->bVisible)
     3436                    {
     3437                        if (pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE)
     3438                        {
     3439                            VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pPrimaryInfo->VidPnSourceId];
     3440                            vboxWddmAssignShadow(pDevExt, pSource, pSrcAlloc, pPrimaryInfo->VidPnSourceId);
     3441                            Assert(pPresent->SrcRect.left == pPresent->DstRect.left);
     3442                            Assert(pPresent->SrcRect.right == pPresent->DstRect.right);
     3443                            Assert(pPresent->SrcRect.top == pPresent->DstRect.top);
     3444                            Assert(pPresent->SrcRect.bottom == pPresent->DstRect.bottom);
     3445                            RECT rect;
     3446                            if (pPresent->SubRectCnt)
     3447                            {
     3448                                rect = pPresent->pDstSubRects[0];
     3449                                for (UINT i = 1; i < pPresent->SubRectCnt; ++i)
     3450                                {
     3451                                    vboxWddmRectUnited(&rect, &rect, &pPresent->pDstSubRects[i]);
     3452                                }
     3453                            }
     3454                            else
     3455                                rect = pPresent->SrcRect;
     3456
     3457//                            if (pSrc->SegmentId)
     3458//                            {
     3459//                                vboxWddmCheckUpdateShadowAddress(pDevExt, pSource, pSrc->SegmentId, (VBOXVIDEOOFFSET)pSrc->PhysicalAddress.QuadPart);
     3460//                                VBOXVBVA_OP(ReportDirtyRect, pDevExt, &pSource->Vbva, &rect);
     3461//                            }
     3462//                            else
     3463                            {
     3464#define VBOXWDDM_DUMMY_DMABUFFER_SIZE sizeof(RECT)
     3465                                pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
     3466                                pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof (VBOXWDDM_DMA_PRIVATE_DATA);
     3467                                Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
     3468                                Assert(pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATE_DATA));
     3469                                if (pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE
     3470                                        && pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATE_DATA))
     3471                                {
     3472                                    memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
     3473            //                        pPresent->pPatchLocationListOut->PatchOffset = 0;
     3474            //                        ++pPresent->pPatchLocationListOut;
     3475                                    pPresent->pPatchLocationListOut->PatchOffset = 0;
     3476                                    pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
     3477                                    ++pPresent->pPatchLocationListOut;
     3478                                    pPresent->pPatchLocationListOut->PatchOffset = 4;
     3479                                    pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
     3480                                    ++pPresent->pPatchLocationListOut;
     3481
     3482                                    /* we do not know the shadow address yet, perform dummy DMA cycle */
     3483                                    pPrivateData->rect = rect;
     3484                                    pPrivateData->srcId = pPrimaryInfo->VidPnSourceId;
     3485                                    if (pSrc->SegmentId)
     3486                                    {
     3487                                        pPrivateData->segmentIdShadow = pSrc->SegmentId;
     3488                                        pPrivateData->offShadow = (VBOXVIDEOOFFSET)pSrc->PhysicalAddress.QuadPart;
     3489                                    }
     3490                                }
     3491                                else
     3492                                {
     3493                                    /* this should not happen actually */
     3494//                                    drprintf((__FUNCTION__": cbCmd too small!! (%d)\n", cbCmd));
     3495                                    Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
     3496                                }
     3497                            }
     3498                        }
     3499                    }
     3500                }
     3501            }
     3502        }
     3503#endif
    32013504    }
    32023505    else
  • trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoWddm.h

    r28031 r28228  
    2929#define VBOXWDDM_C_VDMA_BUFFER_SIZE   (64*_1K)
    3030
    31 //#define VBOXWDDM_WITH_FAKE_SEGMENT
     31#define VBOXWDDM_RENDER_FROM_SHADOW
    3232
    3333#define VBOXWDDM_ROUNDBOUND(_v, _b) (((_v) + ((_b) - 1)) & ~((_b) - 1))
     
    8383{
    8484    VBOXWDDM_ALLOC_TYPE enmType;
     85    UINT SegmentId;
    8586    VBOXVIDEOOFFSET offVram;
    86     UINT SegmentId;
    8787    union
    8888    {
     
    109109    BOOLEAN bAssigned;
    110110} VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE, *PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE;
     111
     112#ifdef VBOXWDDM_RENDER_FROM_SHADOW
     113typedef struct VBOXWDDM_ALLOCATION_SHADOWSURFACE
     114{
     115    D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId;
     116//    VBOXVIDEOOFFSET offAddress;
     117    BOOLEAN bVisible;
     118    BOOLEAN bAssigned;
     119} VBOXWDDM_ALLOCATION_SHADOWSURFACE, *PVBOXWDDM_ALLOCATION_SHADOWSURFACE;
     120#endif
    111121
    112122typedef enum
     
    142152{
    143153    PVBOXWDDM_CONTEXT pContext;
    144     uint8_t Reserved[8];
     154#ifdef VBOXWDDM_RENDER_FROM_SHADOW
     155    RECT rect;
     156    VBOXVIDEOOFFSET offShadow;
     157    UINT segmentIdShadow;
     158    D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId;
     159#endif
     160//    uint8_t Reserved[8];
    145161}VBOXWDDM_DMA_PRIVATE_DATA, *PVBOXWDDM_DMA_PRIVATE_DATA;
    146162
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette