#include "Textur.h" #include "Bild.h" #ifdef WIN32 # include # include # include "d3dx12.h" #endif using namespace Framework; // Inhalt der Textur Klasse // Konstruktor Textur::Textur() : ReferenceCounter() { bild = 0; lastGr = Punkt(0, 0); id = -1; changed = 0; } // Destruktor Textur::~Textur() { if (bild) bild->release(); } // Setzt einen Zeiger auf das Bild, welches die Textur enthält // b: Der Zeiger auf das Bild void Textur::setBildZ(Bild* b) { if (bild != b) changed = 1; if (bild) bild->release(); bild = b; } // Setzt das Bild welches die Textur enthält, indem es kopiert wird // b: Das Bild, was kopiert werden soll void Textur::setBild(Bild* b) { if (!b) return; if (bild != b) changed = 1; if (!bild || bild->getBreite() != b->getBreite() || bild->getHeight() != b->getHeight()) { if (!bild) bild = new Bild(); bild->neuBild(b->getBreite(), b->getHeight(), 0); } bild->drawBild(0, 0, bild->getBreite(), bild->getHeight(), *b); b->release(); } // Gibt einen Zeiger auf das Bild zurück Bild* Textur::getBild() const { return bild ? dynamic_cast(bild->getThis()) : 0; } // Gibt einen Zeiger auf das Bild ohne erhöhten Reference Counter zurück Bild* Textur::zBild() const { return bild; } // Gibt die Id der Textur zurück, wenn sie in einer TexturList registriert // wurde. (siehe Framework::zTexturRegister()) int Textur::getId() const { return id; } // Aktualisiert die Textur. Die Pixel des aktuellen Bildes werden in den // Graphikspeicher kopiert bool DX9Textur::updateTextur() { return 1; } // Gibt true zurük, wenn updateTextur aufgerufen werden muss bool DX9Textur::brauchtUpdate() const { return 0; } DX11Textur::DX11Textur(ID3D11Device* device, ID3D11DeviceContext* context) : Textur(), txt(0), view(0), device(device), context(context), renderTarget(0), useMips(1) {} DX11Textur::~DX11Textur() { #ifdef WIN32 if (txt) txt->Release(); if (view) view->Release(); #endif } // Aktualisiert die Textur. Die Pixel des aktuellen Bildes werden in den // Graphikspeicher kopiert bool DX11Textur::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->getBreite(); bufferDesc.Height = bild->getHeight(); bufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; bufferDesc.BindFlags = (renderTarget || useMips ? D3D11_BIND_RENDER_TARGET : 0) | D3D11_BIND_SHADER_RESOURCE; bufferDesc.CPUAccessFlags = renderTarget || useMips ? 0 : D3D11_CPU_ACCESS_WRITE; bufferDesc.SampleDesc.Count = 1; bufferDesc.MipLevels = useMips ? 0 : 1; bufferDesc.Usage = renderTarget || useMips ? D3D11_USAGE_DEFAULT : D3D11_USAGE_DYNAMIC; bufferDesc.MiscFlags = useMips ? D3D11_RESOURCE_MISC_GENERATE_MIPS : 0; HRESULT r = device->CreateTexture2D(&bufferDesc, 0, &txt); if (r != S_OK) return 0; } if (!renderTarget && (bild->getRend() || changed)) { changed = 0; if (useMips) { context->UpdateSubresource(txt, 0, 0, bild->getBuffer(), 4 * bild->getBreite(), 4 * bild->getBreite() * bild->getHeight()); } else { D3D11_MAPPED_SUBRESOURCE buffer; context->Map( txt, 0, D3D11_MAP::D3D11_MAP_WRITE_DISCARD, 0, &buffer); int* bgBuff = bild->getBuffer(); int tmpBr = 4 * bild->getBreite(); for (int y = 0, pitch = 0, bry = 0; y < bild->getHeight(); ++y, pitch += buffer.RowPitch, bry += bild->getBreite()) memcpy(&((BYTE*)buffer.pData)[pitch], (void*)&(bgBuff[bry]), tmpBr); context->Unmap(txt, 0); } } 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; HRESULT r = device->CreateShaderResourceView(txt, &resourceDesk, &view); if (r != S_OK) return 0; if (context && useMips) context->GenerateMips(view); } lastGr = bild->getSize(); #endif return 1; } // Gibt true zurük, wenn updateTextur aufgerufen werden muss bool DX11Textur::brauchtUpdate() const { return !view; } // Gibt die verwendtete Shader Resource View zurück DX11Textur::operator ID3D11ShaderResourceView*() const { return view; } //! Gibt die verwendete Textur zurück DX11Textur::operator ID3D11Texture2D*() const { return txt; } //! specifies that this texture is used as a render target void DX11Textur::setRenderTarget(bool rt) { if (rt) useMips = 0; renderTarget = rt; } //! specifies if a mip map should be generated void DX11Textur::setUseMips(bool useMips) { this->useMips = useMips; } //! copy the texture to an image void DX11Textur::copyToImage(Bild* zB) { #ifdef WIN32 D3D11_TEXTURE2D_DESC tempBufferDesc; memset(&tempBufferDesc, 0, sizeof(D3D11_TEXTURE2D_DESC)); tempBufferDesc.ArraySize = 1; tempBufferDesc.Width = bild->getBreite(); 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; ID3D11Texture2D* tmpTxt; HRESULT r = device->CreateTexture2D(&tempBufferDesc, 0, &tmpTxt); if (r != S_OK) throw "could not create resource copy with cpu read access"; context->CopyResource(tmpTxt, txt); zB->neuBild(bild->getBreite(), bild->getHeight(), 0); D3D11_MAPPED_SUBRESOURCE buffer; r = context->Map(tmpTxt, 0, D3D11_MAP::D3D11_MAP_READ, 0, &buffer); if (r != S_OK) throw "could not access recource copy"; int* bgBuff = zB->getBuffer(); int tmpBr = 4 * zB->getBreite(); for (int y = 0, pitch = 0, bry = 0; y < zB->getHeight(); ++y, pitch += buffer.RowPitch, bry += zB->getBreite()) memcpy((void*)&(bgBuff[bry]), &((BYTE*)buffer.pData)[pitch], tmpBr); for (int i = 0; i < zB->getBreite() * zB->getHeight(); i++) { if (bgBuff[i]) bgBuff[i] |= 0xFF000000; } context->Unmap(tmpTxt, 0); tmpTxt->Release(); #endif }