openmw-tes3coop/components/myguiplatform/myguitexture.cpp
scrawl e8662bea31 Change the way that image origin is converted to OpenGL's lower-left convention
Flip the texture coordinates instead of flipping textures.

This simplifies the TextureManager (no need to worry if the caller wants flipping or not), should make it easier to generalize & multithread it.
2016-02-05 21:03:11 +01:00

180 lines
5.7 KiB
C++

#include "myguitexture.hpp"
#include <stdexcept>
#include <iostream>
#include <osg/Texture2D>
#include <components/resource/texturemanager.hpp>
namespace osgMyGUI
{
OSGTexture::OSGTexture(const std::string &name, Resource::TextureManager* textureManager)
: mName(name)
, mTextureManager(textureManager)
, mFormat(MyGUI::PixelFormat::Unknow)
, mUsage(MyGUI::TextureUsage::Default)
, mNumElemBytes(0)
{
}
OSGTexture::OSGTexture(osg::Texture2D *texture)
: mTextureManager(NULL)
, mTexture(texture)
, mFormat(MyGUI::PixelFormat::Unknow)
, mUsage(MyGUI::TextureUsage::Default)
, mNumElemBytes(0)
{
}
OSGTexture::~OSGTexture()
{
}
void OSGTexture::createManual(int width, int height, MyGUI::TextureUsage usage, MyGUI::PixelFormat format)
{
GLenum glfmt = GL_NONE;
size_t numelems = 0;
switch(format.getValue())
{
case MyGUI::PixelFormat::L8:
glfmt = GL_LUMINANCE;
numelems = 1;
break;
case MyGUI::PixelFormat::L8A8:
glfmt = GL_LUMINANCE_ALPHA;
numelems = 2;
break;
case MyGUI::PixelFormat::R8G8B8:
glfmt = GL_RGB;
numelems = 3;
break;
case MyGUI::PixelFormat::R8G8B8A8:
glfmt = GL_RGBA;
numelems = 4;
break;
}
if(glfmt == GL_NONE)
throw std::runtime_error("Texture format not supported");
mTexture = new osg::Texture2D();
mTexture->setTextureSize(width, height);
mTexture->setSourceFormat(glfmt);
mTexture->setSourceType(GL_UNSIGNED_BYTE);
mTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
mTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
mTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
mTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
mFormat = format;
mUsage = usage;
mNumElemBytes = numelems;
}
void OSGTexture::destroy()
{
mTexture = nullptr;
mFormat = MyGUI::PixelFormat::Unknow;
mUsage = MyGUI::TextureUsage::Default;
mNumElemBytes = 0;
}
void OSGTexture::loadFromFile(const std::string &fname)
{
if (!mTextureManager)
throw std::runtime_error("No texturemanager set");
mTexture = new osg::Texture2D(mTextureManager->getImage(fname));
mTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
mTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
// disable mip-maps
mTexture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
// FIXME
mFormat = MyGUI::PixelFormat::R8G8B8;
mUsage = MyGUI::TextureUsage::Static | MyGUI::TextureUsage::Write;
mNumElemBytes = 3; // FIXME
}
void OSGTexture::saveToFile(const std::string &fname)
{
std::cerr << "Would save image to file " << fname << std::endl;
}
int OSGTexture::getWidth()
{
if(!mTexture.valid())
return 0;
osg::Image *image = mTexture->getImage();
if(image) return image->s();
return mTexture->getTextureWidth();
}
int OSGTexture::getHeight()
{
if(!mTexture.valid())
return 0;
osg::Image *image = mTexture->getImage();
if(image) return image->t();
return mTexture->getTextureHeight();
}
void *OSGTexture::lock(MyGUI::TextureUsage /*access*/)
{
if (!mTexture.valid())
throw std::runtime_error("Texture is not created");
if (mLockedImage.valid())
throw std::runtime_error("Texture already locked");
mLockedImage = mTexture->getImage();
if(!mLockedImage.valid())
{
mLockedImage = new osg::Image();
mLockedImage->allocateImage(
mTexture->getTextureWidth(), mTexture->getTextureHeight(), mTexture->getTextureDepth(),
mTexture->getSourceFormat(), mTexture->getSourceType()
);
}
return mLockedImage->data();
}
void OSGTexture::unlock()
{
if (!mLockedImage.valid())
throw std::runtime_error("Texture not locked");
mLockedImage->flipVertical();
// mTexture might be in use by the draw thread, so create a new texture instead and use that.
osg::ref_ptr<osg::Texture2D> newTexture = new osg::Texture2D;
newTexture->setTextureSize(getWidth(), getHeight());
newTexture->setSourceFormat(mTexture->getSourceFormat());
newTexture->setSourceType(mTexture->getSourceType());
newTexture->setFilter(osg::Texture::MIN_FILTER, mTexture->getFilter(osg::Texture::MIN_FILTER));
newTexture->setFilter(osg::Texture::MAG_FILTER, mTexture->getFilter(osg::Texture::MAG_FILTER));
newTexture->setWrap(osg::Texture::WRAP_S, mTexture->getWrap(osg::Texture::WRAP_S));
newTexture->setWrap(osg::Texture::WRAP_T, mTexture->getWrap(osg::Texture::WRAP_T));
newTexture->setImage(mLockedImage.get());
// Tell the texture it can get rid of the image for static textures (since
// they aren't expected to update much at all).
newTexture->setUnRefImageDataAfterApply(mUsage.isValue(MyGUI::TextureUsage::Static) ? true : false);
mTexture = newTexture;
mLockedImage = nullptr;
}
bool OSGTexture::isLocked()
{
return mLockedImage.valid();
}
// Render-to-texture not currently implemented.
MyGUI::IRenderTarget* OSGTexture::getRenderTarget()
{
return nullptr;
}
}