diff options
-rw-r--r-- | display/driver.c | 84 | ||||
-rw-r--r-- | display/surface.c | 14 |
2 files changed, 89 insertions, 9 deletions
diff --git a/display/driver.c b/display/driver.c index 54913b8..00dd7ec 100644 --- a/display/driver.c +++ b/display/driver.c @@ -937,7 +937,11 @@ VOID DrvDisableSurface(DHPDEV in_pdev) DEBUG_PRINT((pdev, 1, "%s: 0x%lx\n", __FUNCTION__, pdev)); - DisableQXLPrimarySurface(pdev, 1 /* hide mouse */); + // Don't destroy the primary - it's destroyed by destroy_all_surfaces + // at AssertModeDisable. Also, msdn specifically mentions DrvDisableSurface + // should not touch the hardware, that should be done just via DrvAssertMode + // (http://msdn.microsoft.com/en-us/library/ff556200%28VS.85%29.aspx) + pdev->surf_enable = FALSE; UnmapFB(pdev); if (pdev->surf) { @@ -951,15 +955,56 @@ VOID DrvDisableSurface(DHPDEV in_pdev) pdev->mem_slots = NULL; } - DEBUG_PRINT((NULL, 1, "%s: 0x%lx exit\n", __FUNCTION__, pdev)); + DEBUG_PRINT((pdev, 1, "%s: 0x%lx exit\n", __FUNCTION__, pdev)); } -BOOL DrvAssertMode(DHPDEV in_pdev, BOOL enable) +static BOOL AssertModeDisable(PDev *pdev) { - PDev* pdev = (PDev*)in_pdev; + DEBUG_PRINT((pdev, 3, "%s entry\n", __FUNCTION__)); + /* flush command ring and update all surfaces */ + async_io(pdev, ASYNCABLE_FLUSH_SURFACES, 0); + async_io(pdev, ASYNCABLE_DESTROY_ALL_SURFACES, 0); + /* move all surfaces from device to system memory */ + if (!MoveAllSurfacesToRam(pdev)) { + return FALSE; + } + /* Free release ring contents */ + ReleaseCacheDeviceMemoryResources(pdev); + EmptyReleaseRing(pdev); + /* Get the last free list onto the release ring */ + sync_io(pdev, pdev->flush_release_port, 0); + DEBUG_PRINT((pdev, 4, "%s after FLUSH_RELEASE\n", __FUNCTION__)); + /* And release that. mspace allocators should be clean after. */ + EmptyReleaseRing(pdev); + RemoveVRamSlot(pdev); + DebugCountAliveSurfaces(pdev); + DEBUG_PRINT((pdev, 4, "%s: [%d,%d] [%d,%d] [%d,%d] %lx\n", __FUNCTION__, + pdev->cmd_ring->prod, pdev->cmd_ring->cons, + pdev->cursor_ring->prod, pdev->cursor_ring->cons, + pdev->release_ring->prod, pdev->release_ring->cons, + pdev->Res->free_outputs)); + DEBUG_PRINT((pdev, 4, "%s exit\n", __FUNCTION__)); + return TRUE; +} - DEBUG_PRINT((pdev, 1, "%s: 0x%lx %d\n", __FUNCTION__, pdev, enable)); +static void AssertModeEnable(PDev *pdev) +{ + InitResources(pdev); + InitDeviceMemoryResources(pdev); + DEBUG_PRINT((pdev, 3, "%s: [%d,%d] [%d,%d] [%d,%d] %lx\n", __FUNCTION__, + pdev->cmd_ring->prod, pdev->cmd_ring->cons, + pdev->cursor_ring->prod, pdev->cursor_ring->cons, + pdev->release_ring->prod, pdev->release_ring->cons, + pdev->Res->free_outputs)); + EnableQXLPrimarySurface(pdev); + CreateVRamSlot(pdev); + DebugCountAliveSurfaces(pdev); + MoveAllSurfacesToVideoRam(pdev); + DebugCountAliveSurfaces(pdev); +} +BOOL DrvAssertModeOld(PDev *pdev, BOOL enable) +{ if (enable) { InitResources(pdev); EnableQXLPrimarySurface(pdev); @@ -972,6 +1017,35 @@ BOOL DrvAssertMode(DHPDEV in_pdev, BOOL enable) return TRUE; } +BOOL DrvAssertMode(DHPDEV in_pdev, BOOL enable) +{ + PDev* pdev = (PDev*)in_pdev; + BOOL ret = TRUE; + + DEBUG_PRINT((pdev, 1, "%s: 0x%lx %d\n", __FUNCTION__, pdev, enable)); + if (pdev->pci_revision < QXL_REVISION_STABLE_V10) { + return DrvAssertModeOld(pdev, enable); + } + /* new implementation that works correctly only with newer devices + * that implement QXL_IO_FLUSH_RELEASE */ + if (pdev->enabled == enable) { + DEBUG_PRINT((pdev, 1, "%s: called twice with same argument (%d)\n", __FUNCTION__, + enable)); + return TRUE; + } + pdev->enabled = enable; + if (enable) { + AssertModeEnable(pdev); + } else { + ret = AssertModeDisable(pdev); + if (!ret) { + pdev->enabled = !enable; + } + } + DEBUG_PRINT((pdev, 1, "%s: 0x%lx exit %d\n", __FUNCTION__, pdev, enable)); + return ret; +} + ULONG DrvGetModes(HANDLE driver, ULONG dev_modes_size, DEVMODEW *dev_modes) { PVIDEO_MODE_INFORMATION video_modes; diff --git a/display/surface.c b/display/surface.c index 519d613..b40721d 100644 --- a/display/surface.c +++ b/display/surface.c @@ -136,11 +136,15 @@ static UINT8 *CreateSurfaceHelper(PDev *pdev, UINT32 surface_id, } static void SendSurfaceCreateCommand(PDev *pdev, UINT32 surface_id, SIZEL size, - UINT32 surface_format, INT32 stride, QXLPHYSICAL phys_mem) + UINT32 surface_format, INT32 stride, QXLPHYSICAL phys_mem, + int keep_data) { QXLSurfaceCmd *surface; surface = SurfaceCmd(pdev, QXL_SURFACE_CMD_CREATE, surface_id); + if (keep_data) { + surface->flags |= QXL_SURF_FLAG_KEEP_DATA; + } surface->u.surface_create.format = surface_format; surface->u.surface_create.width = size.cx; surface->u.surface_create.height = size.cy; @@ -185,7 +189,7 @@ HBITMAP CreateDeviceBitmap(PDev *pdev, SIZEL size, ULONG format, QXLPHYSICAL *ph } if (allocation_type != DEVICE_BITMAP_ALLOCATION_TYPE_SURF0) { - SendSurfaceCreateCommand(pdev, surface_id, size, surface_format, -stride, *phys_mem); + SendSurfaceCreateCommand(pdev, surface_id, size, surface_format, -stride, *phys_mem, 0); } return hbitmap; @@ -269,7 +273,7 @@ BOOL MoveSurfaceToVideoRam(PDev *pdev, UINT32 surface_id) EngFreeMem(surface_info->copy); surface_info->copy = NULL; SendSurfaceCreateCommand(pdev, surface_id, surface_info->size, surface_format, - -stride, phys_mem); + -stride, phys_mem, 1); return TRUE; } @@ -356,7 +360,9 @@ BOOL MoveAllSurfacesToRam(PDev *pdev) __FUNCTION__, surface_id)); phys_mem = SurfaceToPhysical(pdev, surface_info->draw_area.base_mem); SendSurfaceCreateCommand(pdev, surface_id, surf_obj->sizlBitmap, - surface_info->bitmap_format, -surf_obj->lDelta, phys_mem); + surface_info->bitmap_format, -surf_obj->lDelta, phys_mem, + /* the surface is still there, tell server not to erase */ + 1); return FALSE; } QXLDelSurface(pdev, surface_info->draw_area.base_mem, DEVICE_BITMAP_ALLOCATION_TYPE_VRAM); |