<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Apr 10, 2017 at 3:33 PM, Frediano Ziglio <span dir="ltr"><<a href="mailto:fziglio@redhat.com" target="_blank">fziglio@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">><br>
> From: "<a href="mailto:yuri.benditovich@daynix.com">yuri.benditovich@daynix.com</a>" <<a href="mailto:yuri.benditovich@daynix.com">yuri.benditovich@daynix.com</a>><br>
><br>
> Preparation for offload of allocations from device's memory<br>
> to separate thread. Procedure PutBytesAlign is called to<br>
> allocate memory chunk from device memory and copy data to it.<br>
> With current commit the procedure (if called with non-NULL<br>
> linked list root entry parameter) can use non-forced allocation.<br>
> If such allocation fails, it allocates 'delayed' chunk from<br>
> OS memory and copies data to it. Later before sending drawable command<br>
> this chunk shall be processed, storage allocated from device memory<br>
> (forced) and data copied to it.<br>
><br>
> Signed-off-by: Yuri Benditovich <<a href="mailto:yuri.benditovich@daynix.com">yuri.benditovich@daynix.com</a>><br>
> ---<br>
>  qxldod/QxlDod.cpp | 68<br>
>  ++++++++++++++++++++++++++++++<wbr>+++++--------------------<br>
>  qxldod/QxlDod.h   |  9 +++++++-<br>
>  2 files changed, 51 insertions(+), 26 deletions(-)<br>
><br>
> diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp<br>
> index 5993016..3dce65b 100755<br>
> --- a/qxldod/QxlDod.cpp<br>
> +++ b/qxldod/QxlDod.cpp<br>
> @@ -4501,7 +4501,8 @@ QXLDrawable *QxlDevice::PrepareBltBits (<br>
><br>
>      for (; src != src_end; src -= pSrc->Pitch, alloc_size -= line_size) {<br>
>          if (!PutBytesAlign(&chunk, &dest, &dest_end, src,<br>
> -            line_size, alloc_size, line_size)) {<br>
> +            line_size, alloc_size, NULL)) {<br>
> +            // not reachable when forced allocation used<br>
>              ReleaseOutput(drawable-><a href="http://release_info.id" rel="noreferrer" target="_blank">releas<wbr>e_info.id</a>);<br>
>              DbgPrint(TRACE_LEVEL_ERROR, ("Cannot allocate additional bitmap<br>
>              for drawable\n"));<br>
>              return NULL;<br>
> @@ -4526,36 +4527,54 @@ QXLDrawable *QxlDevice::PrepareBltBits (<br>
>      return drawable;<br>
>  }<br>
><br>
> +// can work in 2 modes:<br>
> +// forced - as before, when pDelayed not provided or if VSync is not in use<br>
> +// non-forced, if VSync is active and pDelayed provided. In this case, if<br>
> memory<br>
> +// can't be allocated immediately, allocates 'delayed chunk' and copies data<br>
> +// to it. Further, before send to the device, this 'delayed chunk' should be<br>
> processed,<br>
> +// regular chunk allocated from device memory and the data copied to it<br>
>  BOOLEAN QxlDevice::PutBytesAlign(<wbr>QXLDataChunk **chunk_ptr, UINT8 **now_ptr,<br>
>                              UINT8 **end_ptr, UINT8 *src, int size,<br>
> -                            size_t alloc_size, uint32_t alignment)<br>
> +                            size_t alloc_size, PLIST_ENTRY pDelayed)<br>
>  {<br>
>      PAGED_CODE();<br>
> +    BOOLEAN bResult = TRUE;<br>
> +    BOOLEAN bForced = !g_bSupportVSync || !pDelayed;<br>
>      QXLDataChunk *chunk = *chunk_ptr;<br>
>      UINT8 *now = *now_ptr;<br>
>      UINT8 *end = *end_ptr;<br>
> +    size_t maxAllocSize = BITS_BUF_MAX - BITS_BUF_MAX % size;<br>
> +    alloc_size = MIN(size, maxAllocSize);<br>
>      DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));<br>
><br>
>      while (size) {<br>
>          int cp_size = (int)MIN(end - now, size);<br>
>          if (!cp_size) {<br>
> -            size_t aligned_size;<br>
> -            aligned_size = (int)MIN(alloc_size + alignment - 1,<br>
> BITS_BUF_MAX);<br>
> -            aligned_size -=  aligned_size % alignment;<br>
> -<br>
> -            void *ptr = AllocMem(MSPACE_TYPE_VRAM, size +<br>
> sizeof(QXLDataChunk), TRUE);<br>
> -            if (!ptr) {<br>
> -                return FALSE;<br>
> +            void *ptr = (bForced || IsListEmpty(pDelayed)) ?<br>
> AllocMem(MSPACE_TYPE_VRAM, alloc_size + sizeof(QXLDataChunk), bForced) :<br>
> NULL;<br>
> +            if (ptr) {<br>
> +                chunk->next_chunk = PA(ptr, m_SurfaceMemSlot);<br>
> +                ((QXLDataChunk *)ptr)->prev_chunk = PA(chunk,<br>
> m_SurfaceMemSlot);<br>
> +                chunk = (QXLDataChunk *)ptr;<br>
> +                chunk->next_chunk = 0;<br>
> +            }<br>
> +            if (!ptr && pDelayed) {<br>
> +                ptr = new (PagedPool)BYTE[alloc_size +<br>
> sizeof(QXL_DELAYED_CHUNK)];<br>
> +                if (ptr) {<br>
> +                    QXL_DELAYED_CHUNK *pChunk = (QXL_DELAYED_CHUNK *)ptr;<br>
> +                    InsertTailList(pDelayed, &pChunk->list);<br>
> +                    pChunk->chunk.prev_chunk = (QXLPHYSICAL)chunk;<br>
> +                    chunk = &pChunk->chunk;<br>
> +                }<br>
> +            }<br>
> +            if (ptr) {<br>
> +                chunk->data_size = 0;<br>
> +                now = chunk->data;<br>
> +                end = now + alloc_size;<br>
> +                cp_size = (int)MIN(end - now, size);<br>
> +            } else {<br>
> +                bResult = FALSE;<br>
> +                break;<br>
>              }<br>
> -            chunk->next_chunk = PA(ptr, m_SurfaceMemSlot);<br>
> -            ((QXLDataChunk *)ptr)->prev_chunk = PA(chunk, m_SurfaceMemSlot);<br>
> -            chunk = (QXLDataChunk *)ptr;<br>
> -            chunk->data_size = 0;<br>
> -            chunk->next_chunk = 0;<br>
> -            now = chunk->data;<br>
> -            end = now + size;<br>
> -<br>
> -            cp_size = (int)MIN(end - now, size);<br>
>          }<br>
>          RtlCopyMemory(now, src, cp_size);<br>
>          src += cp_size;<br>
> @@ -4567,7 +4586,7 @@ BOOLEAN QxlDevice::PutBytesAlign(<wbr>QXLDataChunk<br>
> **chunk_ptr, UINT8 **now_ptr,<br>
>      *now_ptr = now;<br>
>      *end_ptr = end;<br>
>      DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));<br>
> -    return TRUE;<br>
> +    return bResult;<br>
>  }<br>
><br>
>  VOID QxlDevice::BlackOutScreen(<wbr>CURRENT_BDD_MODE* pCurrentBddMod)<br>
> @@ -4685,12 +4704,11 @@ NTSTATUS  QxlDevice::SetPointerShape(_<wbr>In_ CONST<br>
> DXGKARG_SETPOINTERSHAPE* pSetPoi<br>
>      end = (UINT8 *)res + CURSOR_ALLOC_SIZE;<br>
>      src_end = src + (pSetPointerShape->Pitch * pSetPointerShape->Height *<br>
>      num_images);<br>
>      for (; src != src_end; src += pSetPointerShape->Pitch) {<br>
> -        if (!PutBytesAlign(&chunk, &now, &end, src, line_size,<br>
> -                 PAGE_SIZE, 1))<br>
> -        {<br>
> -            DbgPrint(TRACE_LEVEL_ERROR, ("%s: Failed to allocate cursor<br>
> bitmap\n", __FUNCTION__));<br>
> -            ReleaseOutput(cursor_cmd-><a href="http://release_info.id" rel="noreferrer" target="_blank">rele<wbr>ase_info.id</a>);<br>
> -            return STATUS_INSUFFICIENT_RESOURCES;<br>
> +        if (!PutBytesAlign(&chunk, &now, &end, src, line_size, PAGE_SIZE -<br>
> PAGE_SIZE % line_size, NULL)) {<br>
> +            // we have a chance to get here only with color cursor bigger<br>
> than 45*45<br>
> +            // and only if we modify this procedure to use non-forced<br>
> allocation<br>
> +            DbgPrint(TRACE_LEVEL_ERROR, ("%s: failed to push part of<br>
> shape\n", __FUNCTION__));<br>
> +            break;<br>
>          }<br>
>      }<br>
>      CursorCmdAddRes(cursor_cmd, res);<br>
> diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h<br>
> index 059e1bd..e18afac 100755<br>
> --- a/qxldod/QxlDod.h<br>
> +++ b/qxldod/QxlDod.h<br>
> @@ -260,6 +260,13 @@ public:<br>
>  };<br>
>  #endif<br>
><br>
> +typedef struct _QXL_DELAYED_CHUNK<br>
> +{<br>
> +    LIST_ENTRY list;<br>
> +    UINT32 type;<br>
> +    QXLDataChunk chunk;<br>
> +} QXL_DELAYED_CHUNK;<br>
> +<br>
<br>
</div></div>The name of this type is quite odd.<br>
Is suggests some Windows internal C structure.<br>
This header is only C++ compatible, so the typedef make no sense.<br>
The capital case is used for QXL protocol specific stuff, but<br>
this is not even allocate in QXL memory but in system one.<br>
I would suggest a simple QXLDelayedChunk or even DelayedChunk.<br>
<br>
The "type" field is not used in the code.<br></blockquote><div><br></div><div>The type field is preparation for further extension - we'll need it if we decide to make also allocations of empty Drawable objects and cursor objects non-forced. </div><div> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="HOEnZb"><div class="h5"><br>
>  class QxlDod;<br>
><br>
>  class HwDeviceInterface {<br>
> @@ -603,7 +610,7 @@ private:<br>
>      void PushCursor(void);<br>
>      BOOLEAN PutBytesAlign(QXLDataChunk **chunk_ptr, UINT8 **now_ptr,<br>
>                              UINT8 **end_ptr, UINT8 *src, int size,<br>
> -                            size_t alloc_size, uint32_t alignment);<br>
> +                            size_t alloc_size, PLIST_ENTRY pDelayed);<br>
>      void AsyncIo(UCHAR  Port, UCHAR Value);<br>
>      void SyncIo(UCHAR  Port, UCHAR Value);<br>
>      NTSTATUS UpdateChildStatus(BOOLEAN connect);<br>
<br>
</div></div><span class="HOEnZb"><font color="#888888">Frediano<br>
</font></span></blockquote></div><br></div></div>