VirtualBox

Changeset 82415 in vbox for trunk/src/VBox/Additions


Ignore:
Timestamp:
Dec 5, 2019 12:56:36 PM (5 years ago)
Author:
vboxsync
Message:

WDDM: initial DXVA implementation

Location:
trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/gallium
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/gallium/GaDxva.cpp

    r82330 r82415  
    1616 */
    1717
    18 #include "VBoxGallium.h"
    19 //#include "../../../common/wddm/VBoxMPIf.h"
    2018#include "../VBoxDispD3DCmn.h"
    21 #include "../VBoxDispD3D.h"
    22 
    2319
    2420#define D3D_RELEASE(ptr) do { \
     
    3228struct Vertex
    3329{
    34     float x, y; /* The vertex position. */
    35     float u, v; /* Texture coordinates. */
     30    float x, y; /* The vertex position in pixels. */
     31    float u, v; /* Normalized texture coordinates. */
    3632};
     33
     34/* Saved context. */
     35typedef struct VBOXDXVAD3D9SAVEDSTATE
     36{
     37    D3DVIEWPORT9            Viewport;
     38    DWORD                   rsCull;
     39    DWORD                   rsZEnable;
     40    IDirect3DSurface9      *pRT;
     41    IDirect3DVertexShader9 *pVS;
     42    IDirect3DPixelShader9  *pPS;
     43    IDirect3DBaseTexture9  *pTexture;
     44    float                   aVSConstantData[4];
     45    float                   aPSConstantData[4];
     46    DWORD                   ssMagFilter;
     47    DWORD                   ssMinFilter;
     48    DWORD                   ssMipFilter;
     49} VBOXDXVAD3D9SAVEDSTATE;
    3750
    3851/*
     
    5164    /* The current render target, i.e. the Blt destination. */
    5265    PVBOXWDDMDISP_RESOURCE pRenderTarget;
    53     UINT SubResourceIndex;
    54     IDirect3DTexture9 *pRTTexture;
     66    UINT                   RTSubResourceIndex;
     67    IDirect3DTexture9      *pRTTexture;
     68    IDirect3DSurface9      *pRTSurface;
    5569
    5670    /* Private objects for video processing. */
    57     IDirect3DTexture9           *pTexture;    /* Intermediate texture. */
     71    IDirect3DTexture9           *pStagingTexture;    /* Intermediate texture. */
    5872    IDirect3DVertexBuffer9      *pVB;         /* Vertex buffer which describes the quad we render. */
    5973    IDirect3DVertexDeclaration9 *pVertexDecl; /* Vertex declaration for the quad vertices. */
    6074    IDirect3DVertexShader9      *pVS;         /* Vertex shader. */
    6175    IDirect3DPixelShader9       *pPS;         /* Pixel shader. */
     76
     77    /* Saved D3D device state, which the blitter changes. */
     78    VBOXDXVAD3D9SAVEDSTATE SavedState;
    6279} VBOXWDDMVIDEOPROCESSDEVICE;
    6380
    64 static const GUID gaDeviceGuids[] =
     81static GUID const gaDeviceGuids[] =
    6582{
    6683    DXVADDI_VideoProcProgressiveDevice,
     
    6885};
    6986
    70 static const D3DDDIFORMAT gaInputFormats[] =
     87static D3DDDIFORMAT const gaInputFormats[] =
    7188{
    7289    D3DDDIFMT_YUY2
    7390};
    7491
    75 static const D3DDDIFORMAT gaOutputFormats[] =
     92static D3DDDIFORMAT const gaOutputFormats[] =
    7693{
    7794    D3DDDIFMT_A8R8G8B8,
     
    99116}
    100117
    101 
    102 static HRESULT vboxDxvaInit(VBOXWDDMVIDEOPROCESSDEVICE *pVideoProcessDevice /*,
    103                             DWORD const *paVS, DWORD const *paPS*/)
     118static HRESULT vboxDxvaCopyToVertexBuffer(IDirect3DVertexBuffer9 *pVB, const void *pvSrc, int cbSrc)
     119{
     120    void *pvDst = 0;
     121    HRESULT hr = pVB->Lock(0, 0, &pvDst, 0);
     122    if (SUCCEEDED(hr))
     123    {
     124        memcpy(pvDst, pvSrc, cbSrc);
     125        hr = pVB->Unlock();
     126    }
     127    return hr;
     128}
     129
     130static HRESULT vboxDxvaDeviceStateSave(IDirect3DDevice9 *pDevice9, VBOXDXVAD3D9SAVEDSTATE *pState)
    104131{
    105132    HRESULT hr;
    106133
     134    hr = pDevice9->GetViewport(&pState->Viewport);
     135    AssertReturn(hr == D3D_OK, hr);
     136
     137    hr = pDevice9->GetRenderState(D3DRS_CULLMODE, &pState->rsCull);
     138    AssertReturn(hr == D3D_OK, hr);
     139
     140    hr = pDevice9->GetRenderState(D3DRS_ZENABLE, &pState->rsZEnable);
     141    AssertReturn(hr == D3D_OK, hr);
     142
     143    hr = pDevice9->GetRenderTarget(0, &pState->pRT);
     144    AssertReturn(hr == D3D_OK, hr);
     145
     146    hr = pDevice9->GetVertexShader(&pState->pVS);
     147    AssertReturn(hr == D3D_OK, hr);
     148
     149    hr = pDevice9->GetPixelShader(&pState->pPS);
     150    AssertReturn(hr == D3D_OK, hr);
     151
     152    hr = pDevice9->GetTexture(0, &pState->pTexture);
     153    AssertReturn(hr == D3D_OK, hr);
     154
     155    hr = pDevice9->GetVertexShaderConstantF(0, pState->aVSConstantData, 1);
     156    AssertReturn(hr == D3D_OK, hr);
     157
     158    hr = pDevice9->GetPixelShaderConstantF(0, pState->aPSConstantData, 1);
     159    AssertReturn(hr == D3D_OK, hr);
     160
     161    hr = pDevice9->GetSamplerState(0, D3DSAMP_MAGFILTER, &pState->ssMagFilter);
     162    AssertReturn(hr == D3D_OK, hr);
     163
     164    hr = pDevice9->GetSamplerState(0, D3DSAMP_MINFILTER, &pState->ssMinFilter);
     165    AssertReturn(hr == D3D_OK, hr);
     166
     167    hr = pDevice9->GetSamplerState(0, D3DSAMP_MIPFILTER, &pState->ssMipFilter);
     168    AssertReturn(hr == D3D_OK, hr);
     169
     170    return hr;
     171}
     172
     173static void vboxDxvaDeviceStateRestore(IDirect3DDevice9 *pDevice9, VBOXDXVAD3D9SAVEDSTATE const *pState)
     174{
     175    HRESULT hr;
     176
     177    hr = pDevice9->SetViewport(&pState->Viewport);
     178    Assert(hr == D3D_OK);
     179
     180    hr = pDevice9->SetRenderState(D3DRS_CULLMODE, pState->rsCull);
     181    Assert(hr == D3D_OK);
     182
     183    hr = pDevice9->SetRenderState(D3DRS_ZENABLE, pState->rsZEnable);
     184    Assert(hr == D3D_OK);
     185
     186    hr = pDevice9->SetRenderTarget(0, pState->pRT);
     187    Assert(hr == D3D_OK);
     188
     189    hr = pDevice9->SetVertexShader(pState->pVS);
     190    Assert(hr == D3D_OK);
     191
     192    hr = pDevice9->SetPixelShader(pState->pPS);
     193    Assert(hr == D3D_OK);
     194
     195    hr = pDevice9->SetTexture(0, pState->pTexture);
     196    Assert(hr == D3D_OK);
     197
     198    hr = pDevice9->SetVertexShaderConstantF(0, pState->aVSConstantData, 1);
     199    Assert(hr == D3D_OK);
     200
     201    hr = pDevice9->SetPixelShaderConstantF(0, pState->aPSConstantData, 1);
     202    Assert(hr == D3D_OK);
     203
     204    hr = pDevice9->SetSamplerState(0, D3DSAMP_MAGFILTER, pState->ssMagFilter);
     205    Assert(hr == D3D_OK);
     206
     207    hr = pDevice9->SetSamplerState(0, D3DSAMP_MINFILTER, pState->ssMinFilter);
     208    Assert(hr == D3D_OK);
     209
     210    hr = pDevice9->SetSamplerState(0, D3DSAMP_MIPFILTER, pState->ssMipFilter);
     211    Assert(hr == D3D_OK);
     212}
     213
     214static HRESULT vboxDxvaUploadSample(VBOXWDDMVIDEOPROCESSDEVICE *pVideoProcessDevice,
     215                                    IDirect3DTexture9 *pSrcTexture,
     216                                    UINT SrcSubResourceIndex)
     217{
     218    HRESULT hr;
     219
     220    /*
     221     * Upload the source data to the staging texture.
     222     */
     223    D3DLOCKED_RECT StagingLockedRect;
     224    hr = pVideoProcessDevice->pStagingTexture->LockRect(0, /* texture level */
     225                                                        &StagingLockedRect,
     226                                                        NULL,   /* entire texture */
     227                                                        D3DLOCK_DISCARD);
     228    Assert(hr == D3D_OK);
     229    if (hr == D3D_OK)
     230    {
     231        D3DLOCKED_RECT SampleLockedRect;
     232        hr = pSrcTexture->LockRect(SrcSubResourceIndex, /* texture level */
     233                                   &SampleLockedRect,
     234                                   NULL,   /* entire texture */
     235                                   D3DLOCK_READONLY);
     236        Assert(hr == D3D_OK);
     237        if (hr == D3D_OK)
     238        {
     239            uint8_t *pDst = (uint8_t *)StagingLockedRect.pBits;
     240            const uint8_t *pSrc = (uint8_t *)SampleLockedRect.pBits;
     241            for (uint32_t j = 0; j < pVideoProcessDevice->VideoDesc.SampleHeight; ++j)
     242            {
     243                memcpy(pDst, pSrc, RT_MIN(SampleLockedRect.Pitch, StagingLockedRect.Pitch));
     244
     245                pDst += StagingLockedRect.Pitch;
     246                pSrc += SampleLockedRect.Pitch;
     247            }
     248
     249            pSrcTexture->UnlockRect(SrcSubResourceIndex /* texture level */);
     250        }
     251        pVideoProcessDevice->pStagingTexture->UnlockRect(0 /* texture level */);
     252    }
     253
     254    return hr;
     255}
     256
     257/*
     258 * The shader code has been obtained from the hex listing file (hexdump.txt) produced by fxc HLSL compiler:
     259 * fxc.exe /Op /Tfx_2_0 /Fxhexdump.txt shader.fx
     260 *
     261    uniform extern float4 gTextureInfo; // .xy = (TargetWidth, TargetHeight), .zw = (SourceWidth, SourceHeight) in pixels
     262    uniform extern texture gTexSource;
     263    sampler sSource = sampler_state
     264    {
     265        Texture = <gTexSource>;
     266    };
     267
     268    struct VS_INPUT
     269    {
     270        float2 Position   : POSITION;  // In pixels
     271        float2 TexCoord   : TEXCOORD0; // Normalized
     272    };
     273
     274    struct VS_OUTPUT
     275    {
     276        float4 Position   : POSITION;  // Normalized
     277        float2 TexCoord   : TEXCOORD0; // Normalized
     278    };
     279
     280    VS_OUTPUT VS(VS_INPUT In)
     281    {
     282        VS_OUTPUT Output;
     283
     284        // Target position is in pixels, i.e left,top is 0,0; right,bottom is width - 1,height - 1.
     285        // Convert to the normalized coords in the -1;1 range (x right, y up).
     286        float4 Position;
     287        Position.x =  2.0f * In.Position.x / (gTextureInfo.x - 1.0f) - 1.0f;
     288        Position.y = -2.0f * In.Position.y / (gTextureInfo.y - 1.0f) + 1.0f;
     289        Position.z = 0.0f; // Not used.
     290        Position.w = 1.0f; // It is a point.
     291
     292        Output.Position  = Position;
     293        Output.TexCoord  = In.TexCoord;
     294
     295        return Output;
     296    }
     297
     298    struct PS_OUTPUT
     299    {
     300        float4 Color : COLOR0;
     301    };
     302
     303    static const float3x3 yuvCoeffs =
     304    {
     305        1.164383f,  1.164383f, 1.164383f,
     306        0.0f,      -0.391762f, 2.017232f,
     307        1.596027f, -0.812968f, 0.0f
     308    };
     309
     310    PS_OUTPUT PS(VS_OUTPUT In)
     311    {
     312        PS_OUTPUT Output;
     313
     314        // 4 bytes of an YUV macropixel contain 2 pixels in X for the target.
     315        // I.e. each YUV texture pixel is sampled twice: for both even and odd target pixels.
     316
     317        // In.TexCoord are in [0;1] range for the source texture.
     318        float2 texCoord = In.TexCoord;
     319
     320        // Source texture data is half width, i.e. it contains data in pixels [0; width / 2 - 1].
     321        texCoord.x = texCoord.x / 2.0f;
     322
     323        // Which source pixel needs to be read: xPixel = TexCoord.x * SourceWidth.
     324        float xSourcePixel = texCoord.x * gTextureInfo.z;
     325
     326        // Remainder is about 0.25 for even pixels and about 0.75 for odd pixels.
     327        float remainder = xSourcePixel - trunc(xSourcePixel);
     328
     329        // Fetch YUV
     330        float4 texColor = tex2D(sSource, texCoord);
     331
     332        // Get YUV components.
     333        float y0 = texColor.b;
     334        float u  = texColor.g;
     335        float y1 = texColor.r;
     336        float v  = texColor.a;
     337
     338        // Get y0 for even x coordinates and y1 for odd ones.
     339        float y = remainder < 0.5f ? y0 : y1;
     340
     341        // Make a vector for easier calculation.
     342        float3 yuv = float3(y, u, v);
     343
     344        // Convert YUV to RGB for BT.601:
     345        // https://docs.microsoft.com/en-us/windows/win32/medfound/recommended-8-bit-yuv-formats-for-video-rendering#converting-8-bit-yuv-to-rgb888
     346        //
     347        // For 8bit [0;255] when Y = [16;235], U,V = [16;239]:
     348        //
     349        //   C = Y - 16
     350        //   D = U - 128
     351        //   E = V - 128
     352        //
     353        //   R = 1.164383 * C                + 1.596027 * E
     354        //   G = 1.164383 * C - 0.391762 * D - 0.812968 * E
     355        //   B = 1.164383 * C + 2.017232 * D
     356        //
     357        // For shader values [0;1.0] when Y = [16/255;235/255], U,V = [16/255;239/255]:
     358        //
     359        //   C = Y - 0.0627
     360        //   D = U - 0.5020
     361        //   E = V - 0.5020
     362        //
     363        //   R = 1.164383 * C                + 1.596027 * E
     364        //   G = 1.164383 * C - 0.391762 * D - 0.812968 * E
     365        //   B = 1.164383 * C + 2.017232 * D
     366        //
     367        yuv -= float3(0.0627f, 0.502f, 0.502f);
     368        float3 bgr = mul(yuv, yuvCoeffs);
     369
     370        // Clamp to [0;1]
     371        bgr = saturate(bgr);
     372
     373        // Return RGBA
     374        Output.Color = float4(bgr, 1.0f);
     375
     376        return Output;
     377    }
     378
     379    technique RenderScene
     380    {
     381        pass P0
     382        {
     383            VertexShader = compile vs_2_0 VS();
     384            PixelShader  = compile ps_2_0 PS();
     385        }
     386    }
     387 */
     388
     389static DWORD const aVSCode[] =
     390{
     391    0xfffe0200,                                                             // vs_2_0
     392    0x05000051, 0xa00f0001, 0xbf800000, 0xc0000000, 0x3f800000, 0x00000000, // def c1, -1, -2, 1, 0
     393    0x0200001f, 0x80000000, 0x900f0000,                                     // dcl_position v0
     394    0x0200001f, 0x80000005, 0x900f0001,                                     // dcl_texcoord v1
     395    0x03000002, 0x80010000, 0x90000000, 0x90000000,                         // add r0.x, v0.x, v0.x
     396    0x02000001, 0x80010001, 0xa0000001,                                     // mov r1.x, c1.x
     397    0x03000002, 0x80060000, 0x80000001, 0xa0d00000,                         // add r0.yz, r1.x, c0.xxyw
     398    0x02000006, 0x80020000, 0x80550000,                                     // rcp r0.y, r0.y
     399    0x02000006, 0x80040000, 0x80aa0000,                                     // rcp r0.z, r0.z
     400    0x04000004, 0xc0010000, 0x80000000, 0x80550000, 0xa0000001,             // mad oPos.x, r0.x, r0.y, c1.x
     401    0x03000005, 0x80010000, 0x90550000, 0xa0550001,                         // mul r0.x, v0.y, c1.y
     402    0x04000004, 0xc0020000, 0x80000000, 0x80aa0000, 0xa0aa0001,             // mad oPos.y, r0.x, r0.z, c1.z
     403    0x02000001, 0xc00c0000, 0xa0b40001,                                     // mov oPos.zw, c1.xywz
     404    0x02000001, 0xe0030000, 0x90e40001,                                     // mov oT0.xy, v1
     405    0x0000ffff
     406};
     407
     408static DWORD const aPSCodeYUY2toRGB[] =
     409{
     410    0xffff0200,                                                             // ps_2_0
     411    0x05000051, 0xa00f0001, 0xbd8068dc, 0xbf008312, 0xbf008312, 0x00000000, // def c1, -0.0627000034, -0.501999974, -0.501999974, 0
     412    0x05000051, 0xa00f0002, 0x3f000000, 0x00000000, 0x3f800000, 0x3f000000, // def c2, 0.5, 0, 1, 0.5
     413    0x05000051, 0xa00f0003, 0x3f950a81, 0x00000000, 0x3fcc4a9d, 0x00000000, // def c3, 1.16438305, 0, 1.59602702, 0
     414    0x05000051, 0xa00f0004, 0x3f950a81, 0xbec89507, 0xbf501eac, 0x00000000, // def c4, 1.16438305, -0.391761988, -0.812968016, 0
     415    0x05000051, 0xa00f0005, 0x3f950a81, 0x40011a54, 0x00000000, 0x00000000, // def c5, 1.16438305, 2.01723194, 0, 0
     416    0x0200001f, 0x80000000, 0xb0030000,                                     // dcl t0.xy
     417    0x0200001f, 0x90000000, 0xa00f0800,                                     // dcl_2d s0
     418    0x03000005, 0x80080000, 0xb0000000, 0xa0000002,                         // mul r0.w, t0.x, c2.x
     419    0x03000005, 0x80010000, 0x80ff0000, 0xa0aa0000,                         // mul r0.x, r0.w, c0.z
     420    0x02000013, 0x80020000, 0x80000000,                                     // frc r0.y, r0.x
     421    0x04000058, 0x80040000, 0x81550000, 0xa0550002, 0xa0aa0002,             // cmp r0.z, -r0.y, c2.y, c2.z
     422    0x03000002, 0x80020000, 0x80000000, 0x81550000,                         // add r0.y, r0.x, -r0.y
     423    0x04000058, 0x80010000, 0x80000000, 0xa0550002, 0x80aa0000,             // cmp r0.x, r0.x, c2.y, r0.z
     424    0x03000002, 0x80010000, 0x80000000, 0x80550000,                         // add r0.x, r0.x, r0.y
     425    0x04000004, 0x80010000, 0x80ff0000, 0xa0aa0000, 0x81000000,             // mad r0.x, r0.w, c0.z, -r0.x
     426    0x03000002, 0x80010000, 0x80000000, 0xa1ff0002,                         // add r0.x, r0.x, -c2.w
     427    0x03000005, 0x80030001, 0xb0e40000, 0xa01b0002,                         // mul r1.xy, t0, c2.wzyx
     428    0x03000042, 0x800f0001, 0x80e40001, 0xa0e40800,                         // texld r1, r1, s0
     429    0x04000058, 0x80010001, 0x80000000, 0x80000001, 0x80aa0001,             // cmp r1.x, r0.x, r1.x, r1.z
     430    0x02000001, 0x80040001, 0x80ff0001,                                     // mov r1.z, r1.w
     431    0x03000002, 0x80070000, 0x80e40001, 0xa0e40001,                         // add r0.xyz, r1, c1
     432    0x03000008, 0x80110001, 0x80e40000, 0xa0e40003,                         // dp3_sat r1.x, r0, c3
     433    0x03000008, 0x80120001, 0x80e40000, 0xa0e40004,                         // dp3_sat r1.y, r0, c4
     434    0x0400005a, 0x80140001, 0x80e40000, 0xa0e40005, 0xa0aa0005,             // dp2add_sat r1.z, r0, c5, c5.z
     435    0x02000001, 0x80080001, 0xa0aa0002,                                     // mov r1.w, c2.z
     436    0x02000001, 0x800f0800, 0x80e40001,                                     // mov oC0, r1
     437    0x0000ffff
     438};
     439
     440
     441static HRESULT vboxDxvaInit(VBOXWDDMVIDEOPROCESSDEVICE *pVideoProcessDevice)
     442{
     443    HRESULT hr;
     444
    107445    IDirect3DDevice9 *pDevice9 = pVideoProcessDevice->pDevice->pDevice9If;
    108     AssertPtrReturn(pDevice9, E_INVALIDARG);
    109 
    110 #if 0
     446
     447    DWORD const *paVS = &aVSCode[0];
     448    DWORD const *paPS = &aPSCodeYUY2toRGB[0];
     449
    111450    static D3DVERTEXELEMENT9 const aVertexElements[] =
    112451    {
     
    116455    };
    117456
    118     HRESULT hr = pDevice9->CreateVertexDeclaration(aVertexElements, &pVideoProcessDevice->pVertexDecl);
     457    hr = pDevice9->CreateVertexDeclaration(aVertexElements, &pVideoProcessDevice->pVertexDecl);
    119458    AssertReturn(hr == D3D_OK, hr);
    120459
     
    132471    hr = pDevice9->CreatePixelShader(paPS, &pVideoProcessDevice->pPS);
    133472    AssertReturn(hr == D3D_OK, hr);
    134 #endif
    135473
    136474    hr = pDevice9->CreateTexture(pVideoProcessDevice->VideoDesc.SampleWidth,
    137                                          pVideoProcessDevice->VideoDesc.SampleHeight,
    138                                          0, /* Levels */
    139                                          0, /* D3DUSAGE_ */
    140                                          D3DFMT_YUY2, /** @todo Maybe a stretch is enough because host already does the conversion? */
    141                                          D3DPOOL_DEFAULT,
    142                                          &pVideoProcessDevice->pTexture,
    143                                          NULL);
     475                                 pVideoProcessDevice->VideoDesc.SampleHeight,
     476                                 0, /* Levels */
     477                                 0, /* D3DUSAGE_ */
     478                                 D3DFMT_A8R8G8B8, //D3DFMT_YUY2,
     479                                 D3DPOOL_DEFAULT,
     480                                 &pVideoProcessDevice->pStagingTexture,
     481                                 NULL);
    144482    AssertReturn(hr == D3D_OK, hr);
    145483
     
    147485}
    148486
    149 static HRESULT vboxDxvaBltRect(VBOXWDDMVIDEOPROCESSDEVICE *pVideoProcessDevice,
    150                                IDirect3DTexture9 *pSrcTexture,
    151                                UINT SrcSubResourceIndex,
    152                                RECT const *pSrcRect,
    153                                RECT const *pDstRect)
     487static HRESULT vboxDxvaSetState(VBOXWDDMVIDEOPROCESSDEVICE *pVideoProcessDevice)
    154488{
    155489    HRESULT hr;
    156490
    157491    IDirect3DDevice9 *pDevice9 = pVideoProcessDevice->pDevice->pDevice9If;
    158     AssertPtrReturn(pDevice9, E_INVALIDARG);
    159 
    160     hr = pDevice9->UpdateTexture(pSrcTexture, pVideoProcessDevice->pTexture);
    161     AssertReturn(hr == D3D_OK, hr);
    162 
    163     IDirect3DSurface9 *pSrcSurface;
    164     hr = pVideoProcessDevice->pTexture->GetSurfaceLevel(SrcSubResourceIndex, &pSrcSurface);
    165     AssertReturn(hr == D3D_OK, hr);
    166 
    167     IDirect3DSurface9 *pDstSurface;
    168     hr = pVideoProcessDevice->pRTTexture->GetSurfaceLevel(pVideoProcessDevice->SubResourceIndex, &pDstSurface);
    169     AssertReturnStmt(hr == D3D_OK, D3D_RELEASE(pSrcSurface), hr);
    170 
    171     hr = pDevice9->StretchRect(pSrcSurface, pSrcRect, pDstSurface, pDstRect, D3DTEXF_NONE);
    172 
    173     D3D_RELEASE(pSrcSurface);
    174     D3D_RELEASE(pDstSurface);
    175 
     492
     493    hr = pDevice9->SetStreamSource(0, pVideoProcessDevice->pVB, 0, sizeof(Vertex));
     494    AssertReturn(hr == D3D_OK, hr);
     495
     496    hr = pDevice9->SetVertexDeclaration(pVideoProcessDevice->pVertexDecl);
     497    AssertReturn(hr == D3D_OK, hr);
     498
     499    hr = pDevice9->SetVertexShader(pVideoProcessDevice->pVS);
     500    AssertReturn(hr == D3D_OK, hr);
     501
     502    hr = pDevice9->SetPixelShader(pVideoProcessDevice->pPS);
     503    AssertReturn(hr == D3D_OK, hr);
     504
     505    hr = pDevice9->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
     506    AssertReturn(hr == D3D_OK, hr);
     507
     508    hr = pDevice9->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
     509    AssertReturn(hr == D3D_OK, hr);
     510
     511    hr = pDevice9->SetTexture(0, pVideoProcessDevice->pStagingTexture);
     512    AssertReturn(hr == D3D_OK, hr);
     513
     514    float const cTargetWidth = pVideoProcessDevice->pRenderTarget->aAllocations[0].SurfDesc.width;
     515    float const cTargetHeight = pVideoProcessDevice->pRenderTarget->aAllocations[0].SurfDesc.height;
     516
     517    float const cSampleWidth = pVideoProcessDevice->VideoDesc.SampleWidth;
     518    float const cSampleHeight = pVideoProcessDevice->VideoDesc.SampleHeight;
     519
     520    float aTextureInfo[4];
     521    aTextureInfo[0] = cTargetWidth;
     522    aTextureInfo[1] = cTargetHeight;
     523    aTextureInfo[2] = cSampleWidth;
     524    aTextureInfo[3] = cSampleHeight;
     525
     526    hr = pDevice9->SetVertexShaderConstantF(0, aTextureInfo, 1);
     527    AssertReturn(hr == D3D_OK, hr);
     528    hr = pDevice9->SetPixelShaderConstantF(0, aTextureInfo, 1);
     529    AssertReturn(hr == D3D_OK, hr);
     530
     531    hr = pDevice9->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
     532    AssertReturn(hr == D3D_OK, hr);
     533    hr = pDevice9->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
     534    AssertReturn(hr == D3D_OK, hr);
     535    hr = pDevice9->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
     536    AssertReturn(hr == D3D_OK, hr);
     537
     538    hr = pDevice9->SetRenderTarget(0, pVideoProcessDevice->pRTSurface);
    176539    AssertReturn(hr == D3D_OK, hr);
    177540
    178541    return S_OK;
     542}
     543
     544static HRESULT vboxDxvaUpdateVertexBuffer(VBOXWDDMVIDEOPROCESSDEVICE *pVideoProcessDevice,
     545                                          RECT const *pSrcRect,
     546                                          RECT const *pDstRect)
     547{
     548    HRESULT hr;
     549
     550    /* Do not display anything if the source rectangle is not what is expected.
     551     * But assert anyway in order to be able to investigate.
     552     */
     553    AssertReturn(pSrcRect->right > pSrcRect->left, S_OK);
     554    AssertReturn(pSrcRect->bottom > pSrcRect->top, S_OK);
     555
     556    float const cSrcWidth = pVideoProcessDevice->VideoDesc.SampleWidth;
     557    float const cSrcHeight = pVideoProcessDevice->VideoDesc.SampleHeight;
     558
     559    float const uSrcLeft   = pSrcRect->left/cSrcWidth;
     560    float const uSrcRight  = pSrcRect->right/cSrcWidth;
     561    float const vSrcTop    = pSrcRect->top/cSrcHeight;
     562    float const vSrcBottom = pSrcRect->bottom/cSrcHeight;
     563
     564    /* Subtract 0.5 to line up the pixel centers with texels
     565     * https://docs.microsoft.com/en-us/windows/win32/direct3d9/directly-mapping-texels-to-pixels
     566     */
     567    float const xDstLeft   = pDstRect->left - 0.5f;
     568    float const xDstRight  = pDstRect->right - 0.5f;
     569    float const yDstTop    = pDstRect->top - 0.5f;
     570    float const yDstBottom = pDstRect->bottom - 0.5f;
     571
     572    Vertex const aVertices[] =
     573    {
     574        { xDstLeft,  yDstTop,    uSrcLeft,  vSrcTop},
     575        { xDstRight, yDstTop,    uSrcRight, vSrcTop},
     576        { xDstRight, yDstBottom, uSrcRight, vSrcBottom},
     577
     578        { xDstLeft,  yDstTop,    uSrcLeft,  vSrcTop},
     579        { xDstRight, yDstBottom, uSrcRight, vSrcBottom},
     580        { xDstLeft,  yDstBottom, uSrcLeft,  vSrcBottom},
     581    };
     582
     583    hr = vboxDxvaCopyToVertexBuffer(pVideoProcessDevice->pVB, aVertices, sizeof(aVertices));
     584    AssertReturn(hr == D3D_OK, hr);
     585
     586    return S_OK;
     587}
     588
     589static HRESULT vboxDxvaProcessBlt(VBOXWDDMVIDEOPROCESSDEVICE *pVideoProcessDevice,
     590                                  D3DDDIARG_VIDEOPROCESSBLT const *pData,
     591                                  IDirect3DTexture9 *paSrcTextures[])
     592{
     593    HRESULT hr;
     594
     595    IDirect3DDevice9 *pDevice9 = pVideoProcessDevice->pDevice->pDevice9If;
     596
     597    hr = vboxDxvaDeviceStateSave(pDevice9, &pVideoProcessDevice->SavedState);
     598    if (hr == D3D_OK)
     599    {
     600        /* Set the required state for the blits, inclusding the render target. */
     601        hr = vboxDxvaSetState(pVideoProcessDevice);
     602        if (hr == D3D_OK)
     603        {
     604            /* Clear the target rectangle. */
     605            /** @todo Use pData->BackgroundColor */
     606            D3DCOLOR BgColor = 0;
     607            D3DRECT TargetRect;
     608            TargetRect.x1 = pData->TargetRect.left;
     609            TargetRect.y1 = pData->TargetRect.top;
     610            TargetRect.x2 = pData->TargetRect.right;
     611            TargetRect.y2 = pData->TargetRect.bottom;
     612            hr = pDevice9->Clear(1, &TargetRect, D3DCLEAR_TARGET, BgColor, 0.0f, 0);
     613            Assert(hr == D3D_OK); /* Ignore errors. */
     614
     615            DXVADDI_VIDEOSAMPLE const *pSrcSample = &pData->pSrcSurfaces[0];
     616            IDirect3DTexture9 *pSrcTexture = paSrcTextures[0];
     617
     618            /* Upload the source data to the staging texture. */
     619            hr = vboxDxvaUploadSample(pVideoProcessDevice, pSrcTexture, pSrcSample->SrcSubResourceIndex);
     620            if (hr == D3D_OK)
     621            {
     622                /* Setup the blit dimensions. */
     623                hr = vboxDxvaUpdateVertexBuffer(pVideoProcessDevice, &pSrcSample->SrcRect, &pSrcSample->DstRect);
     624                Assert(hr == D3D_OK);
     625                if (hr == D3D_OK)
     626                {
     627
     628                    hr = pDevice9->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);
     629                    Assert(hr == D3D_OK);
     630                }
     631            }
     632        }
     633
     634        vboxDxvaDeviceStateRestore(pDevice9, &pVideoProcessDevice->SavedState);
     635    }
     636
     637    return hr;
    179638}
    180639
     
    209668    if (pVPI)
    210669    {
    211         LOGREL(("%dx%d", pVPI->VideoDesc.SampleWidth, pVPI->VideoDesc.SampleHeight));
    212 
    213670        if (vboxDxvaFindDeviceGuid(pVPI->pVideoProcGuid) >= 0)
    214671        {
     
    230687    if (pVPI)
    231688    {
    232         LOGREL(("%dx%d", pVPI->VideoDesc.SampleWidth, pVPI->VideoDesc.SampleHeight));
    233 
    234689        if (vboxDxvaFindDeviceGuid(pVPI->pVideoProcGuid) >= 0)
    235690        {
     
    256711    if (pVPI)
    257712    {
    258         LOGREL(("%dx%d", pVPI->VideoDesc.SampleWidth, pVPI->VideoDesc.SampleHeight));
    259 
    260713        if (vboxDxvaFindDeviceGuid(pVPI->pVideoProcGuid) >= 0)
    261714        {
     
    310763HRESULT VBoxDxvaDestroyVideoProcessDevice(PVBOXWDDMDISP_DEVICE pDevice, HANDLE hVideoProcessor)
    311764{
    312     RT_NOREF(pDevice);
    313 
    314     VBOXWDDMVIDEOPROCESSDEVICE *pVideoProcessDevice = (VBOXWDDMVIDEOPROCESSDEVICE *)hVideoProcessor;
    315     if (pVideoProcessDevice)
    316     {
    317         D3D_RELEASE(pVideoProcessDevice->pVertexDecl);
    318         D3D_RELEASE(pVideoProcessDevice->pVB);
    319         D3D_RELEASE(pVideoProcessDevice->pVS);
    320         D3D_RELEASE(pVideoProcessDevice->pPS);
    321 
    322         RTMemFree(pVideoProcessDevice);
    323     }
    324     return S_OK;
    325 }
    326 
    327 HRESULT VBoxDxvaVideoProcessBeginFrame(PVBOXWDDMDISP_DEVICE pDevice, HANDLE hVideoProcessor)
    328 {
    329765    VBOXWDDMVIDEOPROCESSDEVICE *pVideoProcessDevice = (VBOXWDDMVIDEOPROCESSDEVICE *)hVideoProcessor;
    330766    AssertReturn(pDevice == pVideoProcessDevice->pDevice, E_INVALIDARG);
    331767
     768    D3D_RELEASE(pVideoProcessDevice->pRTSurface);
     769
     770    D3D_RELEASE(pVideoProcessDevice->pStagingTexture);
     771    D3D_RELEASE(pVideoProcessDevice->pVertexDecl);
     772    D3D_RELEASE(pVideoProcessDevice->pVB);
     773    D3D_RELEASE(pVideoProcessDevice->pVS);
     774    D3D_RELEASE(pVideoProcessDevice->pPS);
     775
     776    RTMemFree(pVideoProcessDevice);
     777
     778    return S_OK;
     779}
     780
     781HRESULT VBoxDxvaVideoProcessBeginFrame(PVBOXWDDMDISP_DEVICE pDevice, HANDLE hVideoProcessor)
     782{
     783    VBOXWDDMVIDEOPROCESSDEVICE *pVideoProcessDevice = (VBOXWDDMVIDEOPROCESSDEVICE *)hVideoProcessor;
     784    AssertReturn(pDevice == pVideoProcessDevice->pDevice, E_INVALIDARG);
     785    AssertPtrReturn(pDevice->pDevice9If, E_INVALIDARG);
     786
    332787    HRESULT hr = S_OK;
    333     if (!pVideoProcessDevice->pTexture)
     788    if (!pVideoProcessDevice->pStagingTexture)
    334789    {
    335790        hr = vboxDxvaInit(pVideoProcessDevice);
     
    352807    AssertReturn(pDevice == pVideoProcessDevice->pDevice, E_INVALIDARG);
    353808
     809    D3D_RELEASE(pVideoProcessDevice->pRTSurface);
     810    pVideoProcessDevice->pRenderTarget = NULL;
     811    pVideoProcessDevice->RTSubResourceIndex = 0;
     812    pVideoProcessDevice->pRTTexture = NULL;
     813
    354814    PVBOXWDDMDISP_RESOURCE pRc = (PVBOXWDDMDISP_RESOURCE)pData->hRenderTarget;
    355815    AssertReturn(pRc->cAllocations > pData->SubResourceIndex, E_INVALIDARG);
    356 
    357     pVideoProcessDevice->pRenderTarget = pRc;
    358     pVideoProcessDevice->SubResourceIndex = pData->SubResourceIndex;
    359816
    360817    VBOXWDDMDISP_ALLOCATION *pAllocation = &pRc->aAllocations[pData->SubResourceIndex];
     
    362819    AssertReturn(pAllocation->enmD3DIfType == VBOXDISP_D3DIFTYPE_TEXTURE, E_INVALIDARG);
    363820
    364     pVideoProcessDevice->pRTTexture = (IDirect3DTexture9 *)pAllocation->pD3DIf;
    365 
     821#ifdef LOG_ENABLED
    366822    LOGREL_EXACT(("VideoProcess RT %dx%d sid=%u\n",
    367823        pRc->aAllocations[0].SurfDesc.width, pRc->aAllocations[0].SurfDesc.height, pAllocation->hostID));
     824#endif
     825
     826    IDirect3DTexture9 *pRTTexture = (IDirect3DTexture9 *)pAllocation->pD3DIf;
     827    HRESULT hr = pRTTexture->GetSurfaceLevel(pData->SubResourceIndex, &pVideoProcessDevice->pRTSurface);
     828    AssertReturn(hr == D3D_OK, E_INVALIDARG);
     829
     830    pVideoProcessDevice->pRenderTarget = pRc;
     831    pVideoProcessDevice->RTSubResourceIndex = pData->SubResourceIndex;
     832    pVideoProcessDevice->pRTTexture = pRTTexture;
    368833
    369834    return S_OK;
     
    372837HRESULT VBoxDxvaVideoProcessBlt(PVBOXWDDMDISP_DEVICE pDevice, const D3DDDIARG_VIDEOPROCESSBLT *pData)
    373838{
    374     HRESULT  hr;
    375 
    376839    VBOXWDDMVIDEOPROCESSDEVICE *pVideoProcessDevice = (VBOXWDDMVIDEOPROCESSDEVICE *)pData->hVideoProcess;
    377840    AssertReturn(pDevice == pVideoProcessDevice->pDevice, E_INVALIDARG);
     841    AssertPtrReturn(pDevice->pDevice9If, E_INVALIDARG);
     842    AssertPtrReturn(pVideoProcessDevice->pRTSurface, E_INVALIDARG);
     843
     844    AssertReturn(pData->NumSrcSurfaces > 0, E_INVALIDARG);
    378845
    379846    PVBOXWDDMDISP_RESOURCE pSrcRc = (PVBOXWDDMDISP_RESOURCE)pData->pSrcSurfaces[0].SrcResource;
    380 
    381     PVBOXWDDMDISP_RESOURCE pRc = (PVBOXWDDMDISP_RESOURCE)pData->pSrcSurfaces[0].SrcResource;
    382     AssertReturn(pRc->cAllocations > pData->pSrcSurfaces[0].SrcSubResourceIndex, E_INVALIDARG);
    383 
    384     VBOXWDDMDISP_ALLOCATION *pAllocation = &pRc->aAllocations[pData->pSrcSurfaces[0].SrcSubResourceIndex];
     847    AssertReturn(pSrcRc->cAllocations > pData->pSrcSurfaces[0].SrcSubResourceIndex, E_INVALIDARG);
     848
     849    VBOXWDDMDISP_ALLOCATION *pAllocation = &pSrcRc->aAllocations[pData->pSrcSurfaces[0].SrcSubResourceIndex];
    385850    AssertPtrReturn(pAllocation->pD3DIf, E_INVALIDARG);
    386851    AssertReturn(pAllocation->enmD3DIfType == VBOXDISP_D3DIFTYPE_TEXTURE, E_INVALIDARG);
     
    388853    IDirect3DTexture9 *pSrcTexture = (IDirect3DTexture9 *)pAllocation->pD3DIf;
    389854
    390     LOGREL_EXACT(("VideoProcess Blt sid = %u %d,%d %dx%d (%dx%d) -> %d,%d %dx%d (%d,%d %dx%d, %dx%d)\n",
    391         pAllocation->hostID,
     855#ifdef LOG_ENABLED
     856    LOGREL_EXACT(("VideoProcess Blt sid = %u fmt 0x%08x %d,%d %dx%d (%dx%d) -> %d,%d %dx%d (%d,%d %dx%d, %dx%d)\n",
     857        pAllocation->hostID, pSrcRc->aAllocations[0].SurfDesc.format,
    392858        pData->pSrcSurfaces[0].SrcRect.left, pData->pSrcSurfaces[0].SrcRect.top,
    393859        pData->pSrcSurfaces[0].SrcRect.right - pData->pSrcSurfaces[0].SrcRect.left,
     
    406872        pVideoProcessDevice->pRenderTarget->aAllocations[0].SurfDesc.width,
    407873        pVideoProcessDevice->pRenderTarget->aAllocations[0].SurfDesc.height));
    408 
    409     hr = vboxDxvaBltRect(pVideoProcessDevice, pSrcTexture, pData->pSrcSurfaces[0].SrcSubResourceIndex,
    410                          &pData->pSrcSurfaces[0].SrcRect,
    411                          &pData->pSrcSurfaces[0].DstRect);
    412 
    413     return S_OK;
    414 }
     874#endif
     875
     876    HRESULT hr = vboxDxvaProcessBlt(pVideoProcessDevice, pData, &pSrcTexture);
     877    return hr;
     878}
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/gallium/GaDxva.h

    r82330 r82415  
    3232HRESULT VBoxDxvaGetOutputFormats(D3DDDIFORMAT *paFormats, UINT cbFormats, DXVADDI_VIDEOPROCESSORINPUT const *pVPI, bool fSubstream);
    3333
    34 HRESULT VBoxDxvaGetCaps(DXVADDI_VIDEOPROCESSORCAPS *pVideoProcessorCaps,
    35                         DXVADDI_VIDEOPROCESSORINPUT const *pVPI);
     34HRESULT VBoxDxvaGetCaps(DXVADDI_VIDEOPROCESSORCAPS *pVideoProcessorCaps, DXVADDI_VIDEOPROCESSORINPUT const *pVPI);
    3635
    3736HRESULT VBoxDxvaCreateVideoProcessDevice(PVBOXWDDMDISP_DEVICE pDevice, D3DDDIARG_CREATEVIDEOPROCESSDEVICE *pData);
     
    3938HRESULT VBoxDxvaVideoProcessBeginFrame(PVBOXWDDMDISP_DEVICE pDevice, HANDLE hVideoProcessor);
    4039HRESULT VBoxDxvaVideoProcessEndFrame(PVBOXWDDMDISP_DEVICE pDevice, D3DDDIARG_VIDEOPROCESSENDFRAME *pData);
    41 HRESULT VBoxDxvaSetVideoProcessRenderTarget(PVBOXWDDMDISP_DEVICE pDevice,
    42                                             const D3DDDIARG_SETVIDEOPROCESSRENDERTARGET *pData);
     40HRESULT VBoxDxvaSetVideoProcessRenderTarget(PVBOXWDDMDISP_DEVICE pDevice, const D3DDDIARG_SETVIDEOPROCESSRENDERTARGET *pData);
    4341HRESULT VBoxDxvaVideoProcessBlt(PVBOXWDDMDISP_DEVICE pDevice, const D3DDDIARG_VIDEOPROCESSBLT *pData);
    4442
Note: See TracChangeset for help on using the changeset viewer.

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