Add a new texture lock mode for write-only access. The lock method has changed for this. Support is only implemented under OpenGL so far.
git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@3510 dfc29bdd-3216-0410-991c-e03cc46cb475master
parent
54ff5773af
commit
d9c9de5158
|
@ -1,5 +1,7 @@
|
|||
Changes in 1.8 (??.0?.2010)
|
||||
|
||||
- API change: Added write only lock mode for textures. The lock method has changed the signature and uses an enum parameter now instead of a bool. The default is still to lock for read/write (previously 'false'). The old 'true' value should be replaced by ETLM_READ_ONLY.
|
||||
|
||||
- Speedup deleting of particles
|
||||
|
||||
- Add function IParticleSystemSceneNode::clearParticles
|
||||
|
|
|
@ -70,6 +70,21 @@ enum E_TEXTURE_CREATION_FLAG
|
|||
ETCF_FORCE_32_BIT_DO_NOT_USE = 0x7fffffff
|
||||
};
|
||||
|
||||
//! Enum for the mode for texture locking. Read-Only, write-only or read/write.
|
||||
enum E_TEXTURE_LOCK_MODE
|
||||
{
|
||||
//! The default mode. Texture can be read and written to.
|
||||
ETLM_READ_WRITE = 0,
|
||||
|
||||
//! Read only. The texture is downloaded, but not uploaded again.
|
||||
/** Often used to read back shader generated textures. */
|
||||
ETLM_READ_ONLY,
|
||||
|
||||
//! Write only. The texture is not downloaded and might be uninitialised.
|
||||
/** The updated texture is uploaded to the GPU.
|
||||
Used for initialising the shader from the CPU. */
|
||||
ETLM_WRITE_ONLY
|
||||
};
|
||||
|
||||
//! Interface of a Video Driver dependent Texture.
|
||||
/** An ITexture is created by an IVideoDriver by using IVideoDriver::addTexture
|
||||
|
@ -99,14 +114,17 @@ public:
|
|||
unlocked.
|
||||
The size of the i-th mipmap level is defined as max(getSize().Width>>i,1)
|
||||
and max(getSize().Height>>i,1)
|
||||
\param readOnly Specifies that no changes to the locked texture are
|
||||
made. Unspecified behavior will arise if still write access happens.
|
||||
\param mode Specifies what kind of changes to the locked texture are
|
||||
allowed. Unspecified behavior will arise if texture is written in read
|
||||
only mode or read from in write only mode.
|
||||
Support for this feature depends on the driver, so don't rely on the
|
||||
texture being write-protected when locking with read-only, etc.
|
||||
\param mipmapLevel Number of the mipmapLevel to lock. 0 is main texture.
|
||||
Non-existing levels will silently fail and return 0.
|
||||
\return Returns a pointer to the pixel data. The format of the pixel can
|
||||
be determined by using getColorFormat(). 0 is returned, if
|
||||
the texture cannot be locked. */
|
||||
virtual void* lock(bool readOnly = false, u32 mipmapLevel=0) = 0;
|
||||
virtual void* lock(E_TEXTURE_LOCK_MODE mode=ETLM_READ_WRITE, u32 mipmapLevel=0) = 0;
|
||||
|
||||
//! Unlock function. Must be called after a lock() to the texture.
|
||||
/** One should avoid to call unlock more than once before another lock.
|
||||
|
|
|
@ -205,7 +205,7 @@ bool CD3D8Texture::copyTexture(video::IImage* image)
|
|||
|
||||
|
||||
//! lock function
|
||||
void* CD3D8Texture::lock(bool readOnly, u32 mipmapLevel)
|
||||
void* CD3D8Texture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel)
|
||||
{
|
||||
if (!Texture)
|
||||
return 0;
|
||||
|
@ -215,7 +215,7 @@ void* CD3D8Texture::lock(bool readOnly, u32 mipmapLevel)
|
|||
D3DLOCKED_RECT rect;
|
||||
if(!IsRenderTarget)
|
||||
{
|
||||
hr = Texture->LockRect(mipmapLevel, &rect, 0, readOnly?D3DLOCK_READONLY:0);
|
||||
hr = Texture->LockRect(mipmapLevel, &rect, 0, (mode==ETLM_READ_ONLY)?D3DLOCK_READONLY:0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR);
|
||||
|
|
|
@ -38,7 +38,7 @@ public:
|
|||
virtual ~CD3D8Texture();
|
||||
|
||||
//! lock function
|
||||
virtual void* lock(bool readOnly = false, u32 mipmapLevel=0);
|
||||
virtual void* lock(E_TEXTURE_LOCK_MODE mode=ETLM_READ_WRITE, u32 mipmapLevel=0);
|
||||
|
||||
//! unlock function
|
||||
virtual void unlock();
|
||||
|
|
|
@ -383,7 +383,7 @@ bool CD3D9Texture::copyTexture(IImage * image)
|
|||
|
||||
|
||||
//! lock function
|
||||
void* CD3D9Texture::lock(bool readOnly, u32 mipmapLevel)
|
||||
void* CD3D9Texture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel)
|
||||
{
|
||||
if (!Texture)
|
||||
return 0;
|
||||
|
@ -393,7 +393,7 @@ void* CD3D9Texture::lock(bool readOnly, u32 mipmapLevel)
|
|||
D3DLOCKED_RECT rect;
|
||||
if(!IsRenderTarget)
|
||||
{
|
||||
hr = Texture->LockRect(mipmapLevel, &rect, 0, readOnly?D3DLOCK_READONLY:0);
|
||||
hr = Texture->LockRect(mipmapLevel, &rect, 0, (mode==ETLM_READ_ONLY)?D3DLOCK_READONLY:0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR);
|
||||
|
@ -429,7 +429,7 @@ void* CD3D9Texture::lock(bool readOnly, u32 mipmapLevel)
|
|||
os::Printer::log("Could not lock DIRECT3D9 Texture", "Data copy failed.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
hr = RTTSurface->LockRect(&rect, 0, readOnly?D3DLOCK_READONLY:0);
|
||||
hr = RTTSurface->LockRect(&rect, 0, (mode==ETLM_READ_ONLY)?D3DLOCK_READONLY:0);
|
||||
if(FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture", "LockRect failed.", ELL_ERROR);
|
||||
|
|
|
@ -42,7 +42,7 @@ public:
|
|||
virtual ~CD3D9Texture();
|
||||
|
||||
//! lock function
|
||||
virtual void* lock(bool readOnly = false, u32 mipmapLevel=0);
|
||||
virtual void* lock(E_TEXTURE_LOCK_MODE mode=ETLM_READ_WRITE, u32 mipmapLevel=0);
|
||||
|
||||
//! unlock function
|
||||
virtual void unlock();
|
||||
|
|
|
@ -1946,7 +1946,7 @@ Cursor CIrrDeviceLinux::TextureToMonochromeCursor(irr::video::ITexture * tex, co
|
|||
u32 bytesPerPixel = video::IImage::getBitsPerPixelFromFormat(format) / 8;
|
||||
u32 bytesLeftGap = sourceRect.UpperLeftCorner.X * bytesPerPixel;
|
||||
u32 bytesRightGap = tex->getPitch() - sourceRect.LowerRightCorner.X * bytesPerPixel;
|
||||
const u8* data = (const u8*)tex->lock(true, 0);
|
||||
const u8* data = (const u8*)tex->lock(ETLM_READ_ONLY, 0);
|
||||
data += sourceRect.UpperLeftCorner.Y*tex->getPitch();
|
||||
for ( s32 y = 0; y < sourceRect.getHeight(); ++y )
|
||||
{
|
||||
|
@ -2022,7 +2022,7 @@ Cursor CIrrDeviceLinux::TextureToARGBCursor(irr::video::ITexture * tex, const co
|
|||
u32 bytesLeftGap = sourceRect.UpperLeftCorner.X * bytesPerPixel;
|
||||
u32 bytesRightGap = tex->getPitch() - sourceRect.LowerRightCorner.X * bytesPerPixel;
|
||||
XcursorPixel* target = image->pixels;
|
||||
const u8* data = (const u8*)tex->lock(true, 0);
|
||||
const u8* data = (const u8*)tex->lock(ETLM_READ_ONLY, 0);
|
||||
data += sourceRect.UpperLeftCorner.Y*tex->getPitch();
|
||||
for ( s32 y = 0; y < sourceRect.getHeight(); ++y )
|
||||
{
|
||||
|
|
|
@ -1574,7 +1574,7 @@ HCURSOR CIrrDeviceWin32::TextureToCursor(HWND hwnd, irr::video::ITexture * tex,
|
|||
u32 bytesPerPixel = video::IImage::getBitsPerPixelFromFormat(format) / 8;
|
||||
u32 bytesLeftGap = sourceRect.UpperLeftCorner.X * bytesPerPixel;
|
||||
u32 bytesRightGap = tex->getPitch() - sourceRect.LowerRightCorner.X * bytesPerPixel;
|
||||
const u8* data = (const u8*)tex->lock(true, 0);
|
||||
const u8* data = (const u8*)tex->lock(video::ETLM_READ_ONLY, 0);
|
||||
data += sourceRect.UpperLeftCorner.Y*tex->getPitch();
|
||||
for ( s32 y = 0; y < sourceRect.getHeight(); ++y )
|
||||
{
|
||||
|
|
|
@ -1086,7 +1086,7 @@ void CNullDriver::makeColorKeyTexture(video::ITexture* texture,
|
|||
|
||||
if (texture->getColorFormat() == ECF_A1R5G5B5)
|
||||
{
|
||||
u16 *p = (u16*)texture->lock(true);
|
||||
u16 *p = (u16*)texture->lock(ETLM_READ_ONLY);
|
||||
|
||||
if (!p)
|
||||
{
|
||||
|
@ -1102,7 +1102,7 @@ void CNullDriver::makeColorKeyTexture(video::ITexture* texture,
|
|||
}
|
||||
else
|
||||
{
|
||||
u32 *p = (u32*)texture->lock(true);
|
||||
u32 *p = (u32*)texture->lock(ETLM_READ_ONLY);
|
||||
|
||||
if (!p)
|
||||
{
|
||||
|
@ -1442,7 +1442,7 @@ IImage* CNullDriver::createImage(ITexture* texture, const core::position2d<s32>&
|
|||
{
|
||||
if ((pos==core::position2di(0,0)) && (size == texture->getSize()))
|
||||
{
|
||||
IImage* image = new CImage(texture->getColorFormat(), size, texture->lock(true), false);
|
||||
IImage* image = new CImage(texture->getColorFormat(), size, texture->lock(ETLM_READ_ONLY), false);
|
||||
texture->unlock();
|
||||
return image;
|
||||
}
|
||||
|
@ -1457,7 +1457,7 @@ IImage* CNullDriver::createImage(ITexture* texture, const core::position2d<s32>&
|
|||
core::clamp(static_cast<u32>(size.Height), 0u, texture->getSize().Height)));
|
||||
if (!clamped.isValid())
|
||||
return 0;
|
||||
u8* src = static_cast<u8*>(texture->lock(true));
|
||||
u8* src = static_cast<u8*>(texture->lock(ETLM_READ_ONLY));
|
||||
if (!src)
|
||||
return 0;
|
||||
IImage* image = new CImage(texture->getColorFormat(), clamped.getSize());
|
||||
|
|
|
@ -720,7 +720,7 @@ namespace video
|
|||
{
|
||||
SDummyTexture(const io::path& name) : ITexture(name), size(0,0) {};
|
||||
|
||||
virtual void* lock(bool readOnly = false, u32 mipmapLevel=0) { return 0; };
|
||||
virtual void* lock(E_TEXTURE_LOCK_MODE mode=ETLM_READ_WRITE, u32 mipmapLevel=0) { return 0; };
|
||||
virtual void unlock(){}
|
||||
virtual const core::dimension2d<u32>& getOriginalSize() const { return size; }
|
||||
virtual const core::dimension2d<u32>& getSize() const { return size; }
|
||||
|
|
|
@ -354,11 +354,11 @@ void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData, u32 level)
|
|||
|
||||
|
||||
//! lock function
|
||||
void* COpenGLTexture::lock(bool readOnly, u32 mipmapLevel)
|
||||
void* COpenGLTexture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel)
|
||||
{
|
||||
// store info about which image is locked
|
||||
IImage* image = (mipmapLevel==0)?Image:MipImage;
|
||||
ReadOnlyLock |= readOnly;
|
||||
ReadOnlyLock |= (mode==ETLM_READ_ONLY);
|
||||
MipLevelStored = mipmapLevel;
|
||||
|
||||
// if data not available or might have changed on GPU download it
|
||||
|
@ -390,48 +390,51 @@ void* COpenGLTexture::lock(bool readOnly, u32 mipmapLevel)
|
|||
if (!image)
|
||||
return 0;
|
||||
|
||||
u8* pixels = static_cast<u8*>(image->lock());
|
||||
if (!pixels)
|
||||
return 0;
|
||||
|
||||
// we need to keep the correct texture bound later on
|
||||
GLint tmpTexture;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &tmpTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, TextureName);
|
||||
|
||||
// allows to read pixels in top-to-bottom order
|
||||
#ifdef GL_MESA_pack_invert
|
||||
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_MESA_pack_invert))
|
||||
glPixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
|
||||
#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 (mode != ETLM_WRITE_ONLY)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
image->unlock();
|
||||
u8* pixels = static_cast<u8*>(image->lock());
|
||||
if (!pixels)
|
||||
return 0;
|
||||
|
||||
//reset old bound texture
|
||||
glBindTexture(GL_TEXTURE_2D, tmpTexture);
|
||||
// we need to keep the correct texture bound later on
|
||||
GLint tmpTexture;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &tmpTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, TextureName);
|
||||
|
||||
// allows to read pixels in top-to-bottom order
|
||||
#ifdef GL_MESA_pack_invert
|
||||
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_MESA_pack_invert))
|
||||
glPixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
|
||||
#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
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
image->unlock();
|
||||
|
||||
//reset old bound texture
|
||||
glBindTexture(GL_TEXTURE_2D, tmpTexture);
|
||||
}
|
||||
}
|
||||
return image->lock();
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ public:
|
|||
virtual ~COpenGLTexture();
|
||||
|
||||
//! lock function
|
||||
virtual void* lock(bool readOnly=false, u32 mipmapLevel=0);
|
||||
virtual void* lock(E_TEXTURE_LOCK_MODE mode=ETLM_READ_WRITE, u32 mipmapLevel=0);
|
||||
|
||||
//! unlock function
|
||||
virtual void unlock();
|
||||
|
|
|
@ -58,7 +58,7 @@ CSoftwareTexture::~CSoftwareTexture()
|
|||
|
||||
|
||||
//! lock function
|
||||
void* CSoftwareTexture::lock(bool readOnly, u32 mipmapLevel)
|
||||
void* CSoftwareTexture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel)
|
||||
{
|
||||
return Image->lock();
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
virtual ~CSoftwareTexture();
|
||||
|
||||
//! lock function
|
||||
virtual void* lock(bool readOnly = false, u32 mipmapLevel=0);
|
||||
virtual void* lock(E_TEXTURE_LOCK_MODE mode=ETLM_READ_WRITE, u32 mipmapLevel=0);
|
||||
|
||||
//! unlock function
|
||||
virtual void unlock();
|
||||
|
|
|
@ -36,7 +36,7 @@ public:
|
|||
virtual ~CSoftwareTexture2();
|
||||
|
||||
//! lock function
|
||||
virtual void* lock(bool readOnly = false, u32 mipmapLevel=0)
|
||||
virtual void* lock(E_TEXTURE_LOCK_MODE mode=ETLM_READ_WRITE, u32 mipmapLevel=0)
|
||||
{
|
||||
if (Flags & GEN_MIPMAP)
|
||||
MipMapLOD=mipmapLevel;
|
||||
|
|
|
@ -101,7 +101,7 @@ namespace video
|
|||
// select mignify and magnify ( lodLevel )
|
||||
//SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS
|
||||
it->lodLevel = lodLevel;
|
||||
it->data = (tVideoSample*) it->Texture->lock(true,
|
||||
it->data = (tVideoSample*) it->Texture->lock(ETLM_READ_ONLY,
|
||||
core::s32_clamp ( lodLevel + SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS, 0, SOFTWARE_DRIVER_2_MIPMAPPING_MAX - 1 ));
|
||||
|
||||
// prepare for optimal fixpoint
|
||||
|
|
|
@ -55,19 +55,19 @@ static bool lockAllMipLevels(video::E_DRIVER_TYPE driverType)
|
|||
driver->endScene();
|
||||
|
||||
video::ITexture* tex = driver->findTexture("miptest");
|
||||
video::SColor* bits = (video::SColor*)tex->lock(true, 0);
|
||||
video::SColor* bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, 0);
|
||||
result |= (bits[0].color==0xff0000ff);
|
||||
tex->unlock();
|
||||
bits = (video::SColor*)tex->lock(true, 1);
|
||||
bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, 1);
|
||||
result |= (bits[0].color==0x00ff00ff);
|
||||
tex->unlock();
|
||||
bits = (video::SColor*)tex->lock(true, 2);
|
||||
bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, 2);
|
||||
result |= (bits[0].color==0x0000ffff);
|
||||
tex->unlock();
|
||||
bits = (video::SColor*)tex->lock(true, 3);
|
||||
bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, 3);
|
||||
result |= (bits[0].color==0xc2c200ff);
|
||||
tex->unlock();
|
||||
bits = (video::SColor*)tex->lock(true, 4);
|
||||
bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, 4);
|
||||
result |= (bits[0].color==0x001212ff);
|
||||
tex->unlock();
|
||||
|
||||
|
|
Loading…
Reference in New Issue