Merging r5892 through r5916 from trunk to ogl-es branch

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@5917 dfc29bdd-3216-0410-991c-e03cc46cb475
master
cutealien 2019-11-13 10:52:47 +00:00 committed by MoNTE48
parent d5e0914d30
commit 1e6c870ba2
47 changed files with 755 additions and 172 deletions

View File

@ -66,6 +66,9 @@ namespace video
EMF_NORMALIZE_NORMALS = 0x1000,
//! Access to all layers texture wrap settings. Overwrites separate layer settings.
/** Note that if you want to change TextureWrapU, TextureWrapV, TextureWrapW
independently, then you can't work with this flag, but will have to set the variables
directly. */
EMF_TEXTURE_WRAP = 0x2000,
//! AntiAliasing mode

View File

@ -25,7 +25,7 @@ namespace io
ERFT_LIMIT_READ_FILE = MAKE_IRR_ID('r','l','i','m'),
//! Unknown type
EFIT_UNKNOWN = MAKE_IRR_ID('u','n','k','n'),
EFIT_UNKNOWN = MAKE_IRR_ID('u','n','k','n')
};
} // end namespace io
} // end namespace irr

View File

@ -187,10 +187,68 @@ public:
{
}
//! Get mipmaps data.
void* getMipMapsData() const
//! Get the mipmap size for this image for a certain mipmap level
/** level 0 will be full image size. Every further level is half the size.
Doesn't care if the image actually has mipmaps, just which size would be needed. */
core::dimension2du getMipMapsSize(u32 mipmapLevel) const
{
return MipMapsData;
return getMipMapsSize(Size, mipmapLevel);
}
//! Calculate mipmap size for a certain level
/** level 0 will be full image size. Every further level is half the size. */
static core::dimension2du getMipMapsSize(const core::dimension2du& sizeLevel0, u32 mipmapLevel)
{
core::dimension2du result(sizeLevel0);
u32 i=0;
while (i != mipmapLevel)
{
if (result.Width>1)
result.Width >>= 1;
if (result.Height>1)
result.Height>>=1;
++i;
if ( result.Width == 1 && result.Height == 1 && i < mipmapLevel )
return core::dimension2du(0,0);
}
return result;
}
//! Get mipmaps data.
/** Note that different mip levels are just behind each other in memory block.
So if you just get level 1 you also have the data for all other levels.
There is no level 0 - use getData to get the original image data.
*/
void* getMipMapsData(irr::u32 mipLevel=1) const
{
if ( MipMapsData && mipLevel > 0)
{
size_t dataSize = 0;
core::dimension2du mipSize(Size);
u32 i = 1; // We want the start of data for this level, not end.
while (i != mipLevel)
{
if (mipSize.Width > 1)
mipSize.Width >>= 1;
if (mipSize.Height > 1)
mipSize.Height >>= 1;
dataSize += getDataSizeFromFormat(Format, mipSize.Width, mipSize.Height);
++i;
if ( mipSize.Width == 1 && mipSize.Height == 1 && i < mipLevel)
return 0;
}
return MipMapsData + dataSize;
}
return 0;
}
//! Set mipmaps data.
@ -258,19 +316,24 @@ public:
virtual void setPixel(u32 x, u32 y, const SColor &color, bool blend = false ) = 0;
//! Copies the image into the target, scaling the image to fit
/** NOTE: mipmaps are ignored */
virtual void copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT format=ECF_A8R8G8B8, u32 pitch=0) =0;
//! Copies the image into the target, scaling the image to fit
/** NOTE: mipmaps are ignored */
virtual void copyToScaling(IImage* target) =0;
//! copies this surface into another
/** NOTE: mipmaps are ignored */
virtual void copyTo(IImage* target, const core::position2d<s32>& pos=core::position2d<s32>(0,0)) =0;
//! copies this surface into another
/** NOTE: mipmaps are ignored */
virtual void copyTo(IImage* target, const core::position2d<s32>& pos, const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect=0) =0;
//! copies this surface into another, using the alpha mask and cliprect and a color to add with
/** \param combineAlpha - When true then combine alpha channels. When false replace target image alpha with source image alpha.
/** NOTE: mipmaps are ignored
\param combineAlpha - When true then combine alpha channels. When false replace target image alpha with source image alpha.
*/
virtual void copyToWithAlpha(IImage* target, const core::position2d<s32>& pos,
const core::rect<s32>& sourceRect, const SColor &color,
@ -278,6 +341,7 @@ public:
bool combineAlpha=false) =0;
//! copies this surface into another, scaling it to fit, applying a box filter
/** NOTE: mipmaps are ignored */
virtual void copyToScalingBoxFilter(IImage* target, s32 bias = 0, bool blend = false) = 0;
//! fills the surface with given color
@ -453,7 +517,7 @@ public:
switch(format)
{
case ECF_R16:
case ECF_R16F:
case ECF_G16R16F:
case ECF_A16B16G16R16F:
case ECF_R32F:

View File

@ -18,7 +18,7 @@ namespace video
{
//! Enumeration flags telling the video driver in which format textures should be created.
//! Enumeration flags used to tell the video driver with setTextureCreationFlag in which format textures should be created.
enum E_TEXTURE_CREATION_FLAG
{
/** Forces the driver to create 16 bit textures always, independent of
@ -36,6 +36,7 @@ enum E_TEXTURE_CREATION_FLAG
which format the file on disk has. Please note that some drivers (like
the software device) will ignore this, because they are only able to
create and use 16 bit textures.
Default is true.
When using this flag, it does not make sense to use the flags
ETCF_ALWAYS_16_BIT, ETCF_OPTIMIZED_FOR_QUALITY, or
ETCF_OPTIMIZED_FOR_SPEED at the same time.
@ -59,7 +60,9 @@ enum E_TEXTURE_CREATION_FLAG
Not all texture formats are affected (usually those up to ECF_A8R8G8B8). */
ETCF_OPTIMIZED_FOR_SPEED = 0x00000008,
/** Automatically creates mip map levels for the textures. */
/** Creates textures with mipmap levels.
If disabled textures can not have mipmaps.
Default is true. */
ETCF_CREATE_MIP_MAPS = 0x00000010,
/** Discard any alpha layer and use non-alpha color format.
@ -80,6 +83,20 @@ enum E_TEXTURE_CREATION_FLAG
*/
ETCF_ALLOW_MEMORY_COPY = 0x00000080,
//! Enable automatic updating mip maps when the base texture changes.
/** Default is true.
This flag is only used when ETCF_CREATE_MIP_MAPS is also enabled and if the driver supports it.
Please note:
- On D3D (and maybe older OGL?) you can no longer manually set mipmap data when enabled
(for example mips from image loading will be ignored).
- On D3D (and maybe older OGL?) texture locking for mipmap levels usually won't work anymore.
- On new OGL this flag is ignored.
- When disabled you do _not_ get hardware mipmaps on D3D, so mipmap generation can be slower.
- When disabled you can still update your mipmaps when the texture changed by manually calling regenerateMipMapLevels.
- You can still call regenerateMipMapLevels when this flag is enabled (it will be a hint on d3d to update mips immediately)
*/
ETCF_AUTO_GENERATE_MIP_MAPS = 0x00000100,
/** This flag is never used, it only forces the compiler to compile
these enumeration values to 32 bit. */
ETCF_FORCE_32_BIT_DO_NOT_USE = 0x7fffffff
@ -194,7 +211,8 @@ public:
//! Unlock function. Must be called after a lock() to the texture.
/** One should avoid to call unlock more than once before another lock.
The last locked mip level will be unlocked. */
The last locked mip level will be unlocked.
You may want to call regenerateMipMapLevels() after this when you changed any data. */
virtual void unlock() = 0;
//! Regenerates the mip map levels of the texture.
@ -204,8 +222,8 @@ public:
data. The data has to be a continuous pixel data for all mipmaps until
1x1 pixel. Each mipmap has to be half the width and height of the previous
level. At least one pixel will be always kept.
\param layer It informs a texture about layer which needs
mipmaps regeneration. */
\param layer It informs a texture about which cubemap or texture array layer
needs mipmap regeneration. */
virtual void regenerateMipMapLevels(void* data = 0, u32 layer = 0) = 0;
//! Get original size of the texture.

View File

@ -35,8 +35,11 @@ namespace video
u16 EnablePasses;
//! Global enable flag, overwritten by the SceneManager in each pass
/** The Scenemanager uses the EnablePass array and sets Enabled to
true if the Override material is enabled in the current pass. */
/** NOTE: This is generally _not_ set by users of the engine, but the
Scenemanager uses the EnablePass array and sets Enabled to true if the
Override material is enabled in the current pass.
As user you generally _only_ set EnablePasses.
The exception is when rendering without SceneManager but using draw calls in the VideoDriver. */
bool Enabled;
struct SMaterialTypeReplacement

View File

@ -1,81 +1,80 @@
// part of the Irrlicht Engine Shader example.
// Part of the Irrlicht Engine Shader example.
// These simple Direct3D9 pixel and vertex shaders will be loaded by the shaders
// example. Please note that these example shaders don't do anything really useful.
// example. Please note that these example shaders don't do anything really useful.
// They only demonstrate that shaders can be used in Irrlicht.
//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
float4x4 mWorldViewProj; // World * View * Projection transformation
float4x4 mInvWorld; // Inverted world matrix
float4x4 mTransWorld; // Transposed world matrix
float3 mLightPos; // Light position
float4 mLightColor; // Light color
float4x4 mWorldViewProj; // World * View * Projection transformation
float4x4 mInvWorld; // Inverted world matrix
float4x4 mTransWorld; // Transposed world matrix
float3 mLightPos; // Light position (actually just camera-pos in this case)
float4 mLightColor; // Light color
// Vertex shader output structure
struct VS_OUTPUT
{
float4 Position : POSITION; // vertex position
float4 Diffuse : COLOR0; // vertex diffuse color
float2 TexCoord : TEXCOORD0; // tex coords
float4 Position : POSITION; // vertex position
float4 Diffuse : COLOR0; // vertex diffuse color
float2 TexCoord : TEXCOORD0; // tex coords
};
VS_OUTPUT vertexMain( in float4 vPosition : POSITION,
in float3 vNormal : NORMAL,
float2 texCoord : TEXCOORD0 )
VS_OUTPUT vertexMain(in float4 vPosition : POSITION,
in float3 vNormal : NORMAL,
float2 texCoord : TEXCOORD0 )
{
VS_OUTPUT Output;
// transform position to clip space
// transform position to clip space
Output.Position = mul(vPosition, mWorldViewProj);
// transform normal
float3 normal = mul(vNormal, mInvWorld);
// renormalize normal
// transform normal somehow (NOTE: for the real vertex normal you would use an inverse-transpose world matrix instead of mInvWorld)
float3 normal = mul(float4(vNormal,0.0), mInvWorld);
// renormalize normal
normal = normalize(normal);
// position in world coodinates
// position in world coordinates (NOTE: not sure why transposed world is used instead of world?)
float3 worldpos = mul(mTransWorld, vPosition);
// calculate light vector, vtxpos - lightpos
float3 lightVector = worldpos - mLightPos;
// normalize light vector
// normalize light vector
lightVector = normalize(lightVector);
// calculate light color
// calculate light color
float3 tmp = dot(-lightVector, normal);
tmp = lit(tmp.x, tmp.y, 1.0);
tmp = mLightColor * tmp.y;
Output.Diffuse = float4(tmp.x, tmp.y, tmp.z, 0);
Output.TexCoord = texCoord;
return Output;
}
// Pixel shader output structure
struct PS_OUTPUT
{
float4 RGBColor : COLOR0; // Pixel color
float4 RGBColor : COLOR0; // Pixel color
};
sampler2D tex0;
sampler2D myTexture;
PS_OUTPUT pixelMain( float2 TexCoord : TEXCOORD0,
float4 Position : POSITION,
float4 Diffuse : COLOR0 )
{
PS_OUTPUT pixelMain(float2 TexCoord : TEXCOORD0,
float4 Position : POSITION,
float4 Diffuse : COLOR0 )
{
PS_OUTPUT Output;
float4 col = tex2D( tex0, TexCoord ); // sample color map
float4 col = tex2D( myTexture, TexCoord ); // sample color map
// multiply with diffuse and do other senseless operations
Output.RGBColor = Diffuse * col;
Output.RGBColor *= 4.0;

View File

@ -1,18 +1,25 @@
// Part of the Irrlicht Engine Shader example.
// Simple GLSL vertex shader
// Please note that these example shaders don't do anything really useful.
// They only demonstrate that shaders can be used in Irrlicht.
uniform mat4 mWorldViewProj;
uniform mat4 mInvWorld;
uniform mat4 mTransWorld;
uniform vec3 mLightPos;
uniform vec3 mLightPos; // actually just camera-pos in this case
uniform vec4 mLightColor;
void main(void)
{
gl_Position = mWorldViewProj * gl_Vertex;
// transform normal somehow (NOTE: for the real vertex normal you would use an inverse-transpose world matrix instead of mInvWorld)
vec4 normal = vec4(gl_Normal, 0.0);
normal = mInvWorld * normal;
normal = normalize(normal);
// (NOTE: not sure why transposed world is used instead of world?)
vec4 worldpos = gl_Vertex * mTransWorld;
vec4 lightVector = worldpos - vec4(mLightPos,1.0);

View File

@ -57,7 +57,7 @@ namespace irr
if ((Texture != texture) || (CubeSurfaces != cubeSurfaces))
{
needSizeUpdate = true;
CubeSurfaces = cubeSurfaces;
CubeSurfaces = cubeSurfaces; // TODO: we can probably avoid some memory allocating/de-allocating if _only_ CubeSurfaces change.
if (texture.size() > Driver->ActiveRenderTarget.size())
{
@ -78,11 +78,7 @@ namespace irr
Surface.set_used(size);
for (u32 i = 0; i < Texture.size(); ++i)
{
if (Texture[i])
Texture[i]->drop();
}
core::array<ITexture*> prevTextures(Texture);
Texture.set_used(size);
@ -129,6 +125,12 @@ namespace irr
Texture[i] = 0;
}
}
for (u32 i = 0; i < prevTextures.size(); ++i)
{
if (prevTextures[i])
prevTextures[i]->drop();
}
}
// Set depth and stencil attachments.

View File

@ -17,7 +17,7 @@ namespace video
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), LockReadOnly(false), LockData(0), LockLayer(0),
AutoGenerateMipMaps(false), Device(0), Texture(0), CubeTexture(0), RTTSurface(0)
MipLevelLocked(0), HardwareMipMaps(false), Device(0), Texture(0), CubeTexture(0), RTTSurface(0)
{
#ifdef _DEBUG
setDebugName("CD3D9Texture");
@ -32,13 +32,13 @@ CD3D9Texture::CD3D9Texture(const io::path& name, const core::array<IImage*>& ima
DriverType = Driver->getDriverType();
HasMipMaps = Driver->getTextureCreationFlag(ETCF_CREATE_MIP_MAPS);
AutoGenerateMipMaps = Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE);
HardwareMipMaps = Driver->getTextureCreationFlag(ETCF_AUTO_GENERATE_MIP_MAPS) && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE);
getImageValues(image[0]);
DWORD flags = 0;
if (HasMipMaps && AutoGenerateMipMaps)
if (HasMipMaps && HardwareMipMaps)
{
LPDIRECT3D9 intf = Driver->getExposedVideoData().D3D9.D3D9;
D3DDISPLAYMODE d3ddm;
@ -47,7 +47,7 @@ CD3D9Texture::CD3D9Texture(const io::path& name, const core::array<IImage*>& ima
if (D3D_OK == intf->CheckDeviceFormat(Driver->Params.DisplayAdapter, D3DDEVTYPE_HAL, d3ddm.Format, D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, InternalFormat))
flags = D3DUSAGE_AUTOGENMIPMAP;
else
AutoGenerateMipMaps = false;
HardwareMipMaps = false;
}
HRESULT hr = 0;
@ -110,7 +110,7 @@ CD3D9Texture::CD3D9Texture(const io::path& name, const core::array<IImage*>& ima
}
for (u32 i = 0; i < tmpImage.size(); ++i)
uploadTexture(i, 0, tmpImage[i]->getData());
uploadTexture(tmpImage[i]->getData(), 0, i);
bool autoGenerateRequired = true;
@ -152,7 +152,7 @@ CD3D9Texture::CD3D9Texture(const io::path& name, const core::array<IImage*>& ima
CD3D9Texture::CD3D9Texture(CD3D9Driver* driver, const core::dimension2d<u32>& size, const io::path& name, E_TEXTURE_TYPE type, const ECOLOR_FORMAT format)
: ITexture(name, type), Driver(driver), InternalFormat(D3DFMT_UNKNOWN), LockReadOnly(false), LockData(0), LockLayer(0),
AutoGenerateMipMaps(false), Device(0), Texture(0), CubeTexture(0), RTTSurface(0)
MipLevelLocked(0), HardwareMipMaps(false), Device(0), Texture(0), CubeTexture(0), RTTSurface(0)
{
#ifdef _DEBUG
setDebugName("CD3D9Texture");
@ -208,6 +208,7 @@ void* CD3D9Texture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel, u32 layer, E
if (IImage::isCompressedFormat(ColorFormat))
return 0;
MipLevelLocked = mipmapLevel;
LockReadOnly = (mode == ETLM_READ_ONLY);
LockLayer = layer;
@ -218,13 +219,13 @@ void* CD3D9Texture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel, u32 layer, E
{
if (Texture)
{
hr = Texture->LockRect(0, &rect, 0, LockReadOnly ? D3DLOCK_READONLY : 0);
hr = Texture->LockRect(MipLevelLocked, &rect, 0, LockReadOnly ? D3DLOCK_READONLY : 0);
}
else if (CubeTexture)
{
_IRR_DEBUG_BREAK_IF(layer > 5)
hr = CubeTexture->LockRect(static_cast<_D3DCUBEMAP_FACES>(layer), 0, &rect, 0, LockReadOnly ? D3DLOCK_READONLY : 0);
hr = CubeTexture->LockRect(static_cast<_D3DCUBEMAP_FACES>(layer), MipLevelLocked, &rect, 0, LockReadOnly ? D3DLOCK_READONLY : 0);
}
else
{
@ -258,9 +259,9 @@ void* CD3D9Texture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel, u32 layer, E
IDirect3DSurface9 *surface = 0;
if (Texture)
hr = Texture->GetSurfaceLevel(0, &surface);
hr = Texture->GetSurfaceLevel(MipLevelLocked, &surface);
else if (CubeTexture)
hr = CubeTexture->GetCubeMapSurface(static_cast<_D3DCUBEMAP_FACES>(layer), 0, &surface);
hr = CubeTexture->GetCubeMapSurface(static_cast<_D3DCUBEMAP_FACES>(layer), MipLevelLocked, &surface);
if (FAILED(hr))
{
os::Printer::log("Could not lock DIRECT3D9 Texture", "Could not get surface.", ELL_ERROR);
@ -295,11 +296,11 @@ void CD3D9Texture::unlock()
{
if (Texture)
{
Texture->UnlockRect(0);
Texture->UnlockRect(MipLevelLocked);
}
else if (CubeTexture)
{
CubeTexture->UnlockRect(static_cast<_D3DCUBEMAP_FACES>(LockLayer), 0);
CubeTexture->UnlockRect(static_cast<_D3DCUBEMAP_FACES>(LockLayer), MipLevelLocked);
}
}
else if (RTTSurface)
@ -307,9 +308,6 @@ void CD3D9Texture::unlock()
RTTSurface->UnlockRect();
}
if (!LockReadOnly)
regenerateMipMapLevels(0, LockLayer);
LockReadOnly = false;
LockData = 0;
LockLayer = 0;
@ -317,10 +315,20 @@ void CD3D9Texture::unlock()
void CD3D9Texture::regenerateMipMapLevels(void* data, u32 layer)
{
if (!HasMipMaps || (!data && !AutoGenerateMipMaps) || (Size.Width <= 1 && Size.Height <= 1))
if (!HasMipMaps || (Size.Width <= 1 && Size.Height <= 1))
return;
if (data)
if ( HardwareMipMaps )
{
// Can't update with custom data with those unfortunately
// Also MSDN docs don't mention it, but GenerateMipSubLevels only works when AUTOGENMIPMAP is set.
// So we can't call this to get hardware mipmaps when not setting AUTOGENMIPMAP.
if (Texture)
Texture->GenerateMipSubLevels();
else if (CubeTexture)
CubeTexture->GenerateMipSubLevels();
}
else if (data)
{
u32 width = Size.Width;
u32 height = Size.Height;
@ -339,20 +347,195 @@ void CD3D9Texture::regenerateMipMapLevels(void* data, u32 layer)
dataSize = IImage::getDataSizeFromFormat(ColorFormat, width, height);
++level;
uploadTexture(layer, level, tmpData);
uploadTexture(tmpData, level, layer);
tmpData += dataSize;
} while (width != 1 || height != 1);
}
else
{
if (Texture)
Texture->GenerateMipSubLevels();
else if (CubeTexture)
CubeTexture->GenerateMipSubLevels();
createManualMipMaps(1);
}
}
void CD3D9Texture::copy16BitMipMap(char* src, char* tgt,
s32 width, s32 height,
s32 pitchsrc, s32 pitchtgt) const
{
for (s32 y=0; y<height; ++y)
{
for (s32 x=0; x<width; ++x)
{
u32 a=0, r=0, g=0, b=0;
for (s32 dy=0; dy<2; ++dy)
{
const s32 tgy = (y*2)+dy;
for (s32 dx=0; dx<2; ++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();
}
}
a /= 4;
r /= 4;
g /= 4;
b /= 4;
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;
}
}
}
void CD3D9Texture::copy32BitMipMap(char* src, char* tgt,
s32 width, s32 height,
s32 pitchsrc, s32 pitchtgt) const
{
for (s32 y=0; y<height; ++y)
{
for (s32 x=0; x<width; ++x)
{
u32 a=0, r=0, g=0, b=0;
SColor c;
for (s32 dy=0; dy<2; ++dy)
{
const s32 tgy = (y*2)+dy;
for (s32 dx=0; dx<2; ++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();
}
}
a /= 4;
r /= 4;
g /= 4;
b /= 4;
c.set(a, r, g, b);
*(u32*)(&tgt[(x*4)+(y*pitchtgt)]) = c.color;
}
}
}
bool CD3D9Texture::createManualMipMaps(u32 level)
{
if (level==0)
return true;
if (!Texture) //Manual mips for CubeTexture not supported yet
{
return true;
}
// manual mipmap generation
IDirect3DSurface9* upperSurface = 0;
IDirect3DSurface9* lowerSurface = 0;
// get upper level
HRESULT hr = Texture->GetSurfaceLevel(level-1, &upperSurface);
if (FAILED(hr) || !upperSurface)
{
os::Printer::log("Could not get upper surface level for mip map generation", ELL_WARNING);
return false;
}
// 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);
}
else
{
if ((upperDesc.Format == D3DFMT_A1R5G5B5) || (upperDesc.Format == D3DFMT_R5G6B5))
copy16BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits,
lowerDesc.Width, lowerDesc.Height,
upperlr.Pitch, lowerlr.Pitch);
else
if (upperDesc.Format == D3DFMT_A8R8G8B8)
copy32BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits,
lowerDesc.Width, lowerDesc.Height,
upperlr.Pitch, lowerlr.Pitch);
else
os::Printer::log("Unsupported mipmap format, cannot copy.", 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 createManualMipMaps(level+1);
}
IDirect3DBaseTexture9* CD3D9Texture::getDX9BaseTexture() const
{
return (Texture) ? static_cast<IDirect3DBaseTexture9*>(Texture) : static_cast<IDirect3DBaseTexture9*>(CubeTexture);
@ -489,7 +672,7 @@ void CD3D9Texture::getImageValues(const IImage* image)
if (IImage::isCompressedFormat(image->getColorFormat()))
{
AutoGenerateMipMaps = false;
HardwareMipMaps = false;
}
OriginalSize = image->getDimension();
@ -521,13 +704,13 @@ void CD3D9Texture::getImageValues(const IImage* image)
Pitch = Size.Width * IImage::getBitsPerPixelFromFormat(ColorFormat) / 8;
}
void CD3D9Texture::uploadTexture(u32 layer, u32 level, void* data)
void CD3D9Texture::uploadTexture(void* data, u32 mipmapLevel, u32 layer)
{
if (!data)
return;
u32 width = Size.Width >> level;
u32 height = Size.Height >> level;
u32 width = Size.Width >> mipmapLevel;
u32 height = Size.Height >> mipmapLevel;
u32 dataSize = IImage::getDataSizeFromFormat(ColorFormat, width, height);
@ -537,13 +720,13 @@ void CD3D9Texture::uploadTexture(u32 layer, u32 level, void* data)
if (Texture)
{
hr = Texture->LockRect(level, &lockRectangle, 0, 0);
hr = Texture->LockRect(mipmapLevel, &lockRectangle, 0, 0);
}
else if (CubeTexture)
{
_IRR_DEBUG_BREAK_IF(layer > 5)
hr = CubeTexture->LockRect(static_cast<_D3DCUBEMAP_FACES>(layer), level, &lockRectangle, 0, 0);
hr = CubeTexture->LockRect(static_cast<_D3DCUBEMAP_FACES>(layer), mipmapLevel, &lockRectangle, 0, 0);
}
if (FAILED(hr))
@ -556,11 +739,11 @@ void CD3D9Texture::uploadTexture(u32 layer, u32 level, void* data)
if (Texture)
{
hr = Texture->UnlockRect(level);
hr = Texture->UnlockRect(mipmapLevel);
}
else if (CubeTexture)
{
hr = CubeTexture->UnlockRect(static_cast<_D3DCUBEMAP_FACES>(layer), level);
hr = CubeTexture->UnlockRect(static_cast<_D3DCUBEMAP_FACES>(layer), mipmapLevel);
}
if (FAILED(hr))

View File

@ -53,7 +53,19 @@ private:
void getImageValues(const IImage* image);
void uploadTexture(u32 layer, u32 level, void* data);
void uploadTexture(void* data, u32 mipmapLevel, u32 layer);
//! Helper function for mipmap generation.
bool createManualMipMaps(u32 level);
//! Helper function for mipmap generation.
void copy16BitMipMap(char* src, char* tgt,
s32 width, s32 height, s32 pitchsrc, s32 pitchtgt) const;
//! Helper function for mipmap generation.
void copy32BitMipMap(char* src, char* tgt,
s32 width, s32 height, s32 pitchsrc, s32 pitchtgt) const;
CD3D9Driver* Driver;
@ -62,8 +74,9 @@ private:
bool LockReadOnly;
void* LockData;
u32 LockLayer;
u32 MipLevelLocked;
bool AutoGenerateMipMaps;
bool HardwareMipMaps;
IDirect3DDevice9* Device;
IDirect3DTexture9* Texture;

View File

@ -1122,7 +1122,8 @@ bool CIrrDeviceSDL::isWindowActive() const
return false;
}
#endif
return (SDL_GetAppState()&SDL_APPACTIVE) ? true : false;
const Uint8 appState = SDL_GetAppState();
return (appState&SDL_APPACTIVE && appState&SDL_APPINPUTFOCUS) ? true : false;
}

View File

@ -114,6 +114,7 @@ CNullDriver::CNullDriver(io::IFileSystem* io, const core::dimension2d<u32>& scre
setTextureCreationFlag(ETCF_ALWAYS_32_BIT, true);
setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, true);
setTextureCreationFlag(ETCF_AUTO_GENERATE_MIP_MAPS, true);
setTextureCreationFlag(ETCF_ALLOW_MEMORY_COPY, true);
ViewPort = core::rect<s32>(core::position2d<s32>(0,0), core::dimension2di(screenSize));

View File

@ -58,23 +58,18 @@ public:
DepthStencil->drop();
}
virtual void setTexture(const core::array<ITexture*>& texture, ITexture* depthStencil, const core::array<E_CUBE_SURFACE>& cubeSurfaces) _IRR_OVERRIDE_
virtual void setTexture(const core::array<ITexture*>& textures, ITexture* depthStencil, const core::array<E_CUBE_SURFACE>& cubeSurfaces) _IRR_OVERRIDE_
{
bool needSizeUpdate = false;
// Set color attachments.
if ((Texture != texture) || (CubeSurfaces != cubeSurfaces))
if ((Texture != textures) || (CubeSurfaces != cubeSurfaces))
{
needSizeUpdate = true;
CubeSurfaces = cubeSurfaces;
for (u32 i = 0; i < Texture.size(); ++i)
{
if (Texture[i])
Texture[i]->drop();
}
core::array<ITexture*> prevTextures(Texture);
if (texture.size() > static_cast<u32>(ColorAttachment))
if (textures.size() > static_cast<u32>(ColorAttachment))
{
core::stringc message = "This GPU supports up to ";
message += static_cast<u32>(ColorAttachment);
@ -83,11 +78,11 @@ public:
os::Printer::log(message.c_str(), ELL_WARNING);
}
Texture.set_used(core::min_(texture.size(), static_cast<u32>(ColorAttachment)));
Texture.set_used(core::min_(textures.size(), static_cast<u32>(ColorAttachment)));
for (u32 i = 0; i < Texture.size(); ++i)
{
TOpenGLTexture* currentTexture = (texture[i] && texture[i]->getDriverType() == DriverType) ? static_cast<TOpenGLTexture*>(texture[i]) : 0;
TOpenGLTexture* currentTexture = (textures[i] && textures[i]->getDriverType() == DriverType) ? static_cast<TOpenGLTexture*>(textures[i]) : 0;
GLuint textureID = 0;
@ -98,7 +93,7 @@ public:
if (textureID != 0)
{
Texture[i] = texture[i];
Texture[i] = textures[i];
Texture[i]->grab();
}
else
@ -107,6 +102,18 @@ public:
}
}
for (u32 i = 0; i < prevTextures.size(); ++i)
{
if (prevTextures[i])
prevTextures[i]->drop();
}
RequestTextureUpdate = true;
}
if (CubeSurfaces != cubeSurfaces)
{
CubeSurfaces = cubeSurfaces;
RequestTextureUpdate = true;
}

View File

@ -17,6 +17,11 @@
#include "CImage.h"
#include "CColorConverter.h"
// Check if GL version we compile with should have the glGenerateMipmap function.
#if defined(GL_VERSION_3_0) || defined(GL_ES_VERSION_2_0)
#define IRR_OPENGL_HAS_glGenerateMipmap
#endif
namespace irr
{
namespace video
@ -45,37 +50,49 @@ public:
bool IsCached;
};
COpenGLCoreTexture(const io::path& name, const core::array<IImage*>& image, E_TEXTURE_TYPE type, TOpenGLDriver* driver) : ITexture(name, type), Driver(driver), TextureType(GL_TEXTURE_2D),
COpenGLCoreTexture(const io::path& name, const core::array<IImage*>& images, E_TEXTURE_TYPE type, TOpenGLDriver* driver) : ITexture(name, type), Driver(driver), TextureType(GL_TEXTURE_2D),
TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_RGBA), PixelType(GL_UNSIGNED_BYTE), Converter(0), LockReadOnly(false), LockImage(0), LockLayer(0),
KeepImage(false), AutoGenerateMipMaps(false)
KeepImage(false), MipLevelStored(0), LegacyAutoGenerateMipMaps(false)
{
_IRR_DEBUG_BREAK_IF(image.size() == 0)
_IRR_DEBUG_BREAK_IF(images.size() == 0)
DriverType = Driver->getDriverType();
TextureType = TextureTypeIrrToGL(Type);
HasMipMaps = Driver->getTextureCreationFlag(ETCF_CREATE_MIP_MAPS);
AutoGenerateMipMaps = Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE);
KeepImage = Driver->getTextureCreationFlag(ETCF_ALLOW_MEMORY_COPY);
getImageValues(image[0]);
getImageValues(images[0]);
const core::array<IImage*>* tmpImage = &image;
const core::array<IImage*>* tmpImages = &images;
if (KeepImage || OriginalSize != Size || OriginalColorFormat != ColorFormat)
{
Image.set_used(image.size());
Images.set_used(images.size());
for (u32 i = 0; i < image.size(); ++i)
for (u32 i = 0; i < images.size(); ++i)
{
Image[i] = Driver->createImage(ColorFormat, Size);
Images[i] = Driver->createImage(ColorFormat, Size);
if (image[i]->getDimension() == Size)
image[i]->copyTo(Image[i]);
if (images[i]->getDimension() == Size)
images[i]->copyTo(Images[i]);
else
image[i]->copyToScaling(Image[i]);
images[i]->copyToScaling(Images[i]);
if ( images[i]->getMipMapsData() )
{
if ( OriginalSize == Size && OriginalColorFormat == ColorFormat )
{
Images[i]->setMipMapsData( images[i]->getMipMapsData(), false, true);
}
else
{
// TODO: handle at least mipmap with changing color format
os::Printer::log("COpenGLCoreTexture: Can't handle format changes for mipmap data. Mipmap data dropped", ELL_WARNING);
}
}
}
tmpImage = &Image;
tmpImages = &Images;
}
glGenTextures(1, &TextureName);
@ -86,7 +103,8 @@ public:
glTexParameteri(TextureType, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(TextureType, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
if (HasMipMaps && AutoGenerateMipMaps)
#ifdef GL_GENERATE_MIPMAP_HINT
if (HasMipMaps)
{
if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED))
glHint(GL_GENERATE_MIPMAP_HINT, GL_FASTEST);
@ -95,34 +113,36 @@ public:
else
glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE);
}
#if (defined(IRR_OPENGL_VERSION) && IRR_OPENGL_VERSION < 20) || (defined(IRR_OPENGL_ES_VERSION) && IRR_OPENGL_ES_VERSION < 20)
if (HasMipMaps)
glTexParameteri(TextureType, GL_GENERATE_MIPMAP, (AutoGenerateMipMaps) ? GL_TRUE : GL_FALSE);
#endif
for (u32 i = 0; i < (*tmpImage).size(); ++i)
uploadTexture(true, i, 0, (*tmpImage)[i]->getData());
bool autoGenerateRequired = true;
for (u32 i = 0; i < (*tmpImage).size(); ++i)
#if !defined(IRR_OPENGL_HAS_glGenerateMipmap) && defined(GL_GENERATE_MIPMAP)
if (HasMipMaps)
{
void* mipmapsData = (*tmpImage)[i]->getMipMapsData();
LegacyAutoGenerateMipMaps = Driver->getTextureCreationFlag(ETCF_AUTO_GENERATE_MIP_MAPS) &&
Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE);
glTexParameteri(TextureType, GL_GENERATE_MIPMAP, LegacyAutoGenerateMipMaps ? GL_TRUE : GL_FALSE);
}
#endif
if (autoGenerateRequired || mipmapsData)
for (u32 i = 0; i < (*tmpImages).size(); ++i)
uploadTexture(true, i, 0, (*tmpImages)[i]->getData());
if (HasMipMaps && !LegacyAutoGenerateMipMaps)
{
// Create mipmaps (either from image mipmaps or generate them)
for (u32 i = 0; i < (*tmpImages).size(); ++i)
{
void* mipmapsData = (*tmpImages)[i]->getMipMapsData();
regenerateMipMapLevels(mipmapsData, i);
if (!mipmapsData)
autoGenerateRequired = false;
}
}
if (!KeepImage)
{
for (u32 i = 0; i < Image.size(); ++i)
Image[i]->drop();
for (u32 i = 0; i < Images.size(); ++i)
Images[i]->drop();
Image.clear();
Images.clear();
}
@ -135,7 +155,7 @@ public:
: ITexture(name, type),
Driver(driver), TextureType(GL_TEXTURE_2D),
TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_RGBA), PixelType(GL_UNSIGNED_BYTE), Converter(0), LockReadOnly(false), LockImage(0), LockLayer(0), KeepImage(false),
AutoGenerateMipMaps(false)
MipLevelStored(0), LegacyAutoGenerateMipMaps(false)
{
DriverType = Driver->getDriverType();
TextureType = TextureTypeIrrToGL(Type);
@ -210,31 +230,39 @@ public:
if (LockImage)
LockImage->drop();
for (u32 i = 0; i < Image.size(); ++i)
Image[i]->drop();
for (u32 i = 0; i < Images.size(); ++i)
Images[i]->drop();
}
virtual void* lock(E_TEXTURE_LOCK_MODE mode = ETLM_READ_WRITE, u32 mipmapLevel=0, u32 layer = 0, E_TEXTURE_LOCK_FLAGS lockFlags = ETLF_FLIP_Y_UP_RTT) _IRR_OVERRIDE_
{
if (LockImage)
return LockImage->getData();
return getLockImageData(MipLevelStored);
if (IImage::isCompressedFormat(ColorFormat))
return 0;
LockReadOnly |= (mode == ETLM_READ_ONLY);
LockLayer = layer;
MipLevelStored = mipmapLevel;
if (KeepImage)
{
_IRR_DEBUG_BREAK_IF(LockLayer > Image.size())
_IRR_DEBUG_BREAK_IF(LockLayer > Images.size())
LockImage = Image[LockLayer];
LockImage->grab();
if ( mipmapLevel == 0 || (Images[LockLayer] && Images[LockLayer]->getMipMapsData(mipmapLevel)) )
{
LockImage = Images[LockLayer];
LockImage->grab();
}
}
else
if ( !LockImage )
{
LockImage = Driver->createImage(ColorFormat, Size);
core::dimension2d<u32> lockImageSize( IImage::getMipMapsSize(Size, MipLevelStored));
// note: we save mipmap data also in the image because IImage doesn't allow saving single mipmap levels to the mipmap data
LockImage = Driver->createImage(ColorFormat, lockImageSize);
if (LockImage && mode != ETLM_WRITE_ONLY)
{
@ -244,6 +272,7 @@ public:
IImage* tmpImage = LockImage; // not sure yet if the size required by glGetTexImage is always correct, if not we might have to allocate a different tmpImage and convert colors later on.
Driver->getCacheHandler()->getTextureCache().set(0, this);
Driver->testGLError(__LINE__);
GLenum tmpTextureType = TextureType;
@ -254,7 +283,8 @@ public:
tmpTextureType = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
}
glGetTexImage(tmpTextureType, 0, PixelFormat, PixelType, tmpImage->getData());
glGetTexImage(tmpTextureType, MipLevelStored, PixelFormat, PixelType, tmpImage->getData());
Driver->testGLError(__LINE__);
if (IsRenderTarget && lockFlags == ETLF_FLIP_Y_UP_RTT)
{
@ -339,11 +369,11 @@ public:
LockImage = 0;
}
}
Driver->testGLError(__LINE__);
}
Driver->testGLError(__LINE__);
return (LockImage) ? LockImage->getData() : 0;
return (LockImage) ? getLockImageData(MipLevelStored) : 0;
}
virtual void unlock() _IRR_OVERRIDE_
@ -356,11 +386,9 @@ public:
const COpenGLCoreTexture* prevTexture = Driver->getCacheHandler()->getTextureCache().get(0);
Driver->getCacheHandler()->getTextureCache().set(0, this);
uploadTexture(false, LockLayer, 0, LockImage->getData());
uploadTexture(false, LockLayer, MipLevelStored, getLockImageData(MipLevelStored));
Driver->getCacheHandler()->getTextureCache().set(0, prevTexture);
regenerateMipMapLevels(0, LockLayer);
}
LockImage->drop();
@ -372,7 +400,7 @@ public:
virtual void regenerateMipMapLevels(void* data = 0, u32 layer = 0) _IRR_OVERRIDE_
{
if (!HasMipMaps || (!data && !AutoGenerateMipMaps) || (Size.Width <= 1 && Size.Height <= 1))
if (!HasMipMaps || LegacyAutoGenerateMipMaps || (Size.Width <= 1 && Size.Height <= 1))
return;
const COpenGLCoreTexture* prevTexture = Driver->getCacheHandler()->getTextureCache().get(0);
@ -405,7 +433,8 @@ public:
}
else
{
#if (defined(IRR_OPENGL_VERSION) && IRR_OPENGL_VERSION >= 20) || (defined(IRR_OPENGL_ES_VERSION) && IRR_OPENGL_ES_VERSION >= 20)
#ifdef IRR_OPENGL_HAS_glGenerateMipmap
glEnable(GL_TEXTURE_2D); // Hack some ATI cards need this glEnable according to https://www.khronos.org/opengl/wiki/Common_Mistakes
Driver->irrGlGenerateMipmap(TextureType);
#endif
}
@ -429,6 +458,17 @@ public:
}
protected:
void * getLockImageData(irr::u32 miplevel) const
{
if ( KeepImage && MipLevelStored > 0
&& LockImage->getMipMapsData(MipLevelStored) )
{
return LockImage->getMipMapsData(MipLevelStored);
}
return LockImage->getData();
}
ECOLOR_FORMAT getBestColorFormat(ECOLOR_FORMAT format)
{
// We only try for to adapt "simple" formats
@ -489,7 +529,6 @@ protected:
if (IImage::isCompressedFormat(image->getColorFormat()))
{
KeepImage = false;
AutoGenerateMipMaps = false;
}
OriginalSize = image->getDimension();
@ -561,7 +600,7 @@ protected:
glTexImage2D(tmpTextureType, level, InternalFormat, width, height, 0, PixelFormat, PixelType, tmpData);
else
glTexSubImage2D(tmpTextureType, level, 0, 0, width, height, PixelFormat, PixelType, tmpData);
Driver->testGLError(__LINE__);
break;
default:
break;
@ -581,7 +620,7 @@ protected:
Driver->irrGlCompressedTexImage2D(tmpTextureType, level, InternalFormat, width, height, 0, dataSize, data);
else
Driver->irrGlCompressedTexSubImage2D(tmpTextureType, level, 0, 0, width, height, PixelFormat, dataSize, data);
Driver->testGLError(__LINE__);
break;
default:
break;
@ -617,9 +656,10 @@ protected:
u32 LockLayer;
bool KeepImage;
core::array<IImage*> Image;
core::array<IImage*> Images;
bool AutoGenerateMipMaps;
u8 MipLevelStored;
bool LegacyAutoGenerateMipMaps;
mutable SStatesCache StatesCache;
};

View File

@ -133,8 +133,7 @@ void CSoftwareRenderTarget::setTexture(const core::array<ITexture*>& texture, IT
{
if (Texture != texture)
{
if (Texture[0])
Texture[0]->drop();
ITexture* prevTexture = Texture[0];
bool textureDetected = false;
@ -150,6 +149,9 @@ void CSoftwareRenderTarget::setTexture(const core::array<ITexture*>& texture, IT
}
}
if (prevTexture)
prevTexture->drop();
if (!textureDetected)
Texture[0] = 0;
}

View File

@ -185,8 +185,7 @@ void CSoftwareRenderTarget2::setTexture(const core::array<ITexture*>& texture, I
{
if (Texture != texture)
{
if (Texture[0])
Texture[0]->drop();
ITexture* prevTexture = Texture[0];
bool textureDetected = false;
@ -202,6 +201,9 @@ void CSoftwareRenderTarget2::setTexture(const core::array<ITexture*>& texture, I
}
}
if (prevTexture)
prevTexture->drop();
if (!textureDetected)
Texture[0] = 0;
}

View File

@ -85,7 +85,7 @@ bool testWithDriver(video::E_DRIVER_TYPE driverType)
// we use character enumeration as we have more than 9 types
name.append(Type-scene::EPT_POINTS+'a');
name.append(".png");
result &= takeScreenshotAndCompareAgainstReference(driver, name.c_str(), 97.f);
result &= takeScreenshotAndCompareAgainstReference(driver, name.c_str(), 99.5f);
}
device->closeDevice();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -1,4 +1,4 @@
Tests finished. 1 test of 1 passed.
Tests finished. 70 tests of 70 passed.
Compiled as DEBUG
Test suite pass at GMT Thu May 30 10:19:28 2019
Test suite pass at GMT Tue Nov 12 17:06:08 2019

View File

@ -8,7 +8,6 @@ using namespace core;
namespace
{
//! check miplevels by visual test
bool renderMipLevels(video::E_DRIVER_TYPE driverType)
{
@ -26,8 +25,11 @@ bool renderMipLevels(video::E_DRIVER_TYPE driverType)
return true;
}
stabilizeScreenBackground(driver);
// Can't pass manual data with hardware mip maps (at least on d3d, not sure about older GL)
driver->setTextureCreationFlag(video::ETCF_AUTO_GENERATE_MIP_MAPS, false);
stabilizeScreenBackground(driver);
logTestString("Testing driver %ls\n", driver->getName());
scene::ISceneNode* n = smgr->addCubeSceneNode();
@ -53,7 +55,7 @@ bool renderMipLevels(video::E_DRIVER_TYPE driverType)
mipdata[index++]=val;
}
}
image->setMipMapsData(mipdata, false, true);
video::ITexture* tex = driver->addTexture("miptest", image);
if (!tex)
@ -75,7 +77,7 @@ bool renderMipLevels(video::E_DRIVER_TYPE driverType)
smgr->drawAll();
driver->endScene();
bool result = takeScreenshotAndCompareAgainstReference(driver, "-renderMipmap.png");
bool result = takeScreenshotAndCompareAgainstReference(driver, "-renderMipmap.png", 99.5);
if (!result)
logTestString("mipmap render failed.\n", driver->getName());
@ -89,8 +91,232 @@ bool renderMipLevels(video::E_DRIVER_TYPE driverType)
return result;
}
//! Tests locking miplevels
bool lockAllMipLevels(video::E_DRIVER_TYPE driverType)
{
IrrlichtDevice *device = createDevice( driverType, dimension2d<u32>(160, 120), 32);
if (!device)
return true; // Treat a failure to create a driver as benign; this saves a lot of #ifdefs
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager * smgr = device->getSceneManager();
if (!driver->queryFeature(video::EVDF_MIP_MAP))
{
device->closeDevice();
device->run();
device->drop();
return true;
}
// Can't lock surfaces for hardware mip-maps
driver->setTextureCreationFlag(video::ETCF_AUTO_GENERATE_MIP_MAPS, false);
stabilizeScreenBackground(driver);
logTestString("Testing driver %ls\n", driver->getName());
scene::ISceneNode* n = smgr->addCubeSceneNode();
if (n)
{
// create the texture and miplevels with distinct colors
u32 texData[16*16];
for (u32 i=0; i<16*16; ++i)
texData[i]=0xff0000ff-i;
video::IImage* image = driver->createImageFromData(video::ECF_A8R8G8B8, core::dimension2du(16,16), texData, false);
u32 mipdata[8*16];
u32 index=0;
for (u32 j=8; j>0; j/=2)
{
u32 val=(j==8?0x00ff00ff:(j==4?0x0000ffff:(j==2?0xc2c200ff:0x001212ff)));
for (u32 i=0; i<j; ++i)
{
for (u32 k=0; k<j; ++k)
mipdata[index++]=val-i;
}
}
video::ITexture* tex = driver->addTexture("miptest", image, mipdata);
if (!tex)
// is probably an error in the mipdata handling
return false;
else
n->setMaterialTexture(0, tex);
image->drop();
}
smgr->addCameraSceneNode();
driver->beginScene(true, true, video::SColor(255,100,101,140));
smgr->drawAll();
driver->endScene();
video::ITexture* tex = driver->findTexture("miptest");
video::SColor* bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, 0);
bool result = bits && (bits[0].color==0xff0000ff);
tex->unlock();
bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, 1);
result &= bits && (bits[0].color==0x00ff00ff);
tex->unlock();
bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, 2);
result &= bits && (bits[0].color==0x0000ffff);
tex->unlock();
bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, 3);
result &= bits && (bits[0].color==0xc2c200ff);
tex->unlock();
bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, 4);
result &= bits && (bits[0].color==0x001212ff);
tex->unlock();
if (!result)
logTestString("mipmap lock after init with driver %ls failed.\n", driver->getName());
// test with updating a lower level, and reading upper and lower
bits = (video::SColor*)tex->lock(video::ETLM_READ_WRITE, 3);
if ( bits )
{
bits[0]=0xff00ff00;
bits[1]=0xff00ff00;
}
tex->unlock();
bits = (video::SColor*)tex->lock(video::ETLM_READ_WRITE, 4);
result &= bits && (bits[0].color==0x001212ff);
tex->unlock();
bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, 3);
result &= bits && ((bits[0].color==0xff00ff00)&&(bits[2].color==0xc2c200fe));
tex->unlock();
if (!result)
logTestString("mipmap lock after mipmap write with driver %ls failed.\n", driver->getName());
// now test locking level 0
bits = (video::SColor*)tex->lock(video::ETLM_READ_WRITE, 0);
if ( bits )
{
bits[0]=0xff00ff00;
bits[1]=0xff00ff00;
}
tex->unlock();
bits = (video::SColor*)tex->lock(video::ETLM_READ_WRITE, 4);
result &= bits && (bits[0].color==0x001212ff);
tex->unlock();
bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, 0);
result &= bits && ((bits[0].color==0xff00ff00)&&(bits[2].color==0xff0000fd));
tex->unlock();
if (!result)
logTestString("mipmap lock at level 0 after mipmap write with driver %ls failed.\n", driver->getName());
else
logTestString("Passed\n");
device->closeDevice();
device->run();
device->drop();
return result;
}
//! Tests locking miplevels after texture was created with auto mipmap update
bool lockWithAutoMipmap(video::E_DRIVER_TYPE driverType)
{
IrrlichtDevice *device = createDevice( driverType, dimension2d<u32>(160, 120), 32);
if (!device)
return true; // Treat a failure to create a driver as benign; this saves a lot of #ifdefs
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager * smgr = device->getSceneManager();
if (!driver->queryFeature(video::EVDF_MIP_MAP))
{
device->closeDevice();
device->run();
device->drop();
return true;
}
// Can't lock surfaces for hardware mip-maps (sadly... so also can't test if it works like this)
driver->setTextureCreationFlag(video::ETCF_AUTO_GENERATE_MIP_MAPS, false);
stabilizeScreenBackground(driver);
logTestString("Testing driver %ls\n", driver->getName());
scene::ISceneNode* n = smgr->addCubeSceneNode();
if (n)
{
// create the texture
u32 texData[16*16];
for (u32 i=0; i<16*16; ++i)
texData[i]=0xff0000ff-i;
video::IImage* image = driver->createImageFromData(video::ECF_A8R8G8B8, core::dimension2du(16,16), texData, false);
video::ITexture* tex = driver->addTexture("miptest", image);
if (!tex)
return false;
else
n->setMaterialTexture(0, tex);
image->drop();
}
(void)smgr->addCameraSceneNode();
driver->beginScene(true, true, video::SColor(255,100,101,140));
smgr->drawAll();
driver->endScene();
video::ITexture* tex = driver->findTexture("miptest");
video::SColor* bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, 0);
bool result = bits && (bits[0].color==0xff0000ff);
tex->unlock();
if (!result)
logTestString("mipmap lock after init with driver %ls failed.\n", driver->getName());
// test with updating a lower level, and reading upper and lower
bits = (video::SColor*)tex->lock(video::ETLM_READ_WRITE, 3);
if ( bits )
{
bits[0]=0xff00ff00;
bits[1]=0xff00ff00;
}
tex->unlock();
// lock another texture just to invalidate caches in the driver
bits = (video::SColor*)tex->lock(video::ETLM_READ_WRITE, 4);
tex->unlock();
bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, 3);
result &= bits && ((bits[0].color==0xff00ff00)&&(bits[2].color!=0xff00ff00));
tex->unlock();
if (!result)
logTestString("mipmap lock after mipmap write with driver %ls failed.\n", driver->getName());
// now test locking level 0
bits = (video::SColor*)tex->lock(video::ETLM_READ_WRITE, 0);
if ( bits )
{
bits[0]=0x00ff00ff;
bits[1]=0x00ff00ff;
}
tex->unlock();
bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, 3);
result &= bits && ((bits[0].color==0xff00ff00)&&(bits[2].color!=0xff00ff00));
tex->unlock();
if (!result)
logTestString("mipmap lock at level 0 after mipmap write with driver %ls failed.\n", driver->getName());
else
logTestString("Passed\n");
device->closeDevice();
device->run();
device->drop();
return result;
}
//! Tests locking
bool lockTexture(video::E_DRIVER_TYPE driverType)
bool lockCubemapTexture(video::E_DRIVER_TYPE driverType)
{
IrrlichtDevice *device = createDevice( driverType, dimension2d<u32>(160, 120), 32);
if (!device)
@ -177,7 +403,12 @@ bool lockTexture(video::E_DRIVER_TYPE driverType)
for (u32 i = 0; i < 6; ++i)
{
bits = (video::SColor*)tex->lock(video::ETLM_READ_WRITE, i);
bits = (video::SColor*)tex->lock(video::ETLM_READ_WRITE, 0, i);
if ( !bits)
{
result = false;
break;
}
bits[0] = 0xff00ff00;
bits[1] = 0xff00ff00;
tex->unlock();
@ -185,7 +416,12 @@ bool lockTexture(video::E_DRIVER_TYPE driverType)
for (u32 i = 0; i < 6; ++i)
{
bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, i);
bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, 0, i);
if ( !bits)
{
result = false;
break;
}
u32 b0 = bits[0].color;
u32 b2 = bits[2].color;
@ -213,7 +449,9 @@ bool textureFeatures(void)
bool result = true;
TestWithAllDrivers(renderMipLevels);
TestWithAllDrivers(lockTexture);
TestWithAllDrivers(lockAllMipLevels);
TestWithAllDrivers(lockWithAutoMipmap);
TestWithAllDrivers(lockCubemapTexture);
return result;
}