COpenGLTexture with PBO

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
dalerank2
Posts: 121
Joined: Thu Dec 03, 2009 7:41 am

COpenGLTexture with PBO

Post by dalerank2 »

I needed to often update texture when draw chart. Through standard ITexture:: lock (unlock) is updated very slowly, for texture 1920х1080 time of updating near 300ms by GF8600. After profiling found out that is slow in glTexSubImage2D() int function COpenGLTexture::uploadTexture() where data are copying from system memory to video memory. Found solution with pixel buffer object. After modification speed rising, 26 to 200fps. With pbo driver use DMA mode for coping memory from system to video. it tested on Windows and Ubuntu. For dx I didn't look solution, that I work mainly at opengl.

Code: Select all

 
// Copyright (C) 2002-2010 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
 
#include "IrrCompileConfig.h"
 
#ifdef _IRR_COMPILE_WITH_OPENGL_
 
#include "irrTypes.h"
#include "COpenGLTexture.h"
#include "COpenGLDriver.h"
#include "os.h"
#include "CImage.h"
#include "CColorConverter.h"
 
#include <GL/glut.h>
#include "glext.h"
 
#include "irrString.h"
 
namespace irr
{
namespace video
{
 
//! constructor for usual textures
COpenGLTexture::COpenGLTexture(IImage* origImage, const io::path& name, void* mipmapData, COpenGLDriver* driver)
    : ITexture(name), ColorFormat(ECF_A8R8G8B8), Driver(driver), Image(0), MipImage(0),
    TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_BGRA_EXT),
    PixelType(GL_UNSIGNED_BYTE),
    IsRenderTarget(false), AutomaticMipmapUpdate(false),
    ReadOnlyLock(false), KeepImage(true), isPixelBufferObject(false)
{
    #ifdef _DEBUG
    setDebugName("COpenGLTexture");
    #endif
 
    HasMipMaps = Driver->getTextureCreationFlag(ETCF_CREATE_MIP_MAPS);
    getImageValues(origImage);
 
    glGenTextures(1, &TextureName);
 
    if (ImageSize==TextureSize)
    {
        Image = new CImage(ColorFormat, ImageSize);
        origImage->copyTo(Image);
    }
    else
    {
        Image = new CImage(ColorFormat, TextureSize);
        // scale texture
        origImage->copyToScaling(Image);
    }
    uploadTexture(true, mipmapData);
    if (!KeepImage)
    {
        Image->drop();
        Image=0;
    }
}
 
 
//! constructor for basic setup (only for derived classes)
COpenGLTexture::COpenGLTexture(const io::path& name, COpenGLDriver* driver)
    : ITexture(name), ColorFormat(ECF_A8R8G8B8), Driver(driver), Image(0), MipImage(0),
    TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_BGRA_EXT),
    PixelType(GL_UNSIGNED_BYTE),
    HasMipMaps(true), IsRenderTarget(false), AutomaticMipmapUpdate(false),
    ReadOnlyLock(false), KeepImage(true)
{
    #ifdef _DEBUG
    setDebugName("COpenGLTexture");
    #endif
}
 
 
//! destructor
COpenGLTexture::~COpenGLTexture()
{
    if (TextureName)
        glDeleteTextures(1, &TextureName);
    if (Image)
        Image->drop();
    if(isPixelBufferObject)
        glDeleteBuffersARB(1, &pboId);
}
 
 
//! Choose best matching color format, based on texture creation flags
ECOLOR_FORMAT COpenGLTexture::getBestColorFormat(ECOLOR_FORMAT format)
{
    ECOLOR_FORMAT destFormat = ECF_A8R8G8B8;
    switch (format)
    {
        case ECF_A1R5G5B5:
            if (!Driver->getTextureCreationFlag(ETCF_ALWAYS_32_BIT))
                destFormat = ECF_A1R5G5B5;
        break;
        case ECF_R5G6B5:
            if (!Driver->getTextureCreationFlag(ETCF_ALWAYS_32_BIT))
                destFormat = ECF_A1R5G5B5;
        break;
        case ECF_A8R8G8B8:
            if (Driver->getTextureCreationFlag(ETCF_ALWAYS_16_BIT) ||
                    Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED))
                destFormat = ECF_A1R5G5B5;
        break;
        case ECF_R8G8B8:
            if (Driver->getTextureCreationFlag(ETCF_ALWAYS_16_BIT) ||
                    Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED))
                destFormat = ECF_A1R5G5B5;
        default:
        break;
    }
    if (Driver->getTextureCreationFlag(ETCF_NO_ALPHA_CHANNEL))
    {
        switch (destFormat)
        {
            case ECF_A1R5G5B5:
                destFormat = ECF_R5G6B5;
            break;
            case ECF_A8R8G8B8:
                destFormat = ECF_R8G8B8;
            break;
            default:
            break;
        }
    }
    return destFormat;
}
 
 
//! Get opengl values for the GPU texture storage
GLint COpenGLTexture::getOpenGLFormatAndParametersFromColorFormat(ECOLOR_FORMAT format,
                GLint& filtering,
                GLenum& colorformat,
                GLenum& type)
{
    // default
    filtering = GL_LINEAR;
    colorformat = GL_RGBA;
    type = GL_UNSIGNED_BYTE;
 
    switch(format)
    {
        case ECF_A1R5G5B5:
            colorformat=GL_BGRA_EXT;
            type=GL_UNSIGNED_SHORT_1_5_5_5_REV;
            return GL_RGBA;
        case ECF_R5G6B5:
            colorformat=GL_BGR;
            type=GL_UNSIGNED_SHORT_5_6_5_REV;
            return GL_RGB;
        case ECF_R8G8B8:
            colorformat=GL_BGR;
            type=GL_UNSIGNED_BYTE;
            return GL_RGB;
        case ECF_A8R8G8B8:
            colorformat=GL_BGRA_EXT;
            if (Driver->Version > 101)
                type=GL_UNSIGNED_INT_8_8_8_8_REV;
            return GL_RGBA;
        // Floating Point texture formats. Thanks to Patryk "Nadro" Nadrowski.
        case ECF_R16F:
        {
#ifdef GL_ARB_texture_rg
            filtering = GL_NEAREST;
            colorformat = GL_RED;
            type = GL_FLOAT;
 
            return GL_R16F;
#else
            return GL_RGB8;
#endif
        }
        case ECF_G16R16F:
        {
#ifdef GL_ARB_texture_rg
            filtering = GL_NEAREST;
            colorformat = GL_RG;
            type = GL_FLOAT;
 
            return GL_RG16F;
#else
            return GL_RGB8;
#endif
        }
        case ECF_A16B16G16R16F:
        {
#ifdef GL_ARB_texture_rg
            filtering = GL_NEAREST;
            colorformat = GL_RGBA;
            type = GL_FLOAT;
 
            return GL_RGBA16F_ARB;
#else
            return GL_RGBA8;
#endif
        }
        case ECF_R32F:
        {
#ifdef GL_ARB_texture_rg
            filtering = GL_NEAREST;
            colorformat = GL_RED;
            type = GL_FLOAT;
 
            return GL_R32F;
#else
            return GL_RGB8;
#endif
        }
        case ECF_G32R32F:
        {
#ifdef GL_ARB_texture_rg
            filtering = GL_NEAREST;
            colorformat = GL_RG;
            type = GL_FLOAT;
 
            return GL_RG32F;
#else
            return GL_RGB8;
#endif
        }
        case ECF_A32B32G32R32F:
        {
#ifdef GL_ARB_texture_float
            filtering = GL_NEAREST;
            colorformat = GL_RGBA;
            type = GL_FLOAT;
 
            return GL_RGBA32F_ARB;
#else
            return GL_RGBA8;
#endif
        }
        default:
        {
            os::Printer::log("Unsupported texture format", ELL_ERROR);
            return GL_RGBA8;
        }
    }
}
 
 
// prepare values ImageSize, TextureSize, and ColorFormat based on image
void COpenGLTexture::getImageValues(IImage* image)
{
    if (!image)
    {
        os::Printer::log("No image for OpenGL texture.", ELL_ERROR);
        return;
    }
 
    ImageSize = image->getDimension();
 
    if ( !ImageSize.Width || !ImageSize.Height)
    {
        os::Printer::log("Invalid size of image for OpenGL Texture.", ELL_ERROR);
        return;
    }
 
    const f32 ratio = (f32)ImageSize.Width/(f32)ImageSize.Height;
    if ((ImageSize.Width>Driver->MaxTextureSize) && (ratio >= 1.0f))
    {
        ImageSize.Width = Driver->MaxTextureSize;
        ImageSize.Height = (u32)(Driver->MaxTextureSize/ratio);
    }
    else if (ImageSize.Height>Driver->MaxTextureSize)
    {
        ImageSize.Height = Driver->MaxTextureSize;
        ImageSize.Width = (u32)(Driver->MaxTextureSize*ratio);
    }
    TextureSize=ImageSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT));
 
    ColorFormat = getBestColorFormat(image->getColorFormat());
}
 
 
//! copies the the texture into an open gl texture.
void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData, u32 level)
{
 
    // check which image needs to be uploaded
    IImage* image = level?MipImage:Image;
 
    if (!image)
    {
        os::Printer::log("No image for OpenGL texture to upload", ELL_ERROR);
        return;
    }
 
    // get correct opengl color data values
    GLenum oldInternalFormat = InternalFormat;
    GLint filtering;
    InternalFormat = getOpenGLFormatAndParametersFromColorFormat(ColorFormat, filtering, PixelFormat, PixelType);
    // make sure we don't change the internal format of existing images
    if (!newTexture)
        InternalFormat=oldInternalFormat;
 
    Driver->setActiveTexture(0, this);
 
    if (Driver->testGLError())
        os::Printer::log("Could not bind Texture", ELL_ERROR);
 
    // mipmap handling for main texture
    if (!level && newTexture)
    {
#ifndef DISABLE_MIPMAPPING
#ifdef GL_SGIS_generate_mipmap
        // auto generate if possible and no mipmap data is given
        if (HasMipMaps && !mipmapData && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE))
        {
            if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED))
                glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_FASTEST);
            else if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY))
                glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);
            else
                glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_DONT_CARE);
            // automatically generate and update mipmaps
            glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE );
            AutomaticMipmapUpdate=true;
        }
        else
#endif
        {
            // Either generate manually due to missing capability
            // or use predefined mipmap data
            AutomaticMipmapUpdate=false;
            regenerateMipMapLevels(mipmapData);
        }
        if (HasMipMaps) // might have changed in regenerateMipMapLevels
        {
            // enable bilinear mipmap filter
            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        }
        else
#else
            HasMipMaps=false;
            os::Printer::log("Did not create OpenGL texture mip maps.", ELL_INFORMATION);
#endif
        {
            // enable bilinear filter without mipmaps
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        }
    }
 
    // now get image data and upload to GPU
    void* source = image->lock();
    if (newTexture)
        glTexImage2D(GL_TEXTURE_2D, level, InternalFormat, image->getDimension().Width,
            image->getDimension().Height, 0, PixelFormat, PixelType, source);
    else
    {
        if( isPixelBufferObject )
        {
            // bind the texture and PBO
            //glBindTexture(GL_TEXTURE_2D, textureId);
            glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pboId);
 
            // copy pixels from PBO to texture object
            // Use offset instead of ponter.
            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, Image->getDimension().Width, Image->getDimension().Height, PixelFormat, PixelType, 0);
 
            // bind PBO to update pixel values
            glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pboId);
 
            // map the buffer object into client's memory
            // Note that glMapBufferARB() causes sync issue.
            // If GPU is working with this buffer, glMapBufferARB() will wait(stall)
            // for GPU to finish its job. To avoid waiting (stall), you can call
            // first glBufferDataARB() with NULL pointer before glMapBufferARB().
            // If you do that, the previous data in PBO will be discarded and
            // glMapBufferARB() returns a new allocated pointer immediately
            // even if GPU is still working with the previous data.
            glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, image->getImageDataSizeInBytes(), 0, GL_STREAM_DRAW_ARB);
            GLubyte* ptr = (GLubyte*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB);
            if(ptr)
            {
                // update data directly on the mapped buffer
                memcpy( ptr, source, Image->getImageDataSizeInBytes() );
                glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); // release pointer to mapping buffer
            }
 
            // it is good idea to release PBOs with ID 0 after use.
            // Once bound with 0, all pixel operations behave normal ways.
            glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
        }
        else
        {
            glTexSubImage2D( GL_TEXTURE_2D, level, 0, 0, image->getDimension().Width,
                             image->getDimension().Height, PixelFormat, PixelType, source);
        }
    }
    image->unlock();
 
    if (Driver->testGLError())
        os::Printer::log("Could not glTexImage2D", ELL_ERROR);
}
 
 
//! lock function
void* COpenGLTexture::lock(bool readOnly, u32 mipmapLevel)
{
    // store info about which image is locked
    IImage* image = (mipmapLevel==0)?Image:MipImage;
    ReadOnlyLock |= readOnly;
    MipLevelStored = mipmapLevel;
 
    // if data not available or might have changed on GPU download it
    if (!image || IsRenderTarget)
    {
        // prepare the data storage if necessary
        if (!image)
        {
            if (mipmapLevel)
            {
                u32 i=0;
                u32 width = TextureSize.Width;
                u32 height = TextureSize.Height;
                do
                {
                    if (width>1)
                        width>>=1;
                    if (height>1)
                        height>>=1;
                    ++i;
                }
                while (i != mipmapLevel);
                MipImage = image = new CImage(ECF_A8R8G8B8, core::dimension2du(width,height));
            }
            else
                Image = image = new CImage(ECF_A8R8G8B8, ImageSize);
            ColorFormat = ECF_A8R8G8B8;
        }
        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
        {
            // 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();
}
 
 
//! unlock function
void COpenGLTexture::unlock()
{
    // test if miplevel or main texture was locked
    IImage* image = MipImage?MipImage:Image;
    if (!image)
        return;
    // unlock image to see changes
    image->unlock();
    // copy texture data to GPU
    if (!ReadOnlyLock)
        uploadTexture(false, 0, MipLevelStored);
    ReadOnlyLock = false;
    // cleanup local image
    if (MipImage)
    {
        MipImage->drop();
        MipImage=0;
    }
    else if (!KeepImage)
    {
        Image->drop();
        Image=0;
    }
    // update information
    if (Image)
        ColorFormat=Image->getColorFormat();
    else
        ColorFormat=ECF_A8R8G8B8;
}
 
 
//! Returns size of the original image.
const core::dimension2d<u32>& COpenGLTexture::getOriginalSize() const
{
    return ImageSize;
}
 
 
//! Returns size of the texture.
const core::dimension2d<u32>& COpenGLTexture::getSize() const
{
    return TextureSize;
}
 
 
//! returns driver type of texture, i.e. the driver, which created the texture
E_DRIVER_TYPE COpenGLTexture::getDriverType() const
{
    return EDT_OPENGL;
}
 
 
//! returns color format of texture
ECOLOR_FORMAT COpenGLTexture::getColorFormat() const
{
    return ColorFormat;
}
 
 
//! returns pitch of texture (in bytes)
u32 COpenGLTexture::getPitch() const
{
    if (Image)
        return Image->getPitch();
    else
        return 0;
}
 
 
//! return open gl texture name
GLuint COpenGLTexture::getOpenGLTextureName() const
{
    return TextureName;
}
 
 
//! Returns whether this texture has mipmaps
bool COpenGLTexture::hasMipMaps() const
{
    return HasMipMaps;
}
 
 
//! Regenerates the mip map levels of the texture. Useful after locking and
//! modifying the texture
void COpenGLTexture::regenerateMipMapLevels(void* mipmapData)
{
    if (AutomaticMipmapUpdate || !HasMipMaps || !Image)
        return;
    if ((Image->getDimension().Width==1) && (Image->getDimension().Height==1))
        return;
 
    // Manually create mipmaps or use prepared version
    u32 width=Image->getDimension().Width;
    u32 height=Image->getDimension().Height;
    u32 i=0;
    u8* target = static_cast<u8*>(mipmapData);
    do
    {
        if (width>1)
            width>>=1;
        if (height>1)
            height>>=1;
        ++i;
        if (!target)
            target = new u8[width*height*Image->getBytesPerPixel()];
        // create scaled version if no mipdata available
        if (!mipmapData)
            Image->copyToScaling(target, width, height, Image->getColorFormat());
        glTexImage2D(GL_TEXTURE_2D, i, InternalFormat, width, height,
                0, PixelFormat, PixelType, target);
        // get next prepared mipmap data if available
        if (mipmapData)
        {
            mipmapData = static_cast<u8*>(mipmapData)+width*height*Image->getBytesPerPixel();
            target = static_cast<u8*>(mipmapData);
        }
    }
    while (width!=1 || height!=1);
    // cleanup
    if (!mipmapData)
        delete [] target;
}
 
 
bool COpenGLTexture::isRenderTarget() const
{
     return IsRenderTarget;
}
 
 
void COpenGLTexture::setIsRenderTarget(bool isTarget)
{
    IsRenderTarget = isTarget;
}
 
bool COpenGLTexture::initPbo()
{
    if( Driver->queryOpenGLFeature(COpenGLExtensionHandler::IRR_ARB_pixel_buffer_object ) )
    {
        glGenBuffersARB(1, &pboId);
        glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pboId);
        glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, Image->getDimension().Height * Image->getPitch(), 0, GL_STREAM_DRAW_ARB);
        glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
        isPixelBufferObject = true;
        return true;
    }
 
    return false;
}
 
 
bool COpenGLTexture::isFrameBufferObject() const
{
    return false;
}
 
 
//! Bind Render Target Texture
void COpenGLTexture::bindRTT()
{
}
 
 
//! Unbind Render Target Texture
void COpenGLTexture::unbindRTT()
{
    Driver->setActiveTexture(0, this);
 
    // Copy Our ViewPort To The Texture
    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, getSize().Width, getSize().Height);
}
 
} // end namespace video
} // end namespace irr
 
#endif // _IRR_COMPILE_WITH_OPENGL_
 
COpenGLTexture.h

Code: Select all

 
// Copyright (C) 2002-2010 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
 
#ifndef __C_OPEN_GL_TEXTURE_H_INCLUDED__
#define __C_OPEN_GL_TEXTURE_H_INCLUDED__
 
#include "ITexture.h"
#include "IImage.h"
 
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_OPENGL_
 
#if defined(_IRR_OPENGL_USE_EXTPOINTER_)
    #define GL_GLEXT_LEGACY 1
#else
    #define GL_GLEXT_PROTOTYPES 1
#endif
#ifdef _IRR_WINDOWS_API_
    // include windows headers for HWND
    #define WIN32_LEAN_AND_MEAN
    #include <windows.h>
    #include <GL/gl.h>
#ifdef _MSC_VER
    #pragma comment(lib, "OpenGL32.lib")
#endif
#elif defined(_IRR_OSX_PLATFORM_)
    #include <OpenGL/gl.h>
#elif defined(_IRR_COMPILE_WITH_SDL_DEVICE_)
    #define NO_SDL_GLEXT
    #include <SDL/SDL_video.h>
    #include <SDL/SDL_opengl.h>
#else
    #if defined(_IRR_OSX_PLATFORM_)
        #include <OpenGL/gl.h>
    #else
        #include <GL/gl.h>
    #endif
#endif
 
 
namespace irr
{
namespace video
{
 
class COpenGLDriver;
//! OpenGL texture.
class COpenGLTexture : public ITexture
{
public:
 
    //! constructor
    COpenGLTexture(IImage* surface, const io::path& name, void* mipmapData=0, COpenGLDriver* driver=0);
 
    //! destructor
    virtual ~COpenGLTexture();
 
    //! lock function
    virtual void* lock(bool readOnly=false, u32 mipmapLevel=0);
 
    //! unlock function
    virtual void unlock();
 
    //! Returns original size of the texture (image).
    virtual const core::dimension2d<u32>& getOriginalSize() const;
 
    //! Returns size of the texture.
    virtual const core::dimension2d<u32>& getSize() const;
 
    //! returns driver type of texture (=the driver, that created it)
    virtual E_DRIVER_TYPE getDriverType() const;
 
    //! returns color format of texture
    virtual ECOLOR_FORMAT getColorFormat() const;
 
    //! returns pitch of texture (in bytes)
    virtual u32 getPitch() const;
 
    //! return open gl texture name
    GLuint getOpenGLTextureName() const;
 
    //! return whether this texture has mipmaps
    virtual bool hasMipMaps() const;
 
    //! Regenerates the mip map levels of the texture.
    /** Useful after locking and modifying the texture
    \param mipmapData Pointer to raw mipmap data, including all necessary mip levels, in the same format as the main texture image. If not set the mipmaps are derived from the main image. */
    virtual void regenerateMipMapLevels(void* mipmapData=0);
 
    //! Is it a render target?
    virtual bool isRenderTarget() const;
 
    //! Is it a FrameBufferObject?
    virtual bool isFrameBufferObject() const;
 
    //! Bind RenderTargetTexture
    virtual void bindRTT();
 
    //! Unbind RenderTargetTexture
    virtual void unbindRTT();
 
    //! sets whether this texture is intended to be used as a render target.
    void setIsRenderTarget(bool isTarget);
 
    bool initPbo();
 
protected:
 
    //! protected constructor with basic setup, no GL texture name created, for derived classes
    COpenGLTexture(const io::path& name, COpenGLDriver* driver);
 
    //! get the desired color format based on texture creation flags and the input format.
    ECOLOR_FORMAT getBestColorFormat(ECOLOR_FORMAT format);
 
    //! Get the OpenGL color format parameters based on the given Irrlicht color format
    GLint getOpenGLFormatAndParametersFromColorFormat(
        ECOLOR_FORMAT format, GLint& filtering, GLenum& colorformat, GLenum& type);
 
    //! get important numbers of the image and hw texture
    void getImageValues(IImage* image);
 
    //! copies the texture into an OpenGL texture.
    /** \param newTexture True if method is called for a newly created texture for the first time. Otherwise call with false to improve memory handling.
    \param mipmapData Pointer to raw mipmap data, including all necessary mip levels, in the same format as the main texture image.
    \param mipLevel If set to non-zero, only that specific miplevel is updated, using the MipImage member. */
    void uploadTexture(bool newTexture=false, void* mipmapData=0, u32 mipLevel=0);
 
    core::dimension2d<u32> ImageSize;
    core::dimension2d<u32> TextureSize;
    ECOLOR_FORMAT ColorFormat;
    COpenGLDriver* Driver;
    IImage* Image;
    IImage* MipImage;
 
    GLuint TextureName;
    GLint InternalFormat;
    GLenum PixelFormat;
    GLenum PixelType;
 
    u8 MipLevelStored;
    bool HasMipMaps;
    bool IsRenderTarget;
    bool AutomaticMipmapUpdate;
    bool ReadOnlyLock;
    bool KeepImage;
    bool isPixelBufferObject;
    u32 pboId;
};
  
} // end namespace video
} // end namespace irr
 
#endif
#endif // _IRR_COMPILE_WITH_OPENGL_
 
 
REDDemon
Developer
Posts: 1044
Joined: Tue Aug 31, 2010 8:06 pm
Location: Genova (Italy)

Re: COpenGLTexture with PBO

Post by REDDemon »

thought PBO was already in trunk, if not nice addiction :)
Junior Irrlicht Developer.
Real value in social networks is not about "increasing" number of followers, but about getting in touch with Amazing people.
- by Me
ACE247
Posts: 704
Joined: Tue Mar 16, 2010 12:31 am

Re: COpenGLTexture with PBO

Post by ACE247 »

Nice addition. The code looks reasonably irrlicht conformant, so if you know svn, maybe post it as a patch to svn. here: http://sourceforge.net/tracker/?group_i ... tid=540678
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Re: COpenGLTexture with PBO

Post by hybrid »

Patch would indeed help, though we will probably need the extended texture creation flags first. Otherwise it's hard to decide which way to create the texture for optimal usage. After all, not every texture should be created as PBO AFAIK.
dalerank2
Posts: 121
Joined: Thu Dec 03, 2009 7:41 am

Re: COpenGLTexture with PBO

Post by dalerank2 »

agree with hybrid, such textures are necessary for example in video ouput, or often updated textures. it not usually used texture. That it worked for opengl, but i thin dx also have equale solution for data streaming.
Post Reply