Commit 9ce8dd86 authored by hybrid's avatar hybrid

Fix issues with mipmap locking under OpenGL. For some reason, the texture was...

Fix issues with mipmap locking under OpenGL. For some reason, the texture was wrongly flipped, though correctly rendered. Test cases added and fixed for OpenGL driver, all others were correctly working.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@3760 dfc29bdd-3216-0410-991c-e03cc46cb475
parent cbc8f224
......@@ -421,34 +421,41 @@ void* COpenGLTexture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel)
glGetIntegerv(GL_TEXTURE_BINDING_2D, &tmpTexture);
glBindTexture(GL_TEXTURE_2D, TextureName);
// we need to flip textures vertical
// however, it seems that this does not hold for mipmap
// textures, for unknown reasons.
// allows to read pixels in top-to-bottom order
#ifdef GL_MESA_pack_invert
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_MESA_pack_invert))
#ifdef GL_MESA_pack_invert
if (!mipmapLevel && Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_MESA_pack_invert))
glPixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
#endif
#endif
// download GPU data as ARGB8 to pixels;
glGetTexImage(GL_TEXTURE_2D, mipmapLevel, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels);
#ifdef GL_MESA_pack_invert
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_MESA_pack_invert))
glPixelStorei(GL_PACK_INVERT_MESA, GL_FALSE);
else
#endif
if (!mipmapLevel)
{
// opengl images are horizontally flipped, so we have to fix that here.
const s32 pitch=image->getPitch();
u8* p2 = pixels + (image->getDimension().Height - 1) * pitch;
u8* tmpBuffer = new u8[pitch];
for (u32 i=0; i < image->getDimension().Height; i += 2)
#ifdef GL_MESA_pack_invert
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_MESA_pack_invert))
glPixelStorei(GL_PACK_INVERT_MESA, GL_FALSE);
else
#endif
{
memcpy(tmpBuffer, pixels, pitch);
memcpy(pixels, p2, pitch);
memcpy(p2, tmpBuffer, pitch);
pixels += pitch;
p2 -= pitch;
// opengl images are horizontally flipped, so we have to fix that here.
const s32 pitch=image->getPitch();
u8* p2 = pixels + (image->getDimension().Height - 1) * pitch;
u8* tmpBuffer = new u8[pitch];
for (u32 i=0; i < image->getDimension().Height; i += 2)
{
memcpy(tmpBuffer, pixels, pitch);
memcpy(pixels, p2, pitch);
memcpy(p2, tmpBuffer, pitch);
pixels += pitch;
p2 -= pitch;
}
delete [] tmpBuffer;
}
delete [] tmpBuffer;
}
image->unlock();
......
......@@ -6,14 +6,81 @@
using namespace irr;
using namespace core;
//! check miplevels by visual test
static bool renderMipLevels(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();
scene::ISceneNode* n = smgr->addCubeSceneNode();
scene::ISceneNode* n2 = smgr->addCubeSceneNode(10, 0, -1, core::vector3df(20,0,30), core::vector3df(0,45,0));
// we use a main texture with blue on top and red below
// and mipmap with pink on top and cyan below
if (n && n2)
{
// create the texture and miplevels with distinct colors
u32 texData[16*16];
for (u32 i=0; i<16*16; ++i)
texData[i]=(i<8*16?0xff0000ff:0xffff0000);
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)
{
for (u32 i=0; i<j; ++i)
{
u32 val=(i<j/2?0xffff00ff:0xff00ffff);
for (u32 k=0; k<j; ++k)
mipdata[index++]=val;
}
}
video::ITexture* tex = driver->addTexture("miptest", image, mipdata);
if (!tex)
// is probably an error in the mipdata handling
return false;
else
{
n->setMaterialFlag(video::EMF_LIGHTING, false);
n->setMaterialTexture(0, tex);
n2->setMaterialFlag(video::EMF_LIGHTING, false);
n2->setMaterialTexture(0, tex);
}
image->drop();
}
(void)smgr->addCameraSceneNode(0, core::vector3df(10,0,-30));
driver->beginScene(true, true, video::SColor(255,100,101,140));
smgr->drawAll();
driver->endScene();
bool result = takeScreenshotAndCompareAgainstReference(driver, "-renderMipmap.png");
if (!result)
logTestString("mipmap render failed.\n", driver->getName());
else
logTestString("Passed\n");
device->closeDevice();
device->run();
device->drop();
return result;
}
//! Tests locking miplevels
static bool lockAllMipLevels(video::E_DRIVER_TYPE driverType)
{
bool result=true;
IrrlichtDevice *device = createDevice( driverType, dimension2d<u32>(160, 120), 32);
if (!device)
return result; // Treat a failure to create a driver as benign; this saves a lot of #ifdefs
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();
......@@ -25,7 +92,7 @@ static bool lockAllMipLevels(video::E_DRIVER_TYPE driverType)
// create the texture and miplevels with distinct colors
u32 texData[16*16];
for (u32 i=0; i<16*16; ++i)
texData[i]=0xff0000ff;
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;
......@@ -35,7 +102,7 @@ static bool lockAllMipLevels(video::E_DRIVER_TYPE driverType)
for (u32 i=0; i<j; ++i)
{
for (u32 k=0; k<j; ++k)
mipdata[index++]=val;
mipdata[index++]=val-i;
}
}
......@@ -56,7 +123,7 @@ static bool lockAllMipLevels(video::E_DRIVER_TYPE driverType)
video::ITexture* tex = driver->findTexture("miptest");
video::SColor* bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, 0);
result &= (bits[0].color==0xff0000ff);
bool result = (bits[0].color==0xff0000ff);
tex->unlock();
bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, 1);
result &= (bits[0].color==0x00ff00ff);
......@@ -70,9 +137,24 @@ static bool lockAllMipLevels(video::E_DRIVER_TYPE driverType)
bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, 4);
result &= (bits[0].color==0x001212ff);
tex->unlock();
if (!result)
logTestString("mipmap lock after init with driver %ls failed.\n", driver->getName());
bits = (video::SColor*)tex->lock(video::ETLM_READ_WRITE, 3);
bits[0]=0xff00ff00;
bits[1]=0xff00ff00;
tex->unlock();
bits = (video::SColor*)tex->lock(video::ETLM_READ_WRITE, 4);
tex->unlock();
bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, 3);
result &= ((bits[0].color==0xff00ff00)&&(bits[2].color==0xc2c200fe));
tex->unlock();
if (!result)
logTestString("mipmap lock with driver %ls failed.\n", driver->getName());
logTestString("mipmap lock after mipmap write with driver %ls failed.\n", driver->getName());
else
logTestString("Passed\n");
device->closeDevice();
device->run();
......@@ -86,9 +168,17 @@ bool textureFeatures(void)
{
bool passed = true;
logTestString("OpenGL\n");
passed &= renderMipLevels(video::EDT_OPENGL);
passed &= lockAllMipLevels(video::EDT_OPENGL);
logTestString("Burnings Video\n");
passed &= renderMipLevels(video::EDT_BURNINGSVIDEO);
passed &= lockAllMipLevels(video::EDT_BURNINGSVIDEO);
logTestString("Direct3D9\n");
passed &= renderMipLevels(video::EDT_DIRECT3D9);
passed &= lockAllMipLevels(video::EDT_DIRECT3D9);
logTestString("Direct3D8\n");
passed &= renderMipLevels(video::EDT_DIRECT3D8);
passed &= lockAllMipLevels(video::EDT_DIRECT3D8);
return passed;
......
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