From 408dc6ff970ba9b1c0ee28f62da2aa532e0a5aaf Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Sun, 21 Nov 2021 18:25:17 -0800 Subject: [PATCH] Moved texture upload to context. --- common/lc_context.cpp | 119 +++++++++++++++++++++++++++++++++++ common/lc_context.h | 1 + common/lc_texture.cpp | 141 ++++++------------------------------------ common/lc_texture.h | 17 ++++- 4 files changed, 154 insertions(+), 124 deletions(-) diff --git a/common/lc_context.cpp b/common/lc_context.cpp index 1286e641..180dd62b 100644 --- a/common/lc_context.cpp +++ b/common/lc_context.cpp @@ -668,6 +668,125 @@ void lcContext::ClearTextureCubeMap() mTextureCubeMap = 0; } +void lcContext::UploadTexture(lcTexture* Texture) +{ + if (!Texture->mTexture) + glGenTextures(1, &Texture->mTexture); + + constexpr int Filters[2][5] = + { + { GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR }, + { GL_NEAREST, GL_LINEAR, GL_LINEAR, GL_LINEAR, GL_LINEAR }, + }; + + const int Flags = Texture->GetFlags(); + const int FilterFlags = Flags & LC_TEXTURE_FILTER_MASK; + const int FilterIndex = FilterFlags >> LC_TEXTURE_FILTER_SHIFT; + const int MipIndex = Flags & LC_TEXTURE_MIPMAPS ? 0 : 1; + + unsigned int Faces, Target; + + if ((Flags & LC_TEXTURE_CUBEMAP) == 0) + { + Faces = 1; + Target = GL_TEXTURE_2D; + BindTexture2D(Texture); + } + else + { + Faces = 6; + Target = GL_TEXTURE_CUBE_MAP; + BindTextureCubeMap(Texture); + } + + glTexParameteri(Target, GL_TEXTURE_WRAP_S, (Flags & LC_TEXTURE_WRAPU) ? GL_REPEAT : GL_CLAMP_TO_EDGE); + glTexParameteri(Target, GL_TEXTURE_WRAP_T, (Flags & LC_TEXTURE_WRAPV) ? GL_REPEAT : GL_CLAMP_TO_EDGE); + glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, Filters[MipIndex][FilterIndex]); + glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, Filters[1][FilterIndex]); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + + if (gSupportsAnisotropic && FilterFlags == LC_TEXTURE_ANISOTROPIC) + glTexParameterf(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, lcMin(4.0f, gMaxAnisotropy)); + + int Format; + switch (Texture->GetImage(0).mFormat) + { + default: + case lcPixelFormat::Invalid: + Format = 0; + break; + case lcPixelFormat::A8: + Format = GL_ALPHA; + break; + case lcPixelFormat::L8A8: + Format = GL_LUMINANCE_ALPHA; + break; + case lcPixelFormat::R8G8B8: + Format = GL_RGB; + break; + case lcPixelFormat::R8G8B8A8: + Format = GL_RGBA; + break; + } + + int CurrentImage = 0; + if (Flags & LC_TEXTURE_CUBEMAP) + Target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; + + for (size_t FaceIdx = 0; FaceIdx < Faces; FaceIdx++) + { + void* Data = Texture->GetImage(CurrentImage).mData; + glTexImage2D(Target, 0, Format, Texture->mWidth, Texture->mHeight, 0, Format, GL_UNSIGNED_BYTE, Data); + + if (Flags & LC_TEXTURE_MIPMAPS || FilterFlags >= LC_TEXTURE_BILINEAR) + { + int Width = Texture->mWidth; + int Height = Texture->mHeight; + int Components = Texture->GetImage(CurrentImage).GetBPP(); + + for (int Level = 1; ((Width != 1) || (Height != 1)); Level++) + { + int RowStride = Width * Components; + + Width = lcMax(1, Width >> 1); + Height = lcMax(1, Height >> 1); + + if (Texture->GetImageCount() == Faces) + { + GLubyte* Out, * In; + + In = Out = (GLubyte*)Data; + + for (int y = 0; y < Height; y++, In += RowStride) + for (int x = 0; x < Width; x++, Out += Components, In += 2 * Components) + for (int c = 0; c < Components; c++) + Out[c] = (In[c] + In[c + Components] + In[RowStride] + In[c + RowStride + Components]) / 4; + } + else + Data = Texture->GetImage(++CurrentImage).mData; + + glTexImage2D(Target, Level, Format, Width, Height, 0, Format, GL_UNSIGNED_BYTE, Data); + } + + if (Texture->GetImageCount() == Faces) + CurrentImage++; + } + else + CurrentImage++; + + Target++; + } + + if ((Flags & LC_TEXTURE_CUBEMAP) == 0) + ClearTexture2D(); + else + ClearTextureCubeMap(); +} + void lcContext::SetColor(float Red, float Green, float Blue, float Alpha) { SetColor(lcVector4(Red, Green, Blue, Alpha)); diff --git a/common/lc_context.h b/common/lc_context.h index 7d85a0af..8ee257f5 100644 --- a/common/lc_context.h +++ b/common/lc_context.h @@ -172,6 +172,7 @@ public: void BindTextureCubeMap(const lcTexture* Texture); void ClearTexture2D(); void ClearTextureCubeMap(); + void UploadTexture(lcTexture* Texture); void SetColor(const lcVector4& Color) { diff --git a/common/lc_texture.cpp b/common/lc_texture.cpp index 56d311e7..1f61a9c1 100644 --- a/common/lc_texture.cpp +++ b/common/lc_texture.cpp @@ -171,22 +171,26 @@ bool lcTexture::Load() bool lcTexture::Load(const QString& FileName, int Flags) { - mImages.resize(1); + Image Image; - if (!mImages[0].FileLoad(FileName)) + if (!Image.FileLoad(FileName)) return false; - return Load(Flags); + SetImage(std::move(Image), Flags); + + return true; } bool lcTexture::Load(lcMemFile& File, int Flags) { - mImages.resize(1); + Image Image; - if (!mImages[0].FileLoad(File)) + if (!Image.FileLoad(File)) return false; - return Load(Flags); + SetImage(std::move(Image), Flags); + + return true; } void lcTexture::SetImage(Image&& Image, int Flags) @@ -195,7 +199,7 @@ void lcTexture::SetImage(Image&& Image, int Flags) mImages.emplace_back(std::move(Image)); mFlags = Flags; - Load(Flags); + LoadImages(); } void lcTexture::SetImage(std::vector&& Images, int Flags) @@ -203,135 +207,26 @@ void lcTexture::SetImage(std::vector&& Images, int Flags) mImages = std::move(Images); mFlags = Flags; - Load(Flags); + LoadImages(); } void lcTexture::Upload(lcContext* Context) { + if (!NeedsUpload()) + return; + mWidth = mImages[0].mWidth; mHeight = mImages[0].mHeight; - if (!mTexture) - glGenTextures(1, &mTexture); + Context->UploadTexture(this); - constexpr int Filters[2][5] = - { - { GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR }, - { GL_NEAREST, GL_LINEAR, GL_LINEAR, GL_LINEAR, GL_LINEAR }, - }; - - const int FilterFlags = mFlags & LC_TEXTURE_FILTER_MASK; - const int FilterIndex = FilterFlags >> LC_TEXTURE_FILTER_SHIFT; - const int MipIndex = mFlags & LC_TEXTURE_MIPMAPS ? 0 : 1; - - unsigned int Faces, Target; - - if ((mFlags & LC_TEXTURE_CUBEMAP) == 0) - { - Faces = 1; - Target = GL_TEXTURE_2D; - Context->BindTexture2D(this); - } - else - { - Faces = 6; - Target = GL_TEXTURE_CUBE_MAP; - Context->BindTextureCubeMap(this); - } - - glTexParameteri(Target, GL_TEXTURE_WRAP_S, (mFlags & LC_TEXTURE_WRAPU) ? GL_REPEAT : GL_CLAMP_TO_EDGE); - glTexParameteri(Target, GL_TEXTURE_WRAP_T, (mFlags & LC_TEXTURE_WRAPV) ? GL_REPEAT : GL_CLAMP_TO_EDGE); - glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, Filters[MipIndex][FilterIndex]); - glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, Filters[1][FilterIndex]); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - - if (gSupportsAnisotropic && FilterFlags == LC_TEXTURE_ANISOTROPIC) - glTexParameterf(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, lcMin(4.0f, gMaxAnisotropy)); - - int Format; - switch (mImages[0].mFormat) - { - default: - case lcPixelFormat::Invalid: - Format = 0; - break; - case lcPixelFormat::A8: - Format = GL_ALPHA; - break; - case lcPixelFormat::L8A8: - Format = GL_LUMINANCE_ALPHA; - break; - case lcPixelFormat::R8G8B8: - Format = GL_RGB; - break; - case lcPixelFormat::R8G8B8A8: - Format = GL_RGBA; - break; - } - - int CurrentImage = 0; - if (mFlags & LC_TEXTURE_CUBEMAP) - Target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; - - for (size_t FaceIdx = 0; FaceIdx < Faces; FaceIdx++) - { - void* Data = mImages[CurrentImage].mData; - glTexImage2D(Target, 0, Format, mWidth, mHeight, 0, Format, GL_UNSIGNED_BYTE, Data); - - if (mFlags & LC_TEXTURE_MIPMAPS || FilterFlags >= LC_TEXTURE_BILINEAR) - { - int Width = mWidth; - int Height = mHeight; - int Components = mImages[CurrentImage].GetBPP(); - - for (int Level = 1; ((Width != 1) || (Height != 1)); Level++) - { - int RowStride = Width * Components; - - Width = lcMax(1, Width >> 1); - Height = lcMax(1, Height >> 1); - - if (mImages.size() == Faces) - { - GLubyte *Out, *In; - - In = Out = (GLubyte*)Data; - - for (int y = 0; y < Height; y++, In += RowStride) - for (int x = 0; x < Width; x++, Out += Components, In += 2 * Components) - for (int c = 0; c < Components; c++) - Out[c] = (In[c] + In[c + Components] + In[RowStride] + In[c + RowStride + Components]) / 4; - } - else - Data = mImages[++CurrentImage].mData; - - glTexImage2D(Target, Level, Format, Width, Height, 0, Format, GL_UNSIGNED_BYTE, Data); - } - - if (mImages.size() == Faces) - CurrentImage++; - } - else - CurrentImage++; - - Target++; - } - - if ((mFlags & LC_TEXTURE_CUBEMAP) == 0) - Context->ClearTexture2D(); - else - Context->ClearTextureCubeMap(); + mImages.clear(); } -bool lcTexture::Load(int Flags) +bool lcTexture::LoadImages() { for (Image& Image : mImages) Image.ResizePow2(); - mFlags = Flags; if (QThread::currentThread() == qApp->thread()) { diff --git a/common/lc_texture.h b/common/lc_texture.h index 57ca9906..74dbb3ac 100644 --- a/common/lc_texture.h +++ b/common/lc_texture.h @@ -70,6 +70,21 @@ public: return mTexture == 0 && !mImages.empty(); } + int GetFlags() const + { + return mFlags; + } + + const Image& GetImage(int Index) const + { + return mImages[Index]; + } + + size_t GetImageCount() const + { + return mImages.size(); + } + int mWidth; int mHeight; char mName[LC_TEXTURE_NAME_LEN]; @@ -78,7 +93,7 @@ public: protected: bool Load(); - bool Load(int Flags); + bool LoadImages(); bool mTemporary; QAtomicInt mRefCount;