diff --git a/src/graphics/core/device.h b/src/graphics/core/device.h index 2636d2e8..b690cf35 100644 --- a/src/graphics/core/device.h +++ b/src/graphics/core/device.h @@ -357,6 +357,8 @@ public: virtual Texture CreateTexture(ImageData *data, const TextureCreateParams ¶ms) = 0; //! Creates a depth texture with specific dimensions and depth 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 virtual void DestroyTexture(const Texture &texture) = 0; //! Deletes all textures created so far diff --git a/src/graphics/core/nulldevice.cpp b/src/graphics/core/nulldevice.cpp index aeae90f0..5ab4ec08 100644 --- a/src/graphics/core/nulldevice.cpp +++ b/src/graphics/core/nulldevice.cpp @@ -120,6 +120,10 @@ Texture CNullDevice::CreateDepthTexture(int width, int height, int depth) return tex; } +void CNullDevice::UpdateTexture(const Texture& texture, Math::IntPoint offset, ImageData* data, TexImgFormat format) +{ +} + void CNullDevice::DestroyTexture(const Texture &texture) { } diff --git a/src/graphics/core/nulldevice.h b/src/graphics/core/nulldevice.h index d89902a2..68f2effc 100644 --- a/src/graphics/core/nulldevice.h +++ b/src/graphics/core/nulldevice.h @@ -74,6 +74,7 @@ public: Texture CreateTexture(CImage *image, const TextureCreateParams ¶ms) override; Texture CreateTexture(ImageData *data, const TextureCreateParams ¶ms) 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 DestroyAllTextures() override; diff --git a/src/graphics/opengl/gl21device.cpp b/src/graphics/opengl/gl21device.cpp index 66b6dd3b..e4f6145b 100644 --- a/src/graphics/opengl/gl21device.cpp +++ b/src/graphics/opengl/gl21device.cpp @@ -820,113 +820,13 @@ Texture CGL21Device::CreateTexture(ImageData *data, const TextureCreateParams &p glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, level); } - bool convert = false; - GLenum sourceFormat = 0; + PreparedTextureData texData = PrepareTextureData(data, params.format); + result.alpha = texData.alpha; - if (params.format == TEX_IMG_RGB) - { - 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); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texData.actualSurface->w, texData.actualSurface->h, + 0, texData.sourceFormat, GL_UNSIGNED_BYTE, texData.actualSurface->pixels); - 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); - - SDL_FreeSurface(convertedSurface); + SDL_FreeSurface(texData.convertedSurface); m_allTextures.insert(result); @@ -985,6 +885,21 @@ Texture CGL21Device::CreateDepthTexture(int width, int height, int depth) 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) { // Unbind the texture if in use anywhere diff --git a/src/graphics/opengl/gl21device.h b/src/graphics/opengl/gl21device.h index 7e941f82..c772626a 100644 --- a/src/graphics/opengl/gl21device.h +++ b/src/graphics/opengl/gl21device.h @@ -87,6 +87,7 @@ public: Texture CreateTexture(CImage *image, const TextureCreateParams ¶ms) override; Texture CreateTexture(ImageData *data, const TextureCreateParams ¶ms) 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 DestroyAllTextures() override; diff --git a/src/graphics/opengl/gl33device.cpp b/src/graphics/opengl/gl33device.cpp index 9a2d9f1d..f355aff1 100644 --- a/src/graphics/opengl/gl33device.cpp +++ b/src/graphics/opengl/gl33device.cpp @@ -849,116 +849,16 @@ Texture CGL33Device::CreateTexture(ImageData *data, const TextureCreateParams &p glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, level); } - bool convert = false; - GLenum sourceFormat = 0; + PreparedTextureData texData = PrepareTextureData(data, params.format); + result.alpha = texData.alpha; - if (params.format == TEX_IMG_RGB) - { - 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); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texData.actualSurface->w, texData.actualSurface->h, + 0, texData.sourceFormat, GL_UNSIGNED_BYTE, texData.actualSurface->pixels); if (params.mipmap) glGenerateMipmap(GL_TEXTURE_2D); - SDL_FreeSurface(convertedSurface); + SDL_FreeSurface(texData.convertedSurface); m_allTextures.insert(result); @@ -1013,6 +913,20 @@ Texture CGL33Device::CreateDepthTexture(int width, int height, int depth) 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) { // Unbind the texture if in use anywhere diff --git a/src/graphics/opengl/gl33device.h b/src/graphics/opengl/gl33device.h index 49b04977..93e42b08 100644 --- a/src/graphics/opengl/gl33device.h +++ b/src/graphics/opengl/gl33device.h @@ -89,6 +89,7 @@ public: Texture CreateTexture(CImage *image, const TextureCreateParams ¶ms) override; Texture CreateTexture(ImageData *data, const TextureCreateParams ¶ms) 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 DestroyAllTextures() override; diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp index 4b45d0d7..fcaf7d0e 100644 --- a/src/graphics/opengl/gldevice.cpp +++ b/src/graphics/opengl/gldevice.cpp @@ -722,113 +722,13 @@ Texture CGLDevice::CreateTexture(ImageData *data, const TextureCreateParams &par glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, level); } - bool convert = false; - GLenum sourceFormat = 0; + PreparedTextureData texData = PrepareTextureData(data, params.format); + result.alpha = texData.alpha; - if (params.format == TEX_IMG_RGB) - { - 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); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texData.actualSurface->w, texData.actualSurface->h, + 0, texData.sourceFormat, GL_UNSIGNED_BYTE, texData.actualSurface->pixels); - 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); - - SDL_FreeSurface(convertedSurface); + SDL_FreeSurface(texData.convertedSurface); m_allTextures.insert(result); @@ -915,6 +815,23 @@ Texture CGLDevice::CreateDepthTexture(int width, int height, int depth) 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) { // Unbind the texture if in use anywhere diff --git a/src/graphics/opengl/gldevice.h b/src/graphics/opengl/gldevice.h index 0de4d003..390d3ae1 100644 --- a/src/graphics/opengl/gldevice.h +++ b/src/graphics/opengl/gldevice.h @@ -106,6 +106,7 @@ public: Texture CreateTexture(CImage *image, const TextureCreateParams ¶ms) override; Texture CreateTexture(ImageData *data, const TextureCreateParams ¶ms) 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 DestroyAllTextures() override; diff --git a/src/graphics/opengl/glutil.cpp b/src/graphics/opengl/glutil.cpp index e91bbf15..06135e4e 100644 --- a/src/graphics/opengl/glutil.cpp +++ b/src/graphics/opengl/glutil.cpp @@ -19,6 +19,7 @@ #include "graphics/opengl/glutil.h" +#include "common/image.h" #include "common/logger.h" #include "common/make_unique.h" @@ -26,6 +27,7 @@ #include "graphics/opengl/gl33device.h" #include "graphics/opengl/gldevice.h" +#include #include #include #include @@ -536,5 +538,115 @@ std::unique_ptr GetGLFrameBufferPixels(Math::IntPoint size 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 diff --git a/src/graphics/opengl/glutil.h b/src/graphics/opengl/glutil.h index df99ceb8..6fbb9658 100644 --- a/src/graphics/opengl/glutil.h +++ b/src/graphics/opengl/glutil.h @@ -34,6 +34,8 @@ #include #include +struct SDL_Surface; + // Graphics module namespace namespace Gfx @@ -97,6 +99,17 @@ GLint LoadShader(GLint type, const char* filename); 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 { public: