1
0

GS_D3D11Texture2D.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /******************************************************************************
  2. Copyright (C) 2013 by Hugh Bailey <[email protected]>
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ******************************************************************************/
  14. #include "util/base.h"
  15. #include "GS_D3D11SubSystem.hpp"
  16. static inline bool IsPow2(uint32_t num)
  17. {
  18. return num >= 2 && (num & (num-1)) == 0;
  19. }
  20. void gs_texture_2d::InitSRD(D3D11_SUBRESOURCE_DATA *srd, void *data)
  21. {
  22. uint32_t rowSizeBytes = width * GetFormatBPP(format);
  23. uint32_t texSizeBytes = rowSizeBytes * height;
  24. if (type == GS_TEXTURE_2D) {
  25. srd->pSysMem = (uint8_t*)data;
  26. srd->SysMemPitch = rowSizeBytes;
  27. srd->SysMemSlicePitch = texSizeBytes;
  28. } else { /* GS_TEXTURE_CUBE */
  29. void **buffers = (void**)data;
  30. for (size_t i = 0; i < 6; i++) {
  31. srd[i].pSysMem = buffers[i];
  32. srd[i].SysMemPitch = rowSizeBytes;
  33. srd[i].SysMemSlicePitch = texSizeBytes;
  34. }
  35. }
  36. }
  37. void gs_texture_2d::InitTexture(void *data)
  38. {
  39. D3D11_TEXTURE2D_DESC td;
  40. D3D11_SUBRESOURCE_DATA srd[6];
  41. HRESULT hr;
  42. memset(&td, 0, sizeof(td));
  43. td.Width = width;
  44. td.Height = height;
  45. td.MipLevels = genMipmaps ? 0 : 1;
  46. td.ArraySize = type == GS_TEXTURE_CUBE ? 6 : 1;
  47. td.Format = dxgiFormat;
  48. td.BindFlags = D3D10_BIND_SHADER_RESOURCE;
  49. td.SampleDesc.Count = 1;
  50. td.CPUAccessFlags = isDynamic ? D3D11_CPU_ACCESS_WRITE : 0;
  51. td.Usage = isDynamic ? D3D11_USAGE_DYNAMIC :
  52. D3D11_USAGE_DEFAULT;
  53. if (type == GS_TEXTURE_CUBE)
  54. td.MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE;
  55. if (isRenderTarget || isGDICompatible)
  56. td.BindFlags |= D3D10_BIND_RENDER_TARGET;
  57. if (data)
  58. InitSRD(srd, data);
  59. hr = device->device->CreateTexture2D(&td, data ? srd : NULL,
  60. texture.Assign());
  61. if (FAILED(hr))
  62. throw HRError("Failed to create 2D texture", hr);
  63. }
  64. void gs_texture_2d::InitResourceView()
  65. {
  66. D3D11_SHADER_RESOURCE_VIEW_DESC resourceDesc;
  67. HRESULT hr;
  68. memset(&resourceDesc, 0, sizeof(resourceDesc));
  69. resourceDesc.Format = dxgiFormat;
  70. if (type == GS_TEXTURE_CUBE) {
  71. resourceDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURECUBE;
  72. resourceDesc.TextureCube.MipLevels = genMipmaps ? -1 : 1;
  73. } else {
  74. resourceDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
  75. resourceDesc.Texture2D.MipLevels = genMipmaps ? -1 : 1;
  76. }
  77. hr = device->device->CreateShaderResourceView(texture, &resourceDesc,
  78. shaderRes.Assign());
  79. if (FAILED(hr))
  80. throw HRError("Failed to create resource view", hr);
  81. }
  82. void gs_texture_2d::InitRenderTargets()
  83. {
  84. HRESULT hr;
  85. if (type == GS_TEXTURE_2D) {
  86. hr = device->device->CreateRenderTargetView(texture, NULL,
  87. renderTarget[0].Assign());
  88. if (FAILED(hr))
  89. throw HRError("Failed to create render target view",
  90. hr);
  91. } else {
  92. D3D11_RENDER_TARGET_VIEW_DESC rtv;
  93. rtv.Format = dxgiFormat;
  94. rtv.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
  95. rtv.Texture2DArray.MipSlice = 0;
  96. rtv.Texture2DArray.ArraySize = 1;
  97. for (UINT i = 0; i < 6; i++) {
  98. rtv.Texture2DArray.FirstArraySlice = i;
  99. hr = device->device->CreateRenderTargetView(texture,
  100. &rtv, renderTarget[i].Assign());
  101. if (FAILED(hr))
  102. throw HRError("Failed to create cube render "
  103. "target view", hr);
  104. }
  105. }
  106. }
  107. gs_texture_2d::gs_texture_2d(device_t device, uint32_t width, uint32_t height,
  108. gs_color_format colorFormat, void *data, uint32_t flags,
  109. bool isCubeMap, bool gdiCompatible, bool shared)
  110. : gs_texture (device, isCubeMap ? GS_TEXTURE_CUBE : GS_TEXTURE_2D),
  111. width (width),
  112. height (height),
  113. format (colorFormat),
  114. dxgiFormat (ConvertGSTextureFormat(format)),
  115. isGDICompatible (gdiCompatible),
  116. isShared (shared),
  117. isDynamic ((flags & GS_DYNAMIC) != 0),
  118. isRenderTarget ((flags & GS_RENDERTARGET) != 0),
  119. genMipmaps ((flags & GS_BUILDMIPMAPS) != 0)
  120. {
  121. if (genMipmaps && (!IsPow2(width) || !IsPow2(height))) {
  122. blog(LOG_WARNING, "Cannot generate mipmaps for a "
  123. "non-power-of-two texture. Disabling "
  124. "mipmaps for this texture.");
  125. genMipmaps = false;
  126. }
  127. InitTexture(data);
  128. InitResourceView();
  129. if (isRenderTarget)
  130. InitRenderTargets();
  131. }