Page 1 of 1

Bugfix: AutoRenderingSurface + Linux + AMD

Posted: Mon Dec 03, 2012 03:59
by Jabberwocky
02/12/2012 21:43:37 (Std) ********************************************************************************
02/12/2012 21:43:37 (Std) * -------- START OF ESSENTIAL SECTION TO BE POSTED ON THE FORUM -------- *
02/12/2012 21:43:37 (Std) ********************************************************************************
02/12/2012 21:43:37 (Std) ---- Version 0.7.6 (Build: Nov 6 2012 GNU/Linux g++ 4.6.3 32 bit) ----
02/12/2012 21:43:37 (Std) ---- Renderer module is: CEGUI::OgreRenderer - Official OGRE based 2nd generation renderer module. ----
02/12/2012 21:43:37 (Std) ---- XML Parser module is: CEGUI::TinyXMLParser - Official tinyXML based parser module for CEGUI ----
02/12/2012 21:43:37 (Std) ---- Image Codec module is: OgreImageCodec - Integrated ImageCodec using the Ogre engine. ----
02/12/2012 21:43:37 (Std) ---- Scripting module is: None ----


I'm porting my game to linux. I use the CEGUIOgreRenderer. I noticed some texture corruption in CEGUI.

Examples:

Image

Image

Additional notes:
  • This only occurs on linux, using an AMD video card. (Ubuntu 12.04 + Radeon HD 7770)
  • There is no texture corruption on windows, nor linux+NVIDIA geforce card

I figured out the corruption only occurred where I was using the AutoRenderingSurface property.
I've added some code to clear the associated texture when it is created, and it fixes the problem on my system.
I wanted to share my solution here.

File: CEGUIOgreTextureTarget.cpp
Function: OgreTextureTarget::declareRenderSize
Code, added to bottom of function:

Code: Select all

    // clear the texture
    // - appears to be necessary on Linux + AMD Radeon cards or else AutoRenderingSurface textures show corruption
    //   in areas not drawn to.
    Ogre::HardwarePixelBufferSharedPtr pTexBuf = rttTex->getBuffer();
    pTexBuf->lock( Ogre::HardwareBuffer::HBL_DISCARD );
    memset( pTexBuf->getCurrentLock().data, 0x00, pTexBuf->getSizeInBytes() );
    pTexBuf->unlock();


Full function source:

Code: Select all

void OgreTextureTarget::declareRenderSize(const Size& sz)
{
    // exit if current size is enough
    if ((d_area.getWidth() >= sz.d_width) && (d_area.getHeight() >=sz.d_height))
        return;

    Ogre::TexturePtr rttTex = Ogre::TextureManager::getSingleton().createManual(
        OgreTexture::getUniqueName(),
        Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
        Ogre::TEX_TYPE_2D, sz.d_width, sz.d_height, 1, 0, Ogre::PF_A8R8G8B8,
        Ogre::TU_RENDERTARGET);

    d_renderTarget = rttTex->getBuffer()->getRenderTarget();

    Rect init_area(
        Vector2(0, 0),
        Size(d_renderTarget->getWidth(), d_renderTarget->getHeight())
    );

    setArea(init_area);

    // delete viewport and reset ptr so a new one is generated.  This is
    // required because we have changed d_renderTarget so need a new VP also.
    delete d_viewport;
    d_viewport = 0;

    // because Texture takes ownership, the act of setting the new ogre texture
    // also ensures any previous ogre texture is released.
    d_CEGUITexture->setOgreTexture(rttTex, true);

    clear();
   
    // clear the texture
    // - appears to be necessary on Linux + AMD Radeon cards or else AutoRenderingSurface textures show corruption
    //   in areas not drawn to.
    Ogre::HardwarePixelBufferSharedPtr pTexBuf = rttTex->getBuffer();
    pTexBuf->lock( Ogre::HardwareBuffer::HBL_DISCARD );
    memset( pTexBuf->getCurrentLock().data, 0x00, pTexBuf->getSizeInBytes() );
    pTexBuf->unlock();
}