- moved to GZDoom's gl_hwtexture.cpp.

This commit is contained in:
Christoph Oelckers 2020-05-29 01:03:01 +02:00
parent 381e53017d
commit 87a87c155d
18 changed files with 481 additions and 354 deletions

View file

@ -712,8 +712,6 @@ set( FASTMATH_SOURCES
set (PCH_SOURCES
glbackend/gl_hwtexture.cpp
#glbackend/gl_samplers.cpp
glbackend/gl_shader.cpp
glbackend/glbackend.cpp
glbackend/gl_palmanager.cpp
@ -867,6 +865,7 @@ set (PCH_SOURCES
common/objects/dobjtype.cpp
common/rendering/gl_load/gl_interface.cpp
common/rendering/gl/gl_debug.cpp
common/rendering/gl/gl_hwtexture.cpp
common/rendering/gl/gl_samplers.cpp
common/scripting/core/dictionary.cpp
common/scripting/core/dynarrays.cpp

View file

@ -3,7 +3,7 @@
#ifdef USE_OPENGL
#include "hightile.h"
#include "glbackend/gl_hwtexture.h"
#include "gl_hwtexture.h"
#if defined(_M_IX86) || defined(_M_AMD64) || defined(__i386) || defined(__x86_64)
#define SHIFTMOD32(a) (a)
@ -15,7 +15,6 @@
#define IDP3_MAGIC 0x33504449
class FGameTexture;
class FHardwareTexture;
struct mdmodel_t
{
@ -195,7 +194,7 @@ struct voxmodel_t : public mdmodel_t
vec3_t siz;
vec3f_t piv;
int32_t is8bit;
TMap<int, FHardwareTexture*> *texIds;
TMap<int, OpenGLRenderer::FHardwareTexture*> *texIds;
};
EXTERN mdmodel_t **models;

View file

@ -150,7 +150,7 @@ void gltexapplyprops(void)
gl_texture_filter_anisotropic = (int32_t)GLInterface.glinfo.maxanisotropy;
}
GLInterface.mSamplers->SetTextureFilterMode();
screen->SetTextureFilterMode();
}
//--------------------------------------------------------------------------------------------------

View file

@ -35,7 +35,7 @@ static voxmodel_t *gvox;
//pitch must equal xsiz*4
static FHardwareTexture *gloadtex(const int32_t *picbuf, int32_t xsiz, int32_t ysiz, int32_t is8bit, const PalEntry *paldata)
static OpenGLRenderer::FHardwareTexture *gloadtex(const int32_t *picbuf, int32_t xsiz, int32_t ysiz, int32_t is8bit, const PalEntry *paldata)
{
// Correct for GL's RGB order; also apply gamma here:
const coltype *const pic = (const coltype *)picbuf;
@ -64,9 +64,8 @@ static FHardwareTexture *gloadtex(const int32_t *picbuf, int32_t xsiz, int32_t y
}
}
auto tex = GLInterface.NewTexture();
tex->CreateTexture(xsiz, ysiz, FHardwareTexture::TrueColor, false);
tex->LoadTexture((uint8_t*)pic2);
auto tex = GLInterface.NewTexture(4);
tex->CreateTexture((uint8_t*)pic2, xsiz, ysiz, 15, true, "Voxel"); // Mipmap should be false for this but currently this causes render errors because the proper sampler cannot be selected.
Xfree(pic2);
return tex;
@ -843,8 +842,8 @@ void voxfree(voxmodel_t *m)
if (m->texIds)
{
TMap<int, FHardwareTexture*>::Iterator it(*m->texIds);
TMap<int, FHardwareTexture*>::Pair* pair;
TMap<int, OpenGLRenderer::FHardwareTexture*>::Iterator it(*m->texIds);
TMap<int, OpenGLRenderer::FHardwareTexture*>::Pair* pair;
while (it.NextPair(pair))
{
if (pair->Value) delete pair->Value;
@ -1137,9 +1136,9 @@ int32_t polymost_voxdraw(voxmodel_t *m, tspriteptr_t const tspr)
#if 1
int palId = TRANSLATION(Translation_Remap + curbasepal, globalpal);
auto palette = GPalette.TranslationToTable(palId);
if (!m->texIds) m->texIds = new TMap<int, FHardwareTexture*>;
if (!m->texIds) m->texIds = new TMap<int, OpenGLRenderer::FHardwareTexture*>;
auto pTex = m->texIds->CheckKey(palId);
FHardwareTexture* htex;
OpenGLRenderer::FHardwareTexture* htex;
if (!pTex)
{
htex = gloadtex(m->mytex, m->mytexx, m->mytexy, m->is8bit, palette->Palette);

View file

@ -0,0 +1,338 @@
/*
** gl_hwtexture.cpp
** GL texture abstraction
**
**---------------------------------------------------------------------------
** Copyright 2019 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
**
*/
#include "gl_system.h"
#include "templates.h"
#include "c_cvars.h"
#include "hw_material.h"
#include "gl_interface.h"
#include "hw_cvars.h"
#include "gl_debug.h"
#include "gl_renderer.h"
#include "gl_samplers.h"
#include "gl_hwtexture.h"
namespace OpenGLRenderer
{
TexFilter_s TexFilter[] = {
{GL_NEAREST, GL_NEAREST, false},
{GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST, true},
{GL_LINEAR, GL_LINEAR, false},
{GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR, true},
{GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, true},
{GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST, true},
{GL_LINEAR_MIPMAP_LINEAR, GL_NEAREST, true},
};
//===========================================================================
//
// Static texture data
//
//===========================================================================
unsigned int FHardwareTexture::lastbound[FHardwareTexture::MAX_TEXTURES];
//===========================================================================
//
// Loads the texture image into the hardware
//
// NOTE: For some strange reason I was unable to find the source buffer
// should be one line higher than the actual texture. I got extremely
// strange crashes deep inside the GL driver when I didn't do it!
//
//===========================================================================
unsigned int FHardwareTexture::CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, const char *name)
{
int rh,rw;
int texformat = GL_RGBA8;// TexFormat[gl_texture_format];
bool deletebuffer=false;
/*
if (forcenocompression)
{
texformat = GL_RGBA8;
}
*/
bool firstCall = glTexID == 0;
if (firstCall)
{
glGenTextures(1, &glTexID);
}
int textureBinding = UINT_MAX;
if (texunit == -1) glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding);
if (texunit > 0) glActiveTexture(GL_TEXTURE0+texunit);
if (texunit >= 0) lastbound[texunit] = glTexID;
glBindTexture(GL_TEXTURE_2D, glTexID);
FGLDebug::LabelObject(GL_TEXTURE, glTexID, name);
rw = GetTexDimension(w);
rh = GetTexDimension(h);
if (glBufferID > 0)
{
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
buffer = nullptr;
}
else if (!buffer)
{
// The texture must at least be initialized if no data is present.
mipmapped = false;
buffer=(unsigned char *)calloc(4,rw * (rh+1));
deletebuffer=true;
//texheight=-h;
}
else
{
if (rw < w || rh < h)
{
// The texture is larger than what the hardware can handle so scale it down.
unsigned char * scaledbuffer=(unsigned char *)calloc(4,rw * (rh+1));
if (scaledbuffer)
{
Resize(w, h, rw, rh, buffer, scaledbuffer);
deletebuffer=true;
buffer=scaledbuffer;
}
}
}
// store the physical size.
int sourcetype;
if (glTextureBytes > 0)
{
if (glTextureBytes < 4) glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
static const int ITypes[] = { GL_R8, GL_RG8, GL_RGB8, GL_RGBA8 };
static const int STypes[] = { GL_RED, GL_RG, GL_BGR, GL_BGRA };
texformat = ITypes[glTextureBytes - 1];
sourcetype = STypes[glTextureBytes - 1];
}
else
{
sourcetype = GL_BGRA;
}
if (!firstCall && glBufferID > 0)
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rw, rh, sourcetype, GL_UNSIGNED_BYTE, buffer);
else
glTexImage2D(GL_TEXTURE_2D, 0, texformat, rw, rh, 0, sourcetype, GL_UNSIGNED_BYTE, buffer);
if (deletebuffer && buffer) free(buffer);
else if (glBufferID)
{
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
if (mipmap && TexFilter[gl_texture_filter].mipmapping)
{
glGenerateMipmap(GL_TEXTURE_2D);
mipmapped = true;
}
if (texunit > 0) glActiveTexture(GL_TEXTURE0);
else if (texunit == -1) glBindTexture(GL_TEXTURE_2D, textureBinding);
return glTexID;
}
//===========================================================================
//
//
//
//===========================================================================
void FHardwareTexture::AllocateBuffer(int w, int h, int texelsize)
{
int rw = GetTexDimension(w);
int rh = GetTexDimension(h);
if (texelsize < 1 || texelsize > 4) texelsize = 4;
glTextureBytes = texelsize;
bufferpitch = w;
if (rw == w || rh == h)
{
glGenBuffers(1, &glBufferID);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, glBufferID);
glBufferData(GL_PIXEL_UNPACK_BUFFER, w*h*texelsize, nullptr, GL_STREAM_DRAW);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
}
uint8_t *FHardwareTexture::MapBuffer()
{
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, glBufferID);
return (uint8_t*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
}
//===========================================================================
//
// Destroys the texture
//
//===========================================================================
FHardwareTexture::~FHardwareTexture()
{
if (glTexID != 0) glDeleteTextures(1, &glTexID);
if (glBufferID != 0) glDeleteBuffers(1, &glBufferID);
}
//===========================================================================
//
// Binds this patch
//
//===========================================================================
unsigned int FHardwareTexture::Bind(int texunit, bool needmipmap)
{
if (glTexID != 0)
{
if (lastbound[texunit] == glTexID) return glTexID;
lastbound[texunit] = glTexID;
if (texunit != 0) glActiveTexture(GL_TEXTURE0 + texunit);
glBindTexture(GL_TEXTURE_2D, glTexID);
// Check if we need mipmaps on a texture that was creted without them.
if (needmipmap && !mipmapped && TexFilter[gl_texture_filter].mipmapping)
{
glGenerateMipmap(GL_TEXTURE_2D);
mipmapped = true;
}
if (texunit != 0) glActiveTexture(GL_TEXTURE0);
return glTexID;
}
return 0;
}
void FHardwareTexture::Unbind(int texunit)
{
if (lastbound[texunit] != 0)
{
if (texunit != 0) glActiveTexture(GL_TEXTURE0+texunit);
glBindTexture(GL_TEXTURE_2D, 0);
if (texunit != 0) glActiveTexture(GL_TEXTURE0);
lastbound[texunit] = 0;
}
}
void FHardwareTexture::UnbindAll()
{
for(int texunit = 0; texunit < 16; texunit++)
{
Unbind(texunit);
}
}
//===========================================================================
//
// Creates a depth buffer for this texture
//
//===========================================================================
int FHardwareTexture::GetDepthBuffer(int width, int height)
{
if (glDepthID == 0)
{
glGenRenderbuffers(1, &glDepthID);
glBindRenderbuffer(GL_RENDERBUFFER, glDepthID);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
GetTexDimension(width), GetTexDimension(height));
glBindRenderbuffer(GL_RENDERBUFFER, 0);
}
return glDepthID;
}
//===========================================================================
//
// Binds this texture's surfaces to the current framrbuffer
//
//===========================================================================
void FHardwareTexture::BindToFrameBuffer(int width, int height)
{
width = GetTexDimension(width);
height = GetTexDimension(height);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glTexID, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, GetDepthBuffer(width, height));
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, GetDepthBuffer(width, height));
}
//===========================================================================
//
// Binds a texture to the renderer
//
//===========================================================================
bool FHardwareTexture::BindOrCreate(FTexture *tex, int texunit, int clampmode, int translation, int flags)
{
int usebright = false;
bool needmipmap = (clampmode <= CLAMP_XY);
// Bind it to the system.
if (!Bind(texunit, needmipmap))
{
int w = 0, h = 0;
// Create this texture
FTextureBuffer texbuffer;
if (!tex->isHardwareCanvas())
{
texbuffer = tex->CreateTexBuffer(translation, flags | CTF_ProcessData);
w = texbuffer.mWidth;
h = texbuffer.mHeight;
}
else
{
w = tex->GetWidth();
h = tex->GetHeight();
}
if (!CreateTexture(texbuffer.mBuffer, w, h, texunit, needmipmap, "FHardwareTexture.BindOrCreate"))
{
// could not create texture
return false;
}
}
GLRenderer->mSamplerManager->Bind(texunit, clampmode, 255);
return true;
}
}

View file

@ -0,0 +1,80 @@
#pragma once
class FBitmap;
class FTexture;
#include "tarray.h"
#include "hw_ihwtexture.h"
#ifdef LoadImage
#undef LoadImage
#endif
#define SHADED_TEXTURE -1
#define DIRECT_PALETTE -2
#include "tarray.h"
#include "gl_interface.h"
#include "hw_ihwtexture.h"
class FCanvasTexture;
namespace OpenGLRenderer
{
class FHardwareTexture : public IHardwareTexture
{
public:
static unsigned int lastbound[MAX_TEXTURES];
static int GetTexDimension(int value)
{
if (value > gl.max_texturesize) return gl.max_texturesize;
return value;
}
static void InitGlobalState() { for (int i = 0; i < MAX_TEXTURES; i++) lastbound[i] = 0; }
private:
bool forcenofilter;
unsigned int glTexID = 0;
unsigned int glDepthID = 0; // only used by camera textures
unsigned int glBufferID = 0;
int glTextureBytes;
bool mipmapped = false;
int GetDepthBuffer(int w, int h);
public:
FHardwareTexture(int numchannels = 4, bool disablefilter = false)
{
forcenofilter = disablefilter;
glTextureBytes = numchannels;
}
~FHardwareTexture();
static void Unbind(int texunit);
static void UnbindAll();
void BindToFrameBuffer(int w, int h);
unsigned int Bind(int texunit, bool needmipmap);
bool BindOrCreate(FTexture* tex, int texunit, int clampmode, int translation, int flags);
void AllocateBuffer(int w, int h, int texelsize);
uint8_t* MapBuffer();
unsigned int CreateTexture(unsigned char* buffer, int w, int h, int texunit, bool mipmap, const char* name);
unsigned int GetTextureHandle()
{
return glTexID;
}
int numChannels() { return glTextureBytes; }
};
}

View file

@ -52,7 +52,7 @@
#include "gl/renderer/gl_renderbuffers.h"
#include "gl/shaders/gl_shaderprogram.h"
//#include "hwrenderer/data/flatvertices.h"
//#include "gl/textures/gl_samplers.h"
#include "gl_samplers.h"
//#include "hwrenderer/dynlights/hw_lightbuffer.h"
//#include "hwrenderer/data/hw_viewpointbuffer.h"
#include "r_videoscale.h"
@ -108,7 +108,7 @@ void FGLRenderer::Initialize(int width, int height)
mOldFBID = 0;
//mShaderManager = new FShaderManager;
//mSamplerManager = new FSamplerManager;
mSamplerManager = new FSamplerManager;
}
FGLRenderer::~FGLRenderer()
@ -116,7 +116,7 @@ FGLRenderer::~FGLRenderer()
//FlushModels();
//TexMan.FlushAll();
//if (mShaderManager != nullptr) delete mShaderManager;
//if (mSamplerManager != nullptr) delete mSamplerManager;
if (mSamplerManager != nullptr) delete mSamplerManager;
if (mFBID != 0) glDeleteFramebuffers(1, &mFBID);
if (mVAOID != 0)
{
@ -172,13 +172,13 @@ void FGLRenderer::EndOffscreen()
void FGLRenderer::BindToFrameBuffer(FGameTexture *mat)
{
auto pBaseLayer = mat->GetTexture()->SystemTextures.GetHardwareTexture(0, false);
auto BaseLayer = pBaseLayer ? (::FHardwareTexture*)pBaseLayer : nullptr;
auto BaseLayer = pBaseLayer ? (OpenGLRenderer::FHardwareTexture*)pBaseLayer : nullptr;
if (BaseLayer == nullptr)
{
// must create the hardware texture first
BaseLayer = new ::FHardwareTexture;
BaseLayer->CreateTexture(mat->GetTexelWidth()*4, mat->GetTexelHeight()*4, ::FHardwareTexture::TrueColor, false);
BaseLayer = new FHardwareTexture(4);
BaseLayer->CreateTexture(nullptr, mat->GetTexelWidth() * 4, mat->GetTexelHeight() * 4, 15, false, "Camtex");
mat->GetTexture()->SystemTextures.AddHardwareTexture(0, false, BaseLayer);
}
BaseLayer->BindToFrameBuffer(mat->GetTexelWidth()*4, mat->GetTexelHeight()*4);

View file

@ -21,7 +21,6 @@ class FLightBuffer;
class DPSprite;
class FGLRenderBuffers;
class FGL2DDrawer;
class FHardwareTexture;
class SWSceneDrawer;
class HWViewpointBuffer;
struct FRenderViewpoint;
@ -44,7 +43,7 @@ public:
int mMirrorCount = 0;
int mPlaneMirrorCount = 0;
//FShaderManager *mShaderManager = nullptr;
//FSamplerManager *mSamplerManager = nullptr;
FSamplerManager *mSamplerManager = nullptr;
unsigned int mFBID;
unsigned int mVAOID;
//unsigned int PortalQueryObject;

View file

@ -94,10 +94,11 @@ OpenGLFrameBuffer::OpenGLFrameBuffer(void *hMonitor, bool fullscreen) :
// SetVSync needs to be at the very top to workaround a bug in Nvidia's OpenGL driver.
// If wglSwapIntervalEXT is called after glBindFramebuffer in a frame the setting is not changed!
Super::SetVSync(vid_vsync);
FHardwareTexture::InitGlobalState();
#ifdef IMPLEMENT_IT
// Make sure all global variables tracking OpenGL context state are reset..
FHardwareTexture::InitGlobalState();
gl_RenderState.Reset();
#endif
@ -248,7 +249,7 @@ void OpenGLFrameBuffer::Swap()
if (!swapbefore) glFinish();
//Finish.Unclock();
camtexcount = 0;
//FHardwareTexture::UnbindAll();
FHardwareTexture::UnbindAll();
mDebug->Update();
}
@ -282,17 +283,19 @@ void OpenGLFrameBuffer::CleanForRestart()
{
}
#ifdef IMPLEMENT_IT
void OpenGLFrameBuffer::SetTextureFilterMode()
{
//if (GLRenderer != nullptr && GLRenderer->mSamplerManager != nullptr) GLRenderer->mSamplerManager->SetTextureFilterMode();
}
IHardwareTexture *OpenGLFrameBuffer::CreateHardwareTexture(int numchannels)
{
return nullptr;// new FHardwareTexture(true/*tex->bNoCompress*/);
return new FHardwareTexture(numchannels);
}
void OpenGLFrameBuffer::SetTextureFilterMode()
{
if (GLRenderer != nullptr && GLRenderer->mSamplerManager != nullptr) GLRenderer->mSamplerManager->SetTextureFilterMode();
}
#ifdef IMPLEMENT_IT
void OpenGLFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation)
{
auto tex = mat->tex;
@ -337,13 +340,6 @@ IDataBuffer *OpenGLFrameBuffer::CreateDataBuffer(int bindingpoint, bool ssbo, bo
return new GLDataBuffer(bindingpoint, ssbo);
}
#ifdef IMPLEMENT_IT
void OpenGLFrameBuffer::TextureFilterChanged()
{
if (GLRenderer != NULL && GLRenderer->mSamplerManager != NULL) GLRenderer->mSamplerManager->SetTextureFilterMode();
}
#endif
void OpenGLFrameBuffer::BlurScene(float amount)
{
GLRenderer->BlurScene(amount);

View file

@ -27,12 +27,12 @@ public:
void CleanForRestart() override;
const char* DeviceName() const override;
void WriteSavePic(FileWriter* file, int width, int height) override;
#ifdef IMPLEMENT_IT
void SetTextureFilterMode() override;
IHardwareTexture *CreateHardwareTexture(int numchannels) override;
void SetTextureFilterMode() override;
#ifdef IMPLEMENT_IT
void PrecacheMaterial(FMaterial *mat, int translation) override;
FModelRenderer *CreateModelRenderer(int mli) override;
void TextureFilterChanged() override;
#endif
void BeginFrame() override;
//void SetViewportRects(IntRect *bounds) override;

View file

@ -396,7 +396,7 @@ void V_Init2()
Polymost_Startup();
GLInterface.Init(SCREENHEIGHT);
GLInterface.InitGLState(4, 4/*glmultisample*/);
GLInterface.mSamplers->SetTextureFilterMode();
screen->SetTextureFilterMode();
//setsizeneeded = true;
}

View file

@ -233,7 +233,6 @@ public:
virtual IHardwareTexture *CreateHardwareTexture(int numchannels) { return nullptr; }
virtual void PrecacheMaterial(FMaterial *mat, int translation) {}
virtual FModelRenderer *CreateModelRenderer(int mli) { return nullptr; }
virtual void TextureFilterChanged() {}
virtual void BeginFrame() {}
virtual void SetWindowSize(int w, int h) {}
virtual void StartPrecaching() {}

View file

@ -1,198 +0,0 @@
/*
** gl_hwtexture.cpp
** GL texture abstraction
**
**---------------------------------------------------------------------------
** Copyright 2019 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
**
*/
#include <algorithm>
#include "gl_load.h"
#include "glbackend.h"
#include "bitmap.h"
#include "c_dispatch.h"
#include "printf.h"
#include "gl_interface.h"
//#include "compat.h"
// Workaround to avoid including the dirty 'compat.h' header. This will hopefully not be needed anymore once the texture format uses something better.
# define B_LITTLE_ENDIAN 1
# define B_BIG_ENDIAN 0
uint64_t alltexturesize;
CCMD(alltexturesize)
{
Printf("All textures are %llu bytes\n", alltexturesize);
}
//===========================================================================
//
// Allocates an empty texture
//
//===========================================================================
unsigned int FHardwareTexture::CreateTexture(int w, int h, int type, bool mipmapped)
{
static int gltypes[] = { GL_R8, GL_RGBA8, GL_RGB5_A1, GL_RGBA2 };
static uint8_t bytes[] = { 1, 4, 2, 1 };
glGenTextures(1, &glTexID);
glActiveTexture(GL_TEXTURE15);
glBindTexture(GL_TEXTURE_2D, glTexID);
int size = std::max(w, h);
int bits = 0;
while (size) bits++, size >>= 1;
internalType = type;
if (type == Indexed) mipmapped = false;
mWidth = w;
mHeight = h;
allocated = w * h;
if (mipmapped)
{
for (auto mip = allocated>>2; mip > 0; mip >>= 2)
{
allocated += mip;
}
}
allocated *= bytes[type];
alltexturesize += allocated;
glTexStorage2D(GL_TEXTURE_2D, mipmapped? bits : 1, gltypes[type], w, h);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
this->mipmapped = mipmapped;
return glTexID;
}
//===========================================================================
//
// Loads the texture image into the hardware
//
//===========================================================================
unsigned int FHardwareTexture::LoadTexture(const unsigned char * buffer)
{
return LoadTexturePart(buffer, 0, 0, mWidth, mHeight);
}
unsigned int FHardwareTexture::LoadTexture(FBitmap& bmp)
{
return LoadTexture(bmp.GetPixels());
}
//===========================================================================
//
// Loads the texture image into the hardware
//
//===========================================================================
unsigned int FHardwareTexture::LoadTexturePart(const unsigned char* buffer, int x, int y, int w, int h)
{
if (glTexID == 0) return 0;
int srcformat = internalType == Indexed ? GL_RED : GL_BGRA;// TexFormat[gl_texture_format];
glActiveTexture(GL_TEXTURE15);
glBindTexture(GL_TEXTURE_2D, glTexID);
if (internalType == Indexed) glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, srcformat, GL_UNSIGNED_BYTE, buffer);
if (mipmapped) glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
if (internalType == Indexed) glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
return glTexID;
}
//===========================================================================
//
// Destroys the texture
//
//===========================================================================
FHardwareTexture::~FHardwareTexture()
{
alltexturesize -= allocated;
if (glTexID != 0) glDeleteTextures(1, &glTexID);
if (glBufferID != 0) glDeleteBuffers(1, &glBufferID);
}
unsigned int FHardwareTexture::GetTextureHandle()
{
return glTexID;
}
static int GetTexDimension(int value)
{
if (value > gl.max_texturesize) return gl.max_texturesize;
return value;
}
//===========================================================================
//
// Creates a depth buffer for this texture
//
//===========================================================================
int FHardwareTexture::GetDepthBuffer(int width, int height)
{
if (glDepthID == 0)
{
glGenRenderbuffers(1, &glDepthID);
glBindRenderbuffer(GL_RENDERBUFFER, glDepthID);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
}
return glDepthID;
}
//===========================================================================
//
// Binds this texture's surfaces to the current framrbuffer
//
//===========================================================================
void FHardwareTexture::BindToFrameBuffer(int width, int height)
{
width = GetTexDimension(width);
height = GetTexDimension(height);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glTexID, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, GetDepthBuffer(width, height));
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, GetDepthBuffer(width, height));
}

View file

@ -1,55 +0,0 @@
#pragma once
class FBitmap;
class FTexture;
#include "tarray.h"
#include "hw_ihwtexture.h"
class FHardwareTexture : public IHardwareTexture
{
public:
enum
{
Indexed,
TrueColor,
HighColor, // 16 bit - Can be used to save space in memory constrained scenarios at the cost of visual accuracy.
Brightmap, // This can be stored as RGBA2 to save space, it also doesn't really need a mipmap.
};
private:
unsigned int glTexID = 0;
unsigned int glDepthID = 0; // only used by camera textures
unsigned int glBufferID = 0;
int internalType = TrueColor;
bool mipmapped = true;
int mWidth = 0, mHeight = 0;
int colorId = 0;
uint32_t allocated = 0;
int GetDepthBuffer(int w, int h);
public:
~FHardwareTexture();
// Satisfy the virtual interface - currently this isn't being used.
virtual void AllocateBuffer(int w, int h, int texelsize) {}
virtual uint8_t* MapBuffer() { return nullptr; }
virtual unsigned int CreateTexture(unsigned char* buffer, int w, int h, int texunit, bool mipmap, const char* name) { return 0; }
//bool BindOrCreate(FTexture *tex, int texunit, int clampmode, int translation, int flags);
unsigned int CreateTexture(int w, int h, bool type, bool mipmapped) = delete;
unsigned int CreateTexture(int w, int h, int type, bool mipmapped);
unsigned int LoadTexture(const unsigned char * buffer);
unsigned int LoadTexturePart(const unsigned char* buffer, int x, int y, int w, int h);
unsigned int LoadTexture(FBitmap &bmp);
unsigned int GetTextureHandle();
bool isIndexed() const { return internalType == Indexed; }
void BindToFrameBuffer(int w, int h);
friend class FGameTexture;
};

View file

@ -100,9 +100,8 @@ void PaletteManager::BindPalette(int index)
if (palettetextures[index] == nullptr)
{
auto p = GLInterface.NewTexture();
p->CreateTexture(256, 1, FHardwareTexture::TrueColor, false);
p->LoadTexture((uint8_t*)palettedata->Palette);
auto p = GLInterface.NewTexture(4);
p->CreateTexture((uint8_t*)palettedata->Palette, 256, 1, 15, false, "Palette");
palettetextures[index] = p;
}
inst->BindTexture(2, palettetextures[index], SamplerNoFilterClampXY);
@ -127,8 +126,7 @@ void PaletteManager::BindPalswap(int index)
lastsindex = index;
if (palswaptextures[index] == nullptr)
{
auto p = GLInterface.NewTexture();
p->CreateTexture(256, numshades, FHardwareTexture::Indexed, false);
auto p = GLInterface.NewTexture(1);
// Perform a 0<->255 index swap. The lookup tables are still the original data.
TArray<uint8_t> lookup(numshades * 256, true);
@ -139,7 +137,7 @@ void PaletteManager::BindPalswap(int index)
p[255] = p[0];
p[0] = 0;
}
p->LoadTexture(lookup.Data());
p->CreateTexture(lookup.Data(), 256, numshades, 15, false, "Palette");
palswaptextures[index] = p;
}
inst->BindTexture(1, palswaptextures[index], SamplerNoFilterClampXY);

View file

@ -67,19 +67,18 @@ void FlipNonSquareBlock(T* dst, const T* src, int x, int y, int srcpitch)
//
//===========================================================================
FHardwareTexture* GLInstance::CreateIndexedTexture(FGameTexture* tex)
OpenGLRenderer::FHardwareTexture* GLInstance::CreateIndexedTexture(FGameTexture* tex)
{
vec2_t siz = { tex->GetTexelWidth(), tex->GetTexelHeight() };
auto store = tex->GetTexture()->Get8BitPixels(false);
const uint8_t* p = store.Data();
auto glpic = GLInterface.NewTexture();
glpic->CreateTexture(siz.x, siz.y, FHardwareTexture::Indexed, false);
auto glpic = GLInterface.NewTexture(1);
TArray<uint8_t> flipped(siz.x * siz.y, true);
FlipNonSquareBlock(flipped.Data(), p, siz.y, siz.x, siz.y);
glpic->LoadTexture(flipped.Data());
glpic->CreateTexture(flipped.Data(), siz.x, siz.y, 15, false, tex->GetName());
return glpic;
}
@ -89,7 +88,7 @@ FHardwareTexture* GLInstance::CreateIndexedTexture(FGameTexture* tex)
//
//===========================================================================
FHardwareTexture* GLInstance::CreateTrueColorTexture(FGameTexture* tex, int palid, bool checkfulltransparency, bool rgb8bit)
OpenGLRenderer::FHardwareTexture* GLInstance::CreateTrueColorTexture(FGameTexture* tex, int palid, bool checkfulltransparency, bool rgb8bit)
{
if (tex == TexMan.GameByIndex(0))
return nullptr;
@ -110,12 +109,8 @@ FHardwareTexture* GLInstance::CreateTrueColorTexture(FGameTexture* tex, int pali
if (!found) return nullptr;
}
auto glpic = GLInterface.NewTexture();
if (!rgb8bit)
glpic->CreateTexture(texbuffer.mWidth, texbuffer.mHeight, FHardwareTexture::TrueColor, true);
else
glpic->CreateTexture(texbuffer.mWidth, texbuffer.mHeight, FHardwareTexture::Brightmap, false); // Use a more memory friendly format for simple brightmaps.
glpic->LoadTexture(texbuffer.mBuffer);
auto glpic = GLInterface.NewTexture(4);
glpic->CreateTexture(texbuffer.mBuffer, texbuffer.mWidth, texbuffer.mHeight, 15, true, tex->GetName());
return glpic;
}
@ -125,13 +120,13 @@ FHardwareTexture* GLInstance::CreateTrueColorTexture(FGameTexture* tex, int pali
//
//===========================================================================
FHardwareTexture* GLInstance::LoadTexture(FGameTexture* tex, int textype, int palid)
OpenGLRenderer::FHardwareTexture* GLInstance::LoadTexture(FGameTexture* tex, int textype, int palid)
{
if (textype == TT_INDEXED) palid = -1;
auto phwtex = tex->GetTexture()->SystemTextures.GetHardwareTexture(palid, false);
if (phwtex) return (FHardwareTexture*)phwtex;
if (phwtex) return (OpenGLRenderer::FHardwareTexture*)phwtex;
FHardwareTexture *hwtex = nullptr;
OpenGLRenderer::FHardwareTexture *hwtex = nullptr;
if (textype == TT_INDEXED)
hwtex = CreateIndexedTexture(tex);
else if (!tex->GetTexture()->isHardwareCanvas())

View file

@ -52,22 +52,6 @@
float shadediv[MAXPALOOKUPS];
namespace OpenGLRenderer
{
TexFilter_s TexFilter[] = {
{GL_NEAREST, GL_NEAREST, false},
{GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST, true},
{GL_LINEAR, GL_LINEAR, false},
{GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR, true},
{GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, true},
{GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST, true},
{GL_LINEAR_MIPMAP_LINEAR, GL_NEAREST, true},
};
}
static int blendstyles[] = { GL_ZERO, GL_ONE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA };
static int renderops[] = { GL_FUNC_ADD, GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT };
int depthf[] = { GL_ALWAYS, GL_LESS, GL_EQUAL, GL_LEQUAL };
@ -99,11 +83,6 @@ TArray<uint8_t> ttf;
void GLInstance::Init(int ydim)
{
if (!mSamplers)
{
mSamplers = new OpenGLRenderer::FSamplerManager;
}
//glinfo.bufferstorage = !!strstr(glinfo.extensions, "GL_ARB_buffer_storage");
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &glinfo.maxanisotropy);
@ -158,8 +137,6 @@ void GLInstance::Deinit()
ImGui::DestroyContext(im_ctx);
}
#endif
if (mSamplers) delete mSamplers;
mSamplers = nullptr;
if (polymostShader) delete polymostShader;
polymostShader = nullptr;
if (surfaceShader) delete surfaceShader;
@ -169,9 +146,9 @@ void GLInstance::Deinit()
lastPalswapIndex = -1;
}
FHardwareTexture* GLInstance::NewTexture()
OpenGLRenderer::FHardwareTexture* GLInstance::NewTexture(int numchannels)
{
return new FHardwareTexture;
return new OpenGLRenderer::FHardwareTexture(numchannels);
}
void GLInstance::ResetFrame()
@ -320,7 +297,8 @@ void PolymostRenderState::Apply(PolymostShader* shader, GLState &oldState)
reset = true;
}
glBindTexture(GL_TEXTURE_2D, texIds[i]);
GLInterface.mSamplers->Bind(i, samplerIds[i], -1);
if (OpenGLRenderer::GLRenderer)
OpenGLRenderer::GLRenderer->mSamplerManager->Bind(i, samplerIds[i], -1);
oldState.TexId[i] = texIds[i];
oldState.SamplerId[i] = samplerIds[i];
}

View file

@ -10,7 +10,6 @@
#include "palentry.h"
#include "renderstyle.h"
class FSamplerManager;
class FShader;
class PolymostShader;
class SurfaceShader;
@ -40,8 +39,8 @@ enum
class PaletteManager
{
FHardwareTexture* palettetextures[256] = {};
FHardwareTexture* palswaptextures[256] = {};
OpenGLRenderer::FHardwareTexture* palettetextures[256] = {};
OpenGLRenderer::FHardwareTexture* palswaptextures[256] = {};
uint32_t lastindex = ~0u;
uint32_t lastsindex = ~0u;
@ -127,7 +126,7 @@ class GLInstance
int maxTextureSize;
PaletteManager palmanager;
int lastPalswapIndex = -1;
FHardwareTexture* texv;
OpenGLRenderer::FHardwareTexture* texv;
FGameTexture* currentTexture = nullptr;
int TextureType;
int MatrixChange = 0;
@ -144,7 +143,6 @@ class GLInstance
public:
glinfo_t glinfo;
OpenGLRenderer::FSamplerManager *mSamplers;
void Init(int y);
void InitGLState(int fogmode, int multisample);
@ -166,7 +164,7 @@ public:
void DoDraw();
void DrawElement(EDrawType type, size_t start, size_t count, PolymostRenderState& renderState);
FHardwareTexture* NewTexture();
OpenGLRenderer::FHardwareTexture* NewTexture(int numchannels = 4);
void SetVertexBuffer(IVertexBuffer* vb, int offset1, int offset2);
void SetIndexBuffer(IIndexBuffer* vb);
@ -363,13 +361,15 @@ public:
SetColor(r * (1 / 255.f), g * (1 / 255.f), b * (1 / 255.f), a * (1 / 255.f));
}
void BindTexture(int texunit, FHardwareTexture* tex, int sampler)
void BindTexture(int texunit, OpenGLRenderer::FHardwareTexture* tex, int sampler)
{
if (!tex) return;
if (texunit == 0)
{
if (tex->isIndexed()) renderState.Flags |= RF_UsePalette;
else renderState.Flags &= ~RF_UsePalette;
if (tex->numChannels() == 1)
renderState.Flags |= RF_UsePalette;
else
renderState.Flags &= ~RF_UsePalette;
}
renderState.texIds[texunit] = tex->GetTextureHandle();
renderState.samplerIds[texunit] = sampler;
@ -487,9 +487,9 @@ public:
renderState.AlphaThreshold = al;
}
FHardwareTexture* CreateIndexedTexture(FGameTexture* tex);
FHardwareTexture* CreateTrueColorTexture(FGameTexture* tex, int palid, bool checkfulltransparency = false, bool rgb8bit = false);
FHardwareTexture *LoadTexture(FGameTexture* tex, int texturetype, int palid);
OpenGLRenderer::FHardwareTexture* CreateIndexedTexture(FGameTexture* tex);
OpenGLRenderer::FHardwareTexture* CreateTrueColorTexture(FGameTexture* tex, int palid, bool checkfulltransparency = false, bool rgb8bit = false);
OpenGLRenderer::FHardwareTexture *LoadTexture(FGameTexture* tex, int texturetype, int palid);
bool SetTextureInternal(int globalpicnum, FGameTexture* tex, int palette, int method, int sampleroverride, FGameTexture *det, float detscale, FGameTexture *glow);
bool SetNamedTexture(FGameTexture* tex, int palette, int sampleroverride);