summaryrefslogtreecommitdiff
path: root/Source/Core/VideoBackends/D3D/D3DTexture.cpp
blob: fb5e7107113c6cc594f67f9e50b73ffbc50d3e35 (plain)
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
138
139
// Copyright 2010 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.

#include <algorithm>

#include "Common/CommonTypes.h"
#include "Common/MsgHandler.h"
#include "VideoBackends/D3D/D3DBase.h"
#include "VideoBackends/D3D/D3DTexture.h"

namespace DX11
{
namespace D3D
{
void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width,
                          unsigned int height, unsigned int src_pitch, unsigned int level,
                          D3D11_USAGE usage)
{
  if (usage == D3D11_USAGE_DYNAMIC || usage == D3D11_USAGE_STAGING)
  {
    D3D11_MAPPED_SUBRESOURCE map;
    D3D::context->Map(pTexture, level, D3D11_MAP_WRITE_DISCARD, 0, &map);
    if (src_pitch == map.RowPitch)
    {
      memcpy(map.pData, buffer, map.RowPitch * height);
    }
    else
    {
      // Source row size is aligned to texture block size. This can result in a different
      // pitch to what the driver returns, so copy whichever is smaller.
      unsigned int copy_size = std::min(src_pitch, map.RowPitch);
      for (unsigned int y = 0; y < height; ++y)
        memcpy((u8*)map.pData + y * map.RowPitch, buffer + y * src_pitch, copy_size);
    }
    D3D::context->Unmap(pTexture, level);
  }
  else
  {
    D3D11_BOX dest_region = CD3D11_BOX(0, 0, 0, width, height, 1);
    D3D::context->UpdateSubresource(pTexture, level, &dest_region, buffer, src_pitch,
                                    src_pitch * height);
  }
}

}  // namespace

D3DTexture2D* D3DTexture2D::Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind,
                                   D3D11_USAGE usage, DXGI_FORMAT fmt, unsigned int levels,
                                   unsigned int slices, D3D11_SUBRESOURCE_DATA* data)
{
  ID3D11Texture2D* pTexture = nullptr;
  HRESULT hr;

  D3D11_CPU_ACCESS_FLAG cpuflags;
  if (usage == D3D11_USAGE_STAGING)
    cpuflags = (D3D11_CPU_ACCESS_FLAG)((int)D3D11_CPU_ACCESS_WRITE | (int)D3D11_CPU_ACCESS_READ);
  else if (usage == D3D11_USAGE_DYNAMIC)
    cpuflags = D3D11_CPU_ACCESS_WRITE;
  else
    cpuflags = (D3D11_CPU_ACCESS_FLAG)0;
  D3D11_TEXTURE2D_DESC texdesc =
      CD3D11_TEXTURE2D_DESC(fmt, width, height, slices, levels, bind, usage, cpuflags);
  hr = D3D::device->CreateTexture2D(&texdesc, data, &pTexture);
  if (FAILED(hr))
  {
    PanicAlert("Failed to create texture at %s, line %d: hr=%#x\n", __FILE__, __LINE__, hr);
    return nullptr;
  }

  D3DTexture2D* ret = new D3DTexture2D(pTexture, bind);
  SAFE_RELEASE(pTexture);
  return ret;
}

void D3DTexture2D::AddRef()
{
  ++ref;
}

UINT D3DTexture2D::Release()
{
  --ref;
  if (ref == 0)
  {
    delete this;
    return 0;
  }
  return ref;
}

ID3D11Texture2D*& D3DTexture2D::GetTex()
{
  return tex;
}
ID3D11ShaderResourceView*& D3DTexture2D::GetSRV()
{
  return srv;
}
ID3D11RenderTargetView*& D3DTexture2D::GetRTV()
{
  return rtv;
}
ID3D11DepthStencilView*& D3DTexture2D::GetDSV()
{
  return dsv;
}

D3DTexture2D::D3DTexture2D(ID3D11Texture2D* texptr, D3D11_BIND_FLAG bind, DXGI_FORMAT srv_format,
                           DXGI_FORMAT dsv_format, DXGI_FORMAT rtv_format, bool multisampled)
    : ref(1), tex(texptr), srv(nullptr), rtv(nullptr), dsv(nullptr)
{
  D3D11_SRV_DIMENSION srv_dim =
      multisampled ? D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY : D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
  D3D11_DSV_DIMENSION dsv_dim =
      multisampled ? D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY : D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
  D3D11_RTV_DIMENSION rtv_dim =
      multisampled ? D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY : D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
  D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = CD3D11_SHADER_RESOURCE_VIEW_DESC(srv_dim, srv_format);
  D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc = CD3D11_DEPTH_STENCIL_VIEW_DESC(dsv_dim, dsv_format);
  D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = CD3D11_RENDER_TARGET_VIEW_DESC(rtv_dim, rtv_format);
  if (bind & D3D11_BIND_SHADER_RESOURCE)
    D3D::device->CreateShaderResourceView(tex, &srv_desc, &srv);
  if (bind & D3D11_BIND_RENDER_TARGET)
    D3D::device->CreateRenderTargetView(tex, &rtv_desc, &rtv);
  if (bind & D3D11_BIND_DEPTH_STENCIL)
    D3D::device->CreateDepthStencilView(tex, &dsv_desc, &dsv);
  tex->AddRef();
}

D3DTexture2D::~D3DTexture2D()
{
  SAFE_RELEASE(srv);
  SAFE_RELEASE(rtv);
  SAFE_RELEASE(dsv);
  SAFE_RELEASE(tex);
}

}  // namespace DX11