Commit e12ef3a4 authored by nadro's avatar nadro

- Changes for D3D9 texture code (at now it looks like OpenGL texture code)....

- Changes for D3D9 texture code (at now it looks like OpenGL texture code). Those changes was required for upcoming cubemaps support.
- Minor improvements in COGLCoreTexture.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@5237 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 1aba16d8
......@@ -603,9 +603,7 @@ bool CD3D9Driver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const
case EVDF_MIP_MAP:
return (Caps.TextureCaps & D3DPTEXTURECAPS_MIPMAP) != 0;
case EVDF_MIP_MAP_AUTO_UPDATE:
// always return false because a lot of drivers claim they do
// this but actually don't do this at all.
return false; //(Caps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP) != 0;
return (Caps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP) != 0;
case EVDF_STENCIL_BUFFER:
return Params.Stencilbuffer && Caps.StencilCaps;
case EVDF_VERTEX_SHADER_1_1:
......@@ -744,24 +742,19 @@ void CD3D9Driver::setMaterial(const SMaterial& material)
ITexture* CD3D9Driver::createDeviceDependentTexture(const io::path& name, IImage* image)
{
CD3D9Texture* texture = new CD3D9Texture(image, this, TextureCreationFlags, name);
core::array<IImage*> imageArray(1);
imageArray.push_back(image);
CD3D9Texture* texture = new CD3D9Texture(name, imageArray, ETT_2D, this);
return texture;
}
/*ITexture* CD3D9Driver::createDeviceDependentTextureCubemap(const io::path& name, const core::array<IImage*>& image)
ITexture* CD3D9Driver::createDeviceDependentTextureCubemap(const io::path& name, const core::array<IImage*>& image)
{
CD3D9Texture* texture = new CD3D9Texture(name, image, ETT_CUBEMAP, this);
}*/
//! Enables or disables a texture creation flag.
void CD3D9Driver::setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag,
bool enabled)
{
if (flag == video::ETCF_CREATE_MIP_MAPS && !queryFeature(EVDF_MIP_MAP))
enabled = false;
CNullDriver::setTextureCreationFlag(flag, enabled);
return texture;
}
bool CD3D9Driver::setRenderTargetEx(IRenderTarget* target, u16 clearFlag, SColor clearColor, f32 clearDepth, u8 clearStencil)
......@@ -2880,7 +2873,7 @@ bool CD3D9Driver::reset()
for (i=0; i<Textures.size(); ++i)
{
if (Textures[i].Surface->isRenderTarget())
((CD3D9Texture*)(Textures[i].Surface))->createRenderTarget();
((CD3D9Texture*)(Textures[i].Surface))->generateRenderTarget();
}
for (i = 0; i<RenderTargets.size(); ++i)
{
......
......@@ -213,9 +213,6 @@ namespace video
//! call.
virtual u32 getMaximalPrimitiveCount() const _IRR_OVERRIDE_;
//! Enables or disables a texture creation flag.
virtual void setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag, bool enabled) _IRR_OVERRIDE_;
//! Sets the fog mode.
virtual void setFog(SColor color, E_FOG_TYPE fogType, f32 start,
f32 end, f32 density, bool pixelFog, bool rangeFog) _IRR_OVERRIDE_;
......@@ -348,7 +345,7 @@ namespace video
virtual ITexture* createDeviceDependentTexture(const io::path& name, IImage* image) _IRR_OVERRIDE_;
/*virtual ITexture* createDeviceDependentTextureCubemap(const io::path& name, const core::array<IImage*>& image) _IRR_OVERRIDE_;*/
virtual ITexture* createDeviceDependentTextureCubemap(const io::path& name, const core::array<IImage*>& image) _IRR_OVERRIDE_;
//! returns the current size of the screen or rendertarget
virtual const core::dimension2d<u32>& getCurrentRenderTargetSize() const _IRR_OVERRIDE_;
......
......@@ -3,434 +3,157 @@
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
#define _IRR_DONT_DO_MEMORY_DEBUGGING_HERE
#include "CD3D9Texture.h"
#include "CD3D9Driver.h"
#include "os.h"
#include <d3dx9tex.h>
namespace irr
{
namespace video
{
//! rendertarget constructor
CD3D9Texture::CD3D9Texture(CD3D9Driver* driver, const core::dimension2d<u32>& size, const io::path& name, const ECOLOR_FORMAT format)
: ITexture(name, ETT_2D), Texture(0), RTTSurface(0), Driver(driver), HardwareMipMaps(false), IsCompressed(false)
CD3D9Texture::CD3D9Texture(const io::path& name, const core::array<IImage*>& image, E_TEXTURE_TYPE type, CD3D9Driver* driver)
: ITexture(name, type), Driver(driver), InternalFormat(D3DFMT_UNKNOWN), LockData(0), LockLevel(0), AutoGenerateMipMaps(false),
Device(0), Texture(0), CubeTexture(0), RTTSurface(0)
{
#ifdef _DEBUG
setDebugName("CD3D9Texture");
#endif
_IRR_DEBUG_BREAK_IF(image.size() == 0)
Device=driver->getExposedVideoData().D3D9.D3DDev9;
if (Device)
Device->AddRef();
DriverType = EDT_DIRECT3D9;
OriginalSize = size;
Size = size;
IsRenderTarget = true;
createRenderTarget(format);
}
DriverType = Driver->getDriverType();
HasMipMaps = Driver->getTextureCreationFlag(ETCF_CREATE_MIP_MAPS);
AutoGenerateMipMaps = Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE);
//! constructor
CD3D9Texture::CD3D9Texture(IImage* image, CD3D9Driver* driver, u32 flags, const io::path& name)
: ITexture(name, ETT_2D), Texture(0), RTTSurface(0), Driver(driver), HardwareMipMaps(false), IsCompressed(false)
{
#ifdef _DEBUG
setDebugName("CD3D9Texture");
#endif
getImageValues(image[0]);
DriverType = EDT_DIRECT3D9;
HasMipMaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
Device=driver->getExposedVideoData().D3D9.D3DDev9;
if (Device)
Device->AddRef();
core::array<IImage*> tmpImage = image;
if (image)
if (OriginalSize != Size || OriginalColorFormat != ColorFormat)
{
if (IImage::isCompressedFormat(image->getColorFormat()))
for (u32 i = 0; i < image.size(); ++i)
{
if(!Driver->queryFeature(EVDF_TEXTURE_COMPRESSED_DXT))
{
os::Printer::log("DXT texture compression not available.", ELL_ERROR);
return;
}
}
tmpImage[i] = Driver->createImage(ColorFormat, Size);
if (createTexture(flags, image))
{
if (copyTexture(image))
{
if (IsCompressed && !image->getMipMapsData())
HasMipMaps = false;
regenerateMipMapLevels(image->getMipMapsData());
}
if (image[i]->getDimension() == Size)
image[i]->copyTo(tmpImage[i]);
else
image[i]->copyToScaling(tmpImage[i]);
}
else
os::Printer::log("Could not create DIRECT3D9 Texture.", ELL_WARNING);
}
}
//! destructor
CD3D9Texture::~CD3D9Texture()
{
if (Texture)
Texture->Release();
if (RTTSurface)
RTTSurface->Release();
if (Device)
Device->Release();
}
void CD3D9Texture::createRenderTarget(const ECOLOR_FORMAT format)
{
// are texture size restrictions there ?
if(!Driver->queryFeature(EVDF_TEXTURE_NPOT))
{
if (Size != OriginalSize)
os::Printer::log("RenderTarget size has to be a power of two", ELL_INFORMATION);
}
Size = Size.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth);
DWORD flags = 0;
D3DFORMAT d3dformat = Driver->getD3DColorFormat();
if(ColorFormat == ECF_UNKNOWN)
if (HasMipMaps && AutoGenerateMipMaps)
{
// get irrlicht format from backbuffer
// (This will get overwritten by the custom format if it is provided, else kept.)
ColorFormat = Driver->getColorFormat();
setPitch(d3dformat);
// Use color format if provided.
if(format != ECF_UNKNOWN)
{
ColorFormat = format;
d3dformat = Driver->getD3DFormatFromColorFormat(format);
setPitch(d3dformat); // This will likely set pitch to 0 for now.
}
}
else
{
d3dformat = Driver->getD3DFormatFromColorFormat(ColorFormat);
}
// create texture
DWORD usage = (IImage::isDepthFormat(ColorFormat)) ? D3DUSAGE_DEPTHSTENCIL : D3DUSAGE_RENDERTARGET;
HRESULT hr = Device->CreateTexture(Size.Width, Size.Height, 1, usage, d3dformat, D3DPOOL_DEFAULT, &Texture, NULL);
LPDIRECT3D9 intf = Driver->getExposedVideoData().D3D9.D3D9;
D3DDISPLAYMODE d3ddm;
intf->GetAdapterDisplayMode(Driver->Params.DisplayAdapter, &d3ddm);
if (FAILED(hr))
{
if (D3DERR_INVALIDCALL == hr)
os::Printer::log("Could not create render target texture", "Invalid Call");
else
if (D3DERR_OUTOFVIDEOMEMORY == hr)
os::Printer::log("Could not create render target texture", "Out of Video Memory");
else
if (E_OUTOFMEMORY == hr)
os::Printer::log("Could not create render target texture", "Out of Memory");
if (D3D_OK == intf->CheckDeviceFormat(Driver->Params.DisplayAdapter, D3DDEVTYPE_HAL, d3ddm.Format, D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, InternalFormat))
flags = D3DUSAGE_AUTOGENMIPMAP;
else
os::Printer::log("Could not create render target texture");
}
}
bool CD3D9Texture::createMipMaps(u32 level)
{
if (level==0)
return true;
if (HardwareMipMaps && Texture)
{
// generate mipmaps in hardware
Texture->GenerateMipSubLevels();
return true;
AutoGenerateMipMaps = false;
}
// manual mipmap generation
IDirect3DSurface9* upperSurface = 0;
IDirect3DSurface9* lowerSurface = 0;
HRESULT hr = Device->CreateTexture(Size.Width, Size.Height, HasMipMaps ? 0 : 1, flags, InternalFormat, D3DPOOL_MANAGED, &Texture, NULL);
// get upper level
HRESULT hr = Texture->GetSurfaceLevel(level-1, &upperSurface);
if (FAILED(hr) || !upperSurface)
if (SUCCEEDED(hr))
{
os::Printer::log("Could not get upper surface level for mip map generation", ELL_WARNING);
return false;
}
for (u32 i = 0; i < tmpImage.size(); ++i)
uploadTexture(i, 0, tmpImage[i]->getData());
// get lower level
hr = Texture->GetSurfaceLevel(level, &lowerSurface);
if (FAILED(hr) || !lowerSurface)
{
os::Printer::log("Could not get lower surface level for mip map generation", ELL_WARNING);
upperSurface->Release();
return false;
}
D3DSURFACE_DESC upperDesc, lowerDesc;
upperSurface->GetDesc(&upperDesc);
lowerSurface->GetDesc(&lowerDesc);
D3DLOCKED_RECT upperlr;
D3DLOCKED_RECT lowerlr;
// lock upper surface
if (FAILED(upperSurface->LockRect(&upperlr, NULL, 0)))
{
upperSurface->Release();
lowerSurface->Release();
os::Printer::log("Could not lock upper texture for mip map generation", ELL_WARNING);
return false;
}
// lock lower surface
if (FAILED(lowerSurface->LockRect(&lowerlr, NULL, 0)))
{
upperSurface->UnlockRect();
upperSurface->Release();
lowerSurface->Release();
os::Printer::log("Could not lock lower texture for mip map generation", ELL_WARNING);
return false;
}
if (upperDesc.Format != lowerDesc.Format)
{
os::Printer::log("Cannot copy mip maps with different formats.", ELL_WARNING);
for (u32 i = 0; i < tmpImage.size(); ++i)
regenerateMipMapLevels(tmpImage[i]->getMipMapsData(), i);
}
else
{
if ((upperDesc.Format == D3DFMT_A1R5G5B5) || (upperDesc.Format == D3DFMT_R5G6B5))
copy16BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits,
upperDesc.Width, upperDesc.Height,
lowerDesc.Width, lowerDesc.Height,
upperlr.Pitch, lowerlr.Pitch);
else
if (upperDesc.Format == D3DFMT_A8R8G8B8)
copy32BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits,
upperDesc.Width, upperDesc.Height,
lowerDesc.Width, lowerDesc.Height,
upperlr.Pitch, lowerlr.Pitch);
else
os::Printer::log("Unsupported mipmap format, cannot copy.", ELL_WARNING);
os::Printer::log("Could not create DIRECT3D9 Texture.", ELL_WARNING);
}
bool result=true;
// unlock
if (FAILED(upperSurface->UnlockRect()))
result=false;
if (FAILED(lowerSurface->UnlockRect()))
result=false;
// release
upperSurface->Release();
lowerSurface->Release();
if (!result || (upperDesc.Width <= 3 && upperDesc.Height <= 3))
return result; // stop generating levels
// generate next level
return createMipMaps(level+1);
}
//! creates the hardware texture
bool CD3D9Texture::createTexture(u32 flags, IImage * image)
CD3D9Texture::CD3D9Texture(CD3D9Driver* driver, const core::dimension2d<u32>& size, const io::path& name, const ECOLOR_FORMAT format)
: ITexture(name, ETT_2D), Driver(driver), InternalFormat(D3DFMT_UNKNOWN), LockData(0), LockLevel(0), AutoGenerateMipMaps(false),
Device(0), Texture(0), CubeTexture(0), RTTSurface(0)
{
OriginalSize = image->getDimension();
core::dimension2d<u32> optSize = OriginalSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth);
D3DFORMAT format = D3DFMT_A1R5G5B5;
switch(getTextureFormatFromFlags(flags))
{
case ETCF_ALWAYS_16_BIT:
format = D3DFMT_A1R5G5B5; break;
case ETCF_ALWAYS_32_BIT:
format = D3DFMT_A8R8G8B8; break;
case ETCF_OPTIMIZED_FOR_QUALITY:
{
switch(image->getColorFormat())
{
case ECF_R8G8B8:
case ECF_A8R8G8B8:
format = D3DFMT_A8R8G8B8; break;
case ECF_A1R5G5B5:
case ECF_R5G6B5:
format = D3DFMT_A1R5G5B5; break;
}
}
break;
case ETCF_OPTIMIZED_FOR_SPEED:
format = D3DFMT_A1R5G5B5;
break;
default:
break;
}
if (Driver->getTextureCreationFlag(video::ETCF_NO_ALPHA_CHANNEL))
{
if (format == D3DFMT_A8R8G8B8)
format = D3DFMT_R8G8B8;
else if (format == D3DFMT_A1R5G5B5)
format = D3DFMT_R5G6B5;
}
if (IImage::isCompressedFormat(image->getColorFormat()))
{
ColorFormat = image->getColorFormat();
switch(ColorFormat)
{
case ECF_DXT1:
format = D3DFMT_DXT1;
break;
case ECF_DXT2:
format = D3DFMT_DXT2;
break;
case ECF_DXT3:
format = D3DFMT_DXT3;
break;
case ECF_DXT4:
format = D3DFMT_DXT4;
break;
case ECF_DXT5:
format = D3DFMT_DXT5;
break;
default:
break;
}
#ifdef _DEBUG
setDebugName("CD3D9Texture");
#endif
IsCompressed = true;
}
Device = driver->getExposedVideoData().D3D9.D3DDev9;
bool mipmaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
if (Device)
Device->AddRef();
if (IsCompressed && !image->hasMipMaps())
mipmaps = false;
DriverType = Driver->getDriverType();
HasMipMaps = false;
IsRenderTarget = true;
DWORD usage = 0;
OriginalColorFormat = format;
// This enables hardware mip map generation.
if (!IsCompressed && mipmaps && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE))
{
LPDIRECT3D9 intf = Driver->getExposedVideoData().D3D9.D3D9;
D3DDISPLAYMODE d3ddm;
intf->GetAdapterDisplayMode(Driver->Params.DisplayAdapter, &d3ddm);
if (D3D_OK==intf->CheckDeviceFormat(Driver->Params.DisplayAdapter,D3DDEVTYPE_HAL,d3ddm.Format,D3DUSAGE_AUTOGENMIPMAP,D3DRTYPE_TEXTURE,format))
{
usage = D3DUSAGE_AUTOGENMIPMAP;
HardwareMipMaps = true;
}
}
if (ECF_UNKNOWN == OriginalColorFormat)
ColorFormat = getBestColorFormat(Driver->getColorFormat());
else
ColorFormat = OriginalColorFormat;
HRESULT hr = Device->CreateTexture(optSize.Width, optSize.Height,
mipmaps ? 0 : 1, // number of mipmaplevels (0 = automatic all)
usage, // usage
format, D3DPOOL_MANAGED , &Texture, NULL);
OriginalSize = size;
Size = OriginalSize;
if (!IsCompressed && FAILED(hr))
if (!Driver->queryFeature(EVDF_TEXTURE_NPOT))
{
// try brute force 16 bit
HardwareMipMaps = false;
if (format == D3DFMT_A8R8G8B8)
format = D3DFMT_A1R5G5B5;
else if (format == D3DFMT_R8G8B8)
format = D3DFMT_R5G6B5;
else
return false;
Size = OriginalSize.getOptimalSize(true, !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth);
hr = Device->CreateTexture(optSize.Width, optSize.Height,
mipmaps ? 0 : 1, // number of mipmaplevels (0 = automatic all)
0, format, D3DPOOL_MANAGED, &Texture, NULL);
if (Size != OriginalSize)
os::Printer::log("RenderTarget size has to be a power of two", ELL_INFORMATION);
}
if (!IsCompressed)
ColorFormat = Driver->getColorFormatFromD3DFormat(format);
Pitch = Size.Width * IImage::getBitsPerPixelFromFormat(ColorFormat) / 8;
setPitch(format);
InternalFormat = Driver->getD3DFormatFromColorFormat(ColorFormat);
return (SUCCEEDED(hr));
generateRenderTarget();
}
//! copies the image to the texture
bool CD3D9Texture::copyTexture(IImage * image)
CD3D9Texture::~CD3D9Texture()
{
if (Texture && image)
{
D3DSURFACE_DESC desc;
Texture->GetLevelDesc(0, &desc);
Size.Width = desc.Width;
Size.Height = desc.Height;
D3DLOCKED_RECT rect;
HRESULT hr = Texture->LockRect(0, &rect, 0, 0);
if (FAILED(hr))
{
os::Printer::log("Texture data not copied", "Could not LockRect D3D9 Texture.", ELL_ERROR);
return false;
}
if (IsCompressed)
{
u32 compressedDataSize = 0;
if(ColorFormat == ECF_DXT1)
compressedDataSize = ((Size.Width + 3) / 4) * ((Size.Height + 3) / 4) * 8;
else if (ColorFormat == ECF_DXT2 || ColorFormat == ECF_DXT3 || ColorFormat == ECF_DXT4 || ColorFormat == ECF_DXT5)
compressedDataSize = ((Size.Width + 3) / 4) * ((Size.Height + 3) / 4) * 16;
memcpy(rect.pBits, image->lock(), compressedDataSize);
}
else
{
Pitch = rect.Pitch;
image->copyToScaling(rect.pBits, Size.Width, Size.Height, ColorFormat, Pitch);
}
if (Texture)
Texture->Release();
hr = Texture->UnlockRect(0);
if (FAILED(hr))
{
os::Printer::log("Texture data not copied", "Could not UnlockRect D3D9 Texture.", ELL_ERROR);
return false;
}
}
if (RTTSurface)
RTTSurface->Release();
return true;
if (Device)
Device->Release();
}
//! lock function
void* CD3D9Texture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel)
{
if (IsCompressed) // TO-DO
if (IImage::isCompressedFormat(ColorFormat) || mipmapLevel > 0) // TO-DO
return 0;
if (!Texture)
return 0;
bool lockReadOnly = (mode == ETLM_READ_ONLY);
LockLevel = mipmapLevel;
if (LockData)
return LockData;
LockLevel = mipmapLevel;
MipLevelLocked=mipmapLevel;
HRESULT hr;
D3DLOCKED_RECT rect;
if(!IsRenderTarget)
if (!IsRenderTarget)
{
hr = Texture->LockRect(mipmapLevel, &rect, 0, (mode==ETLM_READ_ONLY)?D3DLOCK_READONLY:0);
hr = Texture->LockRect(mipmapLevel, &rect, 0, lockReadOnly ? D3DLOCK_READONLY : 0);
if (FAILED(hr))
{
os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR);
......@@ -466,234 +189,210 @@ void* CD3D9Texture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel)
os::Printer::log("Could not lock DIRECT3D9 Texture", "Data copy failed.", ELL_ERROR);
return 0;
}
hr = RTTSurface->LockRect(&rect, 0, (mode==ETLM_READ_ONLY)?D3DLOCK_READONLY:0);
hr = RTTSurface->LockRect(&rect, 0, lockReadOnly ? D3DLOCK_READONLY : 0);
if(FAILED(hr))
{
os::Printer::log("Could not lock DIRECT3D9 Texture", "LockRect failed.", ELL_ERROR);
return 0;
}
}
return rect.pBits;
}
LockData = rect.pBits;
return LockData;
}
//! unlock function
void CD3D9Texture::unlock()
{
if (IsCompressed) // TO-DO
return;
if (!Texture)
if (!LockData)
return;
if (!IsRenderTarget)
Texture->UnlockRect(MipLevelLocked);
Texture->UnlockRect(0);
else if (RTTSurface)
RTTSurface->UnlockRect();
}
if (LockLevel == 0)
regenerateMipMapLevels(0);
//! returns the DIRECT3D9 Texture
IDirect3DTexture9* CD3D9Texture::getDX9Texture() const
{
return Texture;
LockData = 0;
LockLevel = 0;
}
void CD3D9Texture::copy16BitMipMap(char* src, char* tgt,
const s32 srcWidth, const s32 srcHeight,
const s32 width, const s32 height,
const s32 pitchsrc, const s32 pitchtgt) const
void CD3D9Texture::regenerateMipMapLevels(void* data, u32 layer)
{
const s32 dy_max = (srcHeight==1?1:2);
const s32 dx_max = (srcWidth==1?1:2);
const s32 blockcount= dx_max*dy_max;
for (s32 y=0; y<height; ++y)
if (!HasMipMaps || (!data && !AutoGenerateMipMaps) || (Size.Width <= 1 && Size.Height <= 1))
return;
if (data)
{
for (s32 x=0; x<width; ++x)
u32 width = Size.Width >> layer;
u32 height = Size.Height >> layer;
u8* tmpData = static_cast<u8*>(data);
u32 dataSize = 0;
u32 level = 0;
do
{
u32 a=0, r=0, g=0, b=0;
for (s32 dy=0; dy<dy_max; ++dy)
{
const s32 tgy = (y*2)+dy;
for (s32 dx=0; dx<dx_max; ++dx)
{
const s32 tgx = (x*2)+dx;
SColor c;
if (ColorFormat == ECF_A1R5G5B5)
c = A1R5G5B5toA8R8G8B8(*(u16*)(&src[(tgx*2)+(tgy*pitchsrc)]));
else
c = R5G6B5toA8R8G8B8(*(u16*)(&src[(tgx*2)+(tgy*pitchsrc)]));
a += c.getAlpha();
r += c.getRed();
g += c.getGreen();
b += c.getBlue();
}
}
if (width > 1)
width >>= 1;
a /= blockcount;
r /= blockcount;
g /= blockcount;
b /= blockcount;
if (height > 1)
height >>= 1;
u16 c;
if (ColorFormat == ECF_A1R5G5B5)
c = RGBA16(r,g,b,a);
else
c = A8R8G8B8toR5G6B5(SColor(a,r,g,b).color);
*(u16*)(&tgt[(x*2)+(y*pitchtgt)]) = c;
}
dataSize = IImage::getDataSizeFromFormat(ColorFormat, width, height);
++level;
uploadTexture(layer, level, tmpData);
tmpData += dataSize;
} while (width != 1 || height != 1);
}
else
{
Texture->GenerateMipSubLevels();
}
}
IDirect3DTexture9* CD3D9Texture::getDX9Texture() const
{
return Texture;
}
void CD3D9Texture::copy32BitMipMap(char* src, char* tgt,
const s32 srcWidth, const s32 srcHeight,
const s32 width, const s32 height,
const s32 pitchsrc, const s32 pitchtgt) const
void CD3D9Texture::generateRenderTarget()
{
const s32 dy_max = (srcHeight==1?1:2);
const s32 dx_max = (srcWidth==1?1:2);
const s32 blockcount= dx_max*dy_max;
for (s32 y=0; y<height; ++y)
DWORD flag = (IImage::isDepthFormat(ColorFormat)) ? D3DUSAGE_DEPTHSTENCIL : D3DUSAGE_RENDERTARGET;
HRESULT hr = Device->CreateTexture(Size.Width, Size.Height, 1, flag, InternalFormat, D3DPOOL_DEFAULT, &Texture, NULL);
if (FAILED(hr))
{
for (s32 x=0; x<width; ++x)
{
u32 a=0, r=0, g=0, b=0;
SColor c;
if (D3DERR_INVALIDCALL == hr)
os::Printer::log("Could not create render target texture", "Invalid Call");
else if (D3DERR_OUTOFVIDEOMEMORY == hr)
os::Printer::log("Could not create render target texture", "Out of Video Memory");
else if (E_OUTOFMEMORY == hr)
os::Printer::log("Could not create render target texture", "Out of Memory");
else
os::Printer::log("Could not create render target texture");
}
}
for (s32 dy=0; dy<dy_max; ++dy)
{
const s32 tgy = (y*2)+dy;
for (s32 dx=0; dx<dx_max; ++dx)
{
const s32 tgx = (x*2)+dx;
c = *(u32*)(&src[(tgx*4)+(tgy*pitchsrc)]);
a += c.getAlpha();
r += c.getRed();
g += c.getGreen();
b += c.getBlue();
}
}
ECOLOR_FORMAT CD3D9Texture::getBestColorFormat(ECOLOR_FORMAT format)
{
ECOLOR_FORMAT destFormat = (!IImage::isCompressedFormat(format)) ? ECF_A8R8G8B8 : format;
a /= blockcount;
r /= blockcount;
g /= blockcount;
b /= blockcount;
switch (format)
{
case ECF_A1R5G5B5:
if (!Driver->getTextureCreationFlag(ETCF_ALWAYS_32_BIT))
destFormat = ECF_A1R5G5B5;
break;
case ECF_R5G6B5:
if (!Driver->getTextureCreationFlag(ETCF_ALWAYS_32_BIT))
destFormat = ECF_A1R5G5B5;
break;
case ECF_A8R8G8B8:
if (Driver->getTextureCreationFlag(ETCF_ALWAYS_16_BIT) ||
Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED))
destFormat = ECF_A1R5G5B5;
break;
case ECF_R8G8B8:
if (Driver->getTextureCreationFlag(ETCF_ALWAYS_16_BIT) || Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED))
destFormat = ECF_A1R5G5B5;
default:
break;
}
c.set(a, r, g, b);
*(u32*)(&tgt[(x*4)+(y*pitchtgt)]) = c.color;
if (Driver->getTextureCreationFlag(ETCF_NO_ALPHA_CHANNEL))
{
switch (destFormat)
{
case ECF_A1R5G5B5:
destFormat = ECF_R5G6B5;
break;
case ECF_A8R8G8B8:
destFormat = ECF_R8G8B8;
break;
default:
break;
}
}
return destFormat;
}
void CD3D9Texture::regenerateMipMapLevels(void* data, u32 layer)
void CD3D9Texture::getImageValues(const IImage* image)
{
if (!HasMipMaps)
return;
OriginalColorFormat = image->getColorFormat();
ColorFormat = getBestColorFormat(OriginalColorFormat);
if (IsCompressed && !data)
return;
InternalFormat = Driver->getD3DFormatFromColorFormat(ColorFormat);
if (data)
if (IImage::isCompressedFormat(image->getColorFormat()))
{
u32 compressedDataSize = 0;
core::dimension2du size = Size;
u32 level=0;
do
{
if (size.Width>1)
size.Width /=2;
if (size.Height>1)
size.Height /=2;
++level;
IDirect3DSurface9* mipSurface = 0;
HRESULT hr = Texture->GetSurfaceLevel(level, &mipSurface);
if (FAILED(hr) || !mipSurface)
{
os::Printer::log("Could not get mipmap level", ELL_WARNING);
return;
}
D3DSURFACE_DESC mipDesc;
mipSurface->GetDesc(&mipDesc);
D3DLOCKED_RECT miplr;
AutoGenerateMipMaps = false;
}
// lock mipmap surface
if (FAILED(mipSurface->LockRect(&miplr, NULL, 0)))
{
mipSurface->Release();
os::Printer::log("Could not lock texture", ELL_WARNING);
return;
}
OriginalSize = image->getDimension();
Size = OriginalSize;
if (IsCompressed)
{
if(ColorFormat == ECF_DXT1)
compressedDataSize = ((size.Width + 3) / 4) * ((size.Height + 3) / 4) * 8;
else if (ColorFormat == ECF_DXT2 || ColorFormat == ECF_DXT3 || ColorFormat == ECF_DXT4 || ColorFormat == ECF_DXT5)
compressedDataSize = ((size.Width + 3) / 4) * ((size.Height + 3) / 4) * 16;
if (Size.Width == 0 || Size.Height == 0)
{
os::Printer::log("Invalid size of image for texture.", ELL_ERROR);
return;
}
memcpy(miplr.pBits, data, compressedDataSize);
data = static_cast<u8*>(data)+compressedDataSize;
}
else
{
memcpy(miplr.pBits, data, size.getArea()*getPitch() / Size.Width);
data = (u8*)data + size.getArea()*getPitch() / Size.Width;
}
const f32 ratio = (f32)Size.Width / (f32)Size.Height;
// unlock
mipSurface->UnlockRect();
// release
mipSurface->Release();
} while (size.Width != 1 || size.Height != 1);
if ((Size.Width > Driver->Caps.MaxTextureWidth) && (ratio >= 1.f))
{
Size.Width = Driver->Caps.MaxTextureWidth;
Size.Height = (u32)(Driver->Caps.MaxTextureWidth / ratio);
}
else if (HasMipMaps)
else if (Size.Height > Driver->Caps.MaxTextureHeight)
{
createMipMaps();
Size.Height = Driver->Caps.MaxTextureHeight;
Size.Width = (u32)(Driver->Caps.MaxTextureHeight * ratio);
}
}
Size = Size.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth);
Pitch = Size.Width * IImage::getBitsPerPixelFromFormat(ColorFormat) / 8;
}
void CD3D9Texture::setPitch(D3DFORMAT d3dformat)
void CD3D9Texture::uploadTexture(u32 layer, u32 level, void* data)
{
switch(d3dformat)
if (!data)
return;
u32 width = Size.Width >> level;
u32 height = Size.Height >> level;
u32 dataSize = IImage::getDataSizeFromFormat(ColorFormat, width, height);
HRESULT hr = 0;
D3DLOCKED_RECT lockRectangle;
hr = Texture->LockRect(level, &lockRectangle, 0, 0);
if (FAILED(hr))
{
case D3DFMT_X1R5G5B5:
case D3DFMT_A1R5G5B5:
Pitch = Size.Width * 2;
break;
case D3DFMT_A8B8G8R8:
case D3DFMT_A8R8G8B8:
case D3DFMT_X8R8G8B8:
Pitch = Size.Width * 4;
break;
case D3DFMT_R5G6B5:
Pitch = Size.Width * 2;
break;
case D3DFMT_R8G8B8:
Pitch = Size.Width * 3;
break;
case D3DFMT_DXT1:
Pitch = Size.Width * 2;
break;
case D3DFMT_DXT2:
case D3DFMT_DXT3:
case D3DFMT_DXT4:
case D3DFMT_DXT5:
Pitch = Size.Width * 4;
default:
Pitch = 0;
};
}
os::Printer::log("Texture data not copied", "Could not LockRect D3D9 Texture.", ELL_ERROR);
return;
}
memcpy(lockRectangle.pBits, data, dataSize);
} // end namespace video
} // end namespace irr
hr = Texture->UnlockRect(level);
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
if (FAILED(hr))
{
os::Printer::log("Texture data not copied", "Could not UnlockRect D3D9 Texture.", ELL_ERROR);
}
}
}
}
#endif
......@@ -8,6 +8,7 @@
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
#include "irrArray.h"
#include "ITexture.h"
#include "IImage.h"
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
......@@ -21,82 +22,52 @@ namespace video
{
class CD3D9Driver;
// forward declaration for RTT depth buffer handling
struct SDepthSurface;
/*!
interface for a Video Driver dependent Texture.
*/
class CD3D9Texture : public ITexture
{
public:
CD3D9Texture(const io::path& name, const core::array<IImage*>& image, E_TEXTURE_TYPE type, CD3D9Driver* driver);
//! constructor
CD3D9Texture(IImage* image, CD3D9Driver* driver,
u32 flags, const io::path& name);
//! rendertarget constructor
CD3D9Texture(CD3D9Driver* driver, const core::dimension2d<u32>& size, const io::path& name,
const ECOLOR_FORMAT format = ECF_UNKNOWN);
CD3D9Texture(CD3D9Driver* driver, const core::dimension2d<u32>& size, const io::path& name, const ECOLOR_FORMAT format = ECF_UNKNOWN);
//! destructor
virtual ~CD3D9Texture();
//! lock function
virtual void* lock(E_TEXTURE_LOCK_MODE mode=ETLM_READ_WRITE, u32 mipmapLevel=0) _IRR_OVERRIDE_;
virtual void* lock(E_TEXTURE_LOCK_MODE mode = ETLM_READ_WRITE, u32 mipmapLevel = 0) _IRR_OVERRIDE_;
//! unlock function
virtual void unlock() _IRR_OVERRIDE_;
virtual void regenerateMipMapLevels(void* data = 0, u32 layer = 0) _IRR_OVERRIDE_;
//! returns the DIRECT3D9 Texture
IDirect3DTexture9* getDX9Texture() const;
private:
friend class CD3D9Driver;
void createRenderTarget(const ECOLOR_FORMAT format = ECF_UNKNOWN);
void generateRenderTarget();
ECOLOR_FORMAT getBestColorFormat(ECOLOR_FORMAT format);
//! creates the hardware texture
bool createTexture(u32 flags, IImage * image);
void getImageValues(const IImage* image);
//! copies the image to the texture
bool copyTexture(IImage * image);
void uploadTexture(u32 layer, u32 level, void* data);
//! Helper function for mipmap generation.
bool createMipMaps(u32 level=1);
CD3D9Driver* Driver;
//! Helper function for mipmap generation.
void copy16BitMipMap(char* src, char* tgt,
const s32 srcWidth, const s32 srcHeight,
const s32 width, const s32 height,
const s32 pitchsrc, const s32 pitchtgt) const;
D3DFORMAT InternalFormat;
//! Helper function for mipmap generation.
void copy32BitMipMap(char* src, char* tgt,
const s32 srcWidth, const s32 srcHeight,
const s32 width, const s32 height,
const s32 pitchsrc, const s32 pitchtgt) const;
void* LockData;
u32 LockLevel;
//! set Pitch based on the d3d format
void setPitch(D3DFORMAT d3dformat);
bool AutoGenerateMipMaps;
IDirect3DDevice9* Device;
IDirect3DTexture9* Texture;
IDirect3DCubeTexture9* CubeTexture;
IDirect3DSurface9* RTTSurface;
CD3D9Driver* Driver;
u32 MipLevelLocked;
bool HardwareMipMaps;
bool IsCompressed;
};
}
}
} // end namespace video
} // end namespace irr
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
#endif // __C_DIRECTX9_TEXTURE_H_INCLUDED__
#endif
#endif
......@@ -83,8 +83,6 @@ public:
tmpImage = &Image;
}
Pitch = (*tmpImage)[0]->getPitch();
glGenTextures(1, &TextureName);
const COGLCoreTexture* prevTexture = Driver->getCacheHandler()->getTextureCache().get(0);
......@@ -143,6 +141,8 @@ public:
OriginalSize = size;
Size = OriginalSize;
Pitch = Size.Width * IImage::getBitsPerPixelFromFormat(ColorFormat) / 8;
Driver->getColorFormatParameters(ColorFormat, InternalFormat, PixelFormat, PixelType, &Converter);
glGenTextures(1, &TextureName);
......@@ -284,7 +284,7 @@ public:
Driver->getCacheHandler()->getTextureCache().set(0, prevTexture);
if (LockLevel == 0)
regenerateMipMapLevels(LockImage->getMipMapsData());
regenerateMipMapLevels(0);
}
LockImage->drop();
......@@ -433,6 +433,8 @@ protected:
}
Size = Size.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT));
Pitch = Size.Width * IImage::getBitsPerPixelFromFormat(ColorFormat) / 8;
}
void uploadTexture(bool initTexture, u32 layer, u32 level, void* data)
......@@ -485,7 +487,7 @@ protected:
}
else
{
u32 dataSize = IImage::getDataSizeFromFormat(ColorFormat, Size.Width, height);
u32 dataSize = IImage::getDataSizeFromFormat(ColorFormat, width, height);
switch (TextureType)
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment