[Spice-devel,v2,11/12] qxl-wddm-dod: Implement non-forced bitmap allocation

Submitted by Yuri Benditovich on April 1, 2017, 4:40 p.m.

Details

Message ID 1491064839-13612-12-git-send-email-yuri.benditovich@daynix.com
State New
Headers show
Series "Set of patches for further support of VSync" ( rev: 2 ) in Spice

Not browsing as part of any series.

Commit Message

Yuri Benditovich April 1, 2017, 4:40 p.m.
From: "yuri.benditovich@daynix.com" <yuri.benditovich@daynix.com>

Preparation for non-forced allocations.
Move bitmap creation to dedicated procedure which is able
to allocate device memory forced or non-forced.
In forced case it works as before.
In non-forced case, if allocation fails, the procedure allocates
memory from OS pool for entire bitmap and copies source data to it.
Later, before sending command, memory will be allocated from device
memory and copied from intermediate location to new one.

Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
---
 qxldod/QxlDod.cpp | 162 ++++++++++++++++++++++++++++++++++--------------------
 qxldod/QxlDod.h   |   1 +
 2 files changed, 102 insertions(+), 61 deletions(-)

Patch hide | download patch | download mbox

diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp
index 08143ea..a807396 100755
--- a/qxldod/QxlDod.cpp
+++ b/qxldod/QxlDod.cpp
@@ -4405,6 +4405,93 @@  QXLDrawable *QxlDevice::PrepareCopyBits(const RECT& rect, const POINT& sourcePoi
     return drawable;
 }
 
+BOOLEAN QxlDevice::AttachNewBitmap(QXLDrawable *drawable, UINT8 *src, UINT8 *src_end, INT pitch, BOOLEAN bForce)
+{
+    PAGED_CODE();
+    LONG width, height;
+    size_t alloc_size;
+    UINT32 line_size;
+    Resource *image_res;
+    InternalImage *internal;
+    QXLDataChunk *chunk;
+    PLIST_ENTRY pDelayedList = NULL;
+    UINT8* dest, *dest_end;
+
+    height = drawable->u.copy.src_area.bottom;
+    width = drawable->u.copy.src_area.right;
+    line_size = width * 4;
+
+    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_VRAM, alloc_size, bForce);
+
+    if (image_res) {
+        image_res->refs = 1;
+        image_res->free = FreeBitmapImageEx;
+        image_res->ptr = this;
+
+        internal = (InternalImage *)image_res->res;
+        SetImageId(internal, FALSE, width, height, SPICE_BITMAP_FMT_32BIT, 0);
+        internal->image.descriptor.flags = 0;
+        internal->image.descriptor.type = SPICE_IMAGE_TYPE_BITMAP;
+
+        chunk = (QXLDataChunk *)(&internal->image.bitmap + 1);
+        chunk->data_size = 0;
+        chunk->prev_chunk = 0;
+        chunk->next_chunk = 0;
+        internal->image.bitmap.data = PA(chunk, m_SurfaceMemSlot);
+        internal->image.bitmap.flags = 0;
+        internal->image.descriptor.width = internal->image.bitmap.x = width;
+        internal->image.descriptor.height = internal->image.bitmap.y = height;
+        internal->image.bitmap.format = SPICE_BITMAP_FMT_RGBA;
+        internal->image.bitmap.stride = line_size;
+        internal->image.bitmap.palette = 0;
+
+        dest = chunk->data;
+        dest_end = (UINT8 *)image_res + alloc_size;
+
+        drawable->u.copy.src_bitmap = PA(&internal->image, m_SurfaceMemSlot);
+
+        DrawableAddRes(drawable, image_res);
+        RELEASE_RES(image_res);
+        alloc_size = height * line_size;
+    } else if (!bForce) {
+        alloc_size = height * line_size;
+        // allocate delayed chunck for entire bitmap without limitation
+        QXL_DELAYED_CHUNK *pChunk = (QXL_DELAYED_CHUNK *)new (PagedPool)BYTE[alloc_size + sizeof(QXL_DELAYED_CHUNK)];
+        if (pChunk) {
+            // add it to delayed list
+            InsertTailList(pDelayedList, &pChunk->list);
+            // PutBytesAlign do not need to allocate additional memory
+            pDelayedList = NULL;
+            chunk = &pChunk->chunk;
+            chunk->data_size = 0;
+            chunk->prev_chunk = 0;
+            chunk->next_chunk = 0;
+            // set dest and dest_end
+            dest = chunk->data;
+            dest_end = chunk->data + alloc_size;
+        } else {
+            // can't allocate memory
+            DbgPrint(TRACE_LEVEL_ERROR, ("Cannot allocate delayed bitmap for drawable\n"));
+            return FALSE;
+        }
+    } else {
+        // can't allocate memory (forced), driver abort flow
+        DbgPrint(TRACE_LEVEL_ERROR, ("Cannot get bitmap for drawable (stopping)\n"));
+        return FALSE;
+    }
+
+    for (; src != src_end; src -= pitch, alloc_size -= line_size) {
+        BOOLEAN b = PutBytesAlign(&chunk, &dest, &dest_end, src, line_size, alloc_size, pDelayedList);
+        if (!b) {
+            DbgPrint(TRACE_LEVEL_WARNING, ("%s: aborting copy of lines\n", __FUNCTION__));
+            return FALSE;
+        }
+    }
+    return TRUE;
+}
+
 QXLDrawable *QxlDevice::PrepareBltBits (
     BLT_INFO* pDst,
     CONST BLT_INFO* pSrc,
@@ -4414,11 +4501,6 @@  QXLDrawable *QxlDevice::PrepareBltBits (
 {
     PAGED_CODE();
     QXLDrawable *drawable;
-    Resource *image_res;
-    InternalImage *internal;
-    size_t alloc_size;
-    QXLDataChunk *chunk;
-    UINT32 line_size;
     LONG width;
     LONG height;
 
@@ -4444,72 +4526,30 @@  QXLDrawable *QxlDevice::PrepareBltBits (
 
     height = pRect->bottom - pRect->top;
     width = pRect->right - pRect->left;
-    line_size = width * 4;
 
     drawable->u.copy.src_area.bottom = height;
     drawable->u.copy.src_area.left = 0;
     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_VRAM, alloc_size, TRUE);
-    if (!image_res) {
-        ReleaseOutput(drawable->release_info.id);
-        DbgPrint(TRACE_LEVEL_ERROR, ("Cannot allocate bitmap for drawable\n"));
-        return NULL;
-    }
-
-    image_res->refs = 1;
-    image_res->free = FreeBitmapImageEx;
-    image_res->ptr = this;
+    CopyRect(&drawable->surfaces_rects[1], pRect);
 
-    internal = (InternalImage *)image_res->res;
-    SetImageId(internal, FALSE, width, height, SPICE_BITMAP_FMT_32BIT, 0);
-    internal->image.descriptor.flags = 0;
-    internal->image.descriptor.type = SPICE_IMAGE_TYPE_BITMAP;
-    chunk = (QXLDataChunk *)(&internal->image.bitmap + 1);
-    chunk->data_size = 0;
-    chunk->prev_chunk = 0;
-    chunk->next_chunk = 0;
-    internal->image.bitmap.data = PA(chunk, m_SurfaceMemSlot);
-    internal->image.bitmap.flags = 0;
-    internal->image.descriptor.width = internal->image.bitmap.x = width;
-    internal->image.descriptor.height = internal->image.bitmap.y = height;
-    internal->image.bitmap.format = SPICE_BITMAP_FMT_RGBA;
-    internal->image.bitmap.stride = line_size;
-
-    UINT8* src = (UINT8*)pSrc->pBits+
-                                (pSourcePoint->y) * pSrc->Pitch +
-                                (pSourcePoint->x * 4);
+    UINT8* src = (UINT8*)pSrc->pBits +
+        (pSourcePoint->y) * pSrc->Pitch +
+        (pSourcePoint->x * 4);
     UINT8* src_end = src - pSrc->Pitch;
     src += pSrc->Pitch * (height - 1);
-    UINT8* dest = chunk->data;
-    UINT8* dest_end = (UINT8 *)image_res + alloc_size;
-    alloc_size = height * line_size;
-
-    for (; src != src_end; src -= pSrc->Pitch, alloc_size -= line_size) {
-        if (!PutBytesAlign(&chunk, &dest, &dest_end, src,
-            line_size, alloc_size, NULL)) {
-            // not reachable when forced allocation used
-            ReleaseOutput(drawable->release_info.id);
-            DbgPrint(TRACE_LEVEL_ERROR, ("Cannot allocate additional bitmap for drawable\n"));
-            return NULL;
-        }
-    }
 
-    internal->image.bitmap.palette = 0;
-
-    drawable->u.copy.src_bitmap = PA(&internal->image, m_SurfaceMemSlot);
-
-    CopyRect(&drawable->surfaces_rects[1], pRect);
-    DrawableAddRes(drawable, image_res);
-    RELEASE_RES(image_res);
-
-    DbgPrint(TRACE_LEVEL_INFORMATION, ("%s drawable= %p type = %d, effect = %d Dest right(%d) left(%d) top(%d) bottom(%d) src_bitmap= %p.\n", __FUNCTION__,
-         drawable, drawable->type, drawable->effect, drawable->surfaces_rects[0].right, drawable->surfaces_rects[0].left,
-         drawable->surfaces_rects[0].top, drawable->surfaces_rects[0].bottom,
-         drawable->u.copy.src_bitmap));
+    if (!AttachNewBitmap(drawable, src, src_end, (INT)pSrc->Pitch, TRUE)) {
+        ReleaseOutput(drawable->release_info.id);
+        drawable = NULL;
+    }
+    else {
+        DbgPrint(TRACE_LEVEL_INFORMATION, ("%s drawable= %p type = %d, effect = %d Dest right(%d) left(%d) top(%d) bottom(%d) src_bitmap= %p.\n", __FUNCTION__,
+            drawable, drawable->type, drawable->effect, drawable->surfaces_rects[0].right, drawable->surfaces_rects[0].left,
+            drawable->surfaces_rects[0].top, drawable->surfaces_rects[0].bottom,
+            drawable->u.copy.src_bitmap));
+    }
 
     DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
 
diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h
index ca93322..831d2b0 100755
--- a/qxldod/QxlDod.h
+++ b/qxldod/QxlDod.h
@@ -608,6 +608,7 @@  private:
     void PushCmd(void);
     void WaitForCursorRing(void);
     void PushCursor(void);
+    BOOLEAN AttachNewBitmap(QXLDrawable *drawable, UINT8 *src, UINT8 *src_end, INT pitch, BOOLEAN forced);
     BOOLEAN PutBytesAlign(QXLDataChunk **chunk_ptr, UINT8 **now_ptr,
                             UINT8 **end_ptr, UINT8 *src, int size,
                             size_t alloc_size, PLIST_ENTRY pDelayed);

Comments

> 
> From: "yuri.benditovich@daynix.com" <yuri.benditovich@daynix.com>
> 
> Preparation for non-forced allocations.
> Move bitmap creation to dedicated procedure which is able
> to allocate device memory forced or non-forced.
> In forced case it works as before.
> In non-forced case, if allocation fails, the procedure allocates
> memory from OS pool for entire bitmap and copies source data to it.
> Later, before sending command, memory will be allocated from device
> memory and copied from intermediate location to new one.
> 
> Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>

Would be great to split function creation and addition of non-forced
allocation

Frediano

> ---
>  qxldod/QxlDod.cpp | 162
>  ++++++++++++++++++++++++++++++++++--------------------
>  qxldod/QxlDod.h   |   1 +
>  2 files changed, 102 insertions(+), 61 deletions(-)
> 
> diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp
> index 08143ea..a807396 100755
> --- a/qxldod/QxlDod.cpp
> +++ b/qxldod/QxlDod.cpp
> @@ -4405,6 +4405,93 @@ QXLDrawable *QxlDevice::PrepareCopyBits(const RECT&
> rect, const POINT& sourcePoi
>      return drawable;
>  }
>  
> +BOOLEAN QxlDevice::AttachNewBitmap(QXLDrawable *drawable, UINT8 *src, UINT8
> *src_end, INT pitch, BOOLEAN bForce)
> +{
> +    PAGED_CODE();
> +    LONG width, height;
> +    size_t alloc_size;
> +    UINT32 line_size;
> +    Resource *image_res;
> +    InternalImage *internal;
> +    QXLDataChunk *chunk;
> +    PLIST_ENTRY pDelayedList = NULL;
> +    UINT8* dest, *dest_end;
> +
> +    height = drawable->u.copy.src_area.bottom;
> +    width = drawable->u.copy.src_area.right;
> +    line_size = width * 4;
> +
> +    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_VRAM, alloc_size, bForce);
> +
> +    if (image_res) {
> +        image_res->refs = 1;
> +        image_res->free = FreeBitmapImageEx;
> +        image_res->ptr = this;
> +
> +        internal = (InternalImage *)image_res->res;
> +        SetImageId(internal, FALSE, width, height, SPICE_BITMAP_FMT_32BIT,
> 0);
> +        internal->image.descriptor.flags = 0;
> +        internal->image.descriptor.type = SPICE_IMAGE_TYPE_BITMAP;
> +
> +        chunk = (QXLDataChunk *)(&internal->image.bitmap + 1);
> +        chunk->data_size = 0;
> +        chunk->prev_chunk = 0;
> +        chunk->next_chunk = 0;
> +        internal->image.bitmap.data = PA(chunk, m_SurfaceMemSlot);
> +        internal->image.bitmap.flags = 0;
> +        internal->image.descriptor.width = internal->image.bitmap.x = width;
> +        internal->image.descriptor.height = internal->image.bitmap.y =
> height;
> +        internal->image.bitmap.format = SPICE_BITMAP_FMT_RGBA;
> +        internal->image.bitmap.stride = line_size;
> +        internal->image.bitmap.palette = 0;
> +
> +        dest = chunk->data;
> +        dest_end = (UINT8 *)image_res + alloc_size;
> +
> +        drawable->u.copy.src_bitmap = PA(&internal->image,
> m_SurfaceMemSlot);
> +
> +        DrawableAddRes(drawable, image_res);
> +        RELEASE_RES(image_res);
> +        alloc_size = height * line_size;
> +    } else if (!bForce) {
> +        alloc_size = height * line_size;
> +        // allocate delayed chunck for entire bitmap without limitation
> +        QXL_DELAYED_CHUNK *pChunk = (QXL_DELAYED_CHUNK *)new
> (PagedPool)BYTE[alloc_size + sizeof(QXL_DELAYED_CHUNK)];
> +        if (pChunk) {
> +            // add it to delayed list
> +            InsertTailList(pDelayedList, &pChunk->list);
> +            // PutBytesAlign do not need to allocate additional memory
> +            pDelayedList = NULL;
> +            chunk = &pChunk->chunk;
> +            chunk->data_size = 0;
> +            chunk->prev_chunk = 0;
> +            chunk->next_chunk = 0;
> +            // set dest and dest_end
> +            dest = chunk->data;
> +            dest_end = chunk->data + alloc_size;
> +        } else {
> +            // can't allocate memory
> +            DbgPrint(TRACE_LEVEL_ERROR, ("Cannot allocate delayed bitmap for
> drawable\n"));
> +            return FALSE;
> +        }
> +    } else {
> +        // can't allocate memory (forced), driver abort flow
> +        DbgPrint(TRACE_LEVEL_ERROR, ("Cannot get bitmap for drawable
> (stopping)\n"));
> +        return FALSE;
> +    }
> +
> +    for (; src != src_end; src -= pitch, alloc_size -= line_size) {
> +        BOOLEAN b = PutBytesAlign(&chunk, &dest, &dest_end, src, line_size,
> alloc_size, pDelayedList);
> +        if (!b) {
> +            DbgPrint(TRACE_LEVEL_WARNING, ("%s: aborting copy of lines\n",
> __FUNCTION__));
> +            return FALSE;
> +        }
> +    }
> +    return TRUE;
> +}
> +
>  QXLDrawable *QxlDevice::PrepareBltBits (
>      BLT_INFO* pDst,
>      CONST BLT_INFO* pSrc,
> @@ -4414,11 +4501,6 @@ QXLDrawable *QxlDevice::PrepareBltBits (
>  {
>      PAGED_CODE();
>      QXLDrawable *drawable;
> -    Resource *image_res;
> -    InternalImage *internal;
> -    size_t alloc_size;
> -    QXLDataChunk *chunk;
> -    UINT32 line_size;
>      LONG width;
>      LONG height;
>  
> @@ -4444,72 +4526,30 @@ QXLDrawable *QxlDevice::PrepareBltBits (
>  
>      height = pRect->bottom - pRect->top;
>      width = pRect->right - pRect->left;
> -    line_size = width * 4;
>  
>      drawable->u.copy.src_area.bottom = height;
>      drawable->u.copy.src_area.left = 0;
>      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_VRAM, alloc_size, TRUE);
> -    if (!image_res) {
> -        ReleaseOutput(drawable->release_info.id);
> -        DbgPrint(TRACE_LEVEL_ERROR, ("Cannot allocate bitmap for
> drawable\n"));
> -        return NULL;
> -    }
> -
> -    image_res->refs = 1;
> -    image_res->free = FreeBitmapImageEx;
> -    image_res->ptr = this;
> +    CopyRect(&drawable->surfaces_rects[1], pRect);
>  
> -    internal = (InternalImage *)image_res->res;
> -    SetImageId(internal, FALSE, width, height, SPICE_BITMAP_FMT_32BIT, 0);
> -    internal->image.descriptor.flags = 0;
> -    internal->image.descriptor.type = SPICE_IMAGE_TYPE_BITMAP;
> -    chunk = (QXLDataChunk *)(&internal->image.bitmap + 1);
> -    chunk->data_size = 0;
> -    chunk->prev_chunk = 0;
> -    chunk->next_chunk = 0;
> -    internal->image.bitmap.data = PA(chunk, m_SurfaceMemSlot);
> -    internal->image.bitmap.flags = 0;
> -    internal->image.descriptor.width = internal->image.bitmap.x = width;
> -    internal->image.descriptor.height = internal->image.bitmap.y = height;
> -    internal->image.bitmap.format = SPICE_BITMAP_FMT_RGBA;
> -    internal->image.bitmap.stride = line_size;
> -
> -    UINT8* src = (UINT8*)pSrc->pBits+
> -                                (pSourcePoint->y) * pSrc->Pitch +
> -                                (pSourcePoint->x * 4);
> +    UINT8* src = (UINT8*)pSrc->pBits +
> +        (pSourcePoint->y) * pSrc->Pitch +
> +        (pSourcePoint->x * 4);
>      UINT8* src_end = src - pSrc->Pitch;
>      src += pSrc->Pitch * (height - 1);
> -    UINT8* dest = chunk->data;
> -    UINT8* dest_end = (UINT8 *)image_res + alloc_size;
> -    alloc_size = height * line_size;
> -
> -    for (; src != src_end; src -= pSrc->Pitch, alloc_size -= line_size) {
> -        if (!PutBytesAlign(&chunk, &dest, &dest_end, src,
> -            line_size, alloc_size, NULL)) {
> -            // not reachable when forced allocation used
> -            ReleaseOutput(drawable->release_info.id);
> -            DbgPrint(TRACE_LEVEL_ERROR, ("Cannot allocate additional bitmap
> for drawable\n"));
> -            return NULL;
> -        }
> -    }
>  
> -    internal->image.bitmap.palette = 0;
> -
> -    drawable->u.copy.src_bitmap = PA(&internal->image, m_SurfaceMemSlot);
> -
> -    CopyRect(&drawable->surfaces_rects[1], pRect);
> -    DrawableAddRes(drawable, image_res);
> -    RELEASE_RES(image_res);
> -
> -    DbgPrint(TRACE_LEVEL_INFORMATION, ("%s drawable= %p type = %d, effect =
> %d Dest right(%d) left(%d) top(%d) bottom(%d) src_bitmap= %p.\n",
> __FUNCTION__,
> -         drawable, drawable->type, drawable->effect,
> drawable->surfaces_rects[0].right, drawable->surfaces_rects[0].left,
> -         drawable->surfaces_rects[0].top,
> drawable->surfaces_rects[0].bottom,
> -         drawable->u.copy.src_bitmap));
> +    if (!AttachNewBitmap(drawable, src, src_end, (INT)pSrc->Pitch, TRUE)) {
> +        ReleaseOutput(drawable->release_info.id);
> +        drawable = NULL;
> +    }
> +    else {
> +        DbgPrint(TRACE_LEVEL_INFORMATION, ("%s drawable= %p type = %d,
> effect = %d Dest right(%d) left(%d) top(%d) bottom(%d) src_bitmap= %p.\n",
> __FUNCTION__,
> +            drawable, drawable->type, drawable->effect,
> drawable->surfaces_rects[0].right, drawable->surfaces_rects[0].left,
> +            drawable->surfaces_rects[0].top,
> drawable->surfaces_rects[0].bottom,
> +            drawable->u.copy.src_bitmap));
> +    }
>  
>      DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
>  
> diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h
> index ca93322..831d2b0 100755
> --- a/qxldod/QxlDod.h
> +++ b/qxldod/QxlDod.h
> @@ -608,6 +608,7 @@ private:
>      void PushCmd(void);
>      void WaitForCursorRing(void);
>      void PushCursor(void);
> +    BOOLEAN AttachNewBitmap(QXLDrawable *drawable, UINT8 *src, UINT8
> *src_end, INT pitch, BOOLEAN forced);
>      BOOLEAN PutBytesAlign(QXLDataChunk **chunk_ptr, UINT8 **now_ptr,
>                              UINT8 **end_ptr, UINT8 *src, int size,
>                              size_t alloc_size, PLIST_ENTRY pDelayed);
> --
> 2.7.0.windows.1
> 
> _______________________________________________
> Spice-devel mailing list
> Spice-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/spice-devel
>