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) 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 - Speedup deleting of particles
- Add function IParticleSystemSceneNode::clearParticles - Add function IParticleSystemSceneNode::clearParticles
......
...@@ -70,6 +70,21 @@ enum E_TEXTURE_CREATION_FLAG ...@@ -70,6 +70,21 @@ enum E_TEXTURE_CREATION_FLAG
ETCF_FORCE_32_BIT_DO_NOT_USE = 0x7fffffff 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. //! Interface of a Video Driver dependent Texture.
/** An ITexture is created by an IVideoDriver by using IVideoDriver::addTexture /** An ITexture is created by an IVideoDriver by using IVideoDriver::addTexture
...@@ -99,14 +114,17 @@ public: ...@@ -99,14 +114,17 @@ public:
unlocked. unlocked.
The size of the i-th mipmap level is defined as max(getSize().Width>>i,1) The size of the i-th mipmap level is defined as max(getSize().Width>>i,1)
and max(getSize().Height>>i,1) and max(getSize().Height>>i,1)
\param readOnly Specifies that no changes to the locked texture are \param mode Specifies what kind of changes to the locked texture are
made. Unspecified behavior will arise if still write access happens. 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. \param mipmapLevel Number of the mipmapLevel to lock. 0 is main texture.
Non-existing levels will silently fail and return 0. Non-existing levels will silently fail and return 0.
\return Returns a pointer to the pixel data. The format of the pixel can \return Returns a pointer to the pixel data. The format of the pixel can
be determined by using getColorFormat(). 0 is returned, if be determined by using getColorFormat(). 0 is returned, if
the texture cannot be locked. */ 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. //! Unlock function. Must be called after a lock() to the texture.
/** One should avoid to call unlock more than once before another lock. /** One should avoid to call unlock more than once before another lock.
......
...@@ -205,7 +205,7 @@ bool CD3D8Texture::copyTexture(video::IImage* image) ...@@ -205,7 +205,7 @@ bool CD3D8Texture::copyTexture(video::IImage* image)
//! lock function //! lock function
void* CD3D8Texture::lock(bool readOnly, u32 mipmapLevel) void* CD3D8Texture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel)
{ {
if (!Texture) if (!Texture)
return 0; return 0;
...@@ -215,7 +215,7 @@ void* CD3D8Texture::lock(bool readOnly, u32 mipmapLevel) ...@@ -215,7 +215,7 @@ void* CD3D8Texture::lock(bool readOnly, u32 mipmapLevel)
D3DLOCKED_RECT rect; D3DLOCKED_RECT rect;
if(!IsRenderTarget) 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)) if (FAILED(hr))
{ {
os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR); os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR);
......
...@@ -38,7 +38,7 @@ public: ...@@ -38,7 +38,7 @@ public:
virtual ~CD3D8Texture(); virtual ~CD3D8Texture();
//! lock function //! 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 //! unlock function
virtual void unlock(); virtual void unlock();
......
...@@ -383,7 +383,7 @@ bool CD3D9Texture::copyTexture(IImage * image) ...@@ -383,7 +383,7 @@ bool CD3D9Texture::copyTexture(IImage * image)
//! lock function //! lock function
void* CD3D9Texture::lock(bool readOnly, u32 mipmapLevel) void* CD3D9Texture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel)
{ {
if (!Texture) if (!Texture)
return 0; return 0;
...@@ -393,7 +393,7 @@ void* CD3D9Texture::lock(bool readOnly, u32 mipmapLevel) ...@@ -393,7 +393,7 @@ void* CD3D9Texture::lock(bool readOnly, u32 mipmapLevel)
D3DLOCKED_RECT rect; D3DLOCKED_RECT rect;
if(!IsRenderTarget) 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)) if (FAILED(hr))
{ {
os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR); os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR);
...@@ -429,7 +429,7 @@ void* CD3D9Texture::lock(bool readOnly, u32 mipmapLevel) ...@@ -429,7 +429,7 @@ void* CD3D9Texture::lock(bool readOnly, u32 mipmapLevel)
os::Printer::log("Could not lock DIRECT3D9 Texture", "Data copy failed.", ELL_ERROR); os::Printer::log("Could not lock DIRECT3D9 Texture", "Data copy failed.", ELL_ERROR);
return 0; 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)) if(FAILED(hr))
{ {
os::Printer::log("Could not lock DIRECT3D9 Texture", "LockRect failed.", ELL_ERROR); os::Printer::log("Could not lock DIRECT3D9 Texture", "LockRect failed.", ELL_ERROR);
......
...@@ -42,7 +42,7 @@ public: ...@@ -42,7 +42,7 @@ public:
virtual ~CD3D9Texture(); virtual ~CD3D9Texture();
//! lock function //! 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 //! unlock function
virtual void unlock(); virtual void unlock();
......
...@@ -1946,7 +1946,7 @@ Cursor CIrrDeviceLinux::TextureToMonochromeCursor(irr::video::ITexture * tex, co ...@@ -1946,7 +1946,7 @@ Cursor CIrrDeviceLinux::TextureToMonochromeCursor(irr::video::ITexture * tex, co
u32 bytesPerPixel = video::IImage::getBitsPerPixelFromFormat(format) / 8; u32 bytesPerPixel = video::IImage::getBitsPerPixelFromFormat(format) / 8;
u32 bytesLeftGap = sourceRect.UpperLeftCorner.X * bytesPerPixel; u32 bytesLeftGap = sourceRect.UpperLeftCorner.X * bytesPerPixel;
u32 bytesRightGap = tex->getPitch() - sourceRect.LowerRightCorner.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(); data += sourceRect.UpperLeftCorner.Y*tex->getPitch();
for ( s32 y = 0; y < sourceRect.getHeight(); ++y ) for ( s32 y = 0; y < sourceRect.getHeight(); ++y )
{ {
...@@ -2022,7 +2022,7 @@ Cursor CIrrDeviceLinux::TextureToARGBCursor(irr::video::ITexture * tex, const co ...@@ -2022,7 +2022,7 @@ Cursor CIrrDeviceLinux::TextureToARGBCursor(irr::video::ITexture * tex, const co
u32 bytesLeftGap = sourceRect.UpperLeftCorner.X * bytesPerPixel; u32 bytesLeftGap = sourceRect.UpperLeftCorner.X * bytesPerPixel;
u32 bytesRightGap = tex->getPitch() - sourceRect.LowerRightCorner.X * bytesPerPixel; u32 bytesRightGap = tex->getPitch() - sourceRect.LowerRightCorner.X * bytesPerPixel;
XcursorPixel* target = image->pixels; 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(); data += sourceRect.UpperLeftCorner.Y*tex->getPitch();
for ( s32 y = 0; y < sourceRect.getHeight(); ++y ) for ( s32 y = 0; y < sourceRect.getHeight(); ++y )
{ {
......
...@@ -1574,7 +1574,7 @@ HCURSOR CIrrDeviceWin32::TextureToCursor(HWND hwnd, irr::video::ITexture * tex, ...@@ -1574,7 +1574,7 @@ HCURSOR CIrrDeviceWin32::TextureToCursor(HWND hwnd, irr::video::ITexture * tex,
u32 bytesPerPixel = video::IImage::getBitsPerPixelFromFormat(format) / 8; u32 bytesPerPixel = video::IImage::getBitsPerPixelFromFormat(format) / 8;
u32 bytesLeftGap = sourceRect.UpperLeftCorner.X * bytesPerPixel; u32 bytesLeftGap = sourceRect.UpperLeftCorner.X * bytesPerPixel;
u32 bytesRightGap = tex->getPitch() - sourceRect.LowerRightCorner.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(); data += sourceRect.UpperLeftCorner.Y*tex->getPitch();
for ( s32 y = 0; y < sourceRect.getHeight(); ++y ) for ( s32 y = 0; y < sourceRect.getHeight(); ++y )
{ {
......
...@@ -1086,7 +1086,7 @@ void CNullDriver::makeColorKeyTexture(video::ITexture* texture, ...@@ -1086,7 +1086,7 @@ void CNullDriver::makeColorKeyTexture(video::ITexture* texture,
if (texture->getColorFormat() == ECF_A1R5G5B5) if (texture->getColorFormat() == ECF_A1R5G5B5)
{ {
u16 *p = (u16*)texture->lock(true); u16 *p = (u16*)texture->lock(ETLM_READ_ONLY);
if (!p) if (!p)
{ {
...@@ -1102,7 +1102,7 @@ void CNullDriver::makeColorKeyTexture(video::ITexture* texture, ...@@ -1102,7 +1102,7 @@ void CNullDriver::makeColorKeyTexture(video::ITexture* texture,
} }
else else
{ {
u32 *p = (u32*)texture->lock(true); u32 *p = (u32*)texture->lock(ETLM_READ_ONLY);
if (!p) if (!p)
{ {
...@@ -1442,7 +1442,7 @@ IImage* CNullDriver::createImage(ITexture* texture, const core::position2d<s32>& ...@@ -1442,7 +1442,7 @@ IImage* CNullDriver::createImage(ITexture* texture, const core::position2d<s32>&
{ {
if ((pos==core::position2di(0,0)) && (size == texture->getSize())) 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(); texture->unlock();
return image; return image;
} }
...@@ -1457,7 +1457,7 @@ IImage* CNullDriver::createImage(ITexture* texture, const core::position2d<s32>& ...@@ -1457,7 +1457,7 @@ IImage* CNullDriver::createImage(ITexture* texture, const core::position2d<s32>&
core::clamp(static_cast<u32>(size.Height), 0u, texture->getSize().Height))); core::clamp(static_cast<u32>(size.Height), 0u, texture->getSize().Height)));
if (!clamped.isValid()) if (!clamped.isValid())
return 0; return 0;
u8* src = static_cast<u8*>(texture->lock(true)); u8* src = static_cast<u8*>(texture->lock(ETLM_READ_ONLY));
if (!src) if (!src)
return 0; return 0;
IImage* image = new CImage(texture->getColorFormat(), clamped.getSize()); IImage* image = new CImage(texture->getColorFormat(), clamped.getSize());
......
...@@ -720,7 +720,7 @@ namespace video ...@@ -720,7 +720,7 @@ namespace video
{ {
SDummyTexture(const io::path& name) : ITexture(name), size(0,0) {}; 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 void unlock(){}
virtual const core::dimension2d<u32>& getOriginalSize() const { return size; } virtual const core::dimension2d<u32>& getOriginalSize() const { return size; }
virtual const core::dimension2d<u32>& getSize() 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) ...@@ -354,11 +354,11 @@ void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData, u32 level)
//! lock function //! 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 // store info about which image is locked
IImage* image = (mipmapLevel==0)?Image:MipImage; IImage* image = (mipmapLevel==0)?Image:MipImage;
ReadOnlyLock |= readOnly; ReadOnlyLock |= (mode==ETLM_READ_ONLY);
MipLevelStored = mipmapLevel; MipLevelStored = mipmapLevel;
// if data not available or might have changed on GPU download it // if data not available or might have changed on GPU download it
...@@ -390,48 +390,51 @@ void* COpenGLTexture::lock(bool readOnly, u32 mipmapLevel) ...@@ -390,48 +390,51 @@ void* COpenGLTexture::lock(bool readOnly, u32 mipmapLevel)
if (!image) if (!image)
return 0; return 0;
u8* pixels = static_cast<u8*>(image->lock()); if (mode != ETLM_WRITE_ONLY)
if (!pixels) {
return 0; u8* pixels = static_cast<u8*>(image->lock());
if (!pixels)
// we need to keep the correct texture bound later on return 0;
GLint tmpTexture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &tmpTexture); // we need to keep the correct texture bound later on
glBindTexture(GL_TEXTURE_2D, TextureName); GLint tmpTexture;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &tmpTexture);
// allows to read pixels in top-to-bottom order glBindTexture(GL_TEXTURE_2D, TextureName);
#ifdef GL_MESA_pack_invert
if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_MESA_pack_invert)) // allows to read pixels in top-to-bottom order
glPixelStorei(GL_PACK_INVERT_MESA, GL_TRUE); #ifdef GL_MESA_pack_invert
#endif if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_MESA_pack_invert))
glPixelStorei(GL_PACK_INVERT_MESA, GL_TRUE);
#endif
// download GPU data as ARGB8 to pixels; // download GPU data as ARGB8 to pixels;
glGetTexImage(GL_TEXTURE_2D, mipmapLevel, GL_BGRA_EXT, GL_UNSIGNED_BYTE, 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)) if (Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_MESA_pack_invert))
glPixelStorei(GL_PACK_INVERT_MESA, GL_FALSE); glPixelStorei(GL_PACK_INVERT_MESA, GL_FALSE);
else else
#endif #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); // opengl images are horizontally flipped, so we have to fix that here.
memcpy(pixels, p2, pitch); const s32 pitch=image->getPitch();
memcpy(p2, tmpBuffer, pitch); u8* p2 = pixels + (image->getDimension().Height - 1) * pitch;
pixels += pitch; u8* tmpBuffer = new u8[pitch];
p2 -= 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();
}
image->unlock();
//reset old bound texture //reset old bound texture
glBindTexture(GL_TEXTURE_2D, tmpTexture); glBindTexture(GL_TEXTURE_2D, tmpTexture);
}
} }
return image->lock(); return image->lock();
} }
......
...@@ -57,7 +57,7 @@ public: ...@@ -57,7 +57,7 @@ public:
virtual ~COpenGLTexture(); virtual ~COpenGLTexture();
//! lock function //! 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 //! unlock function
virtual void unlock(); virtual void unlock();
......
...@@ -58,7 +58,7 @@ CSoftwareTexture::~CSoftwareTexture() ...@@ -58,7 +58,7 @@ CSoftwareTexture::~CSoftwareTexture()
//! lock function //! lock function
void* CSoftwareTexture::lock(bool readOnly, u32 mipmapLevel) void* CSoftwareTexture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel)
{ {
return Image->lock(); return Image->lock();
} }
......
...@@ -28,7 +28,7 @@ public: ...@@ -28,7 +28,7 @@ public:
virtual ~CSoftwareTexture(); virtual ~CSoftwareTexture();
//! lock function //! 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 //! unlock function
virtual void unlock(); virtual void unlock();
......
...@@ -36,7 +36,7 @@ public: ...@@ -36,7 +36,7 @@ public:
virtual ~CSoftwareTexture2(); virtual ~CSoftwareTexture2();
//! lock function //! 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) if (Flags & GEN_MIPMAP)
MipMapLOD=mipmapLevel; MipMapLOD=mipmapLevel;
......
...@@ -101,7 +101,7 @@ namespace video ...@@ -101,7 +101,7 @@ namespace video
// select mignify and magnify ( lodLevel ) // select mignify and magnify ( lodLevel )
//SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS //SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS
it->lodLevel = lodLevel; 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 )); core::s32_clamp ( lodLevel + SOFTWARE_DRIVER_2_MIPMAPPING_LOD_BIAS, 0, SOFTWARE_DRIVER_2_MIPMAPPING_MAX - 1 ));
// prepare for optimal fixpoint // prepare for optimal fixpoint
......
...@@ -55,19 +55,19 @@ static bool lockAllMipLevels(video::E_DRIVER_TYPE driverType) ...@@ -55,19 +55,19 @@ static bool lockAllMipLevels(video::E_DRIVER_TYPE driverType)
driver->endScene(); driver->endScene();
video::ITexture* tex = driver->findTexture("miptest"); 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); result |= (bits[0].color==0xff0000ff);
tex->unlock(); tex->unlock();
bits = (video::SColor*)tex->lock(true, 1); bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, 1);
result |= (bits[0].color==0x00ff00ff); result |= (bits[0].color==0x00ff00ff);
tex->unlock(); tex->unlock();
bits = (video::SColor*)tex->lock(true, 2); bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, 2);
result |= (bits[0].color==0x0000ffff); result |= (bits[0].color==0x0000ffff);
tex->unlock(); tex->unlock();
bits = (video::SColor*)tex->lock(true, 3); bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, 3);
result |= (bits[0].color==0xc2c200ff); result |= (bits[0].color==0xc2c200ff);
tex->unlock(); tex->unlock();
bits = (video::SColor*)tex->lock(true, 4); bits = (video::SColor*)tex->lock(video::ETLM_READ_ONLY, 4);
result |= (bits[0].color==0x001212ff); result |= (bits[0].color==0x001212ff);
tex->unlock(); 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