Commit d9c9de51 authored by hybrid's avatar hybrid

Add a new texture lock mode for write-only access. The lock method has changed...

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-e03cc46cb475
parent 54ff5773
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,6 +390,8 @@ void* COpenGLTexture::lock(bool readOnly, u32 mipmapLevel)
if (!image)
return 0;
if (mode != ETLM_WRITE_ONLY)
{
u8* pixels = static_cast<u8*>(image->lock());
if (!pixels)
return 0;
......@@ -400,19 +402,19 @@ void* COpenGLTexture::lock(bool readOnly, u32 mipmapLevel)
glBindTexture(GL_TEXTURE_2D, TextureName);
// allows to read pixels in top-to-bottom order
#ifdef GL_MESA_pack_invert
#ifdef GL_MESA_pack_invert
if (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
#ifdef GL_MESA_pack_invert
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_MESA_pack_invert))
glPixelStorei(GL_PACK_INVERT_MESA, GL_FALSE);
else
#endif
#endif
{
// opengl images are horizontally flipped, so we have to fix that here.
const s32 pitch=image->getPitch();
......@@ -433,6 +435,7 @@ void* COpenGLTexture::lock(bool readOnly, u32 mipmapLevel)
//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();
......
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