Win32SurfaceKHR: use StretchDIBits to replace StrectchBlt.
Use StretchDIBits to copy pixels in PresentImage to the
output window directly. It avoids allocating extra memory
and one pixel copy to DIBSection.
Bug: chromium:1280715
Change-Id: I87e019ef0b33ad86d548a5549ab1ff5b87f9d130
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/62828
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Commit-Queue: Peng Huang <penghuang@chromium.org>
Tested-by: Peng Huang <penghuang@chromium.org>
diff --git a/src/WSI/Win32SurfaceKHR.cpp b/src/WSI/Win32SurfaceKHR.cpp
index cf495c8..6c5a728 100644
--- a/src/WSI/Win32SurfaceKHR.cpp
+++ b/src/WSI/Win32SurfaceKHR.cpp
@@ -43,15 +43,11 @@
{
ASSERT(IsWindow(hwnd) == TRUE);
windowContext = GetDC(hwnd);
- bitmapContext = CreateCompatibleDC(windowContext);
- lazyCreateFrameBuffer();
}
void Win32SurfaceKHR::destroySurface(const VkAllocationCallbacks *pAllocator)
{
- destroyFrameBuffer();
ReleaseDC(hwnd, windowContext);
- DeleteDC(bitmapContext);
}
size_t Win32SurfaceKHR::ComputeRequiredAllocationSize(const VkWin32SurfaceCreateInfoKHR *pCreateInfo)
@@ -85,87 +81,35 @@
VkResult Win32SurfaceKHR::present(PresentImage *image)
{
- // Recreate frame buffer in case window size has changed
- VkResult result = lazyCreateFrameBuffer();
+ VkExtent2D windowExtent = {};
+ VkResult result = getWindowSize(hwnd, windowExtent);
if(result != VK_SUCCESS)
{
return result;
}
- if(!framebuffer)
- {
- // e.g. window width or height is 0
- return VK_SUCCESS;
- }
-
- const VkExtent3D &extent = image->getImage()->getExtent();
-
+ const Image *vkImage = image->getImage();
+ const VkExtent3D &extent = vkImage->getExtent();
if(windowExtent.width != extent.width || windowExtent.height != extent.height)
{
return VK_ERROR_OUT_OF_DATE_KHR;
}
- image->getImage()->copyTo(reinterpret_cast<uint8_t *>(framebuffer), bitmapRowPitch);
-
- StretchBlt(windowContext, 0, 0, extent.width, extent.height, bitmapContext, 0, 0, extent.width, extent.height, SRCCOPY);
-
- return VK_SUCCESS;
-}
-
-VkResult Win32SurfaceKHR::lazyCreateFrameBuffer()
-{
- VkExtent2D currWindowExtent;
- VkResult result = getWindowSize(hwnd, currWindowExtent);
- if(result != VK_SUCCESS)
- {
- destroyFrameBuffer();
- return result;
- }
-
- if(currWindowExtent.width == windowExtent.width && currWindowExtent.height == windowExtent.height)
- {
- return VK_SUCCESS;
- }
-
- windowExtent = currWindowExtent;
-
- if(framebuffer)
- {
- destroyFrameBuffer();
- }
-
- if(windowExtent.width == 0 || windowExtent.height == 0)
- {
- return VK_SUCCESS;
- }
+ int stride = vkImage->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0);
+ int bytesPerPixel = static_cast<int>(vkImage->getFormat(VK_IMAGE_ASPECT_COLOR_BIT).bytes());
BITMAPINFO bitmapInfo = {};
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFO);
- bitmapInfo.bmiHeader.biBitCount = 32;
+ bitmapInfo.bmiHeader.biBitCount = bytesPerPixel * 8;
bitmapInfo.bmiHeader.biPlanes = 1;
- bitmapInfo.bmiHeader.biHeight = -static_cast<LONG>(windowExtent.height); // Negative for top-down DIB, origin in upper-left corner
- bitmapInfo.bmiHeader.biWidth = windowExtent.width;
+ bitmapInfo.bmiHeader.biHeight = -static_cast<LONG>(extent.height); // Negative for top-down DIB, origin in upper-left corner
+ bitmapInfo.bmiHeader.biWidth = stride / bytesPerPixel;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
- bitmap = CreateDIBSection(bitmapContext, &bitmapInfo, DIB_RGB_COLORS, &framebuffer, 0, 0);
- ASSERT(bitmap != NULL);
- SelectObject(bitmapContext, bitmap);
-
- BITMAP header;
- int status = GetObject(bitmap, sizeof(BITMAP), &header);
- ASSERT(status != 0);
- bitmapRowPitch = static_cast<int>(header.bmWidthBytes);
+ void *bits = image->getImage()->getTexelPointer({ 0, 0, 0 }, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0 });
+ StretchDIBits(windowContext, 0, 0, extent.width, extent.height, 0, 0, extent.width, extent.height, bits, &bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
return VK_SUCCESS;
}
-void Win32SurfaceKHR::destroyFrameBuffer()
-{
- SelectObject(bitmapContext, NULL);
- DeleteObject(bitmap);
- bitmap = {};
- bitmapRowPitch = 0;
- framebuffer = nullptr;
-}
-
} // namespace vk
\ No newline at end of file
diff --git a/src/WSI/Win32SurfaceKHR.hpp b/src/WSI/Win32SurfaceKHR.hpp
index 254cbcb..7d859b6 100644
--- a/src/WSI/Win32SurfaceKHR.hpp
+++ b/src/WSI/Win32SurfaceKHR.hpp
@@ -25,8 +25,6 @@
#include <Windows.h>
#include <vulkan/vulkan_win32.h>
-#include <map>
-
namespace vk {
class Win32SurfaceKHR : public SurfaceKHR, public ObjectBase<Win32SurfaceKHR, VkSurfaceKHR>
@@ -45,18 +43,10 @@
VkResult present(PresentImage *image) override;
private:
- VkResult lazyCreateFrameBuffer();
- void destroyFrameBuffer();
-
const HWND hwnd;
HDC windowContext = {};
HDC bitmapContext = {};
- VkExtent2D windowExtent = {};
-
- HBITMAP bitmap = {};
- unsigned int bitmapRowPitch = 0;
- void *framebuffer = nullptr;
};
} // namespace vk