File: devicecontext.cpp

package info (click to toggle)
qt6-multimedia 6.10.2-2
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 43,900 kB
  • sloc: cpp: 186,273; ansic: 78,309; java: 2,870; python: 262; xml: 193; sh: 136; makefile: 30
file content (137 lines) | stat: -rw-r--r-- 4,834 bytes parent folder | download
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;
}