Only upload textures from the main thread.

This commit is contained in:
Leonardo 2017-12-22 05:42:28 -08:00
parent a57c6275c0
commit 880f8f9a47
5 changed files with 67 additions and 42 deletions

View file

@ -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)
{
mLoadMutex.lock();

View file

@ -179,6 +179,8 @@ public:
lcTexture* FindTexture(const char* TextureName, Project* CurrentProject, bool SearchProjectFolder);
bool LoadTexture(lcTexture* Texture);
void ReleaseTexture(lcTexture* Texture);
void QueueTextureUpload(lcTexture* Texture);
void UploadTextures();
bool PieceInCategory(PieceInfo* Info, const char* CategoryKeywords) const;
void GetCategoryEntries(int CategoryIndex, bool GroupPieces, lcArray<PieceInfo*>& SinglePieces, lcArray<PieceInfo*>& GroupedPieces);
@ -246,6 +248,9 @@ protected:
QList<QFuture<void>> mLoadFutures;
QList<PieceInfo*> mLoadQueue;
QMutex mTextureMutex;
std::vector<lcTexture*> mTextureUploads;
QString mCachePath;
qint64 mArchiveCheckSum[4];
QString mLibraryFileName;

View file

@ -219,7 +219,9 @@ void lcScene::DrawRenderMeshes(lcContext* Context, int PrimitiveTypes, bool Enab
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);

View file

@ -27,7 +27,7 @@ lcTexture* lcLoadTexture(const QString& FileName, int Flags)
void lcReleaseTexture(lcTexture* Texture)
{
if (Texture && Texture->Release() == 0)
if (Texture && !Texture->Release())
delete Texture;
}
@ -46,12 +46,12 @@ lcTexture::~lcTexture()
void lcTexture::CreateGridTexture()
{
const int NumLevels = 9;
Image GridImages[NumLevels];
mImages.resize(NumLevels);
quint8* Previous = nullptr;
for (int ImageLevel = 0; ImageLevel < NumLevels; ImageLevel++)
{
Image& GridImage = GridImages[ImageLevel];
Image& GridImage = mImages[ImageLevel];
const int GridSize = 256 >> ImageLevel;
GridImage.Allocate(GridSize, GridSize, LC_PIXEL_FORMAT_A8);
@ -156,9 +156,10 @@ void lcTexture::CreateGridTexture()
Previous = GridImage.mData;
}
Load(GridImages, NumLevels, LC_TEXTURE_WRAPU | LC_TEXTURE_WRAPV | LC_TEXTURE_MIPMAPS | LC_TEXTURE_ANISOTROPIC);
mRefCount = 1;
mFlags = LC_TEXTURE_WRAPU | LC_TEXTURE_WRAPV | LC_TEXTURE_MIPMAPS | LC_TEXTURE_ANISOTROPIC;
lcGetPiecesLibrary()->QueueTextureUpload(this);
}
bool lcTexture::Load()
@ -168,28 +169,28 @@ bool lcTexture::Load()
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 Load(image, Flags);
return Load(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 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;
mHeight = images[0].mHeight;
mWidth = mImages[0].mWidth;
mHeight = mImages[0].mHeight;
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 },
};
int FilterFlags = Flags & LC_TEXTURE_FILTER_MASK;
int FilterFlags = mFlags & LC_TEXTURE_FILTER_MASK;
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);
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_T, (Flags & LC_TEXTURE_WRAPV) ? 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, (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_MAG_FILTER, Filters[1][FilterIndex]);
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));
int Format;
switch (images[0].mFormat)
switch (mImages[0].mFormat)
{
default:
case LC_PIXEL_FORMAT_INVALID:
@ -234,15 +235,15 @@ bool lcTexture::Load(Image* images, int NumLevels, int Flags) // todo: this shou
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);
int MaxLevel = 0;
if (Flags & LC_TEXTURE_MIPMAPS)
if (mFlags & LC_TEXTURE_MIPMAPS)
{
int Width = mWidth;
int Height = mHeight;
int Components = images[0].GetBPP();
int Components = mImages[0].GetBPP();
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);
Height = lcMax(1, Height >> 1);
if (NumLevels == 1)
if (mImages.size() == 1)
{
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;
}
else
Data = images[Level].mData;
Data = mImages[Level].mData;
glTexImage2D(GL_TEXTURE_2D, Level, Format, Width, Height, 0, Format, GL_UNSIGNED_BYTE, Data);
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);
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()

View file

@ -14,7 +14,7 @@
#define LC_TEXTURE_NAME_LEN 256
class Image;
#include "image.h"
class lcTexture
{
@ -26,28 +26,25 @@ public:
bool Load(const QString& FileName, int Flags = 0);
bool Load(lcMemFile& File, int Flags = 0);
bool Load(Image& image, int Flags);
bool Load(Image* images, int NumLevels, int Flags);
void Upload();
void Unload();
int AddRef()
void AddRef()
{
mRefCount++;
mRefCount.ref();
if (mRefCount == 1)
Load();
return mRefCount;
}
int Release()
bool Release()
{
mRefCount--;
bool InUse = mRefCount.deref();
if (!mRefCount)
if (!InUse)
Unload();
return mRefCount;
return InUse;
}
void SetTemporary(bool Temporary)
@ -67,9 +64,12 @@ public:
protected:
bool Load();
bool Load(int Flags);
bool mTemporary;
int mRefCount;
QAtomicInt mRefCount;
std::vector<Image> mImages;
int mFlags;
};
lcTexture* lcLoadTexture(const QString& FileName, int Flags);