mirror of
https://github.com/leozide/leocad
synced 2025-02-07 08:45:49 +01:00
Only upload textures from the main thread.
This commit is contained in:
parent
a57c6275c0
commit
880f8f9a47
5 changed files with 67 additions and 42 deletions
|
@ -1687,6 +1687,22 @@ void lcPiecesLibrary::ReleaseTexture(lcTexture* Texture)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lcPiecesLibrary::QueueTextureUpload(lcTexture* Texture)
|
||||||
|
{
|
||||||
|
QMutexLocker Lock(&mTextureMutex);
|
||||||
|
mTextureUploads.push_back(Texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lcPiecesLibrary::UploadTextures()
|
||||||
|
{
|
||||||
|
QMutexLocker Lock(&mTextureMutex);
|
||||||
|
|
||||||
|
for (lcTexture* Texture : mTextureUploads)
|
||||||
|
Texture->Upload();
|
||||||
|
|
||||||
|
mTextureUploads.clear();
|
||||||
|
}
|
||||||
|
|
||||||
bool lcPiecesLibrary::LoadPrimitive(lcLibraryPrimitive* Primitive)
|
bool lcPiecesLibrary::LoadPrimitive(lcLibraryPrimitive* Primitive)
|
||||||
{
|
{
|
||||||
mLoadMutex.lock();
|
mLoadMutex.lock();
|
||||||
|
|
|
@ -179,6 +179,8 @@ public:
|
||||||
lcTexture* FindTexture(const char* TextureName, Project* CurrentProject, bool SearchProjectFolder);
|
lcTexture* FindTexture(const char* TextureName, Project* CurrentProject, bool SearchProjectFolder);
|
||||||
bool LoadTexture(lcTexture* Texture);
|
bool LoadTexture(lcTexture* Texture);
|
||||||
void ReleaseTexture(lcTexture* Texture);
|
void ReleaseTexture(lcTexture* Texture);
|
||||||
|
void QueueTextureUpload(lcTexture* Texture);
|
||||||
|
void UploadTextures();
|
||||||
|
|
||||||
bool PieceInCategory(PieceInfo* Info, const char* CategoryKeywords) const;
|
bool PieceInCategory(PieceInfo* Info, const char* CategoryKeywords) const;
|
||||||
void GetCategoryEntries(int CategoryIndex, bool GroupPieces, lcArray<PieceInfo*>& SinglePieces, lcArray<PieceInfo*>& GroupedPieces);
|
void GetCategoryEntries(int CategoryIndex, bool GroupPieces, lcArray<PieceInfo*>& SinglePieces, lcArray<PieceInfo*>& GroupedPieces);
|
||||||
|
@ -246,6 +248,9 @@ protected:
|
||||||
QList<QFuture<void>> mLoadFutures;
|
QList<QFuture<void>> mLoadFutures;
|
||||||
QList<PieceInfo*> mLoadQueue;
|
QList<PieceInfo*> mLoadQueue;
|
||||||
|
|
||||||
|
QMutex mTextureMutex;
|
||||||
|
std::vector<lcTexture*> mTextureUploads;
|
||||||
|
|
||||||
QString mCachePath;
|
QString mCachePath;
|
||||||
qint64 mArchiveCheckSum[4];
|
qint64 mArchiveCheckSum[4];
|
||||||
QString mLibraryFileName;
|
QString mLibraryFileName;
|
||||||
|
|
|
@ -219,7 +219,9 @@ void lcScene::DrawRenderMeshes(lcContext* Context, int PrimitiveTypes, bool Enab
|
||||||
|
|
||||||
void lcScene::Draw(lcContext* Context) const
|
void lcScene::Draw(lcContext* Context) const
|
||||||
{
|
{
|
||||||
lcGetPiecesLibrary()->UpdateBuffers(Context); // TODO: find a better place for this update
|
// TODO: find a better place for these updates
|
||||||
|
lcGetPiecesLibrary()->UpdateBuffers(Context);
|
||||||
|
lcGetPiecesLibrary()->UploadTextures();
|
||||||
|
|
||||||
Context->SetViewMatrix(mViewMatrix);
|
Context->SetViewMatrix(mViewMatrix);
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ lcTexture* lcLoadTexture(const QString& FileName, int Flags)
|
||||||
|
|
||||||
void lcReleaseTexture(lcTexture* Texture)
|
void lcReleaseTexture(lcTexture* Texture)
|
||||||
{
|
{
|
||||||
if (Texture && Texture->Release() == 0)
|
if (Texture && !Texture->Release())
|
||||||
delete Texture;
|
delete Texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,12 +46,12 @@ lcTexture::~lcTexture()
|
||||||
void lcTexture::CreateGridTexture()
|
void lcTexture::CreateGridTexture()
|
||||||
{
|
{
|
||||||
const int NumLevels = 9;
|
const int NumLevels = 9;
|
||||||
Image GridImages[NumLevels];
|
mImages.resize(NumLevels);
|
||||||
quint8* Previous = nullptr;
|
quint8* Previous = nullptr;
|
||||||
|
|
||||||
for (int ImageLevel = 0; ImageLevel < NumLevels; ImageLevel++)
|
for (int ImageLevel = 0; ImageLevel < NumLevels; ImageLevel++)
|
||||||
{
|
{
|
||||||
Image& GridImage = GridImages[ImageLevel];
|
Image& GridImage = mImages[ImageLevel];
|
||||||
const int GridSize = 256 >> ImageLevel;
|
const int GridSize = 256 >> ImageLevel;
|
||||||
GridImage.Allocate(GridSize, GridSize, LC_PIXEL_FORMAT_A8);
|
GridImage.Allocate(GridSize, GridSize, LC_PIXEL_FORMAT_A8);
|
||||||
|
|
||||||
|
@ -156,9 +156,10 @@ void lcTexture::CreateGridTexture()
|
||||||
Previous = GridImage.mData;
|
Previous = GridImage.mData;
|
||||||
}
|
}
|
||||||
|
|
||||||
Load(GridImages, NumLevels, LC_TEXTURE_WRAPU | LC_TEXTURE_WRAPV | LC_TEXTURE_MIPMAPS | LC_TEXTURE_ANISOTROPIC);
|
|
||||||
|
|
||||||
mRefCount = 1;
|
mRefCount = 1;
|
||||||
|
mFlags = LC_TEXTURE_WRAPU | LC_TEXTURE_WRAPV | LC_TEXTURE_MIPMAPS | LC_TEXTURE_ANISOTROPIC;
|
||||||
|
|
||||||
|
lcGetPiecesLibrary()->QueueTextureUpload(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lcTexture::Load()
|
bool lcTexture::Load()
|
||||||
|
@ -168,28 +169,28 @@ bool lcTexture::Load()
|
||||||
|
|
||||||
bool lcTexture::Load(const QString& FileName, int Flags)
|
bool lcTexture::Load(const QString& FileName, int Flags)
|
||||||
{
|
{
|
||||||
Image image;
|
mImages.resize(1);
|
||||||
|
|
||||||
if (!image.FileLoad(FileName))
|
if (!mImages[0].FileLoad(FileName))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return Load(image, Flags);
|
return Load(Flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lcTexture::Load(lcMemFile& File, int Flags)
|
bool lcTexture::Load(lcMemFile& File, int Flags)
|
||||||
{
|
{
|
||||||
Image image;
|
mImages.resize(1);
|
||||||
|
|
||||||
if (!image.FileLoad(File))
|
if (!mImages[0].FileLoad(File))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return Load(image, Flags);
|
return Load(Flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lcTexture::Load(Image* images, int NumLevels, int Flags) // todo: this should be part of lcContext, it can be called from multiple threads
|
void lcTexture::Upload()
|
||||||
{
|
{
|
||||||
mWidth = images[0].mWidth;
|
mWidth = mImages[0].mWidth;
|
||||||
mHeight = images[0].mHeight;
|
mHeight = mImages[0].mHeight;
|
||||||
|
|
||||||
glGenTextures(1, &mTexture);
|
glGenTextures(1, &mTexture);
|
||||||
|
|
||||||
|
@ -199,13 +200,13 @@ bool lcTexture::Load(Image* images, int NumLevels, int Flags) // todo: this shou
|
||||||
{ GL_NEAREST, GL_LINEAR, GL_LINEAR, GL_LINEAR, GL_LINEAR },
|
{ GL_NEAREST, GL_LINEAR, GL_LINEAR, GL_LINEAR, GL_LINEAR },
|
||||||
};
|
};
|
||||||
|
|
||||||
int FilterFlags = Flags & LC_TEXTURE_FILTER_MASK;
|
int FilterFlags = mFlags & LC_TEXTURE_FILTER_MASK;
|
||||||
int FilterIndex = FilterFlags >> LC_TEXTURE_FILTER_SHIFT;
|
int FilterIndex = FilterFlags >> LC_TEXTURE_FILTER_SHIFT;
|
||||||
int MipIndex = Flags & LC_TEXTURE_MIPMAPS ? 0 : 1;
|
int MipIndex = mFlags & LC_TEXTURE_MIPMAPS ? 0 : 1;
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, mTexture);
|
glBindTexture(GL_TEXTURE_2D, mTexture);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (Flags & LC_TEXTURE_WRAPU) ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (mFlags & LC_TEXTURE_WRAPU) ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (Flags & LC_TEXTURE_WRAPV) ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (mFlags & LC_TEXTURE_WRAPV) ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filters[MipIndex][FilterIndex]);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filters[MipIndex][FilterIndex]);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Filters[1][FilterIndex]);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Filters[1][FilterIndex]);
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
@ -214,7 +215,7 @@ bool lcTexture::Load(Image* images, int NumLevels, int Flags) // todo: this shou
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, lcMin(4.0f, gMaxAnisotropy));
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, lcMin(4.0f, gMaxAnisotropy));
|
||||||
|
|
||||||
int Format;
|
int Format;
|
||||||
switch (images[0].mFormat)
|
switch (mImages[0].mFormat)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
case LC_PIXEL_FORMAT_INVALID:
|
case LC_PIXEL_FORMAT_INVALID:
|
||||||
|
@ -234,15 +235,15 @@ bool lcTexture::Load(Image* images, int NumLevels, int Flags) // todo: this shou
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* Data = images[0].mData;
|
void* Data = mImages[0].mData;
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, Format, mWidth, mHeight, 0, Format, GL_UNSIGNED_BYTE, Data);
|
glTexImage2D(GL_TEXTURE_2D, 0, Format, mWidth, mHeight, 0, Format, GL_UNSIGNED_BYTE, Data);
|
||||||
int MaxLevel = 0;
|
int MaxLevel = 0;
|
||||||
|
|
||||||
if (Flags & LC_TEXTURE_MIPMAPS)
|
if (mFlags & LC_TEXTURE_MIPMAPS)
|
||||||
{
|
{
|
||||||
int Width = mWidth;
|
int Width = mWidth;
|
||||||
int Height = mHeight;
|
int Height = mHeight;
|
||||||
int Components = images[0].GetBPP();
|
int Components = mImages[0].GetBPP();
|
||||||
|
|
||||||
for (int Level = 1; ((Width != 1) || (Height != 1)); Level++)
|
for (int Level = 1; ((Width != 1) || (Height != 1)); Level++)
|
||||||
{
|
{
|
||||||
|
@ -251,7 +252,7 @@ bool lcTexture::Load(Image* images, int NumLevels, int Flags) // todo: this shou
|
||||||
Width = lcMax(1, Width >> 1);
|
Width = lcMax(1, Width >> 1);
|
||||||
Height = lcMax(1, Height >> 1);
|
Height = lcMax(1, Height >> 1);
|
||||||
|
|
||||||
if (NumLevels == 1)
|
if (mImages.size() == 1)
|
||||||
{
|
{
|
||||||
GLubyte *Out, *In;
|
GLubyte *Out, *In;
|
||||||
|
|
||||||
|
@ -263,7 +264,7 @@ bool lcTexture::Load(Image* images, int NumLevels, int Flags) // todo: this shou
|
||||||
Out[c] = (In[c] + In[c + Components] + In[RowStride] + In[c + RowStride + Components]) / 4;
|
Out[c] = (In[c] + In[c + Components] + In[RowStride] + In[c + RowStride + Components]) / 4;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Data = images[Level].mData;
|
Data = mImages[Level].mData;
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, Level, Format, Width, Height, 0, Format, GL_UNSIGNED_BYTE, Data);
|
glTexImage2D(GL_TEXTURE_2D, Level, Format, Width, Height, 0, Format, GL_UNSIGNED_BYTE, Data);
|
||||||
MaxLevel++;
|
MaxLevel++;
|
||||||
|
@ -272,15 +273,16 @@ bool lcTexture::Load(Image* images, int NumLevels, int Flags) // todo: this shou
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, MaxLevel);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, MaxLevel);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lcTexture::Load(Image& image, int Flags)
|
bool lcTexture::Load(int Flags)
|
||||||
{
|
{
|
||||||
image.ResizePow2();
|
for (Image& Image : mImages)
|
||||||
|
Image.ResizePow2();
|
||||||
|
mFlags = Flags;
|
||||||
|
|
||||||
return Load(&image, 1, Flags);
|
lcGetPiecesLibrary()->QueueTextureUpload(this);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcTexture::Unload()
|
void lcTexture::Unload()
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
#define LC_TEXTURE_NAME_LEN 256
|
#define LC_TEXTURE_NAME_LEN 256
|
||||||
|
|
||||||
class Image;
|
#include "image.h"
|
||||||
|
|
||||||
class lcTexture
|
class lcTexture
|
||||||
{
|
{
|
||||||
|
@ -26,28 +26,25 @@ public:
|
||||||
|
|
||||||
bool Load(const QString& FileName, int Flags = 0);
|
bool Load(const QString& FileName, int Flags = 0);
|
||||||
bool Load(lcMemFile& File, int Flags = 0);
|
bool Load(lcMemFile& File, int Flags = 0);
|
||||||
bool Load(Image& image, int Flags);
|
void Upload();
|
||||||
bool Load(Image* images, int NumLevels, int Flags);
|
|
||||||
void Unload();
|
void Unload();
|
||||||
|
|
||||||
int AddRef()
|
void AddRef()
|
||||||
{
|
{
|
||||||
mRefCount++;
|
mRefCount.ref();
|
||||||
|
|
||||||
if (mRefCount == 1)
|
if (mRefCount == 1)
|
||||||
Load();
|
Load();
|
||||||
|
|
||||||
return mRefCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Release()
|
bool Release()
|
||||||
{
|
{
|
||||||
mRefCount--;
|
bool InUse = mRefCount.deref();
|
||||||
|
|
||||||
if (!mRefCount)
|
if (!InUse)
|
||||||
Unload();
|
Unload();
|
||||||
|
|
||||||
return mRefCount;
|
return InUse;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetTemporary(bool Temporary)
|
void SetTemporary(bool Temporary)
|
||||||
|
@ -67,9 +64,12 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool Load();
|
bool Load();
|
||||||
|
bool Load(int Flags);
|
||||||
|
|
||||||
bool mTemporary;
|
bool mTemporary;
|
||||||
int mRefCount;
|
QAtomicInt mRefCount;
|
||||||
|
std::vector<Image> mImages;
|
||||||
|
int mFlags;
|
||||||
};
|
};
|
||||||
|
|
||||||
lcTexture* lcLoadTexture(const QString& FileName, int Flags);
|
lcTexture* lcLoadTexture(const QString& FileName, int Flags);
|
||||||
|
|
Loading…
Add table
Reference in a new issue