#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; } // 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 ) 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 || 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 ) {} 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 ? D3D11_BIND_RENDER_TARGET : 0) | D3D11_BIND_SHADER_RESOURCE; bufferDesc.CPUAccessFlags = renderTarget ? 0 : D3D11_CPU_ACCESS_WRITE; bufferDesc.SampleDesc.Count = 1; bufferDesc.MipLevels = 1; bufferDesc.Usage = renderTarget ? D3D11_USAGE_DEFAULT : D3D11_USAGE_DYNAMIC; HRESULT r = device->CreateTexture2D( &bufferDesc, 0, &txt ); if( r != S_OK ) return 0; } if( !renderTarget ) { 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 = 1; HRESULT r = device->CreateShaderResourceView( txt, &resourceDesk, &view ); if( r != S_OK ) return 0; } 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 ) { renderTarget = rt; } //! copy the texture to an image void DX11Textur::copyToImage( Bild* zB ) { 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(); }