qxl-wddm-dod: PutBytesAlign supports non-forced allocation

Preparation for offload of allocations from device's memory
to separate thread. Procedure PutBytesAlign is called to
allocate memory chunk from device memory and copy data to it.
With current commit the procedure (if called with non-NULL
linked list root entry parameter) can use non-forced allocation.
If such allocation fails, it allocates 'delayed' chunk from
OS memory and copies data to it. Later before sending drawable command
this chunk shall be processed, storage allocated from device memory
(forced) and data copied to it.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
Acked-by: Frediano Ziglio <fziglio@redhat.com>
This commit is contained in:
yuri.benditovich@daynix.com 2017-04-08 13:46:51 +03:00 committed by Frediano Ziglio
parent 6a01308788
commit 9721a48dc9
2 changed files with 50 additions and 26 deletions

View File

@ -4501,7 +4501,8 @@ QXLDrawable *QxlDevice::PrepareBltBits (
for (; src != src_end; src -= pSrc->Pitch, alloc_size -= line_size) { for (; src != src_end; src -= pSrc->Pitch, alloc_size -= line_size) {
if (!PutBytesAlign(&chunk, &dest, &dest_end, src, if (!PutBytesAlign(&chunk, &dest, &dest_end, src,
line_size, alloc_size, line_size)) { line_size, alloc_size, NULL)) {
// not reachable when forced allocation used
ReleaseOutput(drawable->release_info.id); ReleaseOutput(drawable->release_info.id);
DbgPrint(TRACE_LEVEL_ERROR, ("Cannot allocate additional bitmap for drawable\n")); DbgPrint(TRACE_LEVEL_ERROR, ("Cannot allocate additional bitmap for drawable\n"));
return NULL; return NULL;
@ -4526,36 +4527,54 @@ QXLDrawable *QxlDevice::PrepareBltBits (
return drawable; return drawable;
} }
// can work in 2 modes:
// forced - as before, when pDelayed not provided or if VSync is not in use
// non-forced, if VSync is active and pDelayed provided. In this case, if memory
// can't be allocated immediately, allocates 'delayed chunk' and copies data
// to it. Further, before send to the device, this 'delayed chunk' should be processed,
// regular chunk allocated from device memory and the data copied to it
BOOLEAN QxlDevice::PutBytesAlign(QXLDataChunk **chunk_ptr, UINT8 **now_ptr, BOOLEAN QxlDevice::PutBytesAlign(QXLDataChunk **chunk_ptr, UINT8 **now_ptr,
UINT8 **end_ptr, UINT8 *src, int size, UINT8 **end_ptr, UINT8 *src, int size,
size_t alloc_size, uint32_t alignment) size_t alloc_size, PLIST_ENTRY pDelayed)
{ {
PAGED_CODE(); PAGED_CODE();
BOOLEAN bResult = TRUE;
BOOLEAN bForced = !g_bSupportVSync || !pDelayed;
QXLDataChunk *chunk = *chunk_ptr; QXLDataChunk *chunk = *chunk_ptr;
UINT8 *now = *now_ptr; UINT8 *now = *now_ptr;
UINT8 *end = *end_ptr; UINT8 *end = *end_ptr;
size_t maxAllocSize = BITS_BUF_MAX - BITS_BUF_MAX % size;
alloc_size = MIN(size, maxAllocSize);
DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__)); DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
while (size) { while (size) {
int cp_size = (int)MIN(end - now, size); int cp_size = (int)MIN(end - now, size);
if (!cp_size) { if (!cp_size) {
size_t aligned_size; void *ptr = (bForced || IsListEmpty(pDelayed)) ? AllocMem(MSPACE_TYPE_VRAM, alloc_size + sizeof(QXLDataChunk), bForced) : NULL;
aligned_size = (int)MIN(alloc_size + alignment - 1, BITS_BUF_MAX); if (ptr) {
aligned_size -= aligned_size % alignment;
void *ptr = AllocMem(MSPACE_TYPE_VRAM, size + sizeof(QXLDataChunk), TRUE);
if (!ptr) {
return FALSE;
}
chunk->next_chunk = PA(ptr, m_SurfaceMemSlot); chunk->next_chunk = PA(ptr, m_SurfaceMemSlot);
((QXLDataChunk *)ptr)->prev_chunk = PA(chunk, m_SurfaceMemSlot); ((QXLDataChunk *)ptr)->prev_chunk = PA(chunk, m_SurfaceMemSlot);
chunk = (QXLDataChunk *)ptr; chunk = (QXLDataChunk *)ptr;
chunk->data_size = 0;
chunk->next_chunk = 0; chunk->next_chunk = 0;
}
if (!ptr && pDelayed) {
ptr = new (PagedPool)BYTE[alloc_size + sizeof(DelayedChunk)];
if (ptr) {
DelayedChunk *pChunk = (DelayedChunk *)ptr;
InsertTailList(pDelayed, &pChunk->list);
pChunk->chunk.prev_chunk = (QXLPHYSICAL)chunk;
chunk = &pChunk->chunk;
}
}
if (ptr) {
chunk->data_size = 0;
now = chunk->data; now = chunk->data;
end = now + size; end = now + alloc_size;
cp_size = (int)MIN(end - now, size); cp_size = (int)MIN(end - now, size);
} else {
bResult = FALSE;
break;
}
} }
RtlCopyMemory(now, src, cp_size); RtlCopyMemory(now, src, cp_size);
src += cp_size; src += cp_size;
@ -4567,7 +4586,7 @@ BOOLEAN QxlDevice::PutBytesAlign(QXLDataChunk **chunk_ptr, UINT8 **now_ptr,
*now_ptr = now; *now_ptr = now;
*end_ptr = end; *end_ptr = end;
DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__)); DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
return TRUE; return bResult;
} }
VOID QxlDevice::BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod) VOID QxlDevice::BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod)
@ -4685,12 +4704,11 @@ NTSTATUS QxlDevice::SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPoi
end = (UINT8 *)res + CURSOR_ALLOC_SIZE; end = (UINT8 *)res + CURSOR_ALLOC_SIZE;
src_end = src + (pSetPointerShape->Pitch * pSetPointerShape->Height * num_images); src_end = src + (pSetPointerShape->Pitch * pSetPointerShape->Height * num_images);
for (; src != src_end; src += pSetPointerShape->Pitch) { for (; src != src_end; src += pSetPointerShape->Pitch) {
if (!PutBytesAlign(&chunk, &now, &end, src, line_size, if (!PutBytesAlign(&chunk, &now, &end, src, line_size, PAGE_SIZE - PAGE_SIZE % line_size, NULL)) {
PAGE_SIZE, 1)) // we have a chance to get here only with color cursor bigger than 45*45
{ // and only if we modify this procedure to use non-forced allocation
DbgPrint(TRACE_LEVEL_ERROR, ("%s: Failed to allocate cursor bitmap\n", __FUNCTION__)); DbgPrint(TRACE_LEVEL_ERROR, ("%s: failed to push part of shape\n", __FUNCTION__));
ReleaseOutput(cursor_cmd->release_info.id); break;
return STATUS_INSUFFICIENT_RESOURCES;
} }
} }
CursorCmdAddRes(cursor_cmd, res); CursorCmdAddRes(cursor_cmd, res);

View File

@ -260,6 +260,12 @@ public:
}; };
#endif #endif
struct DelayedChunk
{
LIST_ENTRY list;
QXLDataChunk chunk;
};
class QxlDod; class QxlDod;
class HwDeviceInterface { class HwDeviceInterface {
@ -603,7 +609,7 @@ private:
void PushCursor(void); void PushCursor(void);
BOOLEAN PutBytesAlign(QXLDataChunk **chunk_ptr, UINT8 **now_ptr, BOOLEAN PutBytesAlign(QXLDataChunk **chunk_ptr, UINT8 **now_ptr,
UINT8 **end_ptr, UINT8 *src, int size, UINT8 **end_ptr, UINT8 *src, int size,
size_t alloc_size, uint32_t alignment); size_t alloc_size, PLIST_ENTRY pDelayed);
void AsyncIo(UCHAR Port, UCHAR Value); void AsyncIo(UCHAR Port, UCHAR Value);
void SyncIo(UCHAR Port, UCHAR Value); void SyncIo(UCHAR Port, UCHAR Value);
NTSTATUS UpdateChildStatus(BOOLEAN connect); NTSTATUS UpdateChildStatus(BOOLEAN connect);