2024-05-19 17:52:27 -03:00
|
|
|
#include "platform-dx/implementations.hpp"
|
2024-05-20 10:41:40 -03:00
|
|
|
#include "platform-dx/dxhelpers.hpp"
|
2024-03-18 15:41:46 -03:00
|
|
|
|
2024-05-04 21:07:39 -03:00
|
|
|
namespace xna {
|
2024-05-23 14:38:16 -03:00
|
|
|
Texture2D::~Texture2D() {
|
|
|
|
impl = nullptr;
|
|
|
|
}
|
|
|
|
|
2024-04-26 11:35:59 -03:00
|
|
|
sptr<Texture2D> Texture2D::FromStream(GraphicsDevice& device, String const& fileName, xna_error_ptr_arg)
|
2024-04-07 14:06:12 -03:00
|
|
|
{
|
2024-05-06 15:57:09 -03:00
|
|
|
auto _this = device.shared_from_this();
|
|
|
|
auto texture2d = New<Texture2D>(_this);
|
2024-04-14 16:11:15 -03:00
|
|
|
ID3D11Resource* resource = nullptr;
|
2024-04-14 21:23:09 -03:00
|
|
|
auto wstr = XnaHToWString(fileName);
|
2024-04-07 14:06:12 -03:00
|
|
|
|
|
|
|
HRESULT result = DirectX::CreateWICTextureFromFile(
|
2024-05-24 22:26:10 -03:00
|
|
|
device.impl->_device,
|
|
|
|
device.impl->_context,
|
2024-04-14 16:11:15 -03:00
|
|
|
wstr.c_str(),
|
|
|
|
&resource,
|
2024-05-23 14:38:16 -03:00
|
|
|
&texture2d->impl->dxShaderResource,
|
2024-04-14 16:11:15 -03:00
|
|
|
0U);
|
2024-04-07 14:06:12 -03:00
|
|
|
|
|
|
|
if (FAILED(result))
|
|
|
|
{
|
2024-04-14 16:11:15 -03:00
|
|
|
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
2024-04-07 14:06:12 -03:00
|
|
|
|
|
|
|
if (resource) {
|
|
|
|
resource->Release();
|
|
|
|
resource = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
2024-04-14 16:11:15 -03:00
|
|
|
|
2024-05-23 14:38:16 -03:00
|
|
|
result = resource->QueryInterface(IID_ID3D11Texture2D, (void**)&texture2d->impl->dxTexture2D);
|
2024-04-07 14:06:12 -03:00
|
|
|
|
|
|
|
if (FAILED(result)) {
|
2024-04-14 16:11:15 -03:00
|
|
|
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
2024-04-07 14:06:12 -03:00
|
|
|
|
|
|
|
if (resource) {
|
|
|
|
resource->Release();
|
|
|
|
resource = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2024-04-14 16:11:15 -03:00
|
|
|
D3D11_TEXTURE2D_DESC desc;
|
2024-05-23 14:38:16 -03:00
|
|
|
texture2d->impl->dxTexture2D->GetDesc(&desc);
|
|
|
|
texture2d->impl->dxDescription = desc;
|
2024-04-07 14:06:12 -03:00
|
|
|
|
|
|
|
resource->Release();
|
|
|
|
resource = nullptr;
|
|
|
|
|
|
|
|
return texture2d;
|
|
|
|
}
|
2024-05-04 21:07:39 -03:00
|
|
|
|
|
|
|
bool Texture2D::Initialize(xna_error_ptr_arg)
|
|
|
|
{
|
2024-05-23 14:38:16 -03:00
|
|
|
if (impl->dxTexture2D) {
|
2024-05-04 21:07:39 -03:00
|
|
|
xna_error_apply(err, XnaErrorCode::WARNING_INITIALIZED_RESOURCE);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-05-24 22:26:10 -03:00
|
|
|
if (!m_device || !m_device->impl->_device) {
|
2024-05-04 21:07:39 -03:00
|
|
|
xna_error_apply(err, XnaErrorCode::INVALID_OPERATION);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-05-24 22:26:10 -03:00
|
|
|
auto hr = m_device->impl->_device->CreateTexture2D(&impl->dxDescription, nullptr, &impl->dxTexture2D);
|
2024-05-04 21:07:39 -03:00
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
ID3D11Resource* resource = nullptr;
|
2024-05-23 14:38:16 -03:00
|
|
|
hr = impl->dxTexture2D->QueryInterface(IID_ID3D11Resource, (void**)&resource);
|
2024-05-04 21:07:39 -03:00
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-05-24 22:26:10 -03:00
|
|
|
hr = m_device->impl->_device->CreateShaderResourceView(resource, &impl->dxShaderDescription, &impl->dxShaderResource);
|
2024-05-04 21:07:39 -03:00
|
|
|
|
|
|
|
if (resource) {
|
|
|
|
resource->Release();
|
|
|
|
resource = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2024-05-05 15:50:17 -03:00
|
|
|
|
2024-05-23 14:38:16 -03:00
|
|
|
void setDefaultDesc(Texture2D::PlatformImplementation& impl) {
|
|
|
|
impl.dxDescription.MipLevels = 1;
|
|
|
|
impl.dxDescription.ArraySize = 1;
|
|
|
|
impl.dxDescription.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
|
|
impl.dxDescription.SampleDesc.Count = 1;
|
|
|
|
impl.dxDescription.Usage = D3D11_USAGE_DEFAULT;
|
|
|
|
impl.dxDescription.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
|
|
|
|
|
|
|
impl.dxShaderDescription.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
|
|
impl.dxShaderDescription.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
|
|
|
impl.dxShaderDescription.Texture2D.MipLevels = impl.dxDescription.MipLevels;
|
|
|
|
impl.dxShaderDescription.Texture2D.MostDetailedMip = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Texture2D::Texture2D() : GraphicsResource(nullptr) {
|
|
|
|
impl = unew<PlatformImplementation>();
|
|
|
|
setDefaultDesc(*impl);
|
|
|
|
}
|
|
|
|
|
|
|
|
Texture2D::Texture2D(sptr<GraphicsDevice> const& device, size_t width, size_t height) : GraphicsResource(device) {
|
|
|
|
impl = unew<PlatformImplementation>();
|
|
|
|
setDefaultDesc(*impl);
|
|
|
|
impl->dxDescription.Width = static_cast<UINT>(width);
|
|
|
|
impl->dxDescription.Height = static_cast<UINT>(height);
|
2024-05-05 15:50:17 -03:00
|
|
|
}
|
|
|
|
|
2024-05-06 15:57:09 -03:00
|
|
|
Texture2D::Texture2D(sptr<GraphicsDevice> const& device) : GraphicsResource(device) {
|
2024-05-23 14:38:16 -03:00
|
|
|
impl = unew<PlatformImplementation>();
|
|
|
|
setDefaultDesc(*impl);
|
2024-05-05 15:50:17 -03:00
|
|
|
}
|
|
|
|
|
2024-05-06 15:57:09 -03:00
|
|
|
Texture2D::Texture2D(sptr<GraphicsDevice> const& device, size_t width, size_t height, size_t mipMap, SurfaceFormat format) : GraphicsResource(device)
|
2024-05-05 15:50:17 -03:00
|
|
|
{
|
2024-05-23 14:38:16 -03:00
|
|
|
impl = unew<PlatformImplementation>();
|
|
|
|
setDefaultDesc(*impl);
|
|
|
|
impl->dxDescription.Width = static_cast<UINT>(width);
|
|
|
|
impl->dxDescription.Height = static_cast<UINT>(height);
|
|
|
|
impl->dxDescription.MipLevels = static_cast<UINT>(mipMap);
|
|
|
|
impl->dxDescription.Format = DxHelpers::ConvertSurfaceToDXGIFORMAT(format);
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT internalSetData(Texture2D::PlatformImplementation& impl, GraphicsDevice& device, UINT const* data, xna_error_ptr_arg)
|
|
|
|
{
|
|
|
|
if (!impl.dxTexture2D) {
|
2024-05-24 22:26:10 -03:00
|
|
|
auto hr = device.impl->_device->CreateTexture2D(&impl.dxDescription, nullptr, &impl.dxTexture2D);
|
2024-05-23 14:38:16 -03:00
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ID3D11Resource* resource = nullptr;
|
|
|
|
auto hr = impl.dxTexture2D->QueryInterface(IID_ID3D11Resource, (void**)&resource);
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
constexpr int R8G8B8A8U_BYTE_SIZE = 4;
|
2024-05-24 22:26:10 -03:00
|
|
|
device.impl->_context->UpdateSubresource(resource, 0, nullptr, data, impl.dxDescription.Width * R8G8B8A8U_BYTE_SIZE, 0);
|
2024-05-23 14:38:16 -03:00
|
|
|
|
|
|
|
if (impl.dxShaderResource) {
|
|
|
|
impl.dxShaderResource->Release();
|
|
|
|
impl.dxShaderResource = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl.dxShaderDescription.Texture2D.MipLevels = impl.dxDescription.MipLevels;
|
2024-05-24 22:26:10 -03:00
|
|
|
hr = device.impl->_device->CreateShaderResourceView(resource, &impl.dxShaderDescription, &impl.dxShaderResource);
|
2024-05-23 14:38:16 -03:00
|
|
|
|
|
|
|
if (resource) {
|
|
|
|
resource->Release();
|
|
|
|
resource = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl.dxTexture2D->GetDesc(&impl.dxDescription);
|
|
|
|
|
|
|
|
return NO_ERROR;
|
2024-05-05 15:50:17 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
void Texture2D::SetData(std::vector<Uint> const& data, size_t startIndex, size_t elementCount, xna_error_ptr_arg)
|
|
|
|
{
|
2024-05-24 22:26:10 -03:00
|
|
|
if (!impl || !m_device || !m_device->impl->_device || !m_device->impl->_context) {
|
2024-05-05 15:50:17 -03:00
|
|
|
xna_error_apply(err, XnaErrorCode::INVALID_OPERATION);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-05-23 14:38:16 -03:00
|
|
|
internalSetData(*impl, *m_device, data.data(), err);
|
2024-05-05 15:50:17 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
void Texture2D::SetData(std::vector<Byte> const& data, size_t startIndex, size_t elementCount, xna_error_ptr_arg)
|
|
|
|
{
|
2024-05-24 22:26:10 -03:00
|
|
|
if (!m_device || !m_device->impl->_device || !m_device->impl->_context) {
|
2024-05-05 15:50:17 -03:00
|
|
|
xna_error_apply(err, XnaErrorCode::INVALID_OPERATION);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<UINT> finalData(elementCount / 4);
|
|
|
|
auto fIndex = 0;
|
|
|
|
|
|
|
|
for (size_t i = startIndex; i < elementCount; ++i) {
|
|
|
|
const auto& r = data[i];
|
|
|
|
const auto& g = data[++i];
|
|
|
|
const auto& b = data[++i];
|
|
|
|
const auto& a = data[++i];
|
|
|
|
finalData[fIndex] = Color(r, g, b, a);
|
|
|
|
++fIndex;
|
|
|
|
}
|
|
|
|
|
2024-05-23 14:38:16 -03:00
|
|
|
internalSetData(*impl, *m_device, finalData.data(), err);
|
2024-05-05 15:50:17 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
void Texture2D::SetData(Int level, Rectangle* rect, std::vector<Byte> const& data, size_t startIndex, size_t elementCount, xna_error_ptr_arg)
|
|
|
|
{
|
2024-05-24 22:26:10 -03:00
|
|
|
if (!m_device || !m_device->impl->_device || !m_device->impl->_context) {
|
2024-05-05 15:50:17 -03:00
|
|
|
xna_error_apply(err, XnaErrorCode::INVALID_OPERATION);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<UINT> finalData(elementCount / 4);
|
|
|
|
auto fIndex = 0;
|
|
|
|
|
|
|
|
for (size_t i = startIndex; i < elementCount; ++i) {
|
|
|
|
const auto& r = data[i];
|
|
|
|
const auto& g = data[++i];
|
|
|
|
const auto& b = data[++i];
|
|
|
|
const auto& a = data[++i];
|
|
|
|
finalData[fIndex] = Color(r, g, b, a);
|
|
|
|
++fIndex;
|
|
|
|
}
|
|
|
|
|
2024-05-23 14:38:16 -03:00
|
|
|
if (!impl->dxTexture2D) {
|
2024-05-24 22:26:10 -03:00
|
|
|
auto hr = m_device->impl->_device->CreateTexture2D(&impl->dxDescription, nullptr, &impl->dxTexture2D);
|
2024-05-05 15:50:17 -03:00
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ID3D11Resource* resource = nullptr;
|
2024-05-23 14:38:16 -03:00
|
|
|
auto hr = impl->dxTexture2D->QueryInterface(IID_ID3D11Resource, (void**)&resource);
|
2024-05-05 15:50:17 -03:00
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
D3D11_BOX box{};
|
|
|
|
|
|
|
|
if (rect) {
|
|
|
|
box.left = rect->X;
|
|
|
|
box.right = rect->X + rect->Width;
|
|
|
|
box.top = rect->Y;
|
|
|
|
box.bottom = rect->Y + rect->Height;
|
|
|
|
box.back = level;
|
|
|
|
box.front = 0;
|
|
|
|
}
|
|
|
|
|
2024-05-23 14:38:16 -03:00
|
|
|
constexpr int R8G8B8A8U_BYTE_SIZE = 4;
|
2024-05-24 22:26:10 -03:00
|
|
|
m_device->impl->_context->UpdateSubresource(resource, 0, rect ? &box : nullptr, finalData.data(), impl->dxDescription.Width * R8G8B8A8U_BYTE_SIZE, 0);
|
2024-05-05 15:50:17 -03:00
|
|
|
|
2024-05-23 14:38:16 -03:00
|
|
|
if (impl->dxShaderResource) {
|
|
|
|
impl->dxShaderResource->Release();
|
|
|
|
impl->dxShaderResource = nullptr;
|
2024-05-05 15:50:17 -03:00
|
|
|
}
|
|
|
|
|
2024-05-23 14:38:16 -03:00
|
|
|
impl->dxShaderDescription.Texture2D.MipLevels = impl->dxDescription.MipLevels;
|
2024-05-24 22:26:10 -03:00
|
|
|
hr = m_device->impl->_device->CreateShaderResourceView(resource, &impl->dxShaderDescription, &impl->dxShaderResource);
|
2024-05-05 15:50:17 -03:00
|
|
|
|
|
|
|
if (resource) {
|
|
|
|
resource->Release();
|
|
|
|
resource = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-05-23 14:38:16 -03:00
|
|
|
impl->dxTexture2D->GetDesc(&impl->dxDescription);
|
2024-05-05 15:50:17 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
void Texture2D::SetData(std::vector<Color> const& data, size_t startIndex, size_t elementCount, xna_error_ptr_arg)
|
|
|
|
{
|
2024-05-24 22:26:10 -03:00
|
|
|
if (!m_device || !m_device->impl->_device || !m_device->impl->_context) {
|
2024-05-05 15:50:17 -03:00
|
|
|
xna_error_apply(err, XnaErrorCode::INVALID_OPERATION);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<UINT> finalData(elementCount);
|
|
|
|
auto finalDataIndex = 0;
|
|
|
|
|
|
|
|
for (size_t i = startIndex; i < elementCount; ++i) {
|
|
|
|
finalData[finalDataIndex] = static_cast<UINT>(data[i]);
|
|
|
|
++finalDataIndex;
|
|
|
|
}
|
|
|
|
|
2024-05-23 14:38:16 -03:00
|
|
|
internalSetData(*impl, *m_device, finalData.data(), err);
|
2024-05-05 15:50:17 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
sptr<Texture2D> Texture2D::FromMemory(GraphicsDevice& device, std::vector<Byte> const& data, xna_error_ptr_arg)
|
|
|
|
{
|
2024-05-06 15:57:09 -03:00
|
|
|
auto _this = device.shared_from_this();
|
|
|
|
auto texture2d = New<Texture2D>(_this);
|
2024-05-05 15:50:17 -03:00
|
|
|
ID3D11Resource* resource = nullptr;
|
|
|
|
|
|
|
|
auto hr = DirectX::CreateWICTextureFromMemory(
|
2024-05-24 22:26:10 -03:00
|
|
|
device.impl->_device,
|
|
|
|
device.impl->_context,
|
2024-05-05 15:50:17 -03:00
|
|
|
data.data(),
|
|
|
|
data.size(),
|
|
|
|
&resource,
|
2024-05-23 14:38:16 -03:00
|
|
|
&texture2d->impl->dxShaderResource);
|
2024-05-05 15:50:17 -03:00
|
|
|
|
|
|
|
if (FAILED(hr))
|
|
|
|
{
|
|
|
|
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
|
|
|
|
|
|
|
if (resource) {
|
|
|
|
resource->Release();
|
|
|
|
resource = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2024-05-23 14:38:16 -03:00
|
|
|
hr = resource->QueryInterface(IID_ID3D11Texture2D, (void**)&texture2d->impl->dxTexture2D);
|
2024-05-05 15:50:17 -03:00
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
xna_error_apply(err, XnaErrorCode::FAILED_OPERATION);
|
|
|
|
|
|
|
|
if (resource) {
|
|
|
|
resource->Release();
|
|
|
|
resource = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
D3D11_TEXTURE2D_DESC desc;
|
2024-05-23 14:38:16 -03:00
|
|
|
texture2d->impl->dxTexture2D->GetDesc(&desc);
|
|
|
|
texture2d->impl->dxDescription = desc;
|
2024-05-05 15:50:17 -03:00
|
|
|
|
|
|
|
resource->Release();
|
|
|
|
resource = nullptr;
|
|
|
|
|
|
|
|
return texture2d;
|
2024-05-23 14:38:16 -03:00
|
|
|
}
|
2024-03-18 15:41:46 -03:00
|
|
|
}
|