API for updating texture data

dev-time-step
Piotr Dziwinski 2016-03-18 10:45:03 +13:00
parent 15c9cbd228
commit 4b770adf46
11 changed files with 196 additions and 315 deletions

View File

@ -357,6 +357,8 @@ public:
virtual Texture CreateTexture(ImageData *data, const TextureCreateParams &params) = 0; virtual Texture CreateTexture(ImageData *data, const TextureCreateParams &params) = 0;
//! Creates a depth texture with specific dimensions and depth //! Creates a depth texture with specific dimensions and depth
virtual Texture CreateDepthTexture(int width, int height, int depth) = 0; virtual Texture CreateDepthTexture(int width, int height, int depth) = 0;
//! Updates a part of texture from raw image data
virtual void UpdateTexture(const Texture& texture, Math::IntPoint offset, ImageData* data, TexImgFormat format) = 0;
//! Deletes a given texture, freeing it from video memory //! Deletes a given texture, freeing it from video memory
virtual void DestroyTexture(const Texture &texture) = 0; virtual void DestroyTexture(const Texture &texture) = 0;
//! Deletes all textures created so far //! Deletes all textures created so far

View File

@ -120,6 +120,10 @@ Texture CNullDevice::CreateDepthTexture(int width, int height, int depth)
return tex; return tex;
} }
void CNullDevice::UpdateTexture(const Texture& texture, Math::IntPoint offset, ImageData* data, TexImgFormat format)
{
}
void CNullDevice::DestroyTexture(const Texture &texture) void CNullDevice::DestroyTexture(const Texture &texture)
{ {
} }

View File

@ -74,6 +74,7 @@ public:
Texture CreateTexture(CImage *image, const TextureCreateParams &params) override; Texture CreateTexture(CImage *image, const TextureCreateParams &params) override;
Texture CreateTexture(ImageData *data, const TextureCreateParams &params) override; Texture CreateTexture(ImageData *data, const TextureCreateParams &params) override;
Texture CreateDepthTexture(int width, int height, int depth) override; Texture CreateDepthTexture(int width, int height, int depth) override;
void UpdateTexture(const Texture& texture, Math::IntPoint offset, ImageData* data, TexImgFormat format) override;
void DestroyTexture(const Texture &texture) override; void DestroyTexture(const Texture &texture) override;
void DestroyAllTextures() override; void DestroyAllTextures() override;

View File

@ -820,113 +820,13 @@ Texture CGL21Device::CreateTexture(ImageData *data, const TextureCreateParams &p
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, level); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, level);
} }
bool convert = false; PreparedTextureData texData = PrepareTextureData(data, params.format);
GLenum sourceFormat = 0; result.alpha = texData.alpha;
if (params.format == TEX_IMG_RGB) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texData.actualSurface->w, texData.actualSurface->h,
{ 0, texData.sourceFormat, GL_UNSIGNED_BYTE, texData.actualSurface->pixels);
sourceFormat = GL_RGB;
result.alpha = false;
}
else if (params.format == TEX_IMG_BGR)
{
sourceFormat = GL_BGR;
result.alpha = false;
}
else if (params.format == TEX_IMG_RGBA)
{
sourceFormat = GL_RGBA;
result.alpha = true;
}
else if (params.format == TEX_IMG_BGRA)
{
sourceFormat = GL_BGRA;
result.alpha = true;
}
else if (params.format == TEX_IMG_AUTO)
{
if (data->surface->format->BytesPerPixel == 4)
{
if ((data->surface->format->Amask == 0xFF000000) &&
(data->surface->format->Rmask == 0x00FF0000) &&
(data->surface->format->Gmask == 0x0000FF00) &&
(data->surface->format->Bmask == 0x000000FF))
{
sourceFormat = GL_BGRA;
result.alpha = true;
}
else if ((data->surface->format->Amask == 0xFF000000) &&
(data->surface->format->Bmask == 0x00FF0000) &&
(data->surface->format->Gmask == 0x0000FF00) &&
(data->surface->format->Rmask == 0x000000FF))
{
sourceFormat = GL_RGBA;
result.alpha = true;
}
else
{
sourceFormat = GL_RGBA;
convert = true;
}
}
else if (data->surface->format->BytesPerPixel == 3)
{
if ((data->surface->format->Rmask == 0xFF0000) &&
(data->surface->format->Gmask == 0x00FF00) &&
(data->surface->format->Bmask == 0x0000FF))
{
sourceFormat = GL_BGR;
result.alpha = false;
}
else if ((data->surface->format->Bmask == 0xFF0000) &&
(data->surface->format->Gmask == 0x00FF00) &&
(data->surface->format->Rmask == 0x0000FF))
{
sourceFormat = GL_RGB;
result.alpha = false;
}
else
{
sourceFormat = GL_RGBA;
convert = true;
}
}
else
{
GetLogger()->Error("Unknown data surface format");
assert(false);
}
}
else
assert(false);
SDL_Surface* actualSurface = data->surface; SDL_FreeSurface(texData.convertedSurface);
SDL_Surface* convertedSurface = nullptr;
if (convert)
{
SDL_PixelFormat format;
format.BytesPerPixel = 4;
format.BitsPerPixel = 32;
format.Aloss = format.Bloss = format.Gloss = format.Rloss = 0;
format.Amask = 0xFF000000;
format.Ashift = 24;
format.Bmask = 0x00FF0000;
format.Bshift = 16;
format.Gmask = 0x0000FF00;
format.Gshift = 8;
format.Rmask = 0x000000FF;
format.Rshift = 0;
format.palette = nullptr;
convertedSurface = SDL_ConvertSurface(data->surface, &format, SDL_SWSURFACE);
if (convertedSurface != nullptr)
actualSurface = convertedSurface;
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, actualSurface->w, actualSurface->h,
0, sourceFormat, GL_UNSIGNED_BYTE, actualSurface->pixels);
SDL_FreeSurface(convertedSurface);
m_allTextures.insert(result); m_allTextures.insert(result);
@ -985,6 +885,21 @@ Texture CGL21Device::CreateDepthTexture(int width, int height, int depth)
return result; return result;
} }
void CGL21Device::UpdateTexture(const Texture& texture, Math::IntPoint offset, ImageData* data, TexImgFormat format)
{
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture.id);
PreparedTextureData texData = PrepareTextureData(data, format);
glTexSubImage2D(GL_TEXTURE_2D, 0, offset.x, offset.y, texData.actualSurface->w, texData.actualSurface->h,
texData.sourceFormat, GL_UNSIGNED_BYTE, texData.actualSurface->pixels);
SDL_FreeSurface(texData.convertedSurface);
}
void CGL21Device::DestroyTexture(const Texture &texture) void CGL21Device::DestroyTexture(const Texture &texture)
{ {
// Unbind the texture if in use anywhere // Unbind the texture if in use anywhere

View File

@ -87,6 +87,7 @@ public:
Texture CreateTexture(CImage *image, const TextureCreateParams &params) override; Texture CreateTexture(CImage *image, const TextureCreateParams &params) override;
Texture CreateTexture(ImageData *data, const TextureCreateParams &params) override; Texture CreateTexture(ImageData *data, const TextureCreateParams &params) override;
Texture CreateDepthTexture(int width, int height, int depth) override; Texture CreateDepthTexture(int width, int height, int depth) override;
void UpdateTexture(const Texture& texture, Math::IntPoint offset, ImageData* data, TexImgFormat format) override;
void DestroyTexture(const Texture &texture) override; void DestroyTexture(const Texture &texture) override;
void DestroyAllTextures() override; void DestroyAllTextures() override;

View File

@ -849,116 +849,16 @@ Texture CGL33Device::CreateTexture(ImageData *data, const TextureCreateParams &p
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, level); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, level);
} }
bool convert = false; PreparedTextureData texData = PrepareTextureData(data, params.format);
GLenum sourceFormat = 0; result.alpha = texData.alpha;
if (params.format == TEX_IMG_RGB) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texData.actualSurface->w, texData.actualSurface->h,
{ 0, texData.sourceFormat, GL_UNSIGNED_BYTE, texData.actualSurface->pixels);
sourceFormat = GL_RGB;
result.alpha = false;
}
else if (params.format == TEX_IMG_BGR)
{
sourceFormat = GL_BGR;
result.alpha = false;
}
else if (params.format == TEX_IMG_RGBA)
{
sourceFormat = GL_RGBA;
result.alpha = true;
}
else if (params.format == TEX_IMG_BGRA)
{
sourceFormat = GL_BGRA;
result.alpha = true;
}
else if (params.format == TEX_IMG_AUTO)
{
if (data->surface->format->BytesPerPixel == 4)
{
if ((data->surface->format->Amask == 0xFF000000) &&
(data->surface->format->Rmask == 0x00FF0000) &&
(data->surface->format->Gmask == 0x0000FF00) &&
(data->surface->format->Bmask == 0x000000FF))
{
sourceFormat = GL_BGRA;
result.alpha = true;
}
else if ((data->surface->format->Amask == 0xFF000000) &&
(data->surface->format->Bmask == 0x00FF0000) &&
(data->surface->format->Gmask == 0x0000FF00) &&
(data->surface->format->Rmask == 0x000000FF))
{
sourceFormat = GL_RGBA;
result.alpha = true;
}
else
{
sourceFormat = GL_RGBA;
convert = true;
}
}
else if (data->surface->format->BytesPerPixel == 3)
{
if ((data->surface->format->Rmask == 0xFF0000) &&
(data->surface->format->Gmask == 0x00FF00) &&
(data->surface->format->Bmask == 0x0000FF))
{
sourceFormat = GL_BGR;
result.alpha = false;
}
else if ((data->surface->format->Bmask == 0xFF0000) &&
(data->surface->format->Gmask == 0x00FF00) &&
(data->surface->format->Rmask == 0x0000FF))
{
sourceFormat = GL_RGB;
result.alpha = false;
}
else
{
sourceFormat = GL_RGBA;
convert = true;
}
}
else
{
GetLogger()->Error("Unknown data surface format");
assert(false);
}
}
else
assert(false);
SDL_Surface* actualSurface = data->surface;
SDL_Surface* convertedSurface = nullptr;
if (convert)
{
SDL_PixelFormat format;
format.BytesPerPixel = 4;
format.BitsPerPixel = 32;
format.Aloss = format.Bloss = format.Gloss = format.Rloss = 0;
format.Amask = 0xFF000000;
format.Ashift = 24;
format.Bmask = 0x00FF0000;
format.Bshift = 16;
format.Gmask = 0x0000FF00;
format.Gshift = 8;
format.Rmask = 0x000000FF;
format.Rshift = 0;
format.palette = nullptr;
convertedSurface = SDL_ConvertSurface(data->surface, &format, SDL_SWSURFACE);
if (convertedSurface != nullptr)
actualSurface = convertedSurface;
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, actualSurface->w, actualSurface->h,
0, sourceFormat, GL_UNSIGNED_BYTE, actualSurface->pixels);
if (params.mipmap) if (params.mipmap)
glGenerateMipmap(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D);
SDL_FreeSurface(convertedSurface); SDL_FreeSurface(texData.convertedSurface);
m_allTextures.insert(result); m_allTextures.insert(result);
@ -1013,6 +913,20 @@ Texture CGL33Device::CreateDepthTexture(int width, int height, int depth)
return result; return result;
} }
void CGL33Device::UpdateTexture(const Texture& texture, Math::IntPoint offset, ImageData* data, TexImgFormat format)
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture.id);
PreparedTextureData texData = PrepareTextureData(data, format);
glTexSubImage2D(GL_TEXTURE_2D, 0, offset.x, offset.y, texData.actualSurface->w, texData.actualSurface->h,
texData.sourceFormat, GL_UNSIGNED_BYTE, texData.actualSurface->pixels);
SDL_FreeSurface(texData.convertedSurface);
}
void CGL33Device::DestroyTexture(const Texture &texture) void CGL33Device::DestroyTexture(const Texture &texture)
{ {
// Unbind the texture if in use anywhere // Unbind the texture if in use anywhere

View File

@ -89,6 +89,7 @@ public:
Texture CreateTexture(CImage *image, const TextureCreateParams &params) override; Texture CreateTexture(CImage *image, const TextureCreateParams &params) override;
Texture CreateTexture(ImageData *data, const TextureCreateParams &params) override; Texture CreateTexture(ImageData *data, const TextureCreateParams &params) override;
Texture CreateDepthTexture(int width, int height, int depth) override; Texture CreateDepthTexture(int width, int height, int depth) override;
void UpdateTexture(const Texture& texture, Math::IntPoint offset, ImageData* data, TexImgFormat format) override;
void DestroyTexture(const Texture &texture) override; void DestroyTexture(const Texture &texture) override;
void DestroyAllTextures() override; void DestroyAllTextures() override;

View File

@ -722,113 +722,13 @@ Texture CGLDevice::CreateTexture(ImageData *data, const TextureCreateParams &par
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, level); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, level);
} }
bool convert = false; PreparedTextureData texData = PrepareTextureData(data, params.format);
GLenum sourceFormat = 0; result.alpha = texData.alpha;
if (params.format == TEX_IMG_RGB) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texData.actualSurface->w, texData.actualSurface->h,
{ 0, texData.sourceFormat, GL_UNSIGNED_BYTE, texData.actualSurface->pixels);
sourceFormat = GL_RGB;
result.alpha = false;
}
else if (params.format == TEX_IMG_BGR)
{
sourceFormat = GL_BGR;
result.alpha = false;
}
else if (params.format == TEX_IMG_RGBA)
{
sourceFormat = GL_RGBA;
result.alpha = true;
}
else if (params.format == TEX_IMG_BGRA)
{
sourceFormat = GL_BGRA;
result.alpha = true;
}
else if (params.format == TEX_IMG_AUTO)
{
if (data->surface->format->BytesPerPixel == 4)
{
if ((data->surface->format->Amask == 0xFF000000) &&
(data->surface->format->Rmask == 0x00FF0000) &&
(data->surface->format->Gmask == 0x0000FF00) &&
(data->surface->format->Bmask == 0x000000FF))
{
sourceFormat = GL_BGRA;
result.alpha = true;
}
else if ((data->surface->format->Amask == 0xFF000000) &&
(data->surface->format->Bmask == 0x00FF0000) &&
(data->surface->format->Gmask == 0x0000FF00) &&
(data->surface->format->Rmask == 0x000000FF))
{
sourceFormat = GL_RGBA;
result.alpha = true;
}
else
{
sourceFormat = GL_RGBA;
convert = true;
}
}
else if (data->surface->format->BytesPerPixel == 3)
{
if ((data->surface->format->Rmask == 0xFF0000) &&
(data->surface->format->Gmask == 0x00FF00) &&
(data->surface->format->Bmask == 0x0000FF))
{
sourceFormat = GL_BGR;
result.alpha = false;
}
else if ((data->surface->format->Bmask == 0xFF0000) &&
(data->surface->format->Gmask == 0x00FF00) &&
(data->surface->format->Rmask == 0x0000FF))
{
sourceFormat = GL_RGB;
result.alpha = false;
}
else
{
sourceFormat = GL_RGBA;
convert = true;
}
}
else
{
GetLogger()->Error("Unknown data surface format");
assert(false);
}
}
else
assert(false);
SDL_Surface* actualSurface = data->surface; SDL_FreeSurface(texData.convertedSurface);
SDL_Surface* convertedSurface = nullptr;
if (convert)
{
SDL_PixelFormat format;
format.BytesPerPixel = 4;
format.BitsPerPixel = 32;
format.Aloss = format.Bloss = format.Gloss = format.Rloss = 0;
format.Amask = 0xFF000000;
format.Ashift = 24;
format.Bmask = 0x00FF0000;
format.Bshift = 16;
format.Gmask = 0x0000FF00;
format.Gshift = 8;
format.Rmask = 0x000000FF;
format.Rshift = 0;
format.palette = nullptr;
convertedSurface = SDL_ConvertSurface(data->surface, &format, SDL_SWSURFACE);
if (convertedSurface != nullptr)
actualSurface = convertedSurface;
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, actualSurface->w, actualSurface->h,
0, sourceFormat, GL_UNSIGNED_BYTE, actualSurface->pixels);
SDL_FreeSurface(convertedSurface);
m_allTextures.insert(result); m_allTextures.insert(result);
@ -915,6 +815,23 @@ Texture CGLDevice::CreateDepthTexture(int width, int height, int depth)
return result; return result;
} }
void CGLDevice::UpdateTexture(const Texture& texture, Math::IntPoint offset, ImageData* data, TexImgFormat format)
{
// Use & enable 1st texture stage
glActiveTexture(GL_TEXTURE0 + m_remap[0]);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture.id);
PreparedTextureData texData = PrepareTextureData(data, format);
glTexSubImage2D(GL_TEXTURE_2D, 0, offset.x, offset.y, texData.actualSurface->w, texData.actualSurface->h,
texData.sourceFormat, GL_UNSIGNED_BYTE, texData.actualSurface->pixels);
SDL_FreeSurface(texData.convertedSurface);
}
void CGLDevice::DestroyTexture(const Texture &texture) void CGLDevice::DestroyTexture(const Texture &texture)
{ {
// Unbind the texture if in use anywhere // Unbind the texture if in use anywhere

View File

@ -106,6 +106,7 @@ public:
Texture CreateTexture(CImage *image, const TextureCreateParams &params) override; Texture CreateTexture(CImage *image, const TextureCreateParams &params) override;
Texture CreateTexture(ImageData *data, const TextureCreateParams &params) override; Texture CreateTexture(ImageData *data, const TextureCreateParams &params) override;
Texture CreateDepthTexture(int width, int height, int depth) override; Texture CreateDepthTexture(int width, int height, int depth) override;
void UpdateTexture(const Texture& texture, Math::IntPoint offset, ImageData* data, TexImgFormat format) override;
void DestroyTexture(const Texture &texture) override; void DestroyTexture(const Texture &texture) override;
void DestroyAllTextures() override; void DestroyAllTextures() override;

View File

@ -19,6 +19,7 @@
#include "graphics/opengl/glutil.h" #include "graphics/opengl/glutil.h"
#include "common/image.h"
#include "common/logger.h" #include "common/logger.h"
#include "common/make_unique.h" #include "common/make_unique.h"
@ -26,6 +27,7 @@
#include "graphics/opengl/gl33device.h" #include "graphics/opengl/gl33device.h"
#include "graphics/opengl/gldevice.h" #include "graphics/opengl/gldevice.h"
#include <SDL.h>
#include <physfs.h> #include <physfs.h>
#include <cstring> #include <cstring>
#include <vector> #include <vector>
@ -536,5 +538,115 @@ std::unique_ptr<CGLFrameBufferPixels> GetGLFrameBufferPixels(Math::IntPoint size
return pixels; return pixels;
} }
PreparedTextureData PrepareTextureData(ImageData* imageData, TexImgFormat format)
{
PreparedTextureData texData;
bool convert = false;
texData.sourceFormat = 0;
if (format == TEX_IMG_RGB)
{
texData.sourceFormat = GL_RGB;
texData.alpha = false;
}
else if (format == TEX_IMG_BGR)
{
texData.sourceFormat = GL_BGR;
texData.alpha = false;
}
else if (format == TEX_IMG_RGBA)
{
texData.sourceFormat = GL_RGBA;
texData.alpha = true;
}
else if (format == TEX_IMG_BGRA)
{
texData.sourceFormat = GL_BGRA;
texData.alpha = true;
}
else if (format == TEX_IMG_AUTO)
{
if (imageData->surface->format->BytesPerPixel == 4)
{
if ((imageData->surface->format->Amask == 0xFF000000) &&
(imageData->surface->format->Rmask == 0x00FF0000) &&
(imageData->surface->format->Gmask == 0x0000FF00) &&
(imageData->surface->format->Bmask == 0x000000FF))
{
texData.sourceFormat = GL_BGRA;
texData.alpha = true;
}
else if ((imageData->surface->format->Amask == 0xFF000000) &&
(imageData->surface->format->Bmask == 0x00FF0000) &&
(imageData->surface->format->Gmask == 0x0000FF00) &&
(imageData->surface->format->Rmask == 0x000000FF))
{
texData.sourceFormat = GL_RGBA;
texData.alpha = true;
}
else
{
texData.sourceFormat = GL_RGBA;
convert = true;
}
}
else if (imageData->surface->format->BytesPerPixel == 3)
{
if ((imageData->surface->format->Rmask == 0xFF0000) &&
(imageData->surface->format->Gmask == 0x00FF00) &&
(imageData->surface->format->Bmask == 0x0000FF))
{
texData.sourceFormat = GL_BGR;
texData.alpha = false;
}
else if ((imageData->surface->format->Bmask == 0xFF0000) &&
(imageData->surface->format->Gmask == 0x00FF00) &&
(imageData->surface->format->Rmask == 0x0000FF))
{
texData.sourceFormat = GL_RGB;
texData.alpha = false;
}
else
{
texData.sourceFormat = GL_RGBA;
convert = true;
}
}
else
{
GetLogger()->Error("Unknown data surface format");
assert(false);
}
}
else
assert(false);
texData.actualSurface = imageData->surface;
texData.convertedSurface = nullptr;
if (convert)
{
SDL_PixelFormat format;
format.BytesPerPixel = 4;
format.BitsPerPixel = 32;
format.Aloss = format.Bloss = format.Gloss = format.Rloss = 0;
format.Amask = 0xFF000000;
format.Ashift = 24;
format.Bmask = 0x00FF0000;
format.Bshift = 16;
format.Gmask = 0x0000FF00;
format.Gshift = 8;
format.Rmask = 0x000000FF;
format.Rshift = 0;
format.palette = nullptr;
texData.convertedSurface = SDL_ConvertSurface(imageData->surface, &format, SDL_SWSURFACE);
if (texData.convertedSurface != nullptr)
texData.actualSurface = texData.convertedSurface;
}
return texData;
}
} // namespace Gfx } // namespace Gfx

View File

@ -34,6 +34,8 @@
#include <string> #include <string>
#include <memory> #include <memory>
struct SDL_Surface;
// Graphics module namespace // Graphics module namespace
namespace Gfx namespace Gfx
@ -97,6 +99,17 @@ GLint LoadShader(GLint type, const char* filename);
GLint LinkProgram(int count, GLint shaders[]); GLint LinkProgram(int count, GLint shaders[]);
// TODO: Moved this here temporarily only to remove code duplication in CGLDeviceXX
struct PreparedTextureData
{
SDL_Surface* actualSurface = nullptr;
SDL_Surface* convertedSurface = nullptr;
GLenum sourceFormat = 0;
bool alpha = false;
};
PreparedTextureData PrepareTextureData(ImageData* data, TexImgFormat format);
class CGLFrameBufferPixels : public CFrameBufferPixels class CGLFrameBufferPixels : public CFrameBufferPixels
{ {
public: public: