#include "DX11Texture.h" #include "Image.h" #ifdef WIN32 # include #endif using namespace Framework; DX11Texture::DX11Texture(ID3D11Device* device, ID3D11DeviceContext* context, Critical& deviceLock, TextureDirection dir) : Texture(dir), txt(0), view(0), device(device), context(context), useMips(dir == RAM_TO_GPU), deviceLock(deviceLock), readAccessTexture(0) {} DX11Texture::~DX11Texture() { #ifdef WIN32 if (txt) txt->Release(); if (view) view->Release(); if (readAccessTexture) readAccessTexture->Release(); #endif } // Updates the texture. The pixels of the current image are copied into // the graphics memory bool DX11Texture::updateTextur() { if (!bild) return 0; #ifdef WIN32 if (!txt || lastGr != bild->getSize()) { if (txt) txt->Release(); txt = 0; D3D11_TEXTURE2D_DESC bufferDesc; memset(&bufferDesc, 0, sizeof(D3D11_TEXTURE2D_DESC)); bufferDesc.ArraySize = 1; bufferDesc.Width = bild->getWidth(); bufferDesc.Height = bild->getHeight(); bufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; bufferDesc.BindFlags = (getDirection() == GPU_TO_RAM || useMips ? D3D11_BIND_RENDER_TARGET : 0) | D3D11_BIND_SHADER_RESOURCE; bufferDesc.CPUAccessFlags = getDirection() == GPU_TO_RAM || useMips ? 0 : D3D11_CPU_ACCESS_WRITE; bufferDesc.SampleDesc.Count = 1; bufferDesc.MipLevels = useMips ? 0 : 1; bufferDesc.Usage = getDirection() == GPU_TO_RAM || useMips ? D3D11_USAGE_DEFAULT : D3D11_USAGE_DYNAMIC; bufferDesc.MiscFlags = useMips ? D3D11_RESOURCE_MISC_GENERATE_MIPS : 0; deviceLock.lock(); HRESULT r = device->CreateTexture2D(&bufferDesc, 0, &txt); deviceLock.unlock(); if (r != S_OK) return 0; } if (getDirection() == RAM_TO_GPU && (bild->getNeedRender() || changed)) { changed = 0; if (useMips) { deviceLock.lock(); context->UpdateSubresource(txt, 0, 0, bild->getBuffer(), 4 * bild->getWidth(), 4 * bild->getWidth() * bild->getHeight()); deviceLock.unlock(); } else { D3D11_MAPPED_SUBRESOURCE buffer; deviceLock.lock(); context->Map( txt, 0, D3D11_MAP::D3D11_MAP_WRITE_DISCARD, 0, &buffer); int* bgBuff = bild->getBuffer(); int tmpBr = 4 * bild->getWidth(); for (int y = 0, pitch = 0, bry = 0; y < bild->getHeight(); ++y, pitch += buffer.RowPitch, bry += bild->getWidth()) { memcpy(&((BYTE*)buffer.pData)[pitch], (void*)&(bgBuff[bry]), tmpBr); } context->Unmap(txt, 0); deviceLock.unlock(); } } else if (getDirection() == GPU_TO_RAM) { if (!readAccessTexture || lastGr != bild->getSize()) { if (readAccessTexture) readAccessTexture->Release(); readAccessTexture = 0; D3D11_TEXTURE2D_DESC tempBufferDesc; memset(&tempBufferDesc, 0, sizeof(D3D11_TEXTURE2D_DESC)); tempBufferDesc.ArraySize = 1; tempBufferDesc.Width = bild->getWidth(); tempBufferDesc.Height = bild->getHeight(); tempBufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; tempBufferDesc.BindFlags = 0; tempBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; tempBufferDesc.SampleDesc.Count = 1; tempBufferDesc.MipLevels = 1; tempBufferDesc.Usage = D3D11_USAGE_STAGING; deviceLock.lock(); HRESULT r = device->CreateTexture2D( &tempBufferDesc, 0, &readAccessTexture); deviceLock.unlock(); if (r != S_OK) return 0; } else { deviceLock.lock(); context->CopyResource(readAccessTexture, txt); deviceLock.unlock(); D3D11_MAPPED_SUBRESOURCE buffer; deviceLock.lock(); HRESULT r = context->Map( readAccessTexture, 0, D3D11_MAP::D3D11_MAP_READ, 0, &buffer); deviceLock.unlock(); if (r != S_OK) return 0; int* bgBuff = bild->getBuffer(); int tmpBr = 4 * bild->getWidth(); for (int y = 0, pitch = 0, bry = 0; y < bild->getHeight(); ++y, pitch += buffer.RowPitch, bry += bild->getWidth()) { memcpy((void*)&(bgBuff[bry]), &((BYTE*)buffer.pData)[pitch], tmpBr); } for (int i = 0; i < bild->getWidth() * bild->getHeight(); i++) { if (bgBuff[i]) bgBuff[i] |= 0xFF000000; } deviceLock.lock(); context->Unmap(readAccessTexture, 0); deviceLock.unlock(); } } if (!view || lastGr != bild->getSize()) { if (view) view->Release(); view = 0; D3D11_SHADER_RESOURCE_VIEW_DESC resourceDesk; memset(&resourceDesk, 0, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC)); resourceDesk.Format = DXGI_FORMAT_B8G8R8A8_UNORM; resourceDesk.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; resourceDesk.Texture2D.MipLevels = useMips ? -1 : 1; deviceLock.lock(); HRESULT r = device->CreateShaderResourceView(txt, &resourceDesk, &view); deviceLock.unlock(); if (r != S_OK) return 0; if (context && useMips) { deviceLock.lock(); context->GenerateMips(view); deviceLock.unlock(); } } lastGr = bild->getSize(); #endif return 1; } // Returns true if updateTextur needs to be called bool DX11Texture::needsUpdate() const { return !view; } // Returns the used shader resource view DX11Texture::operator ID3D11ShaderResourceView*() const { return view; } //! Returns the used texture DX11Texture::operator ID3D11Texture2D*() const { return txt; } //! specifies if a mip map should be generated void DX11Texture::setUseMips(bool useMips) { this->useMips = useMips; }