1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "devicecontext.h"
ComResult<QColor> DeviceContext::getFirstPixelColor(const ComPtr<ID3D11Texture2D> &texture) const
{
// Get the texture description
D3D11_TEXTURE2D_DESC desc{};
texture->GetDesc(&desc);
// Create a staging texture to map the data
D3D11_TEXTURE2D_DESC stagingDesc = desc;
stagingDesc.Usage = D3D11_USAGE_STAGING;
stagingDesc.BindFlags = 0;
stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
stagingDesc.MiscFlags = 0;
ComPtr<ID3D11Texture2D> stagingTexture;
HRESULT hr = device->CreateTexture2D(&stagingDesc, nullptr, &stagingTexture);
if (hr != S_OK)
return q23::unexpected{ hr };
// Copy the texture data to the staging texture
context->CopyResource(stagingTexture.Get(), texture.Get());
// Map the staging texture to access its data
D3D11_MAPPED_SUBRESOURCE mappedResource{};
hr = context->Map(stagingTexture.Get(), 0, D3D11_MAP_READ, 0, &mappedResource);
if (hr != S_OK)
return q23::unexpected{ hr };
// Get the value of the first pixel (top-left corner)
unsigned char *data = static_cast<unsigned char *>(mappedResource.pData);
QColor firstPixel{ data[0], data[1], data[2], data[3] };
// Unmap the staging texture
context->Unmap(stagingTexture.Get(), 0);
return firstPixel;
}
ComResult<ComPtr<ID3D11Texture2D>>
DeviceContext::createTextureArray(QSize size, const std::vector<QColor> &colors) const
{
D3D11_TEXTURE2D_DESC texDesc{};
texDesc.Width = size.width();
texDesc.Height = size.height();
texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
texDesc.Usage = D3D11_USAGE_DEFAULT;
texDesc.CPUAccessFlags = 0;
texDesc.MiscFlags = 0;
texDesc.BindFlags = 0;
texDesc.ArraySize = static_cast<UINT>(colors.size());
texDesc.MipLevels = 1;
texDesc.SampleDesc = { 1, 0 };
ComPtr<ID3D11Texture2D> tex;
HRESULT hr = device->CreateTexture2D(&texDesc, nullptr, tex.GetAddressOf());
if (hr != S_OK)
return q23::unexpected{ hr };
hr = fillTextureWithColors(tex, colors);
if (hr != S_OK)
return q23::unexpected{ hr };
return tex;
}
HRESULT DeviceContext::fillTextureWithColors(const ComPtr<ID3D11Texture2D> &texture,
const std::vector<QColor> &colors) const
{
// Get the texture description
D3D11_TEXTURE2D_DESC desc{};
texture->GetDesc(&desc);
// Create a staging texture to map the data
D3D11_TEXTURE2D_DESC stagingDesc = desc;
stagingDesc.Usage = D3D11_USAGE_STAGING;
stagingDesc.BindFlags = 0;
stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
stagingDesc.MiscFlags = 0;
ComPtr<ID3D11Texture2D> stagingTexture;
HRESULT hr = device->CreateTexture2D(&stagingDesc, nullptr, stagingTexture.GetAddressOf());
if (hr != S_OK)
return hr;
// Map the staging texture to access its data
D3D11_MAPPED_SUBRESOURCE mappedResource{};
context->CopyResource(stagingTexture.Get(), texture.Get());
hr = context->Map(stagingTexture.Get(), 0, D3D11_MAP_WRITE, 0, &mappedResource);
if (hr != S_OK)
return hr;
unsigned char *data = static_cast<unsigned char *>(mappedResource.pData);
for (UINT plane = 0; plane < desc.ArraySize; ++plane) {
const QColor color = colors[plane];
for (UINT row = 0; row < desc.Height; ++row) {
for (UINT col = 0; col < desc.Width; ++col) {
unsigned char *pixel = data + row * mappedResource.RowPitch
+ plane * mappedResource.DepthPitch + col * 4;
pixel[0] = static_cast<unsigned char>(color.red());
pixel[1] = static_cast<unsigned char>(color.green());
pixel[2] = static_cast<unsigned char>(color.blue());
pixel[3] = static_cast<unsigned char>(color.alpha());
}
}
}
// Unmap the staging texture and copy it back to the original texture
context->Unmap(stagingTexture.Get(), 0);
context->CopyResource(texture.Get(), stagingTexture.Get());
return S_OK;
}
ComResult<DeviceContext> createDeviceContext()
{
DeviceContext devContext;
ComPtr<ID3D11Device> srcDev;
HRESULT hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr,
D3D11_CREATE_DEVICE_DISABLE_GPU_TIMEOUT, nullptr, 0,
D3D11_SDK_VERSION, srcDev.GetAddressOf(), nullptr,
devContext.context.GetAddressOf());
if (hr != S_OK)
return q23::unexpected{ hr };
hr = srcDev.As(&devContext.device);
if (hr != S_OK)
return q23::unexpected{ hr };
return devContext;
}
|