From 81b623f09682f0d80099a562b75048274b69fc31 Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Mon, 16 Jun 2014 21:26:18 +1000 Subject: [PATCH] cursor shape and move support funtions --- qxldod/QxlDod.cpp | 231 +++++++++++++++++++++++++++++++++++++++++++--- qxldod/QxlDod.h | 31 ++++--- 2 files changed, 234 insertions(+), 28 deletions(-) diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp index 1a690cf..d8ab0ee 100755 --- a/qxldod/QxlDod.cpp +++ b/qxldod/QxlDod.cpp @@ -395,12 +395,12 @@ NTSTATUS QxlDod::QueryAdapterInfo(_In_ CONST DXGKARG_QUERYADAPTERINFO* pQueryAda pDriverCaps->WDDMVersion = DXGKDDI_WDDMv1_2; pDriverCaps->HighestAcceptableAddress.QuadPart = -1; -/* + pDriverCaps->MaxPointerWidth = 64; pDriverCaps->MaxPointerHeight = 64; pDriverCaps->PointerCaps.Monochrome = 1; - pDriverCaps->PointerCaps.Color = 1; -*/ +// pDriverCaps->PointerCaps.Color = 1; + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s 1\n", __FUNCTION__)); return STATUS_SUCCESS; } @@ -427,7 +427,7 @@ NTSTATUS QxlDod::SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetP DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s Cursor is not visible\n", __FUNCTION__)); return STATUS_SUCCESS; } - return STATUS_UNSUCCESSFUL; + return m_pHWDevice->SetPointerPosition(pSetPointerPosition); } // Basic Sample Display Driver does not support hardware cursors, and reports such @@ -439,7 +439,7 @@ NTSTATUS QxlDod::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointer DbgPrint(TRACE_LEVEL_INFORMATION, ("<---> %s Height = %d, Width = %d, XHot= %d, YHot = %d SourceId = %d\n", __FUNCTION__, pSetPointerShape->Height, pSetPointerShape->Width, pSetPointerShape->XHot, pSetPointerShape->YHot, pSetPointerShape->VidPnSourceId)); - return STATUS_NOT_SUPPORTED; + return m_pHWDevice->SetPointerShape(pSetPointerShape); } NTSTATUS QxlDod::Escape(_In_ CONST DXGKARG_ESCAPE* pEscape) @@ -1577,7 +1577,6 @@ NTSTATUS QxlDod::IsVidPnPathFieldsValid(CONST D3DKMDT_VIDPN_PRESENT_PATH* pPath) return STATUS_SUCCESS; } - NTSTATUS QxlDod::IsVidPnSourceModeFieldsValid(CONST D3DKMDT_VIDPN_SOURCE_MODE* pSourceMode) const { PAGED_CODE(); @@ -2824,6 +2823,16 @@ VOID VgaDevice::ResetDevice(VOID) { } +NTSTATUS VgaDevice::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape) +{ + return STATUS_NOT_SUPPORTED; +} + +NTSTATUS VgaDevice::SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition) +{ + return STATUS_SUCCESS; +} + QxlDevice::QxlDevice(_In_ QxlDod* pQxlDod) { m_pQxlDod = pQxlDod; @@ -2963,7 +2972,6 @@ NTSTATUS QxlDevice::QueryCurrentMode(PVIDEO_MODE RequestedMode) NTSTATUS QxlDevice::SetCurrentMode(ULONG Mode) { DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s Mode = %x\n", __FUNCTION__, Mode)); -// UNREFERENCED_PARAMETER(Mode); for (ULONG idx = 0; idx < m_ModeCount; idx++) { if (Mode == m_ModeNumbers[idx]) @@ -3213,7 +3221,7 @@ void QxlDevice::CreatePrimarySurface(PVIDEO_MODE_INFORMATION pModeInfo) primary_surface_create->mem = PA( m_RamStart, m_MainMemSlot); - primary_surface_create->flags = QXL_SURF_FLAG_KEEP_DATA; //0; + primary_surface_create->flags = QXL_SURF_FLAG_KEEP_DATA; primary_surface_create->type = QXL_SURF_TYPE_PRIMARY; DbgPrint(TRACE_LEVEL_VERBOSE, ("<--> %s format = %d, width = %d, height = %d, stride = %d\n", __FUNCTION__, pModeInfo->BitsPerPlane, pModeInfo->VisScreenWidth, pModeInfo->VisScreenHeight, pModeInfo->ScreenStride)); @@ -3273,6 +3281,7 @@ BOOL QxlDevice::CreateEvents() KeInitializeMutex(&m_MemLock,1); KeInitializeMutex(&m_CmdLock,1); KeInitializeMutex(&m_IoLock,1); + KeInitializeMutex(&m_CrsLock,1); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); return TRUE; @@ -3371,7 +3380,6 @@ void QxlDevice::InitDeviceMemoryResources(void) DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } - void QxlDevice::InitMspace(UINT32 mspace_type, UINT8 *start, size_t capacity) { DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s type = %d, start = %p, capacity = %d\n", __FUNCTION__, mspace_type, start, capacity)); @@ -3389,7 +3397,6 @@ void QxlDevice::ResetDevice(void) DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } - NTSTATUS QxlDevice::ExecutePresentDisplayOnly( _In_ BYTE* DstAddr, @@ -3607,7 +3614,6 @@ void QxlDevice::WaitForReleaseRing(void) DbgPrint(TRACE_LEVEL_VERBOSE, ("%s: <---\n", __FUNCTION__)); } - void QxlDevice::FlushReleaseRing() { UINT64 output; @@ -3738,7 +3744,6 @@ void QxlDevice::FreeMem(UINT32 mspace_type, void *ptr) DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } - QXLDrawable *QxlDevice::GetDrawable() { QXLOutput *output; @@ -3751,6 +3756,21 @@ QXLDrawable *QxlDevice::GetDrawable() return(QXLDrawable *)output->data; } +QXLCursorCmd *QxlDevice::CursorCmd() +{ + QXLCursorCmd *cursor_cmd; + QXLOutput *output; + + DbgPrint(TRACE_LEVEL_FATAL, ("---> %s\n", __FUNCTION__)); + output = (QXLOutput *)AllocMem(MSPACE_TYPE_DEVRAM, sizeof(QXLOutput) + sizeof(QXLCursorCmd), TRUE); + output->num_res = 0; + RESOURCE_TYPE(output, RESOURCE_TYPE_CURSOR); + cursor_cmd = (QXLCursorCmd *)output->data; + cursor_cmd->release_info.id = (UINT64)output; + DbgPrint(TRACE_LEVEL_FATAL, ("<--- %s\n", __FUNCTION__)); + return cursor_cmd; +} + BOOL QxlDevice::SetClip(const RECT *clip, QXLDrawable *drawable) { Resource *rects_res; @@ -3794,6 +3814,14 @@ void QxlDevice::DrawableAddRes(QXLDrawable *drawable, Resource *res) AddRes(output, res); } +void QxlDevice::CursorCmdAddRes(QXLCursorCmd *cmd, Resource *res) +{ + QXLOutput *output; + + output = (QXLOutput *)((UINT8 *)cmd - sizeof(QXLOutput)); + AddRes(output, res); +} + void QxlDevice::FreeClipRectsEx(Resource *res) { DbgPrint(TRACE_LEVEL_VERBOSE, ("<--> %s\n", __FUNCTION__)); @@ -3842,6 +3870,29 @@ void QxlDevice::FreeBitmapImage(Resource *res) DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } +void QxlDevice::FreeCursorEx(Resource *res) +{ + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--> %s\n", __FUNCTION__)); + QxlDevice* pqxl = (QxlDevice*)res->ptr; + pqxl->FreeCursor(res); +} + +void QxlDevice::FreeCursor(Resource *res) +{ + QXLPHYSICAL chunk_phys; + + DbgPrint(TRACE_LEVEL_FATAL, ("---> %s\n", __FUNCTION__)); + chunk_phys = ((InternalCursor *)res->res)->cursor.chunk.next_chunk; + while (chunk_phys) { + QXLDataChunk *chunk = (QXLDataChunk *)VA(chunk_phys, m_MainMemSlot); + chunk_phys = chunk->next_chunk; + FreeMem(MSPACE_TYPE_DEVRAM, chunk); + } + + FreeMem(MSPACE_TYPE_DEVRAM, res); + DbgPrint(TRACE_LEVEL_FATAL, ("<--- %s\n", __FUNCTION__)); +} + QXLDrawable *QxlDevice::Drawable(UINT8 type, CONST RECT *area, CONST RECT *clip, UINT32 surface_id) { QXLDrawable *drawable; @@ -3890,6 +3941,29 @@ void QxlDevice::PushDrawable(QXLDrawable *drawable) { DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } +void QxlDevice::PushCursorCmd(QXLCursorCmd *cursor_cmd) +{ + QXLCommand *cmd; + + DbgPrint(TRACE_LEVEL_FATAL, ("---> %s\n", __FUNCTION__)); + + KeWaitForSingleObject + ( + &m_CrsLock, + Executive, + KernelMode, + FALSE, + NULL + ); + WaitForCursorRing(); + cmd = SPICE_RING_PROD_ITEM(m_CursorRing); + cmd->type = QXL_CMD_CURSOR; + cmd->data = PA(cursor_cmd, m_MainMemSlot); + PushCursor(); + KeReleaseMutex(&m_CrsLock,FALSE); + DbgPrint(TRACE_LEVEL_FATAL, ("<--- %s\n", __FUNCTION__)); +} + VOID QxlDevice::SetImageId(InternalImage *internal, BOOL cache_me, LONG width, @@ -3909,7 +3983,6 @@ VOID QxlDevice::SetImageId(InternalImage *internal, } } - VOID QxlDevice::BltBits ( BLT_INFO* pDst, CONST BLT_INFO* pSrc, @@ -3952,7 +4025,6 @@ VOID QxlDevice::BltBits ( drawable->u.copy.src_area.top = 0; drawable->u.copy.src_area.right = width; - alloc_size = BITMAP_ALLOC_BASE + BITS_BUF_MAX - BITS_BUF_MAX % line_size; alloc_size = MIN(BITMAP_ALLOC_BASE + height * line_size, alloc_size); image_res = (Resource*)AllocMem(MSPACE_TYPE_DEVRAM, alloc_size, TRUE); @@ -4048,7 +4120,6 @@ VOID QxlDevice::PutBytesAlign(QXLDataChunk **chunk_ptr, UINT8 **now_ptr, DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); } - VOID QxlDevice::BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod) { QXLDrawable *drawable; @@ -4085,6 +4156,103 @@ NTSTATUS QxlDevice::HWClose(void) return STATUS_SUCCESS; } +NTSTATUS QxlDevice::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape) +{ + QXLCursorCmd *cursor_cmd; + InternalCursor *internal; + QXLCursor *cursor; + Resource *res; + QXLDataChunk *chunk; + ULONG unique; + UINT8 *src; + UINT8 *src_end; + UINT8 *now; + UINT8 *end; + int line_size; + + DbgPrint(TRACE_LEVEL_FATAL, ("<--> %s flag = %d pitch = %d, pixels = %p, id = %d, w = %d, h = %d, x = %d, y = %d\n", __FUNCTION__, + pSetPointerShape->Flags.Value, + pSetPointerShape->Pitch, + pSetPointerShape->pPixels, + pSetPointerShape->VidPnSourceId, + pSetPointerShape->Width, + pSetPointerShape->Height, + pSetPointerShape->XHot, + pSetPointerShape->YHot)); + if (!pSetPointerShape->Flags.Monochrome) + return STATUS_UNSUCCESSFUL; + cursor_cmd = CursorCmd(); + cursor_cmd->type = QXL_CURSOR_SET; + + cursor_cmd->u.set.visible = TRUE; + cursor_cmd->u.set.position.x = (INT16)pSetPointerShape->XHot; + cursor_cmd->u.set.position.y = (INT16)pSetPointerShape->YHot; + + res = (Resource *)AllocMem(MSPACE_TYPE_DEVRAM, CURSOR_ALLOC_SIZE, TRUE); + res->refs = 1; + res->free = FreeCursorEx; + res->ptr = this; + RESOURCE_TYPE(res, RESOURCE_TYPE_CURSOR); + + internal = (InternalCursor *)res->res; + + cursor = &internal->cursor; + cursor->header.type = SPICE_CURSOR_TYPE_MONO; + cursor->header.unique = 0; + cursor->header.width = (UINT16)pSetPointerShape->Width; + cursor->header.height = (UINT16)pSetPointerShape->Height; + cursor->header.hot_spot_x = (UINT16)pSetPointerShape->XHot; + cursor->header.hot_spot_y = (UINT16)pSetPointerShape->YHot; + + line_size = pSetPointerShape->Pitch; + cursor->data_size = line_size * pSetPointerShape->Width; + + chunk = &cursor->chunk; + chunk->data_size = cursor->data_size; + chunk->prev_chunk = 0; + chunk->next_chunk = 0; + + src = (UINT8*)pSetPointerShape->pPixels; + now = chunk->data; + end = (UINT8 *)res + CURSOR_ALLOC_SIZE; + + +// src_end = src + (local_surf->lDelta * local_surf->sizlBitmap.cy); +// for (; src != src_end; src += local_surf->lDelta) { +// PutBytesAlign(&chunk, &now, &end, src, line_size, +// PAGE_SIZE, 1); +// } + memcpy(chunk->data, src, chunk->data_size); + CursorCmdAddRes(cursor_cmd, res); + RELEASE_RES(res); + cursor_cmd->u.set.shape = PA(&internal->cursor, m_MainMemSlot); + PushCursorCmd(cursor_cmd); + DbgPrint(TRACE_LEVEL_FATAL, ("<--- %s\n", __FUNCTION__)); + + return STATUS_SUCCESS; +} + +NTSTATUS QxlDevice::SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition) +{ + QXLCursorCmd *cursor_cmd; + DbgPrint(TRACE_LEVEL_FATAL, ("<--> %s flag = %d id = %d, x = %d, y = %d\n", __FUNCTION__, + pSetPointerPosition->Flags.Value, + pSetPointerPosition->VidPnSourceId, + pSetPointerPosition->X, + pSetPointerPosition->Y)); + cursor_cmd = CursorCmd(); + if (pSetPointerPosition->X < 0) { + cursor_cmd->type = QXL_CURSOR_HIDE; + } else { + cursor_cmd->type = QXL_CURSOR_MOVE; + cursor_cmd->u.position.x = (INT16)pSetPointerPosition->X; + cursor_cmd->u.position.y = (INT16)pSetPointerPosition->Y; + } + PushCursorCmd(cursor_cmd); + DbgPrint(TRACE_LEVEL_FATAL, ("<--- %s\n", __FUNCTION__)); + return STATUS_SUCCESS; +} + VOID QxlDevice::WaitForCmdRing() { int wait; @@ -4112,6 +4280,39 @@ VOID QxlDevice::PushCmd() DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s notify = %d\n", __FUNCTION__, notify)); } +VOID QxlDevice::WaitForCursorRing(VOID) +{ + int wait; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + + for (;;) { + SPICE_RING_PROD_WAIT(m_CursorRing, wait); + + if (!wait) { + break; + } + + LARGE_INTEGER timeout; // 1 => 100 nanoseconds + timeout.QuadPart = -1 * (1000 * 1000 * 10); //negative => relative // 1s + WAIT_FOR_EVENT(m_CursorEvent, &timeout); + + if (SPICE_RING_IS_FULL(m_CursorRing)) { + DbgPrint(TRACE_LEVEL_ERROR, ("%s: timeout\n", __FUNCTION__)); + } + } +} + +VOID QxlDevice::PushCursor(VOID) +{ + int notify; + DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); + SPICE_RING_PUSH(m_CursorRing, notify); + if (notify) { + SyncIo(QXL_IO_NOTIFY_CURSOR, 0); + } + DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s notify = %d\n", __FUNCTION__, notify)); +} + BOOLEAN QxlDevice::InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber) { UNREFERENCED_PARAMETER(MessageNumber); diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h index 6b6bd90..b734bbb 100755 --- a/qxldod/QxlDod.h +++ b/qxldod/QxlDod.h @@ -239,6 +239,8 @@ public: _In_ const CURRENT_BDD_MODE* pModeCur) = 0; virtual VOID BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod) = 0; + virtual NTSTATUS SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape) = 0; + virtual NTSTATUS SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition) = 0; protected: virtual NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo) = 0; protected: @@ -276,6 +278,8 @@ public: BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber); VOID DpcRoutine(PVOID); VOID ResetDevice(VOID); + NTSTATUS SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape); + NTSTATUS SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition); protected: NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo); private: @@ -379,23 +383,15 @@ typedef struct Ring { RingItem *next; } Ring; -typedef struct CacheImage { - struct CacheImage *next; - RingItem lru_link; - UINT32 key; - UINT32 hits; - UINT8 format; - UINT32 width; - UINT32 height; - struct InternalImage *image; -} CacheImage; - typedef struct InternalImage { - CacheImage *cache; QXLImage image; } InternalImage; +typedef struct InternalCursor { + QXLCursor cursor; +} InternalCursor; +#define CURSOR_ALLOC_SIZE (PAGE_SIZE << 1) typedef struct DpcCbContext { void* ptr; @@ -433,6 +429,8 @@ public: BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber); VOID DpcRoutine(PVOID); VOID ResetDevice(VOID); + NTSTATUS SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape); + NTSTATUS SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition); protected: NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo); VOID BltBits (BLT_INFO* pDst, @@ -444,7 +442,9 @@ protected: CONST RECT *clip, UINT32 surface_id); void PushDrawable(QXLDrawable *drawable); + void PushCursorCmd(QXLCursorCmd *cursor_cmd); QXLDrawable *GetDrawable(); + QXLCursorCmd *CursorCmd(); void *AllocMem(UINT32 mspace_type, size_t size, BOOL force); VOID UpdateArea(CONST RECT* area, UINT32 surface_id); VOID SetImageId(InternalImage *internal, @@ -475,12 +475,17 @@ private: BOOL SetClip(const RECT *clip, QXLDrawable *drawable); void AddRes(QXLOutput *output, Resource *res); void DrawableAddRes(QXLDrawable *drawable, Resource *res); + void CursorCmdAddRes(QXLCursorCmd *cmd, Resource *res); void FreeClipRects(Resource *res); void static FreeClipRectsEx(Resource *res); void FreeBitmapImage(Resource *res); void static FreeBitmapImageEx(Resource *res); + void static FreeCursorEx(Resource *res); + void FreeCursor(Resource *res); void WaitForCmdRing(void); void PushCmd(void); + void WaitForCursorRing(void); + void PushCursor(void); void PutBytesAlign(QXLDataChunk **chunk_ptr, UINT8 **now_ptr, UINT8 **end_ptr, UINT8 *src, int size, size_t alloc_size, uint32_t alignment); @@ -527,7 +532,7 @@ private: KMUTEX m_MemLock; KMUTEX m_CmdLock; KMUTEX m_IoLock; - + KMUTEX m_CrsLock; MspaceInfo m_MSInfo[NUM_MSPACES]; UINT64 m_FreeOutputs;