/* Called to create DirectDraw surface.
 * Note: we always return DDHAL_DRIVER_NOTHANDLED, which asks DirectDraw memory manager
 * to perform actual memory allocation in our DDraw heap.
 */
DWORD APIENTRY VBoxDispDDCreateSurface(PDD_CREATESURFACEDATA lpCreateSurface)
{
    PVBOXDISPDEV pDev = (PVBOXDISPDEV) lpCreateSurface->lpDD->dhpdev;
    LOGF_ENTER();

    PDD_SURFACE_LOCAL pSurf = lpCreateSurface->lplpSList[0];

    if (pSurf->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
    {
        LOG(("primary surface"));
        pSurf->lpGbl->fpVidMem = 0;
    }
    else
    {
        LOG(("non primary surface"));
        pSurf->lpGbl->fpVidMem = DDHAL_PLEASEALLOC_BLOCKSIZE;
    }
    pSurf->lpGbl->dwReserved1 = 0;

#ifdef VBOX_WITH_VIDEOHWACCEL
    if(pDev->vhwa.bEnabled)
    {
        VBOXVHWACMD* pCmd;

        pCmd = VBoxDispVHWACommandCreate(pDev, VBOXVHWACMD_TYPE_SURF_CREATE, sizeof(VBOXVHWACMD_SURF_CREATE));
        if (pCmd)
        {
            VBOXVHWACMD_SURF_CREATE *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_CREATE);
            PVBOXVHWASURFDESC pDesc;
            int rc;

            memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_CREATE));
            rc = VBoxDispVHWAFromDDSURFACEDESC(&pBody->SurfInfo, lpCreateSurface->lpDDSurfaceDesc);
            VBOX_WARNRC(rc);

            pBody->SurfInfo.surfCaps = VBoxDispVHWAFromDDSCAPS(pSurf->ddsCaps.dwCaps);
            pBody->SurfInfo.flags |= DDSD_CAPS;

            pBody->SurfInfo.height = pSurf->lpGbl->wHeight;
            pBody->SurfInfo.width = pSurf->lpGbl->wWidth;
            pBody->SurfInfo.flags |= DDSD_HEIGHT | DDSD_WIDTH;

            VBoxDispVHWAFromDDPIXELFORMAT(&pBody->SurfInfo.PixelFormat, &pSurf->lpGbl->ddpfSurface);
            pBody->SurfInfo.flags |= VBOXVHWA_SD_PIXELFORMAT;

            if (pSurf->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
            {
                pBody->SurfInfo.offSurface = VBoxDispVHWAVramOffsetFromPDEV(pDev, 0);
            }
            else
            {
                pBody->SurfInfo.offSurface = VBOXVHWA_OFFSET64_VOID;
            }

            pDesc = VBoxDispVHWASurfDescAlloc();
            if (pDesc)
            {
                VBoxDispVHWACommandSubmit(pDev, pCmd);
                if (RT_SUCCESS(pCmd->rc))
                {
                    uint32_t surfSizeX = pBody->SurfInfo.sizeX;
                    uint32_t surfSizeY = pBody->SurfInfo.sizeY;
                    pDesc->hHostHandle = pBody->SurfInfo.hSurf;

                    if(!!(pSurf->ddsCaps.dwCaps & DDSCAPS_OVERLAY)
                       && !!(pSurf->ddsCaps.dwCaps & DDSCAPS_VISIBLE))
                    {
                        pDesc->bVisible = true;
                    }

                    pSurf->lpGbl->dwBlockSizeX = pBody->SurfInfo.sizeX;
                    pSurf->lpGbl->dwBlockSizeY = pBody->SurfInfo.sizeY;
                    pSurf->lpGbl->lPitch       = pBody->SurfInfo.pitch;

                    lpCreateSurface->lpDDSurfaceDesc->lPitch = pSurf->lpGbl->lPitch;
                    lpCreateSurface->lpDDSurfaceDesc->dwFlags |= DDSD_PITCH;


                    /*@todo: it's probably a memory leak, because DDDestroySurface wouldn't be called for
                     *       primary surfaces.
                     */
                    pSurf->lpGbl->dwReserved1 = (ULONG_PTR)pDesc;
                }
                else
                {
                    WARN(("VBoxDispVHWACommandSubmit failed with rc=%#x", rc));
                    VBoxDispVHWASurfDescFree(pDesc);
                }
            }
            else
            {
                WARN(("VBoxDispVHWASurfDescAlloc failed"));
            }
            VBoxDispVHWACommandRelease(pDev, pCmd);
        }
        else
        {
            WARN(("VBoxDispVHWACommandCreate failed"));
        }
        return DDHAL_DRIVER_NOTHANDLED;
    }
#endif /*VBOX_WITH_VIDEOHWACCEL*/

    LPDDSURFACEDESC pDesc = lpCreateSurface->lpDDSurfaceDesc;

    if (pDesc->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4)
    {
        pSurf->lpGbl->lPitch = RT_ALIGN_T(pSurf->lpGbl->wWidth/2, 32, LONG);
    }
    else
    if (pDesc->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8)
    {
        pSurf->lpGbl->lPitch = RT_ALIGN_T(pSurf->lpGbl->wWidth, 32, LONG);
    }
    else
    {
        pSurf->lpGbl->lPitch = pSurf->lpGbl->wWidth*(pDesc->ddpfPixelFormat.dwRGBBitCount/8);
    }

    pSurf->lpGbl->dwBlockSizeX = pSurf->lpGbl->lPitch;
    pSurf->lpGbl->dwBlockSizeY = pSurf->lpGbl->wHeight;

    pDesc->lPitch = pSurf->lpGbl->lPitch;
    pDesc->dwFlags |= DDSD_PITCH;

    LOGF_LEAVE();
    return DDHAL_DRIVER_NOTHANDLED;
}
Ejemplo n.º 2
0
int VBoxDispVHWAFromDDSURFACEDESC(VBOXVHWA_SURFACEDESC *pVHWADesc, DDSURFACEDESC *pDdDesc)
{
    uint32_t unsupds = VBoxDispVHWAUnsupportedDSS(pDdDesc->dwFlags);
    Assert(!unsupds);
    if(unsupds)
        return VERR_GENERAL_FAILURE;

    pVHWADesc->flags = 0;

    if(pDdDesc->dwFlags & DDSD_BACKBUFFERCOUNT)
    {
        pVHWADesc->flags |= VBOXVHWA_SD_BACKBUFFERCOUNT;
        pVHWADesc->cBackBuffers = pDdDesc->dwBackBufferCount;
    }
    if(pDdDesc->dwFlags & DDSD_CAPS)
    {
        uint32_t unsup = VBoxDispVHWAUnsupportedDDSCAPS(pDdDesc->ddsCaps.dwCaps);
        Assert(!unsup);
        if(unsup)
            return VERR_GENERAL_FAILURE;
        pVHWADesc->flags |= VBOXVHWA_SD_CAPS;
        pVHWADesc->surfCaps = VBoxDispVHWAFromDDSCAPS(pDdDesc->ddsCaps.dwCaps);
    }
    if(pDdDesc->dwFlags & DDSD_CKDESTBLT)
    {
        pVHWADesc->flags |= VBOXVHWA_SD_CKDESTBLT;
        VBoxDispVHWAFromDDCOLORKEY(&pVHWADesc->DstBltCK, &pDdDesc->ddckCKDestBlt);
    }
    if(pDdDesc->dwFlags & DDSD_CKDESTOVERLAY)
    {
        pVHWADesc->flags |= VBOXVHWA_SD_CKDESTOVERLAY;
        VBoxDispVHWAFromDDCOLORKEY(&pVHWADesc->DstOverlayCK, &pDdDesc->ddckCKDestOverlay);
    }
    if(pDdDesc->dwFlags & DDSD_CKSRCBLT)
    {
        pVHWADesc->flags |= VBOXVHWA_SD_CKSRCBLT;
        VBoxDispVHWAFromDDCOLORKEY(&pVHWADesc->SrcBltCK, &pDdDesc->ddckCKSrcBlt);
    }
    if(pDdDesc->dwFlags & DDSD_CKSRCOVERLAY)
    {
        pVHWADesc->flags |= VBOXVHWA_SD_CKSRCOVERLAY;
        VBoxDispVHWAFromDDCOLORKEY(&pVHWADesc->SrcOverlayCK, &pDdDesc->ddckCKSrcOverlay);
    }
    if(pDdDesc->dwFlags & DDSD_HEIGHT)
    {
        pVHWADesc->flags |= VBOXVHWA_SD_HEIGHT;
        pVHWADesc->height = pDdDesc->dwHeight;
    }
    if(pDdDesc->dwFlags & DDSD_WIDTH)
    {
        pVHWADesc->flags |= VBOXVHWA_SD_WIDTH;
        pVHWADesc->width = pDdDesc->dwWidth;
    }
    if(pDdDesc->dwFlags & DDSD_PITCH)
    {
        pVHWADesc->flags |= VBOXVHWA_SD_PITCH;
        pVHWADesc->pitch = pDdDesc->lPitch;
    }
    if(pDdDesc->dwFlags & DDSD_PIXELFORMAT)
    {
        int rc = VBoxDispVHWAFromDDPIXELFORMAT(&pVHWADesc->PixelFormat, &pDdDesc->ddpfPixelFormat);
        if(RT_FAILURE(rc))
            return rc;
        pVHWADesc->flags |= VBOXVHWA_SD_PIXELFORMAT;
    }
    return VINF_SUCCESS;
}