feat(gx): add uncompleted CGxDeviceGLSDL targeting Windows and Linux

This commit is contained in:
superp00t 2023-11-15 19:31:16 -05:00
parent 827c86b194
commit b3b75a716c
42 changed files with 7681 additions and 5 deletions

View File

@ -14,6 +14,10 @@
#include "gx/d3d/CGxDeviceD3d.hpp"
#endif
#if defined(WHOA_SYSTEM_LINUX) || defined(WHOA_SYSTEM_WIN)
#include "gx/glsdl/CGxDeviceGLSDL.hpp"
#endif
#if defined(WHOA_SYSTEM_MAC)
#include "gx/gll/CGxDeviceGLL.hpp"
#endif
@ -119,13 +123,13 @@ CGxDevice* CGxDevice::NewGLL() {
}
#endif
CGxDevice* CGxDevice::NewOpenGl() {
// TODO
// auto m = SMemAlloc(sizeof(CGxDeviceOpenGl), __FILE__, __LINE__, 0x0);
// return new (m) CGxDeviceOpenGl();
return nullptr;
#if defined(WHOA_SYSTEM_WIN) || defined(WHOA_SYSTEM_LINUX)
CGxDevice* CGxDevice::NewOpenGl() {
auto m = SMemAlloc(sizeof(CGxDeviceGLSDL), __FILE__, __LINE__, 0x0);
return new (m) CGxDeviceGLSDL();
}
#endif
uint32_t CGxDevice::PrimCalcCount(EGxPrim primType, uint32_t count) {
auto div = CGxDevice::s_primVtxDiv[primType];

View File

@ -19,6 +19,12 @@ if(WHOA_SYSTEM_MAC)
list(APPEND GX_SOURCES ${GLL_SOURCES})
endif()
# Build OpenGL/SDL graphics device on Windows and Linux
if(WHOA_SYSTEM_WIN OR WHOA_SYSTEM_LINUX)
file(GLOB GLSDL_SOURCES "glsdl/*.cpp")
list(APPEND GX_SOURCES ${GLSDL_SOURCES})
endif()
add_library(gx STATIC ${GX_SOURCES})
target_include_directories(gx
@ -47,6 +53,15 @@ if(WHOA_SYSTEM_WIN)
)
endif()
# Link SDL3 and GLEW for Windows and Linux
if (WHOA_SYSTEM_WIN OR WHOA_SYSTEM_LINUX)
target_link_libraries(gx
PRIVATE
SDL3::SDL3
libglew_static
)
endif()
if(WHOA_SYSTEM_MAC)
target_link_libraries(gx
PRIVATE

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,82 @@
#ifndef GX_GL_SDL_C_GX_DEVICE_GL_SDL_HPP
#define GX_GL_SDL_C_GX_DEVICE_GL_SDL_HPP
#include "gx/CGxDevice.hpp"
#include "gx/glsdl/GLSDLDevice.hpp"
#include "gx/glsdl/GLSDLWindow.hpp"
class CGxBatch;
class CGxShader;
class CGxDeviceGLSDL : public CGxDevice {
public:
// Static variables
static GLEnum s_glCubeMapFaces[];
static GLEnum s_glDstBlend[];
static GLEnum s_glSrcBlend[];
static GLTextureFormat s_gxTexFmtToGLSDLFmt[];
static GLEnum s_poolTarget2BufferFormat[];
static GLEnum s_poolTarget2BufferType[];
static GLEnum s_poolUsage2BufferUsage[];
static GLEnum s_primitiveConversion[];
// Member variables
GLSDLDevice m_GLSDLDevice;
GLSDLWindow m_GLSDLWindow;
GLVertexFormat m_glFormats[GxVertexBufferFormats_Last] = {};
// Virtual member functions
virtual void ITexMarkAsUpdated(CGxTex*);
virtual void IRsSendToHw(EGxRenderState);
virtual int32_t DeviceCreate(int32_t (*windowProc)(void* window, uint32_t message, uintptr_t wparam, intptr_t lparam), const CGxFormat&);
virtual int32_t DeviceSetFormat(const CGxFormat&);
virtual void* DeviceWindow();
virtual void DeviceWM(EGxWM wm, uintptr_t param1, uintptr_t param2) {};
virtual void CapsWindowSize(CRect&);
virtual void CapsWindowSizeInScreenCoords(CRect& dst);
virtual void ScenePresent();
virtual void SceneClear(uint32_t, CImVector);
virtual void XformSetProjection(const C44Matrix&);
virtual void XformSetView(const C44Matrix&);
virtual void Draw(CGxBatch* batch, int32_t indexed);
virtual void PoolSizeSet(CGxPool*, uint32_t);
virtual char* BufLock(CGxBuf*);
virtual int32_t BufUnlock(CGxBuf*, uint32_t);
virtual void BufData(CGxBuf* buf, const void* data, size_t size, uintptr_t offset);
virtual void TexDestroy(CGxTex* texId);
virtual void IShaderCreate(CGxShader*);
virtual void ShaderCreate(CGxShader*[], EGxShTarget, const char*, const char*, int32_t);
virtual int32_t StereoEnabled();
// Member functions
CGxDeviceGLSDL();
char* IBufLock(CGxBuf*);
int32_t IBufUnlock(CGxBuf*);
void ISceneBegin();
void ISetCaps(const CGxFormat& format);
void IShaderBindPixel(CGxShader*);
void IShaderBindVertex(CGxShader*);
void IShaderConstantsFlush();
void IShaderCreatePixel(CGxShader*);
void IShaderCreateVertex(CGxShader*);
void IStateSetGLSDLDefaults();
void IStateSync();
void IStateSyncEnables();
void IStateSyncIndexPtr();
void IStateSyncLights();
void IStateSyncMaterial();
void IStateSyncScissorRect();
void IStateSyncVertexPtrs();
void IStateSyncXforms();
void ITexCreate(CGxTex*);
void ITexSetFlags(CGxTex*);
void ITexUpload(CGxTex*);
void IXformSetProjection(const C44Matrix&);
void IXformSetView(const C44Matrix&);
void IXformSetViewport();
void PatchPixelShader(CGxShader*);
void PatchVertexShader(CGxShader*);
void Resize(uint32_t width, uint32_t height);
};
#endif

50
src/gx/glsdl/GL.cpp Normal file
View File

@ -0,0 +1,50 @@
#include "gx/glsdl/GL.hpp"
TextureFormatInfo k_TextureFormatInfo[GLTF_NUM_TEXTURE_FORMATS] = {
{ 0, 0, 0, 0, 0, "GLTF INVALID!!" },
{ GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0, 4, "ARGB8888" },
{ GL_RGB8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0, 4, "XRGB8888" },
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, 0, 4, "RGBA8888" },
{ GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 0, 4, "ABGR8888" },
{ GL_RGB8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0, 4, "ARGB0888" },
{ GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE, 0, 3, "RGB888" },
{ GL_RGB8, GL_BGR, GL_UNSIGNED_BYTE, 0, 3, "BGR888" },
{ GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, 0, 16, "RGBA32F" },
{ GL_RGBA16F_ARB, GL_RGBA, GL_HALF_FLOAT, 0, 8, "RGBA16F" },
{ GL_RGB16F_ARB, GL_RGB, GL_HALF_FLOAT, 0, 6, "RG16F" },
{ GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0, 4, "D32" },
{ GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0, 4, "D24" },
{ GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 0, 2, "D16" },
{ GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_HALF_FLOAT, 0, 4, "DF" },
{ GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0, 4, "D24S8" },
{ GL_ALPHA8, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, 0, 1, "S8" },
{ GL_RGBA4, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV, 0, 2, "ARGB4444" },
{ GL_RGB5_A1, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 0, 2, "ARGB1555" },
{ GL_RGB5, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 0, 2, "ARGB0555" },
{ GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0, 2, "RGB565" },
{ GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV, 0, 4, "A2RGB10" },
{ GL_RGB16, GL_RGB, GL_UNSIGNED_SHORT, 0, 6, "RGB16" },
{ GL_LUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, 1, "L8" },
{ GL_ALPHA8, GL_ALPHA, GL_UNSIGNED_BYTE, 0, 1, "A8" },
{ GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 0, 2, "A8L8" },
{ GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_RGBA, GL_UNSIGNED_BYTE, 1, 8, "DXT1" },
{ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_BYTE, 1, 16, "DXT3" },
{ GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_BYTE, 1, 16, "DXT5" }
};
VertexTypeInfo k_VertexTypeInfo[GLVT_NUM_VERTEX_TYPES] = {
{ 0, 0, 0, 0, "INVALID" },
{ GL_FLOAT, 1, 0, 4, "FLOAT1" },
{ GL_FLOAT, 2, 0, 8, "FLOAT2" },
{ GL_FLOAT, 3, 0, 12, "FLOAT3" },
{ GL_FLOAT, 4, 0, 16, "FLOAT4" },
{ GL_UNSIGNED_BYTE, 4, 0, 4, "UBYTE4" },
{ GL_UNSIGNED_BYTE, 4, 1, 4, "UBYTE4N" },
{ GL_SHORT, 1, 0, 2, "SHORT" },
{ GL_SHORT, 2, 0, 4, "SHORT2" },
{ GL_SHORT, 4, 0, 8, "SHORT4" },
{ GL_SHORT, 2, 1, 4, "SHORT2N" },
{ GL_SHORT, 4, 1, 8, "SHORT4N" },
{ GL_UNSIGNED_SHORT, 2, 1, 4, "USHORT2N" },
{ GL_UNSIGNED_SHORT, 4, 1, 8, "USHORT4N" }
};

33
src/gx/glsdl/GL.hpp Normal file
View File

@ -0,0 +1,33 @@
#ifndef GX_GL_SDL_GL_HPP
#define GX_GL_SDL_GL_HPP
#include <GL/glew.h>
#include <GL/gl.h>
#include "gx/glsdl/GLTypes.hpp"
typedef GLenum GLEnum;
#define kMAX_VERTEX_ATTRIBS 16
struct TextureFormatInfo {
GLenum m_InternalFormat;
GLenum m_DataFormat;
GLenum m_DataType;
int32_t m_IsCompressed;
int32_t m_BytePerPixel;
char m_Name[16];
};
struct VertexTypeInfo {
GLenum m_Type;
GLint m_Size;
GLboolean m_Normalized;
GLint m_ByteSize;
const char* m_Name;
};
extern TextureFormatInfo k_TextureFormatInfo[GLTF_NUM_TEXTURE_FORMATS];
extern VertexTypeInfo k_VertexTypeInfo[GLVT_NUM_VERTEX_TYPES];
#endif

45
src/gx/glsdl/GLBatch.hpp Normal file
View File

@ -0,0 +1,45 @@
#ifndef GX_GL_SDL_GL_BATCH_HPP
#define GX_GL_SDL_GL_BATCH_HPP
#include "gx/glsdl/GLBuffer.hpp"
#include "gx/glsdl/GLShader.hpp"
#include "gx/glsdl/GLTexture.hpp"
#include "gx/glsdl/GLTypes.hpp"
#include "gx/glsdl/GLVertexFormat.hpp"
#include <cstdint>
class GLBatch {
public:
GLShader* var0;
GLShader* var1;
GLTexture* textures[16];
GLBuffer* var3;
GLBuffer* var4[4];
uint32_t var5[4];
uint32_t var6[4];
GLVertexFormat* var7;
uint32_t var8;
uint32_t var9;
uint32_t var10;
uint32_t var11;
uint32_t var12;
uint32_t var13;
uint32_t var14;
int32_t var15;
bool var16;
bool var17;
GLStates var18;
GLTexture2D* colorBuffer[4];
GLTexture2D* var20;
uint32_t var21[128];
char var22[64];
char var23[1024];
uint32_t var24;
bool var25;
int64_t var26;
int64_t var27;
float var28[4096];
float var29[1024];
};
#endif

130
src/gx/glsdl/GLBuffer.cpp Normal file
View File

@ -0,0 +1,130 @@
#include "gx/glsdl/GLBuffer.hpp"
#include "gx/glsdl/GLSDLDevice.hpp"
#include "gx/glsdl/GLPool.hpp"
#include "gx/glsdl/GL.hpp"
#include <bc/Debug.hpp>
#include <bc/Memory.hpp>
bool GLBuffer::m_UsingVBO = 1;
GLEnum GLBuffer::s_FlagToAccess[] = {
GL_READ_WRITE, // GLMap_None
GL_WRITE_ONLY, // GLMap_Unk1
GL_WRITE_ONLY, // GLMap_Unk2
GL_READ_ONLY // GLMap_Unk3
};
GLBuffer* GLBuffer::Create(GLEnum type, uint32_t size, const void* a3, GLEnum usage, GLEnum format) {
GLBuffer* buffer = GLPool<GLBuffer>::Get()->GetNextObject();
buffer->m_Type = type;
buffer->m_Size = size;
buffer->m_Usage = usage;
buffer->m_IndexFormat = format;
GLSDLDevice* device = GLSDLDevice::Get();
device->BindBuffer(buffer, GL_ZERO);
if (GLBuffer::m_UsingVBO) {
glBufferData(buffer->m_Type, buffer->m_Size, a3, buffer->m_Usage);
// glBufferParameteriAPPLE(buffer->m_Type, GL_BUFFER_SERIALIZED_MODIFY_APPLE, buffer->m_Usage - GL_DYNAMIC_DRAW > 1);
// glBufferParameteriAPPLE(buffer->m_Type, GL_BUFFER_FLUSHING_UNMAP_APPLE, 0);
} else {
Blizzard::Memory::Free(buffer->m_Data);
void* data = Blizzard::Memory::Allocate(size);
if (a3) {
memcpy(data, a3, size);
}
buffer->m_Data = reinterpret_cast<char*>(data);
}
// TODO
// buffer->m_TimeStamp = Blizzard::Time::GetTimestamp();
return buffer;
}
GLBuffer::GLBuffer() : GLObject() {
if (GLBuffer::m_UsingVBO) {
this->m_BufferID = GLPool<GLBuffer>::Get()->GetNextName();
}
}
char* GLBuffer::Map(uint32_t offset, uint32_t size, eMapFlag flag) {
BLIZZARD_ASSERT((offset + size) <= this->m_Size);
BLIZZARD_ASSERT(this->m_Usage == GL_STATIC_DRAW || flag != GLMap_None);
BLIZZARD_ASSERT(this->m_MapFlag == GLMap_NotMapped);
BLIZZARD_ASSERT(flag >= GLMap_None && flag < GLMap_Count);
this->m_MapOffset = offset;
this->m_MapSize = offset + size == 0 ? this->m_Size : size;
this->m_MapFlag = flag;
if (GLBuffer::m_UsingVBO) {
GLSDLDevice* device = GLSDLDevice::Get();
device->BindBuffer(this, GL_ZERO);
if (flag == GLMap_Unk2) {
if (this->m_Usage - GL_DYNAMIC_DRAW <= 1) {
BLIZZARD_ASSERT(offset == 0);
}
glBufferData(this->m_Type, this->m_Size, nullptr, this->m_Usage);
}
void* data = glMapBuffer(this->m_Type, GLBuffer::s_FlagToAccess[flag]);
this->m_Data = reinterpret_cast<char*>(data);
BLIZZARD_ASSERT(this->m_Data != nullptr);
}
return this->m_Data + offset;
}
void GLBuffer::ReleaseObject() {
if (GLBuffer::m_UsingVBO) {
if (this->m_Type) {
GLSDLDevice* device = GLSDLDevice::Get();
device->BindBuffer(this, GL_ZERO);
glBufferData(this->m_Type, 1, nullptr, this->m_Usage);
// TODO GLPool<GLBuffer>::GLObjectPool::Push((GLPool<GLBuffer>::m_pool + 32776), this);
} else {
// TODO GLPool<GLBuffer>::GLObjectPool::Push((GLPool<GLBuffer>::m_pool + 32776), this);
}
} else {
Blizzard::Memory::Free(this->m_Data);
this->m_Data = nullptr;
// TODO GLPool<GLBuffer>::GLObjectPool::Push((GLPool<GLBuffer>::m_pool + 32776), this);
}
}
void GLBuffer::Unmap(uint32_t size) {
BLIZZARD_ASSERT((this->m_MapOffset + size) <= m_Size);
GLSDLDevice* device = GLSDLDevice::Get();
device->BindBuffer(this, GL_ZERO);
if (this->m_MapFlag != 3) {
if (GLBuffer::m_UsingVBO) {
glFlushMappedBufferRange(this->m_Type, this->m_MapOffset, size ? size : this->m_MapSize);
}
// TODO
// this->m_TimeStamp = Blizzard::Time::GetTimestamp();
}
if (!GLBuffer::m_UsingVBO) {
this->m_MapFlag = GLMap_NotMapped;
return;
}
GLboolean result = glUnmapBuffer(this->m_Type);
BLIZZARD_ASSERT(result);
this->m_MapFlag = GLMap_NotMapped;
}

47
src/gx/glsdl/GLBuffer.hpp Normal file
View File

@ -0,0 +1,47 @@
#ifndef GX_GL_SDL_GL_BUFFER_HPP
#define GX_GL_SDL_GL_BUFFER_HPP
#include "gx/glsdl/GL.hpp"
#include "gx/glsdl/GLObject.hpp"
#include "gx/glsdl/GLTypes.hpp"
class GLBuffer : public GLObject {
public:
// Types
enum eMapFlag {
GLMap_NotMapped = -1,
GLMap_None = 0,
GLMap_Unk1 = 1,
GLMap_Unk2 = 2,
GLMap_Unk3 = 3,
GLMap_Count = 4
};
// Static variables
static bool m_UsingVBO;
static GLEnum s_FlagToAccess[];
// Static functions
static GLBuffer* Create(GLEnum, uint32_t, const void*, GLEnum, GLEnum);
// Member variables
uint32_t m_Size = 0;
GLEnum m_Type = 0;
GLEnum m_Usage = 0;
uint32_t m_BufferID = 0;
GLEnum m_IndexFormat = 0;
char* m_Data = nullptr;
uint32_t m_MapOffset = 0;
uint32_t m_MapSize = 0;
uint32_t m_MapFlag = GLMap_NotMapped;
// Virtual member functions
virtual void ReleaseObject();
// Member functions
GLBuffer();
char* Map(uint32_t, uint32_t, eMapFlag);
void Unmap(uint32_t);
};
#endif

View File

@ -0,0 +1,8 @@
#ifndef GX_GL_SDL_GL_BUFFER_POOL_HPP
#define GX_GL_SDL_GL_BUFFER_POOL_HPP
class GLBufferPool {
public:
};
#endif

View File

@ -0,0 +1,8 @@
#ifndef GX_GL_SDL_GL_DEBUG_MIPMAP_2D_HPP
#define GX_GL_SDL_GL_DEBUG_MIPMAP_2D_HPP
class GLDebugMipmap2D {
public:
};
#endif

View File

@ -0,0 +1,150 @@
#include "gx/glsdl/GLFramebuffer.hpp"
#include "gx/glsdl/GLSDLDevice.hpp"
#include "gx/glsdl/GLMipmap.hpp"
#include "gx/glsdl/GLPool.hpp"
#include "gx/glsdl/GLTypes.hpp"
#include <bc/Debug.hpp>
GLFramebuffer* GLFramebuffer::Create(bool a1) {
GLFramebuffer* framebuffer = new GLFramebuffer(a1);
if (!a1) {
// TODO
// BLIZZARD_ASSERT(framebuffer->m_FramebufferID >= PoolStats<GLFramebuffer>::NAME_POOL_FIRST_NAME);
}
BLIZZARD_ASSERT(framebuffer->m_NumAttach == 0);
framebuffer->m_Width = 0;
framebuffer->m_Height = 0;
framebuffer->m_Device = GLSDLDevice::Get();
return framebuffer;
}
GLFramebuffer::GLFramebuffer(bool a1) : GLObject() {
if (!a1) {
this->m_FramebufferID = GLPool<GLFramebuffer>::Get()->GetNextName();
}
}
void GLFramebuffer::Attach(GLMipmap* image, GLenum a3, int32_t a4) {
BLIZZARD_ASSERT(this->m_Device == GLSDLDevice::Get());
if (!image) {
this->Detach(a3);
return;
}
if (a3 == GL_DEPTH_STENCIL) {
BLIZZARD_ASSERT(image->GetFormat() == GLTF_D24S8);
this->Attach(image, GL_DEPTH_ATTACHMENT, 0);
this->Attach(image, GL_STENCIL_ATTACHMENT, 0);
(*image->m_AttachPoints)[this->m_FramebufferID].point = GL_DEPTH_STENCIL;
return;
}
int32_t index;
if (a3 == GL_DEPTH_ATTACHMENT) {
index = 4;
} else if (a3 == GL_STENCIL_ATTACHMENT) {
index = 5;
} else {
index = a3 - GL_COLOR_ATTACHMENT0;
}
BLIZZARD_ASSERT(index < MAX_ATTACHMENT);
GLMipmap* oldImage = this->m_Attachments[index];
if (image != oldImage) {
if (oldImage) {
oldImage->Detach(this, a3, true);
} else {
++this->m_NumAttach;
}
this->m_Attachments[index] = image;
this->m_Width = image->m_Width;
this->m_Height = image->m_Height;
image->Attach(this, a3, a4);
this->m_Device->Sub38460(0);
}
BLIZZARD_ASSERT((*image->m_AttachPoints)[m_FramebufferID].framebuffer == this);
}
void GLFramebuffer::Detach(GLenum a2) {
int32_t v2 = a2;
int32_t index;
if (a2 == GL_DEPTH_STENCIL) {
index = 5;
v2 = GL_STENCIL_ATTACHMENT;
this->Detach(GL_DEPTH_ATTACHMENT);
} else if (a2 == GL_DEPTH_ATTACHMENT) {
index = 4;
} else if (a2 == GL_STENCIL_ATTACHMENT) {
index = 5;
} else {
index = a2 - GL_COLOR_ATTACHMENT0;
}
BLIZZARD_ASSERT(index < MAX_ATTACHMENT);
GLMipmap* oldImage = this->m_Attachments[index];
if (oldImage) {
oldImage->Detach(this, v2, 0);
--this->m_NumAttach;
this->m_Attachments[index] = 0;
if (this->m_Device == GLSDLDevice::Get()) {
this->m_Device->Sub38460(0);
}
if (this->m_NumAttach == 0) {
this->m_Width = 0;
this->m_Height = 0;
}
}
}
GLMipmap* GLFramebuffer::GetAttachment(GLEnum a2) {
int32_t index;
if (a2 == GL_DEPTH_ATTACHMENT) {
index = 4;
} else if (a2 == GL_STENCIL_ATTACHMENT) {
index = 5;
} else {
index = a2 - GL_COLOR_ATTACHMENT0;
}
BLIZZARD_ASSERT(index < MAX_ATTACHMENT);
return this->m_Attachments[index];
}
int32_t GLFramebuffer::GetSampleCount() {
return this->m_FramebufferID
? 1
: this->m_Device->m_Context.GetSampleCount();
}
bool GLFramebuffer::IsValid() {
auto status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
return status == GL_FRAMEBUFFER_COMPLETE;
}
void GLFramebuffer::ReleaseObject() {
// TODO
}

View File

@ -0,0 +1,38 @@
#ifndef GX_GL_SDL_GL_FRAMEBUFFER_HPP
#define GX_GL_SDL_GL_FRAMEBUFFER_HPP
#include "gx/glsdl/GL.hpp"
#include "gx/glsdl/GLObject.hpp"
#include <cstdint>
#define MAX_ATTACHMENT 6
class GLSDLDevice;
class GLMipmap;
class GLFramebuffer : public GLObject {
public:
// Static functions
static GLFramebuffer* Create(bool);
// Member variables
int32_t m_Width = 0;
int32_t m_Height = 0;
uint32_t m_FramebufferID = 0;
GLSDLDevice* m_Device;
GLMipmap* m_Attachments[6] = {};
uint32_t m_NumAttach = 0;
// Virtual member functions
virtual void ReleaseObject();
// Member functions
GLFramebuffer(bool);
void Attach(GLMipmap*, GLenum, int32_t);
void Detach(GLenum);
GLMipmap* GetAttachment(GLEnum);
int32_t GetSampleCount(void);
bool IsValid();
};
#endif

View File

@ -0,0 +1,7 @@
#include "gx/glsdl/GLGLSLProgram.hpp"
#include "gx/glsdl/GLShader.hpp"
GLGLSLProgram* GLGLSLProgram::Find(GLShader* a1, GLShader* a2) {
// TODO
return nullptr;
}

View File

@ -0,0 +1,14 @@
#ifndef GX_GL_SDL_GL_GLSL_PROGRAM_HPP
#define GX_GL_SDL_GL_GLSL_PROGRAM_HPP
#include "gx/glsdl/GLObject.hpp"
class GLShader;
class GLGLSLProgram : public GLObject {
public:
// Static functions
static GLGLSLProgram* Find(GLShader*, GLShader*);
};
#endif

480
src/gx/glsdl/GLMipmap.cpp Normal file
View File

@ -0,0 +1,480 @@
#include "gx/glsdl/GLMipmap.hpp"
#include "gx/glsdl/GLSDLDevice.hpp"
#include "gx/glsdl/GLFramebuffer.hpp"
#include <bc/Debug.hpp>
int32_t GLMipmap::GetDepthBits() {
return this->m_DepthBits;
}
void GLMipmap::Attach(GLFramebuffer* framebuffer, GLenum attachPoint, int32_t a4) {
if (!this->m_AttachPoints) {
this->m_AttachPoints = new std::vector<GLAttachPoint>();
}
auto& attachPoints = *this->m_AttachPoints;
auto framebufferID = framebuffer->m_FramebufferID;
if (framebufferID >= attachPoints.size()) {
attachPoints.resize(framebufferID + 1);
} else {
BLIZZARD_ASSERT(attachPoints[framebufferID].framebuffer != framebuffer || attachPoints[framebufferID].point != attachPoint);
auto& attach = attachPoints[framebufferID];
if (
attach.point
&& (attach.point != GL_DEPTH_ATTACHMENT || attachPoint != GL_STENCIL_ATTACHMENT)
&& (attach.point != GL_STENCIL_ATTACHMENT || attachPoint != GL_DEPTH_ATTACHMENT)
) {
framebuffer->Detach(attach.point);
}
}
GLSDLDevice* device = GLSDLDevice::Get();
auto currentTarget = device->GetCurrentTarget();
device->BindFramebuffer(framebuffer);
if (framebufferID) {
if (this->m_Target == GL_TEXTURE_3D) {
glFramebufferTexture3DEXT(
GL_FRAMEBUFFER,
attachPoint,
GL_TEXTURE_3D,
this->m_Texture->m_TextureID,
this->m_Level,
a4
);
} else {
glFramebufferTexture2DEXT(
GL_FRAMEBUFFER,
attachPoint,
this->m_Target,
this->m_Texture->m_TextureID,
this->m_Level
);
}
}
if (attachPoint == GL_DEPTH_ATTACHMENT && !this->m_DepthBits) {
GLint depthBits = 0;
glGetIntegerv(GL_DEPTH_BITS, &depthBits);
this->m_DepthBits = depthBits;
}
device->BindFramebuffer(currentTarget);
auto& attach = attachPoints[framebufferID];
attach.framebuffer = framebuffer;
attach.zOffset = a4;
if (
(attach.point != GL_DEPTH_ATTACHMENT || attachPoint != GL_STENCIL_ATTACHMENT)
&& (attach.point != GL_STENCIL_ATTACHMENT || attachPoint != GL_DEPTH_ATTACHMENT)
) {
attach.point = attachPoint;
} else {
attach.point = GL_DEPTH_STENCIL;
}
}
void GLMipmap::Detach(GLFramebuffer* framebuffer, GLenum attachPoint, bool a4) {
GLuint framebufferID = framebuffer->m_FramebufferID;
auto& attachPoints = *this->m_AttachPoints;
BLIZZARD_ASSERT(attachPoints.size() >= framebufferID);
BLIZZARD_ASSERT(attachPoints[framebufferID].framebuffer == framebuffer);
if (!a4 && framebufferID) {
GLSDLDevice* v12 = GLSDLDevice::Get();
GLFramebuffer* v14 = v12->GetCurrentTarget();
v12->BindFramebuffer(framebuffer);
if (this->m_Target == GL_TEXTURE_3D) {
glFramebufferTexture3DEXT(GL_FRAMEBUFFER, attachPoint, GL_TEXTURE_3D, 0, 0, 0);
} else {
glFramebufferTexture2DEXT(GL_FRAMEBUFFER, attachPoint, this->m_Target, 0, 0);
}
v12->BindFramebuffer(v14);
}
GLAttachPoint* v9 = &attachPoints[framebufferID];
if (v9->point == GL_DEPTH_STENCIL) {
BLIZZARD_ASSERT(this->GetFormat() == GLTF_D24S8);
if (attachPoint == GL_DEPTH_ATTACHMENT) {
v9->point = GL_STENCIL_ATTACHMENT;
} else if (attachPoint == GL_STENCIL_ATTACHMENT) {
v9->point = GL_DEPTH_ATTACHMENT;
} else {
BLIZZARD_ASSERT(false);
}
} else {
BLIZZARD_ASSERT(attachPoints[framebufferID].point == attachPoint);
v9->framebuffer = 0;
v9->point = 0;
v9->zOffset = 0;
// TODO
// this->m_Texture->m_TimeStamp = Blizzard::Time::GetTimestamp();
}
}
void GLMipmap::DetachAll() {
if (!this->m_AttachPoints) {
return;
}
auto& attachPoints = *this->m_AttachPoints;
for (int32_t i = 0; i < attachPoints.size(); i++) {
BLIZZARD_ASSERT(attachPoints[i].point != GL_ZERO);
BLIZZARD_ASSERT(attachPoints[i].framebuffer->m_FramebufferID == i);
attachPoints[i].framebuffer->Detach(attachPoints[i].point);
}
}
GLTextureFormat GLMipmap::GetFormat() {
return this->m_Texture->GetFormat();
}
TextureFormatInfo& GLMipmap::GetFormatInfo() {
return this->m_Texture->GetFormatInfo();
};
uint16_t GLMipmap::GetHeight() {
return this->m_Height;
}
int32_t GLMipmap::GetPitch() {
int32_t bpp = this->GetFormatInfo().m_BytePerPixel;
int32_t v4 = this->m_Texture->var12 >> this->m_Level;
return v4 >= bpp ? v4 : bpp;
}
GLTexture* GLMipmap::GetTexture() {
return this->m_Texture;
}
uint32_t GLMipmap::GetTextureID() {
return this->m_Texture->m_TextureID;
}
uint16_t GLMipmap::GetWidth() {
return this->m_Width;
}
void* GLMipmap::Map(GLEnum mode, const GLBox* area) {
BLIZZARD_ASSERT(!this->m_Texture->IsSystemBuffer());
BLIZZARD_ASSERT(this->m_Data != nullptr);
BLIZZARD_ASSERT(!this->m_Texture->IsRenderTarget());
BLIZZARD_ASSERT(mode != GL_ZERO);
BLIZZARD_ASSERT(this->m_MapParams == nullptr);
if (mode != GL_READ_ONLY) {
this->m_Texture->m_MappedMipmaps++;
}
MapParams* mapParams = new MapParams();
this->m_MapParams = mapParams;
if (area) {
BLIZZARD_ASSERT(area->width > 0);
BLIZZARD_ASSERT(area->height > 0);
BLIZZARD_ASSERT(area->depth > 0);
BLIZZARD_ASSERT(!this->GetFormatInfo().m_IsCompressed || ((area->top & 0x3) == 0 && (area->left & 0x3) == 0 && (area->width & 0x3) == 0 && (area->height & 0x3) == 0));
BLIZZARD_ASSERT((area->height + area->top) <= this->m_Height);
BLIZZARD_ASSERT((area->depth + area->front) <= this->m_Depth);
BLIZZARD_ASSERT((area->width + area->left) <= this->m_Width);
mapParams->m_MapArea = {
area->left,
area->top,
area->front,
area->width,
area->height,
area->depth
};
int32_t size = this->GetFormatInfo().m_BytePerPixel
* this->m_Width
* mapParams->m_MapArea.depth
* mapParams->m_MapArea.height;
mapParams->m_Size = this->GetFormatInfo().m_IsCompressed
? size >> 4
: size;
mapParams->m_Unk7 = (this->GetFormatInfo().m_BytePerPixel * mapParams->m_MapArea.left)
>> this->GetFormatInfo().m_IsCompressed ? 2 : 0;
} else {
mapParams->m_MapArea = {
0,
0,
0,
this->m_Width,
this->m_Height,
this->m_Depth
};
mapParams->m_Size = this->m_Size;
mapParams->m_Unk7 = 0;
}
mapParams->m_MapMode = mode;
int32_t rowPitch = this->GetPitch();
BLIZZARD_ASSERT(((mapParams->m_MapArea.top * rowPitch) + mapParams->m_MapArea.left * this->GetFormatInfo().m_BytePerPixel) < (this->GetFormatInfo().m_IsCompressed ? this->m_Size << 4 : this->m_Size));
int32_t v22 = rowPitch * this->m_Height;
if (this->GetFormatInfo().m_IsCompressed) {
v22 >>= 2;
}
unsigned char* v24 = this->m_Data
+ ((mapParams->m_MapArea.top * rowPitch) >> (this->GetFormatInfo().m_IsCompressed ? 2 : 0))
+ (mapParams->m_MapArea.front * v22);
mapParams->m_Unk8 = v24;
return v24 + mapParams->m_Unk7;
}
void* GLMipmap::Map(GLEnum mode, const GLRect* rect) {
if (rect) {
GLBox area = {
rect->left,
rect->top,
0,
rect->width,
rect->height,
1
};
return this->Map(mode, &area);
} else {
return this->Map(mode, static_cast<GLBox*>(nullptr));
}
}
void GLMipmap::ReleaseObject() {
BLIZZARD_ASSERT(this->m_MapParams == nullptr);
this->RemoveDebugMipmap();
this->DetachAll();
if (this->m_AttachPoints) {
delete this->m_AttachPoints;
}
this->m_AttachPoints = nullptr;
this->m_Unk24 = 0;
}
void GLMipmap::RemoveDebugMipmap() {
// TODO
}
void GLMipmap::ResetData(GLEnum target, int32_t level, unsigned char* data) {
BLIZZARD_ASSERT(this->m_Target != GL_TEXTURE_3D || !this->GetFormatInfo().m_IsCompressed);
this->m_Target = target;
this->m_Level = level;
this->m_Data = data;
BLIZZARD_ASSERT(this->GetFormat() != GLTF_INVALID);
BLIZZARD_ASSERT(this->GetFormat() < GLTF_NUM_TEXTURE_FORMATS);
if (!this->m_Texture->IsSystemBuffer() && this->m_Texture->IsRenderTarget()) {
BLIZZARD_ASSERT(!this->GetFormatInfo().m_IsCompressed);
this->TexImage(nullptr);
this->m_Unk24 = 1;
}
}
void GLMipmap::ResetSize(uint32_t width, uint32_t height, uint32_t depth) {
this->m_Width = width ? width : 1;
this->m_Height = height ? height : 1;
this->m_Depth = depth ? depth : 1;
if (this->GetFormatInfo().m_IsCompressed) {
BLIZZARD_ASSERT(this->m_Depth == 1);
this->m_Width = (this->m_Width + 3) & 0xFFFC;
this->m_Height = (this->m_Height + 3) & 0xFFFC;
}
uint32_t v11 = this->GetFormatInfo().m_BytePerPixel;
uint32_t v20 = this->m_Texture->var12 >> this->m_Level;
if (v20 >= v11) {
v11 = v20;
}
uint32_t v15 = v11 * this->m_Height;
uint32_t v12;
if (this->GetFormatInfo().m_IsCompressed) {
v12 = v15 >> 2;
} else {
v12 = v15;
}
this->m_Size = this->m_Depth * v12;
}
void GLMipmap::TexImage(const void* pixels) {
BLIZZARD_ASSERT((this->m_Texture->IsRenderTarget() || pixels != nullptr) && GLSDLDevice::Get()->GetVertexArrayStates().buffers[eGLBT_PIXEL_UNPACK] == 0);
if (this->m_Target == GL_TEXTURE_3D) {
glTexImage3D(
GL_TEXTURE_3D,
this->m_Level,
this->GetFormatInfo().m_InternalFormat,
this->m_Width,
this->m_Height,
this->m_Depth,
0,
this->GetFormatInfo().m_DataFormat,
this->GetFormatInfo().m_DataType,
pixels
);
} else if (this->GetFormatInfo().m_IsCompressed) {
glCompressedTexImage2D(
this->m_Target,
this->m_Level,
this->GetFormatInfo().m_InternalFormat,
this->m_Width,
this->m_Height,
0,
this->m_Size,
pixels
);
} else {
glTexImage2D(
this->m_Target,
this->m_Level,
this->GetFormatInfo().m_InternalFormat,
this->m_Width,
this->m_Height,
0,
this->GetFormatInfo().m_DataFormat,
this->GetFormatInfo().m_DataType,
pixels
);
}
}
void GLMipmap::TexSubImage(const GLBox& a2, int32_t size, const void* pixels) {
BLIZZARD_ASSERT(!this->m_Texture->IsRenderTarget() && pixels != nullptr && GLSDLDevice::Get()->GetVertexArrayStates().buffers[eGLBT_PIXEL_UNPACK] == 0);
if (this->m_Target == GL_TEXTURE_3D) {
glPixelStorei(GL_UNPACK_ROW_LENGTH, this->m_Width);
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, this->m_Height);
glTexSubImage3D(
this->m_Target,
this->m_Level,
a2.left,
a2.top,
a2.front,
a2.width,
a2.height,
a2.depth,
this->GetFormatInfo().m_DataFormat,
this->GetFormatInfo().m_DataType,
pixels
);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
} else if (this->GetFormatInfo().m_IsCompressed) {
glCompressedTexSubImage2D(
this->m_Target,
this->m_Level,
0,
a2.top,
this->m_Width,
a2.height,
this->GetFormatInfo().m_InternalFormat,
size,
pixels
);
} else {
glPixelStorei(GL_UNPACK_ROW_LENGTH, this->m_Width);
glTexSubImage2D(
this->m_Target,
this->m_Level,
a2.left,
a2.top,
a2.width,
a2.height,
this->GetFormatInfo().m_DataFormat,
this->GetFormatInfo().m_DataType,
pixels
);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
}
}
void GLMipmap::Unmap() {
BLIZZARD_ASSERT(!this->m_Texture->IsRenderTarget());
BLIZZARD_ASSERT(!this->m_Texture->IsSystemBuffer());
BLIZZARD_ASSERT(this->m_MapParams != nullptr);
if (this->m_MapParams->m_MapMode == GL_READ_ONLY) {
delete this->m_MapParams;
this->m_MapParams = nullptr;
return;
}
GLSDLDevice* device = GLSDLDevice::Get();
BLIZZARD_ASSERT(this->m_Texture->m_MappedMipmaps > 0);
this->Unmap(this->m_MapParams);
this->m_MapParams = nullptr;
}
void GLMipmap::Unmap(MapParams* mapParams) {
BLIZZARD_ASSERT(mapParams != nullptr);
this->m_Texture->Bind(nullptr, 0);
if (this->m_Unk24) {
if (this->GetFormatInfo().m_IsCompressed) {
GLBox area = {
0,
mapParams->m_MapArea.top,
mapParams->m_MapArea.front,
this->m_Width,
mapParams->m_MapArea.height,
mapParams->m_MapArea.depth
};
this->TexSubImage(area, mapParams->m_Size, mapParams->m_Unk8);
} else {
this->TexSubImage(mapParams->m_MapArea, mapParams->m_Size, mapParams->m_Unk8 + mapParams->m_Unk7);
}
} else {
this->TexImage(this->m_Data);
this->m_Unk24 = 1;
}
delete mapParams;
// TODO
this->m_Texture->m_MappedMipmaps--;
}

62
src/gx/glsdl/GLMipmap.hpp Normal file
View File

@ -0,0 +1,62 @@
#ifndef GX_GL_SDL_GL_MIPMAP_HPP
#define GX_GL_SDL_GL_MIPMAP_HPP
#include "gx/glsdl/GL.hpp"
#include "gx/glsdl/GLTypes.hpp"
#include <cstdint>
#include <vector>
class GLFramebuffer;
class GLTexture;
class GLMipmap {
public:
// Types
struct MapParams {
GLBox m_MapArea;
int32_t m_MapMode = 0;
int32_t m_Unk7 = 0;
unsigned char* m_Unk8 = nullptr;
int32_t m_Size = 0;
};
// Member variables
GLTexture* m_Texture = nullptr;
uint16_t m_Width = 0;
uint16_t m_Height = 0;
uint16_t m_Depth = 0;
uint8_t m_Level = 0;
uint8_t m_DepthBits = 0;
uint32_t m_Size = 0;
int32_t m_Target = 0;
unsigned char* m_Data = nullptr; // TODO proper type
MapParams* m_MapParams = nullptr;
std::vector<GLAttachPoint>* m_AttachPoints = nullptr;
uint32_t m_Unk20 = 0;
uint32_t m_Unk24 = 0;
// Member functions
void Attach(GLFramebuffer*, GLenum, int32_t);
void Detach(GLFramebuffer*, GLenum, bool);
void DetachAll();
int32_t GetDepthBits(void);
GLTextureFormat GetFormat(void);
TextureFormatInfo& GetFormatInfo(void);
uint16_t GetHeight(void);
int32_t GetPitch(void);
GLTexture* GetTexture();
uint32_t GetTextureID(void);
uint16_t GetWidth(void);
void* Map(GLEnum, const GLBox*);
void* Map(GLEnum, const GLRect*);
void ReleaseObject();
void RemoveDebugMipmap();
void ResetData(GLEnum, int32_t, unsigned char*);
void ResetSize(uint32_t, uint32_t, uint32_t);
void TexImage(const void*);
void TexSubImage(const GLBox&, int32_t, const void*);
void Unmap(void);
void Unmap(MapParams*);
};
#endif

22
src/gx/glsdl/GLObject.cpp Normal file
View File

@ -0,0 +1,22 @@
#include "gx/glsdl/GLObject.hpp"
#include <bc/Debug.hpp>
void GLObject::AddRefTwin() {
}
uint32_t GLObject::Release() {
BLIZZARD_ASSERT(this->m_RefCount > 0);
this->m_RefCount--;
if (this->m_RefCount == 0) {
this->ReleaseObject();
}
this->ReleaseTwin();
return this->m_RefCount;
}
void GLObject::ReleaseTwin() {
}

22
src/gx/glsdl/GLObject.hpp Normal file
View File

@ -0,0 +1,22 @@
#ifndef GX_GL_SDL_GL_OBJECT_HPP
#define GX_GL_SDL_GL_OBJECT_HPP
#include <cstdint>
class GLObject {
public:
// Member variables
GLObject* m_Next;
uint32_t m_RefCount;
int64_t m_TimeStamp;
// Virtual member functions
virtual void ReleaseObject() = 0;
virtual void AddRefTwin();
virtual void ReleaseTwin();
// Member functions
uint32_t Release();
};
#endif

View File

@ -0,0 +1,17 @@
#include "gx/glsdl/GLPixelShader.hpp"
#include "gx/glsdl/GL.hpp"
GLPixelShader* GLPixelShader::Create() {
// TODO
// GLPool stuff
GLPixelShader* shader = new GLPixelShader();
shader->m_ShaderID = 0;
shader->m_RefCount = 1;
shader->m_ShaderType = ePixelShader;
shader->m_UsingGLSL = 0;
shader->var5 = GL_FRAGMENT_PROGRAM_ARB;
return shader;
}

View File

@ -0,0 +1,12 @@
#ifndef GX_SDL_GL_PIXEL_SHADER_HPP
#define GX_SDL_GL_PIXEL_SHADER_HPP
#include "gx/glsdl/GLShader.hpp"
class GLPixelShader : public GLShader {
public:
// Static functions
static GLPixelShader* Create(void);
};
#endif

57
src/gx/glsdl/GLPool.hpp Normal file
View File

@ -0,0 +1,57 @@
#ifndef GX_GL_SDL_GL_POOL_HPP
#define GX_GL_SDL_GL_POOL_HPP
#include <atomic>
#include <cstdint>
template<class T>
class GLPool {
public:
// Static variables
static GLPool<T>* m_pool;
// Static functions
static GLPool<T>* Get(void);
static void Init(void);
// Member variables
std::atomic<uint32_t> m_NextName;
// Member functions
uint32_t GetNextName(void);
T* GetNextObject(void);
void SetNextName(uint32_t);
};
template<class T>
GLPool<T>* GLPool<T>::m_pool;
template<class T>
GLPool<T>* GLPool<T>::Get() {
return GLPool<T>::m_pool;
}
template<class T>
void GLPool<T>::Init() {
GLPool<T>::m_pool = new GLPool<T>();
}
template<class T>
uint32_t GLPool<T>::GetNextName() {
return this->m_NextName++;
}
template<class T>
T* GLPool<T>::GetNextObject() {
// TODO
// - pop off of GLObjectPool
return new T();
}
template<class T>
void GLPool<T>::SetNextName(uint32_t name) {
this->m_NextName = name;
}
#endif

View File

@ -0,0 +1,48 @@
#include "gx/glsdl/GLSDLContext.hpp"
#include <bc/Debug.hpp>
#include <storm/Error.hpp>
static bool s_GLEW_Initialized = false;
void GLSDLContext::Create(GLSDLWindow* window) {
BLIZZARD_ASSERT(this->m_sdlGLContext == nullptr);
this->m_sdlGLContext = SDL_GL_CreateContext(window->m_sdlWindow);
BLIZZARD_ASSERT(this->m_sdlGLContext != nullptr);
if (s_GLEW_Initialized == false) {
glewExperimental = true;
auto glewError = glewInit();
if (glewError != GLEW_OK) {
SErrDisplayAppFatal("Error initializing GLEW: %s\n", glewGetErrorString(glewError));
}
s_GLEW_Initialized = true;
}
}
void GLSDLContext::Destroy() {
BLIZZARD_ASSERT(this->m_sdlGLContext != nullptr);
SDL_GL_DeleteContext(this->m_sdlGLContext);
this->m_sdlGLContext = nullptr;
}
bool GLSDLContext::IsCurrentContext() {
return this->m_sdlGLContext == SDL_GL_GetCurrentContext();
}
void GLSDLContext::MakeCurrent(GLSDLWindow* window) {
auto status = SDL_GL_MakeCurrent(window->m_sdlWindow, this->m_sdlGLContext);
BLIZZARD_ASSERT(status == 0);
}
int32_t GLSDLContext::GetSampleCount() {
int samples;
auto status = SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &samples);
BLIZZARD_ASSERT(status == 0);
return static_cast<int32_t>(samples);
}

View File

@ -0,0 +1,20 @@
#ifndef GX_GL_SDL_GL_SDL_CONTEXT_HPP
#include <SDL3/SDL.h>
#include "gx/glsdl/GLSDLWindow.hpp"
#include "gx/glsdl/GLTypes.hpp"
class GLSDLContext {
public:
SDL_GLContext m_sdlGLContext = nullptr;
GLSDLContext() = default;
void Create(GLSDLWindow* window);
void Destroy();
bool IsCurrentContext();
void MakeCurrent(GLSDLWindow* window);
int32_t GetSampleCount();
};
#endif

2769
src/gx/glsdl/GLSDLDevice.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,190 @@
#ifndef GX_GL_SDL_GL_SDL_DEVICE_HPP
#define GX_GL_SDL_GL_SDL_DEVICE_HPP
#include "gx/glsdl/GL.hpp"
#include "gx/glsdl/GLSDLWindow.hpp"
#include "gx/glsdl/GLBatch.hpp"
#include "gx/glsdl/GLBufferPool.hpp"
#include "gx/glsdl/GLSDLContext.hpp"
#include "gx/glsdl/GLDebugMipmap2D.hpp"
#include "gx/glsdl/GLFramebuffer.hpp"
#include "gx/glsdl/GLGLSLProgram.hpp"
#include "gx/glsdl/GLMipmap.hpp"
#include "gx/glsdl/GLShader.hpp"
#include "gx/glsdl/GLTexture.hpp"
#include "gx/glsdl/GLTypes.hpp"
#include "gx/glsdl/GLVertexArray.hpp"
#include <cstdint>
#include <list>
#include <string>
#include <vector>
#include <bc/Thread.hpp>
class GLSDLDevice {
public:
// Types
enum GLSDLDeviceOption {
eUseMTGL = 0,
eUseVertexArray = 1,
eUseGLSL = 2,
eCheckGLStates = 3,
eFlushBeforeDraw = 4,
eDeviceOption5 = 5,
eUseHybridShader = 6,
eDeviceOption7 = 7,
eDeviceOption8 = 8,
eShaderConstantBindings = 9
};
struct RendererInfo {
uint8_t init = 0;
uint32_t vendor_id;
uint32_t renderer_id;
uint32_t max_color_attachments;
uint32_t unk36; // max clip planes
uint32_t unk100;
};
// Static variables
static Blizzard::Thread::TLSSlot m_CurrentDevice;
static std::vector<GLSDLDevice*> m_Devices;
static bool m_ExtARBShadow;
static bool m_ExtColorMaskIndexed;
static RendererInfo m_RendererInfo;
static bool m_ShaderConstantBindings;
static int32_t m_StaticResourcesRefCount;
static bool m_UseHybridShader;
static GLBuffer* m_BlitQuadVBO;
static GLShader* m_DeviceShaders[];
static GLTexture* m_DeviceTextures[];
static GLVertexFormat m_NormalBlitVF;
static GLVertexFormat m_InvertedBlitVF;
static GLFramebuffer* m_F8330C;
// Static functions
static GLSDLDevice* Get();
static void Set(GLSDLDevice* device);
static void InitPools();
static RendererInfo GetRendererInfo();
static void InitRendererInfo();
static void SetOption(GLSDLDeviceOption option, bool enable);
static void StaticInit();
// Member variables
std::string m_DebugName;
GLStates m_States;
GLTexture* m_Textures[16] = {};
GLShader* m_PixelShader = nullptr;
GLShader* m_VertexShader = nullptr;
GLGLSLProgram* m_GLSLProgram = nullptr;
GLVertexArray* m_VertexArrayObject = &m_DefaultVertexArrayObject;
GLFramebuffer* m_SystemTarget = nullptr;
GLFramebuffer* m_FBOTarget = nullptr;
GLFramebuffer* m_CurrentTarget = nullptr;
GLMipmap* m_CurrentTargetColor[4] = {};
GLMipmap* m_CurrentTargetDepth = nullptr;
GLMipmap* m_CurrentTargetStencil = nullptr;
GLMipmap* m_CurrentDepthBuffer = nullptr;
GLTexture2D* m_BackBufferColor = nullptr;
GLTexture2D* m_BackBufferDepth = nullptr;
GLTexture2D* m_BackBufferStencil = nullptr;
GLSDLWindow* m_Window = nullptr;
GLBufferPool* m_PBOPool = nullptr;
GLSDLContext m_Context;
GLTexture* m_BoundTextures[4][16] = {};
GLVertexArray m_DefaultVertexArrayObject;
GLDirtyRange m_DirtyVertexShaderConsts;
GLDirtyRange m_DirtyPixelShaderConsts;
float m_ConstantDepthBias = 0.0f;
float m_SlopeScaledDepthBias = 0.0f;
bool m_Init = 0;
uint32_t m_DrawCount = 0;
uint32_t m_ID = -1;
std::list<GLTexture*> m_TextureList;
std::list<GLTexture*>::iterator m_OldestActiveTexture;
uint32_t m_TextureTotalSize = 0;
uint32_t m_FrameNumber = 1;
std::list<GLDebugMipmap2D*> m_DebugMipmaps;
bool m_BatchViewerEnabled = 0;
bool m_UseWindowSystemBuffer = 0;
bool m_FlippedSystemBuffer = 0;
bool m_ShaderCompiler = 0;
bool m_WorkerDevice;
GLStates m_DefaultStates;
std::vector<GLBatch>* m_FrameBatches;
bool m_CaptureOnlyOneFrame = 0;
bool m_StopCapturingBatches = 0;
bool m_CaptureBatches = 0;
int32_t m_IndentLevel = 0;
// Member functions
GLSDLDevice();
void ApplyGLBindings(const GLStates& states, bool a3);
void ApplyGLStates(const GLStates& states, bool force);
void ApplyShaderConstants();
void ApplyTransforms();
void BindBuffer(GLBuffer* buffer, GLEnum target);
void BindFramebuffer(GLFramebuffer* framebuffer);
void BindGLSLProgram(GLGLSLProgram* a2);
void BindShader(GLShader* shader);
void BindTexture(GLEnum textureType, GLTexture* texture);
void BindVertexArray(GLVertexArray* a2);
void BlitFramebuffer(GLMipmap* src, const GLRect* srcRect, GLMipmap* dst, const GLRect* dstRect, GLEnum mask, GLEnum filter);
void CheckDepthTarget();
void Clear(uint32_t clearMask, const GLColor4f& clearColor, double clearDepth, int32_t clearStencil);
void CopyTex(uint32_t a2, uint32_t a3, GLMipmap* dst, const GLRect* framebufferRect);
GLBuffer* CreateBuffer(GLEnum type, uint32_t a3, const void* a4, GLEnum usage, GLEnum format);
GLShader* CreateShader(GLShader::ShaderType type, const void* buf, int32_t codeLen, const char* name);
GLTexture* CreateTexture2D(uint32_t width, uint32_t height, uint32_t numMipMap, GLTextureFormat format, uint32_t flags);
GLTexture* CreateTextureCubeMap(uint32_t size, uint32_t numMipMap, GLTextureFormat format, uint32_t flags);
void Draw(GLEnum primitive, uint32_t a3, uint32_t a4);
void DrawIndexed(GLEnum primitive, uint32_t a3, uint32_t a4, uint32_t a5, uint32_t a6, uint32_t count);
void DrawRect();
GLFramebuffer* GetCurrentTarget(); // invented name
uint32_t GetID();
GLShader* GetShader(GLShader::ShaderType shaderType);
const GLStates::VertexArrayObject& GetVertexArrayStates();
void GLSDLDraw(GLEnum mode, uint32_t start, uint32_t end, uint32_t a5, uint32_t a6, uint32_t count);
void Init(GLSDLWindow* a2, const char* a3, uint32_t a4);
void LoadDefaultStates();
void ResetBackbuffer(uint32_t width, uint32_t height, GLTextureFormat colorFormat, GLTextureFormat depthFormat,uint32_t sampleCount);
void Resize(uint32_t width, uint32_t height);
void RestoreTextures();
void SetActiveTexture(uint32_t a2);
void SetAlphaBlend(GLEnum srcBlend, GLEnum dstBlend, GLEnum blendOp);
void SetAlphaBlendEnable(bool enable);
void SetAlphaTest(GLEnum func, float ref);
void SetAlphaTestEnable(bool enable);
void SetClearColor(const GLColor4f& clearColor);
void SetClearDepth(double clearDepth);
void SetClearStencil(int32_t clearStencil);
void SetColorWriteMask(bool red, bool green, bool blue, bool alpha, uint32_t index);
void SetCullMode(GLEnum cullMode);
void SetDepthBias(float constantBias, float slopeScaledBias);
void SetDepthTestEnable(bool enable);
void SetDepthTestFunc(GLEnum func);
void SetDepthWriteMask(bool enable);
void SetDisplay(uint32_t width, uint32_t height, GLTextureFormat colorFormat, GLTextureFormat depthFormat, uint32_t refreshRate, bool windowed, bool captureDisplay, uint32_t sampleCount);
void SetFogColor(float r, float g, float b, float a);
void SetFogEnable(bool enable);
void SetFogParam(GLEnum param, float value);
void SetIndexBuffer(GLBuffer* buffer);
void SetLightingEnable(bool enable);
void SetModelView(GLEnum transform);
void SetScissor(bool a2, const GLRect& a3);
void SetShader(GLShader::ShaderType shaderType, GLShader* shader);
void SetShaderConstants(GLShader::ShaderType shaderType, uint32_t index, const float* constants, uint32_t count);
void SetShaderConstantsInternal(GLShader::ShaderType shaderType, uint32_t index, const float* constants, uint32_t count);
void SetTexture(uint32_t stage, GLTexture* texture);
void SetTransform(GLEnum transform, const float* a3);
void SetUnpackClientStorage(bool enable);
void SetVertexBuffer(uint32_t index, GLBuffer* buffer, uint32_t offset, uint32_t stride);
void SetVertexFormat(GLVertexFormat* format);
void SetViewport(const GLRect& viewport, double zNear, double zFar);
void Sub34BB0(GLEnum a2, GLMipmap* a3, uint32_t index);
void Sub38460(bool a2);
void Swap();
void UpdateFFPTexturing();
};
#endif

View File

@ -0,0 +1,131 @@
#include "gx/glsdl/GLSDLWindow.hpp"
#include <bc/Debug.hpp>
static bool s_GLSDL_Initialized = false;
void GLSDLWindow::Create(const char* title, const GLSDLWindowRect& rect, GLTextureFormat depthFormat, uint32_t sampleCount) {
BLIZZARD_ASSERT(this->m_sdlWindow == nullptr);
if (!s_GLSDL_Initialized) {
// Initialize SDL video context
SDL_Init(SDL_INIT_VIDEO);
// Set GL version profile
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
s_GLSDL_Initialized = true;
}
// Set depth and stencil size according to format
uint32_t depthSize = 0;
uint32_t stencilSize = 0;
switch (depthFormat) {
case GLTF_INVALID:
break;
case GLTF_D32:
depthSize = 32;
break;
case GLTF_D24:
depthSize = 24;
break;
case GLTF_D16:
depthSize = 16;
break;
case GLTF_D24S8:
depthSize = 24;
stencilSize = 8;
break;
default:
BLIZZARD_ASSERT(false);
break;
}
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, depthSize);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, stencilSize);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
// Set multisampling
if (sampleCount >= 1) {
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, sampleCount);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
}
this->m_sdlWindow = SDL_CreateWindow(
title,
static_cast<int>(rect.size.width), static_cast<int>(rect.size.height),
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE
);
BLIZZARD_ASSERT(this->m_sdlWindow != nullptr);
}
void GLSDLWindow::Swap() {
SDL_GL_SwapWindow(this->m_sdlWindow);
}
void GLSDLWindow::Destroy() {
SDL_DestroyWindow(this->m_sdlWindow);
this->m_sdlWindow = nullptr;
}
GLSDLWindowRect GLSDLWindow::GetRect() {
// Default rectangle
GLSDLWindowRect rect;
int origin_x = 0;
int origin_y = 0;
if (SDL_GetWindowPosition(this->m_sdlWindow, &origin_x, &origin_y) == 0) {
rect.origin.x = static_cast<int32_t>(origin_x);
rect.origin.y = static_cast<int32_t>(origin_y);
}
int width = 0;
int height = 0;
if (SDL_GetWindowSize(this->m_sdlWindow, &width, &height) == 0) {
rect.size.width = static_cast<int32_t>(width);
rect.size.height = static_cast<int32_t>(height);
}
return rect;
}
GLSDLWindowRect GLSDLWindow::GetBackingRect() {
// Default rectangle
GLSDLWindowRect rect;
// Query backing width/height
int width = 0;
int height = 0;
if (SDL_GetWindowSizeInPixels(this->m_sdlWindow, &width, &height) == 0) {
rect.size.width = static_cast<int32_t>(width);
rect.size.height = static_cast<int32_t>(height);
}
return rect;
}
void GLSDLWindow::Resize(const GLSDLWindowRect& rect) {
auto current = this->GetBackingRect();
if (current.size.width != rect.size.width || current.size.height != rect.size.width) {
auto status = SDL_SetWindowSize(this->m_sdlWindow, rect.size.width, rect.size.height);
BLIZZARD_ASSERT(status == 0);
}
}
int32_t GLSDLWindow::GetWidth() {
return this->GetBackingRect().size.width;
}
int32_t GLSDLWindow::GetHeight() {
return this->GetBackingRect().size.height;
}

View File

@ -0,0 +1,44 @@
#ifndef GX_GL_SDL_GL_SDL_WINDOW_HPP
#define GX_GL_SDL_GL_SDL_WINDOW_HPP
#include <cstdint>
#include <SDL3/SDL.h>
#include "gx/glsdl/GLTypes.hpp"
class GLSDLWindowRect {
public:
struct Point {
int32_t x = 0;
int32_t y = 0;
};
struct Size {
int32_t width = 0;
int32_t height = 0;
};
Point origin;
Size size;
};
class GLSDLWindow {
public:
SDL_Window* m_sdlWindow = nullptr;
// Create an SDL window with the requested OpenGL attributes
void Create(const char* title, const GLSDLWindowRect& rect, GLTextureFormat depthFormat, uint32_t sampleCount);
void Destroy();
void Swap();
void Resize(const GLSDLWindowRect& rect);
GLSDLWindowRect GetRect();
GLSDLWindowRect GetBackingRect();
int32_t GetWidth();
int32_t GetHeight();
};
#endif

135
src/gx/glsdl/GLShader.cpp Normal file
View File

@ -0,0 +1,135 @@
#include "gx/glsdl/GLShader.hpp"
#include "gx/glsdl/GLSDLDevice.hpp"
#include "gx/glsdl/GLPixelShader.hpp"
#include "gx/glsdl/GLPool.hpp"
#include "gx/glsdl/GLVertexShader.hpp"
#include "gx/glsdl/GL.hpp"
#include <bc/Debug.hpp>
// TODO
// - threaded compiler support
// - glsl support
// - hybrid support
GLShader* GLShader::Create(ShaderType shaderType, bool hybrid, bool usingCG, const char* a4, const void* buf, int32_t codeLen, const char* a7, const char* name, GLShaderLogInfo* logInfo) {
const char* shaderCode = reinterpret_cast<const char*>(buf);
if (*reinterpret_cast<const int32_t*>(buf) == 'GSL1') {
BLIZZARD_ASSERT(!usingCG);
const ShaderDataHeader header = *reinterpret_cast<const ShaderDataHeader*>(buf);
BLIZZARD_ASSERT(header.shaderType == shaderType);
BLIZZARD_ASSERT(header.size == codeLen);
BLIZZARD_ASSERT(header.codePos >= sizeof(ShaderDataHeader));
BLIZZARD_ASSERT(header.codeSize > 0);
shaderCode = &reinterpret_cast<const char*>(buf)[header.codePos];
}
GLShader* shader = nullptr;
if (shaderType == ePixelShader) {
shader = GLPixelShader::Create();
} else if (shaderType == eVertexShader) {
shader = GLVertexShader::Create();
} else {
// TODO
// sub_1C5E0(&v38, "Unknown shader type %d!", shaderType);
}
shader->m_UsingCG = usingCG;
if (usingCG) {
shader->CompileCG(a4, shaderCode, codeLen, a7, logInfo);
} else {
shader->m_Code.assign(shaderCode, codeLen);
// TODO
// sub_5CD10(shader);
}
return shader;
}
bool GLShader::CheckErrorsARB(GLShaderLogInfo* logInfo) {
GLint errorPos;
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
const GLubyte* errorStr = glGetString(GL_PROGRAM_ERROR_STRING_ARB);
// TODO
// Blizzard::Debug::VAssert(logInfo != 0 || errorPos == -1, errorStr);
return errorPos == -1;
}
void GLShader::Compile(GLShaderLogInfo* logInfo) {
this->ImmediateCompile(logInfo);
}
void GLShader::CompileCG(const char* a2, const void* shaderCode, int32_t codeLen, const char* a5, GLShaderLogInfo* logInfo) {
// TODO
}
void GLShader::FlushUniforms(GLGLSLProgram* program) {
// TODO
}
std::string& GLShader::GetCode() {
return this->m_Code;
}
int32_t GLShader::GetShaderType() {
return this->m_ShaderType;
}
void GLShader::ImmediateCompile(GLShaderLogInfo* logInfo) {
BLIZZARD_ASSERT(!this->GetCode().empty());
this->m_Device = GLSDLDevice::Get();
if (!this->m_UsingGLSL) {
if (!this->m_ShaderID) {
if (this->m_ShaderType == eVertexShader) {
this->m_ShaderID = GLPool<GLVertexShader>::Get()->GetNextName();
} else {
this->m_ShaderID = GLPool<GLPixelShader>::Get()->GetNextName();
}
}
this->m_Device->BindShader(this);
const char* arbCode = this->GetCode().c_str();
size_t arbLen = strlen(arbCode);
glProgramStringARB(this->var5, GL_PROGRAM_FORMAT_ASCII_ARB, arbLen, arbCode);
BLIZZARD_ASSERT(this->CheckErrorsARB(logInfo));
} else {
// TODO
// - handle GLSL shaders
// - handle hybrid shaders
}
if (logInfo) {
// TODO
// this->var20 = logInfo[0];
} else {
this->var20 = 1;
}
// TODO
// this->m_TimeStamp = Blizzard::Time::GetTimestamp();
}
bool GLShader::IsEnabled() {
return this->m_Enabled;
}
void GLShader::ReleaseObject() {
// TODO
}
void GLShader::SetShaderConstants(ShaderType shaderType, uint32_t index, const float* constants, uint32_t count) {
// TODO
}

75
src/gx/glsdl/GLShader.hpp Normal file
View File

@ -0,0 +1,75 @@
#ifndef GX_GL_SDL_GL_SHADER_HPP
#define GX_GL_SDL_GL_SHADER_HPP
#include "gx/glsdl/GLObject.hpp"
#include "gx/glsdl/GLShaderInput.hpp"
#include <cstdint>
#include <string>
#include <vector>
class GLSDLDevice;
class GLGLSLProgram;
class GLShaderLogInfo;
class GLShader : public GLObject {
public:
// Types
enum ShaderType {
eVertexShader = 1,
ePixelShader = 2,
eShaderTypeCount = 3
};
struct ShaderDataHeader {
uint32_t signature;
uint32_t size;
ShaderType shaderType;
uint32_t codePos;
uint32_t codeSize;
uint32_t unk1;
uint32_t unk2;
uint32_t unk3;
};
// Static functions
static GLShader* Create(ShaderType, bool, bool, const char*, const void*, int32_t, const char*, const char*, GLShaderLogInfo*);
// Member variables
int32_t m_ShaderType = 0;
int32_t var5 = 0;
uint32_t m_ShaderID = 0;
bool m_UsingCG = false;
bool m_UsingGLSL = false;
uint32_t m_UniformRegisterCount = 0;
GLShaderInput** var10 = nullptr;
float* var11 = nullptr;
bool var12 = false;
uint32_t var13 = 0;
uint32_t var14 = 0;
std::vector<GLShaderInput*, std::allocator<GLShaderInput*>> var15;
std::vector<GLShaderInput*, std::allocator<GLShaderInput*>> var16;
std::vector<GLShaderInput*, std::allocator<GLShaderInput*>> var17;
GLShader* var18 = nullptr;
GLSDLDevice* m_Device = nullptr;
bool var20 = 0;
bool m_Enabled = true;
std::basic_string<char, std::char_traits<char>, std::allocator<char>> m_Code;
std::basic_string<char, std::char_traits<char>, std::allocator<char>> var23;
// Virtual member functions
virtual void ReleaseObject();
// Member functions
bool CheckErrorsARB(GLShaderLogInfo*);
bool CheckErrorsGLSL(GLShaderLogInfo*);
void Compile(GLShaderLogInfo*);
void CompileCG(const char*, const void*, int32_t, const char*, GLShaderLogInfo*);
void FlushUniforms(GLGLSLProgram*);
std::string& GetCode(void);
int32_t GetShaderType(void);
void ImmediateCompile(GLShaderLogInfo*);
bool IsEnabled(void);
void SetShaderConstants(ShaderType, uint32_t, const float*, uint32_t);
};
#endif

View File

@ -0,0 +1,33 @@
#ifndef GX_GL_SDL_GL_SHADER_INPUT_HPP
#define GX_GL_SDL_GL_SHADER_INPUT_HPP
#include <string>
class GLShader;
class GLShaderInput {
public:
// Member variables
GLShader *m_Shader;
std::basic_string<char, std::char_traits<char>, std::allocator<char>> m_Name;
std::basic_string<char, std::char_traits<char>, std::allocator<char>> var2;
int16_t m_MapIndex;
int16_t var4;
int16_t var5;
int16_t m_UsedSize;
int16_t var7;
int16_t var8;
GLShaderInput *m_Parent;
int32_t var10;
int32_t var11;
int32_t var12;
int8_t m_ChildrenCount;
int8_t var14;
uint16_t var15;
int8_t var16;
int8_t m_Variability;
int8_t var18;
int8_t var19;
};
#endif

632
src/gx/glsdl/GLTexture.cpp Normal file
View File

@ -0,0 +1,632 @@
#include "gx/glsdl/GLTexture.hpp"
#include "gx/glsdl/GLSDLDevice.hpp"
#include "gx/glsdl/GLPool.hpp"
#include "gx/glsdl/GLUtil.hpp"
#include "gx/texture/CGxTex.hpp"
#include <deque>
#include <bc/Debug.hpp>
#include <bc/Memory.hpp>
Blizzard::Thread::TLSSlot GLTexture::m_Bindings[4];
void* GLTexture::CreateBindings(void* ptr) {
return new std::deque<std::vector<Binding>>;
}
void GLTexture::DestroyBindings(void* ptr) {
delete static_cast<std::deque<std::vector<Binding>>*>(ptr);
}
void GLTexture::Bind(GLSDLDevice* device, bool force) {
BLIZZARD_ASSERT(!this->IsSystemBuffer());
BLIZZARD_ASSERT(this->m_Depth != 0);
if (!device) {
device = GLSDLDevice::Get();
}
BLIZZARD_ASSERT(device != nullptr);
auto& bindings = this->GetBindings();
uint32_t deviceID = device->GetID();
if (deviceID >= bindings.size()) {
bindings.resize(deviceID + 1);
}
bindings[deviceID].device = device;
uint32_t currentActiveTexture = device->m_States.binding.currentActiveTexture;
if (bindings[deviceID].boundStages[currentActiveTexture]) {
return;
}
if (force) {
bindings[deviceID].boundStages[currentActiveTexture] = 1;
device->BindTexture(this->m_TextureType, this);
return;
}
for (int32_t i = 0; i < 16; i++) {
if (bindings[deviceID].boundStages[i]) {
device->SetActiveTexture(i);
return;
}
}
bindings[deviceID].boundStages[currentActiveTexture] = 1;
device->BindTexture(this->m_TextureType, this);
}
void GLTexture::FreeTexture() {
auto device = GLSDLDevice::Get();
int32_t numFace = this->m_TextureType == GL_TEXTURE_CUBE_MAP ? 6 : 1;
for (int32_t face = 0; face < numFace; face++) {
if (this->m_Mipmaps[face]) {
delete[] this->m_Mipmaps[face];
}
}
if (this->m_Mipmaps) {
delete[] this->m_Mipmaps;
}
this->m_Mipmaps = nullptr;
this->m_Depth = 0;
// TODO this->Sub690D0();
glDeleteTextures(1, &this->m_TextureID);
this->m_GenerateMipmaps = 0;
this->m_MaxMipmapLevel = 1000;
this->m_BaseMipmapLevel = 0;
this->m_CompareMode = 0;
this->m_Sampler.mipmapBias = 0.0f;
this->m_Sampler.borderColor = { 0.0f, 0.0f, 0.0f, 0.0f };
this->m_Sampler.addressModeS = GL_REPEAT;
this->m_Sampler.addressModeT = GL_REPEAT;
this->m_Sampler.addressModeR = GL_REPEAT;
this->m_Sampler.magFilterMode = GL_LINEAR;
this->m_Sampler.minFilterMode = GL_NEAREST_MIPMAP_LINEAR;
this->m_Sampler.maxAnisotropy = 1.0f;
Blizzard::Memory::Free(this->m_Data);
this->m_Data = nullptr;
switch (this->m_TextureType) {
case GL_TEXTURE_3D:
// TODO GLPool<GLTexture3D>::GLObjectPool::Push(GLPool<GLTexture3D>::m_pool + 264, this);
break;
case GL_TEXTURE_CUBE_MAP:
// TODO GLPool<GLTextureCubeMap>::GLObjectPool::Push(GLPool<GLTextureCubeMap>::m_pool + 520, this);
break;
case GL_TEXTURE_2D:
// TODO GLPool<GLTexture2D>::GLObjectPool::Push(GLPool<GLTexture2D>::m_pool + 131080, this);
break;
}
}
std::vector<GLTexture::Binding>& GLTexture::GetBindings() {
uint32_t index = GLSDLTextureTypeToIndex(this->m_TextureType);
uint32_t id;
if (index == 0) {
id = this->m_TextureID - 33;
} else if (index == 1) {
id = this->m_TextureID - 32801;
} else if (index == 2) {
id = this->m_TextureID - 32865;
} else if (index == 3) {
id = this->m_TextureID - 1;
}
auto target = static_cast<std::deque<std::vector<Binding>>*>(
Blizzard::Thread::RegisterLocalStorage(
&GLTexture::m_Bindings[index],
GLTexture::CreateBindings,
nullptr,
GLTexture::DestroyBindings
)
);
if (id >= target->size()) {
target->resize(id + 1);
}
return (*target)[id];
}
GLTextureFormat GLTexture::GetFormat() {
return this->m_Format;
}
TextureFormatInfo& GLTexture::GetFormatInfo() {
return k_TextureFormatInfo[this->m_Format];
}
GLMipmap* GLTexture::GetMipmap(uint32_t level, GLEnum face) {
BLIZZARD_ASSERT(face >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
BLIZZARD_ASSERT(level < this->m_NumMipmap);
BLIZZARD_ASSERT(this->m_Mipmaps != nullptr);
BLIZZARD_ASSERT(this->m_Mipmaps[face - GL_TEXTURE_CUBE_MAP_POSITIVE_X] != nullptr);
return &this->m_Mipmaps[face - GL_TEXTURE_CUBE_MAP_POSITIVE_X][level];
}
bool GLTexture::IsRenderTarget() {
return this->m_Flags & GLTFLAG_RENDERTARGET;
}
bool GLTexture::IsSystemBuffer() {
return this->m_Flags & GLTFLAG_SYSTEM_BUFFER;
}
bool GLTexture::IsValid() {
return this->m_Depth;
}
void* GLTexture::Map(uint32_t level, const GLRect* a3, uint32_t& a4, GLEnum a5) {
BLIZZARD_ASSERT(this->m_TextureType != GL_TEXTURE_3D);
auto mipmap = this->GetMipmap(level, GL_TEXTURE_CUBE_MAP_POSITIVE_X);
a4 = mipmap->GetPitch();
return mipmap->Map(a5, a3);
}
void GLTexture::RecreateGLTexture() {
if (this->m_TextureType == GL_TEXTURE_RECTANGLE) {
return;
}
bool isCubeMap = this->m_TextureType == GL_TEXTURE_CUBE_MAP;
int32_t numFace = isCubeMap ? 6 : 1;
for (int32_t face = 0; face < numFace; face++) {
for (int32_t level = 0; level < this->m_NumMipmap; level++) {
this->m_Mipmaps[face][level].Map(GL_WRITE_ONLY, static_cast<GLBox*>(nullptr));
this->m_Mipmaps[face][level].Unmap();
}
}
glTexParameterf(this->m_TextureType, GL_TEXTURE_LOD_BIAS, this->m_Sampler.mipmapBias);
glTexParameteri(this->m_TextureType, GL_TEXTURE_WRAP_S, this->m_Sampler.addressModeS);
glTexParameteri(this->m_TextureType, GL_TEXTURE_WRAP_T, this->m_Sampler.addressModeT);
glTexParameteri(this->m_TextureType, GL_TEXTURE_WRAP_R, this->m_Sampler.addressModeR);
glTexParameteri(this->m_TextureType, GL_TEXTURE_MIN_FILTER, this->m_Sampler.minFilterMode);
glTexParameteri(this->m_TextureType, GL_TEXTURE_MAG_FILTER, this->m_Sampler.magFilterMode);
glTexParameterf(this->m_TextureType, GL_TEXTURE_MAX_ANISOTROPY_EXT, this->m_Sampler.maxAnisotropy);
glTexParameterfv(this->m_TextureType, GL_TEXTURE_BORDER_COLOR, reinterpret_cast<GLfloat*>(&this->m_Sampler.borderColor));
glTexParameteri(this->m_TextureType, GL_TEXTURE_MAX_LEVEL, this->m_MaxMipmapLevel);
glTexParameteri(this->m_TextureType, GL_TEXTURE_BASE_LEVEL, this->m_BaseMipmapLevel);
glTexParameteri(this->m_TextureType, GL_GENERATE_MIPMAP, this->m_GenerateMipmaps);
}
void GLTexture::ResizeMipmaps() {
BLIZZARD_ASSERT(this->m_Mipmaps == nullptr);
int32_t numFace = this->m_TextureType == GL_TEXTURE_CUBE_MAP ? 6 : 1;
this->m_Mipmaps = new GLMipmap*[numFace];
for (int32_t face = 0; face < numFace; face++) {
this->m_Mipmaps[face] = new GLMipmap[this->m_NumMipmap];
}
}
void GLTexture::SetAddressModeR(GLEnum mode) {
// TODO
}
void GLTexture::SetAddressModeS(GLEnum mode) {
if (this->m_Sampler.addressModeS == mode) {
return;
}
if (mode == GL_CLAMP_TO_EDGE) {
this->Bind(nullptr, 0);
glTexParameteri(this->m_TextureType, GL_TEXTURE_WRAP_S, mode);
this->m_Sampler.addressModeS = mode;
} else {
// Workaround for buggy GPU (possibly ATI Radeon X1900)
if (GLSDLDevice::GetRendererInfo().renderer_id == 0x21900) {
if (this->m_Width & (this->m_Width - 1)) {
return;
}
if (this->m_Height & (this->m_Height - 1)) {
return;
}
}
this->Bind(nullptr, 0);
glTexParameteri(this->m_TextureType, GL_TEXTURE_WRAP_S, mode);
this->m_Sampler.addressModeS = mode;
}
}
void GLTexture::SetAddressModeT(GLEnum mode) {
if (this->m_Sampler.addressModeT == mode) {
return;
}
if (mode == GL_CLAMP_TO_EDGE) {
this->Bind(nullptr, 0);
glTexParameteri(this->m_TextureType, GL_TEXTURE_WRAP_T, mode);
this->m_Sampler.addressModeT = mode;
} else {
// Workaround for buggy GPU (possibly ATI Radeon X1900)
if (GLSDLDevice::GetRendererInfo().renderer_id == 0x21900) {
if (this->m_Width & (this->m_Width - 1)) {
return;
}
if (this->m_Height & (this->m_Height - 1)) {
return;
}
}
this->Bind(nullptr, 0);
glTexParameteri(this->m_TextureType, GL_TEXTURE_WRAP_T, mode);
this->m_Sampler.addressModeT = mode;
}
}
void GLTexture::SetBorderColor(const GLColor4f& color) {
// TODO
}
void GLTexture::SetCompareMode(GLEnum compareMode) {
BLIZZARD_ASSERT(
this->GetFormatInfo().m_DataFormat == GL_DEPTH_COMPONENT
|| this->GetFormatInfo().m_DataFormat == GL_DEPTH_STENCIL_EXT
|| compareMode == GL_NONE
);
if (this->m_CompareMode != compareMode) {
this->Bind(nullptr, 0);
glTexParameteri(this->m_TextureType, GL_TEXTURE_COMPARE_MODE, compareMode);
this->m_CompareMode = compareMode;
}
}
void GLTexture::SetMagFilterMode(GLEnum mode) {
if (this->m_Sampler.magFilterMode == mode) {
return;
}
if (GLSDLDevice::GetRendererInfo().vendor_id == 2 && this->IsRenderTarget() && mode != GL_LINEAR) {
return;
}
this->Bind(nullptr, 0);
glTexParameteri(this->m_TextureType, GL_TEXTURE_MAG_FILTER, mode);
this->m_Sampler.magFilterMode = mode;
}
void GLTexture::SetMaxAnisotropy(int32_t maxAnisotropy) {
if (this->m_Sampler.maxAnisotropy == maxAnisotropy) {
return;
}
this->Bind(nullptr, 0);
glTexParameterf(this->m_TextureType, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy);
this->m_Sampler.maxAnisotropy = maxAnisotropy;
}
void GLTexture::SetMinFilterMode(GLEnum mode) {
if (this->m_Sampler.minFilterMode == mode) {
return;
}
if (GLSDLDevice::GetRendererInfo().vendor_id == 2 && this->IsRenderTarget() && mode != GL_LINEAR) {
return;
}
this->Bind(nullptr, 0);
glTexParameteri(this->m_TextureType, GL_TEXTURE_MIN_FILTER, mode);
this->m_Sampler.minFilterMode = mode;
}
void GLTexture::SetupTexture() {
BLIZZARD_ASSERT(this->m_NumMipmap == 1 || (this->m_Flags & GLTFLAG_AUTOGEN_MIPMAP) == 0);
BLIZZARD_ASSERT(!this->IsRenderTarget() || this->m_NumMipmap == 1);
BLIZZARD_ASSERT(!this->IsRenderTarget() || (this->m_Flags & GLTFLAG_READ_ACCESS) == 0);
GLSDLDevice* device = GLSDLDevice::Get();
if (this->GetFormatInfo().m_IsCompressed) {
int32_t smallestDim = std::min(this->m_Width, this->m_Height);
BLIZZARD_ASSERT(smallestDim >= 4);
if (smallestDim == 4) {
this->m_NumMipmap = 1;
} else if (smallestDim == 8) {
this->m_NumMipmap = 2;
} else if (smallestDim == 16) {
this->m_NumMipmap = 3;
} else if (smallestDim == 32) {
this->m_NumMipmap = 4;
} else if (smallestDim == 64) {
this->m_NumMipmap = 5;
} else if (smallestDim == 128) {
this->m_NumMipmap = 6;
} else if (smallestDim == 256) {
this->m_NumMipmap = 7;
} else if (smallestDim == 512) {
this->m_NumMipmap = 8;
} else if (smallestDim == 1024) {
this->m_NumMipmap = 9;
} else if (smallestDim == 2048) {
this->m_NumMipmap = 10;
} else if (smallestDim == 4096) {
this->m_NumMipmap = 11;
} else {
int32_t i = smallestDim >> 1;
int32_t n = 0;
while (i) {
i >>= 1;
n++;
}
this->m_NumMipmap = n - 1;
}
} else {
int32_t largestDim = std::max(this->m_Width, this->m_Height);
if (largestDim == 1) {
this->m_NumMipmap = 1;
} else if (largestDim == 2) {
this->m_NumMipmap = 2;
} else if (largestDim == 4) {
this->m_NumMipmap = 3;
} else if (largestDim == 8) {
this->m_NumMipmap = 4;
} else if (largestDim == 16) {
this->m_NumMipmap = 5;
} else if (largestDim == 32) {
this->m_NumMipmap = 6;
} else if (largestDim == 64) {
this->m_NumMipmap = 7;
} else if (largestDim == 128) {
this->m_NumMipmap = 8;
} else if (largestDim == 256) {
this->m_NumMipmap = 9;
} else if (largestDim == 512) {
this->m_NumMipmap = 10;
} else if (largestDim == 1024) {
this->m_NumMipmap = 11;
} else if (largestDim == 2048) {
this->m_NumMipmap = 12;
} else if (largestDim == 4096) {
this->m_NumMipmap = 13;
} else {
int32_t i = largestDim >> 1;
int32_t n = 0;
while (i) {
i >>= 1;
n++;
}
this->m_NumMipmap = n + 1;
}
}
if (!(this->m_Flags & GLTFLAG_SYSTEM_BUFFER)) {
BLIZZARD_ASSERT(this->m_RequestedNumMipmaps != 0);
this->m_NumMipmap = std::min(this->m_NumMipmap, this->m_RequestedNumMipmaps);
}
this->var12 = this->GetFormatInfo().m_BytePerPixel * this->m_Width;
if (this->GetFormatInfo().m_IsCompressed) {
this->var12 >>= 2;
}
this->ResizeMipmaps();
bool isCubeMap = this->m_TextureType == GL_TEXTURE_CUBE_MAP;
this->m_Size = 0;
int32_t numFace = isCubeMap ? 6 : 1;
for (int32_t face = 0; face < numFace; face++) {
for (int32_t level = 0; level < this->m_NumMipmap; level++) {
GLMipmap* mip = this->GetMipmap(level, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face);
mip->m_Level = level;
mip->m_Texture = this;
mip->ResetSize(this->m_Width >> level, this->m_Height >> level, this->m_Depth >> level);
this->m_Size += mip->m_Size;
}
}
this->var7 = GLSDLDevice::m_Devices[0]->m_TextureList.begin();
if (this->m_Flags & GLTFLAG_SYSTEM_BUFFER) {
return;
}
BLIZZARD_ASSERT(this->m_Data == nullptr);
if (!this->IsRenderTarget()) {
this->m_Data = static_cast<char*>(Blizzard::Memory::Allocate(this->m_Size));
}
this->Bind(nullptr, 0);
if (this->IsRenderTarget()) {
this->SetAddressModeR(GL_CLAMP_TO_EDGE);
this->SetAddressModeS(GL_CLAMP_TO_EDGE);
this->SetAddressModeT(GL_CLAMP_TO_EDGE);
this->SetMinFilterMode(GL_LINEAR);
this->SetMagFilterMode(GL_LINEAR);
// glTexParameteri(this->m_TextureType, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_CACHED_APPLE);
} else {
this->SetAddressModeR(GL_REPEAT);
this->SetAddressModeS(GL_REPEAT);
this->SetAddressModeT(GL_REPEAT);
this->SetMinFilterMode(GL_NEAREST_MIPMAP_NEAREST);
this->SetMagFilterMode(GL_NEAREST);
}
if (this->GetFormatInfo().m_DataFormat == GL_DEPTH_COMPONENT || this->GetFormatInfo().m_DataFormat == GL_DEPTH_STENCIL) {
this->SetCompareMode(GLSDLDevice::m_ExtARBShadow >= 1 ? GL_COMPARE_R_TO_TEXTURE : 0);
glTexParameteri(this->m_TextureType, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexParameteri(this->m_TextureType, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
} else {
this->SetCompareMode(0);
}
this->SetMaxAnisotropy(1);
this->SetBorderColor(GLColor4f::ZERO);
int32_t autogenMipmap = this->m_Flags & GLTFLAG_AUTOGEN_MIPMAP;
if (autogenMipmap != this->m_GenerateMipmaps) {
this->Bind(nullptr, 0);
glTexParameteri(this->m_TextureType, GL_GENERATE_MIPMAP, autogenMipmap);
this->m_GenerateMipmaps = autogenMipmap;
}
int32_t maxMipmapLevel = this->m_NumMipmap - 1;
if (maxMipmapLevel != this->m_MaxMipmapLevel) {
this->Bind(nullptr, 0);
glTexParameteri(this->m_TextureType, GL_TEXTURE_MAX_LEVEL, maxMipmapLevel);
this->m_MaxMipmapLevel = maxMipmapLevel;
}
if (this->m_TextureType == GL_TEXTURE_RECTANGLE) {
return;
}
if (this->IsRenderTarget()) {
device->SetUnpackClientStorage(0);
}
unsigned char* data = reinterpret_cast<unsigned char*>(this->m_Data);
for (int32_t face = 0; face < numFace; face++) {
for (int32_t level = 0; level < this->m_NumMipmap; level++) {
GLMipmap* mip = this->GetMipmap(level, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face);
if (this->m_TextureType == GL_TEXTURE_CUBE_MAP) {
mip->ResetData(face, level, data);
} else {
mip->ResetData(this->m_TextureType, level, data);
}
if (data) {
data += mip->m_Size;
}
}
}
// TODO
// this->m_TimeStamp = Blizzard::Time::GetTimestamp();
if (this->IsRenderTarget()) {
device->SetUnpackClientStorage(1);
}
}
void GLTexture::Unbind(GLSDLDevice* device, uint32_t stage) {
auto& bindings = this->GetBindings();
BLIZZARD_ASSERT(device->GetID() < bindings.size());
BLIZZARD_ASSERT(bindings[device->GetID()].device == device);
BLIZZARD_ASSERT(bindings[device->GetID()].boundStages[stage]);
bindings[device->GetID()].boundStages[stage] = 0;
}
void GLTexture::Unmap(uint32_t level, GLEnum face) {
auto mipmap = this->GetMipmap(level, face);
mipmap->Unmap();
}
GLTexture2D* GLTexture2D::Create(uint32_t width, uint32_t height, uint32_t numMipMap, GLTextureFormat format, uint32_t flags) {
GLTexture2D* tex;
// TODO
// tex = GLPool<GLTexture2D>::GLObjectPool::Pop(GLPool<GLTexture2D>::m_pool + 131080);
tex = nullptr;
if (!tex) {
tex = new GLTexture2D();
}
// TODO
// Blizzard::Debug::Assert(tex->m_refCount == 0);
tex->m_RefCount = 1;
// TODO
// Blizzard::Debug::Assert(tex->m_TextureID >= PoolStats<GLTexture2D>::NAME_POOL_FIRST_NAME);
tex->m_TextureType = GL_TEXTURE_2D;
tex->m_Width = width;
tex->m_Depth = 1;
tex->m_Height = height;
tex->m_Format = format;
tex->m_NumMipmap = numMipMap;
tex->m_RequestedNumMipmaps = numMipMap;
tex->m_Flags = flags;
tex->SetupTexture();
return tex;
}
GLTexture2D::GLTexture2D() : GLTexture() {
this->m_TextureType = GL_TEXTURE_2D;
this->m_TextureID = GLPool<GLTexture2D>::Get()->GetNextName();
// TODO
// Blizzard::Debug::Assert(this->m_TextureID >= PoolStats<GLTexture2D>::NAME_POOL_FIRST_NAME);
}
void GLTexture2D::ReleaseObject() {
BLIZZARD_ASSERT(this->m_TextureType == GL_TEXTURE_2D);
this->FreeTexture();
}
void GLSDLTexSetFlags(CGxTex* texId, GLTexture* a2) {
static GLEnum convertMagFilterToOgl[] = {
GL_NEAREST,
GL_LINEAR,
GL_NEAREST,
GL_LINEAR,
GL_LINEAR,
GL_LINEAR
};
static GLEnum convertMinFilterToOgl[] = {
GL_NEAREST,
GL_LINEAR,
GL_NEAREST_MIPMAP_NEAREST,
GL_LINEAR_MIPMAP_NEAREST,
GL_LINEAR_MIPMAP_LINEAR,
GL_LINEAR_MIPMAP_LINEAR
};
a2->SetMagFilterMode(convertMagFilterToOgl[texId->m_flags.m_filter]);
a2->SetMinFilterMode(convertMinFilterToOgl[texId->m_flags.m_filter]);
a2->SetAddressModeS(texId->m_flags.m_wrapU ? GL_REPEAT : GL_CLAMP_TO_EDGE);
a2->SetAddressModeT(texId->m_flags.m_wrapV ? GL_REPEAT : GL_CLAMP_TO_EDGE);
a2->SetMaxAnisotropy(texId->m_flags.m_maxAnisotropy);
}

101
src/gx/glsdl/GLTexture.hpp Normal file
View File

@ -0,0 +1,101 @@
#ifndef GX_GL_SDL_GL_TEXTURE_HPP
#define GX_GL_SDL_GL_TEXTURE_HPP
#include "gx/glsdl/GL.hpp"
#include "gx/glsdl/GLObject.hpp"
#include "gx/glsdl/GLTypes.hpp"
#include <list>
#include <vector>
#include <atomic>
#include <bc/Thread.hpp>
#define GLTFLAG_RENDERTARGET 0x1
#define GLTFLAG_DEPTH 0x2
#define GLTFLAG_STENCIL 0x4
#define GLTFLAG_AUTOGEN_MIPMAP 0x8
#define GLTFLAG_READ_ACCESS 0x10
#define GLTFLAG_SYSTEM_BUFFER 0x20
class CGxTex;
class GLMipmap;
class GLSDLDevice;
class GLTexture : public GLObject {
public:
// Types
struct Binding {
uint8_t boundStages[16];
GLSDLDevice* device;
};
// Static variables
static Blizzard::Thread::TLSSlot m_Bindings[4];
// Static functions
static void* CreateBindings(void*);
static void DestroyBindings(void*);
// Member variables
uint32_t m_TextureID = 0;
GLEnum m_TextureType = 0;
GLMipmap** m_Mipmaps = nullptr;
std::list<GLTexture*>::iterator var7;
uint32_t m_LastFrameUsed;
uint32_t m_Width = 0;
uint32_t m_Height = 0;
uint32_t m_Depth = 0;
uint32_t var12 = 0;
uint32_t m_Size = 0;
GLTextureFormat m_Format = GLTF_INVALID;
uint32_t m_Flags = 0;
uint32_t m_NumMipmap = 0;
uint32_t m_RequestedNumMipmaps;
char* m_Data = nullptr;
std::atomic<int32_t> m_MappedMipmaps = { 0 };
GLStates::Sampler m_Sampler;
bool m_GenerateMipmaps = 0;
int32_t m_MaxMipmapLevel = 1000;
int32_t m_BaseMipmapLevel = 0;
int32_t m_CompareMode = 0;
// Member functions
void Bind(GLSDLDevice*, bool);
void FreeTexture();
std::vector<Binding>& GetBindings(void); // invented name
GLTextureFormat GetFormat(void);
TextureFormatInfo& GetFormatInfo(void);
GLMipmap* GetMipmap(uint32_t, GLEnum);
bool IsRenderTarget(void);
bool IsSystemBuffer(void);
bool IsValid(void);
void* Map(uint32_t, const GLRect*, uint32_t&, GLEnum);
void RecreateGLTexture(void);
void ResizeMipmaps(void);
void SetAddressModeR(GLEnum);
void SetAddressModeS(GLEnum);
void SetAddressModeT(GLEnum);
void SetBorderColor(const GLColor4f&);
void SetCompareMode(GLEnum);
void SetMagFilterMode(GLEnum);
void SetMaxAnisotropy(int32_t);
void SetMinFilterMode(GLEnum);
void SetupTexture(void);
void Unbind(GLSDLDevice*, uint32_t); // invented name
void Unmap(uint32_t level, GLEnum face);
};
class GLTexture2D : public GLTexture {
public:
// Static functions
static GLTexture2D* Create(uint32_t, uint32_t, uint32_t, GLTextureFormat, uint32_t);
// Virtual member functions
virtual void ReleaseObject();
// Member functions
GLTexture2D();
};
void GLSDLTexSetFlags(CGxTex*, GLTexture*);
#endif

58
src/gx/glsdl/GLTypes.cpp Normal file
View File

@ -0,0 +1,58 @@
#include "gx/glsdl/GLTypes.hpp"
#include <cstring>
GLColor4f GLColor4f::ZERO = { 0.0, 0.0, 0.0, 0.0 };
GLColor4f GLColor4f::WHITE = { 1.0, 1.0, 1.0, 1.0 };
GLColor4f GLColor4f::BLACK = { 0.0, 0.0, 0.0, 1.0 };
bool GLTransform::operator==(const float m[16]) const {
return this->m[0] == m[0]
&& this->m[1] == m[1]
&& this->m[2] == m[2]
&& this->m[3] == m[3]
&& this->m[4] == m[4]
&& this->m[5] == m[5]
&& this->m[6] == m[6]
&& this->m[7] == m[7]
&& this->m[8] == m[8]
&& this->m[9] == m[9]
&& this->m[10] == m[10]
&& this->m[11] == m[11]
&& this->m[12] == m[12]
&& this->m[13] == m[13]
&& this->m[14] == m[14]
&& this->m[15] == m[15];
}
bool GLTransform::operator!=(const float m[16]) const {
return !(*this == m);
}
void GLTransform::Set(const float m[16]) {
memcpy(this->m, m, sizeof(this->m));
this->isDirty = true;
this->isIdentity = this->a0 == 1.0f
&& this->a1 == 0.0f
&& this->a2 == 0.0f
&& this->a3 == 0.0f
&& this->b0 == 0.0f
&& this->b1 == 1.0f
&& this->b2 == 0.0f
&& this->b3 == 0.0f
&& this->c0 == 0.0f
&& this->c1 == 0.0f
&& this->c2 == 1.0f
&& this->c3 == 0.0f
&& this->d0 == 0.0f
&& this->d1 == 0.0f
&& this->d2 == 0.0f
&& this->d3 == 1.0f;
}
void GLTransform::SetIdentity() {
memset(this->m, 0, sizeof(this->m));
this->a0 = 1.0f;
this->b1 = 1.0f;
this->c2 = 1.0f;
this->d3 = 1.0f;
}

376
src/gx/glsdl/GLTypes.hpp Normal file
View File

@ -0,0 +1,376 @@
#ifndef GX_GL_SDL_GL_TYPES_HPP
#define GX_GL_SDL_GL_TYPES_HPP
#include <cstdint>
#include <GL/glew.h>
class GLBuffer;
class GLFramebuffer;
enum GLTextureFormat {
GLTF_INVALID = 0,
GLTF_ARGB8888 = 1,
GLTF_XRGB8888 = 2,
GLTF_RGBA8888 = 3,
GLTF_ABGR8888 = 4,
GLTF_ARGB0888 = 5,
GLTF_RGB888 = 6,
GLTF_BGR888 = 7,
GLTF_RGBA32F = 8,
GLTF_RGBA16F = 9,
GLTF_RG16F = 10,
GLTF_D32 = 11,
GLTF_D24 = 12,
GLTF_D16 = 13,
GLTF_DF = 14,
GLTF_D24S8 = 15,
GLTF_S8 = 16,
GLTF_ARGB4444 = 17,
GLTF_ARGB1555 = 18,
GLTF_ARGB0555 = 19,
GLTF_RGB565 = 20,
GLTF_A2RGB10 = 21,
GLTF_RGB16 = 22,
GLTF_L8 = 23,
GLTF_A8 = 24,
GLTF_A8L8 = 25,
GLTF_DXT1 = 26,
GLTF_DXT3 = 27,
GLTF_DXT5 = 28,
GLTF_NUM_TEXTURE_FORMATS = 29
};
enum GLVertexType {
GLVT_INVALID = 0,
GLVT_FLOAT1 = 1,
GLVT_FLOAT2 = 2,
GLVT_FLOAT3 = 3,
GLVT_FLOAT4 = 4,
GLVT_UBYTE4 = 5,
GLVT_UBYTE4N = 6,
GLVT_SHORT = 7,
GLVT_SHORT2 = 8,
GLVT_SHORT4 = 9,
GLVT_SHORT2N = 10,
GLVT_SHORT4N = 11,
GLVT_USHORT2N = 12,
GLVT_USHORT4N = 13,
GLVT_NUM_VERTEX_TYPES = 14
};
enum GLBufferType {
eGLBT_PIXEL_UNPACK = 3,
};
struct GLAttachPoint {
GLFramebuffer* framebuffer;
int32_t point; // TODO GLenum?
int32_t zOffset; // TODO check type
};
struct GLBox {
int32_t left;
int32_t top;
int32_t front;
int32_t width;
int32_t height;
int32_t depth;
};
struct GLColor4f {
float r;
float g;
float b;
float a;
static GLColor4f ZERO;
static GLColor4f WHITE;
static GLColor4f BLACK;
};
struct GLDirtyRange {
uint16_t start;
uint16_t end;
};
struct GLfloat4 {
float x;
float y;
float z;
float w;
};
struct GLRect {
int32_t left;
int32_t top;
int32_t width;
int32_t height;
};
struct GLTransform {
bool isDirty;
union {
struct {
float a0;
float a1;
float a2;
float a3;
float b0;
float b1;
float b2;
float b3;
float c0;
float c1;
float c2;
float c3;
float d0;
float d1;
float d2;
float d3;
};
struct {
float rows[4][4];
};
float m[16];
};
bool isIdentity;
bool operator==(const float m[16]) const;
bool operator!=(const float m[16]) const;
void Set(const float m[16]);
void SetIdentity();
};
struct GLStates {
struct Depth {
bool testEnable;
int32_t compareFunc;
bool writeMask;
};
struct Stencil {
struct StencilFace {
int32_t compareFunc;
int32_t opFail;
int32_t opZFail;
int32_t opZPass;
};
bool testEnable;
int32_t ref;
uint32_t mask;
uint32_t writeMask;
bool useTwoSidedStencil;
StencilFace front;
StencilFace back;
};
struct Rasterizer {
struct ClipPlane {
double plane[4];
};
int32_t cullMode;
int32_t cullFaceMode;
int32_t fillMode;
float constantDepthBias;
float slopeScaledDepthBias;
GLRect viewport;
double zNear;
double zFar;
bool scissorEnable;
GLRect scissor;
uint32_t clipPlaneMask;
ClipPlane clipPlanes[6];
};
struct Blend {
struct ColorMask {
bool red;
bool green;
bool blue;
bool alpha;
};
ColorMask colorMask[4];
bool alphaBlend;
int32_t srcBlendFactor;
int32_t destBlendFactor;
int32_t blendOp;
GLColor4f blendColor;
};
struct Clear {
GLColor4f clearColor;
double clearDepth;
int32_t clearStencil;
};
struct FixedFunc {
struct TexOp {
int32_t texturing;
GLColor4f constant;
int32_t colorOp;
float colorScale;
int32_t colorArg0;
int32_t colorArg1;
int32_t colorArg2;
int32_t alphaOp;
float alphaScale;
int32_t alphaArg0;
int32_t alphaArg1;
int32_t alphaArg2;
};
struct Light {
bool enable;
GLfloat4 position;
GLTransform view;
float constantAttenuation;
float linearAttenuation;
float quadraticAttenuation;
GLColor4f ambient;
GLColor4f diffuse;
GLColor4f specular;
};
struct Material {
bool colorTracking;
int32_t materialSource;
GLColor4f ambient;
GLColor4f diffuse;
GLColor4f specular;
float shininess;
GLColor4f emission;
};
struct Lighting {
bool enable;
GLColor4f sceneAmbient;
Light lights[8];
Material material;
};
struct Transforms {
int32_t matrixMode;
int32_t modelviewStatus;
GLTransform modelView;
GLTransform world;
GLTransform view;
GLTransform projection;
GLTransform texture[8];
};
struct TexGen {
int32_t S;
int32_t T;
int32_t R;
int32_t Q;
};
struct PointSprite {
bool enable;
float size;
float attenuation[3];
float min;
float max;
};
bool fogEnable;
GLColor4f fogColor;
int32_t fogMode;
float fogStart;
float fogEnd;
float fogDensity;
bool alphaTestEnable;
int32_t alphaTestFunc;
float alphaTestRef;
TexOp texOp[8];
Lighting lighting;
Transforms transforms;
int32_t texCoordIndex[8];
TexGen texGen[8];
PointSprite pointSprite;
bool normalizeNormal;
};
struct Sampler {
float mipmapBias;
int32_t addressModeS;
int32_t addressModeT;
int32_t addressModeR;
int32_t magFilterMode;
int32_t minFilterMode;
float maxAnisotropy;
GLColor4f borderColor;
};
struct Shader {
bool vertexShaderEnable;
GLfloat4 vertexShaderConst[256];
bool pixelShaderEnable;
GLfloat4 pixelShaderConst[64];
};
struct Binding {
uint32_t currentActiveTexture;
uint32_t texture[4][16];
uint32_t framebuffer;
uint32_t renderbuffer;
uint32_t vertexProgram;
uint32_t pixelProgram;
uint32_t glslProgram;
uint32_t vertexArrayObject;
};
struct Misc {
bool unpackClientStorage;
int32_t drawBuffers[4];
int32_t readBuffer;
};
struct VertexArrayObject {
struct VertexAttrib {
bool enable = 0;
uint32_t size = 4;
int32_t type = GL_FLOAT;
bool normalized = 0;
uint32_t stride = 0;
void* offset = nullptr;
GLBuffer* buffer = nullptr;
};
uint32_t buffers[4] = {};
VertexAttrib vertexAttribs[16];
VertexAttrib position;
VertexAttrib normal;
VertexAttrib color0;
VertexAttrib color1;
VertexAttrib texCoord[8];
};
Depth depth;
Stencil stencil;
Rasterizer rasterizer;
Blend blend;
Clear clear;
FixedFunc fixedFunc;
Sampler samplers[16];
Shader shader;
Binding binding;
Misc misc;
};
struct GLVertexAttrib {
uint32_t stream;
int32_t slot;
int32_t type;
uint32_t offset;
};
#endif

22
src/gx/glsdl/GLUtil.cpp Normal file
View File

@ -0,0 +1,22 @@
#include "gx/glsdl/GLUtil.hpp"
#include <bc/Debug.hpp>
uint32_t GLSDLTextureTypeToIndex(GLEnum textureType) {
uint32_t index;
if (textureType == GL_TEXTURE_2D) {
index = 0;
} else if (textureType == GL_TEXTURE_3D) {
index = 1;
} else if (textureType == GL_TEXTURE_CUBE_MAP) {
index = 2;
} else if (textureType == GL_TEXTURE_RECTANGLE) {
index = 3;
} else {
index = 5;
BLIZZARD_ASSERT(false);
}
return index;
}

9
src/gx/glsdl/GLUtil.hpp Normal file
View File

@ -0,0 +1,9 @@
#ifndef GX_GL_SDL_GL_UTIL_HPP
#define GX_GL_SDL_GL_UTIL_HPP
#include "gx/glsdl/GL.hpp"
#include <cstdint>
uint32_t GLSDLTextureTypeToIndex(GLEnum textureType);
#endif

View File

@ -0,0 +1,316 @@
#include "gx/glsdl/GLVertexArray.hpp"
#include "gx/glsdl/GLSDLDevice.hpp"
#include <bc/Debug.hpp>
bool GLVertexArray::s_VertexArrayEnable = false;
GLVertexArray::GLVertexArray(bool a2) {
// TODO
}
void GLVertexArray::FindVertexArray(GLSDLDevice* a1, GLVertexArray& a2) {
if (GLVertexArray::s_VertexArrayEnable) {
// TODO
}
a2.ApplyVertexFormat(a1);
}
void GLVertexArray::ApplyGLStates(GLStates::VertexArrayObject& vao) {
GLSDLDevice* device = GLSDLDevice::Get();
device->BindVertexArray(this);
for (int32_t i = 0; i < kMAX_VERTEX_ATTRIBS; i++) {
auto& attrib = vao.vertexAttribs[i];
if (attrib.enable) {
glBindBuffer(attrib.buffer->m_Type, attrib.buffer->m_BufferID);
glVertexAttribPointerARB(
i,
attrib.size,
attrib.type,
attrib.normalized,
attrib.stride,
reinterpret_cast<void*>(attrib.offset)
);
glEnableVertexAttribArrayARB(i);
} else {
glDisableVertexAttribArrayARB(i);
}
}
if (vao.position.enable) {
glBindBuffer(vao.position.buffer->m_Type, vao.position.buffer->m_BufferID);
glVertexPointer(vao.position.size, vao.position.type, vao.position.stride, vao.position.offset);
glEnableClientState(GL_VERTEX_ARRAY);
} else {
glDisableClientState(GL_VERTEX_ARRAY);
}
if (vao.normal.enable) {
glBindBuffer(vao.normal.buffer->m_Type, vao.normal.buffer->m_BufferID);
glNormalPointer(vao.normal.type, vao.normal.stride, vao.normal.offset);
glEnableClientState(GL_NORMAL_ARRAY);
} else {
glDisableClientState(GL_NORMAL_ARRAY);
}
if (vao.color0.enable) {
glBindBuffer(vao.color0.buffer->m_Type, vao.color0.buffer->m_BufferID);
glColorPointer(vao.color0.size, vao.color0.type, vao.color0.stride, vao.color0.offset);
glEnableClientState(GL_COLOR_ARRAY);
} else {
glDisableClientState(GL_COLOR_ARRAY);
}
if (vao.color1.enable) {
glBindBuffer(vao.color1.buffer->m_Type, vao.color1.buffer->m_BufferID);
glColorPointer(vao.color1.size, vao.color1.type, vao.color1.stride, vao.color1.offset);
glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
} else {
glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
}
for (int32_t i = 0; i < 8; i++) {
glClientActiveTextureARB(GL_TEXTURE0 + i);
if (vao.texCoord[i].enable) {
glBindBuffer(vao.texCoord[i].buffer->m_Type, vao.texCoord[0].buffer->m_BufferID);
glTexCoordPointer(vao.texCoord[i].size, vao.texCoord[i].type, vao.texCoord[i].stride, vao.texCoord[i].offset);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
} else {
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
}
glBindBuffer(GL_ARRAY_BUFFER, vao.buffers[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vao.buffers[1]);
glBindBuffer(GL_PIXEL_PACK_BUFFER, vao.buffers[2]);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, vao.buffers[3]);
this->m_GLStates = vao;
}
void GLVertexArray::ApplyVertexFormat(GLSDLDevice* device) {
if (GLVertexArray::s_VertexArrayEnable) {
device->BindVertexArray(this);
}
auto indexBuffer = this->m_Properties.m_IndexBuffer;
uint32_t indexBufferID = indexBuffer ? indexBuffer->m_BufferID : 0;
if (this->m_GLStates.buffers[1] != indexBufferID) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
this->m_GLStates.buffers[1] = indexBufferID;
}
BLIZZARD_ASSERT(this->GetProperties().m_VertexBufferFormat != nullptr);
auto& properties = this->GetProperties();
bool attribEnable[16] = {};
bool useVertexShader = device->GetShader(GLShader::eVertexShader) != nullptr;
for (int32_t index = 0; index < this->GetProperties().m_VertexBufferFormat->m_Size; index++) {
BLIZZARD_ASSERT(index < kMAX_VERTEX_ATTRIBS);
auto& attrib = this->GetProperties().m_VertexBufferFormat->m_Attribs[index];
BLIZZARD_ASSERT(attrib.type != GLVT_INVALID);
BLIZZARD_ASSERT(attrib.type < GLVT_NUM_VERTEX_TYPES);
auto vertexBuffer = this->GetProperties().m_VertexBuffer[attrib.stream];
if (useVertexShader || static_cast<uint32_t>(attrib.slot - 1) > 1) {
if (this->m_GLStates.buffers[0] != vertexBuffer->m_BufferID) {
glBindBuffer(vertexBuffer->m_Type, vertexBuffer->m_BufferID);
this->m_GLStates.buffers[0] = vertexBuffer->m_BufferID;
}
attribEnable[attrib.slot] = 1;
int32_t stride = properties.m_VertexBufferStride[attrib.stream];
int32_t offset = attrib.offset
+ properties.m_VertexBufferOffset[attrib.stream]
+ properties.m_VertexBase * stride;
if (useVertexShader) {
glVertexAttribPointerARB(
attrib.slot,
k_VertexTypeInfo[attrib.type].m_Size,
k_VertexTypeInfo[attrib.type].m_Type,
k_VertexTypeInfo[attrib.type].m_Normalized,
stride,
reinterpret_cast<void*>(offset)
);
} else {
switch (attrib.slot) {
case 0: {
glVertexPointer(
k_VertexTypeInfo[attrib.type].m_Size,
k_VertexTypeInfo[attrib.type].m_Type,
stride,
reinterpret_cast<void*>(offset)
);
break;
}
case 3: {
glNormalPointer(
k_VertexTypeInfo[attrib.type].m_Type,
stride,
reinterpret_cast<void*>(offset)
);
break;
}
case 4: {
glColorPointer(
k_VertexTypeInfo[attrib.type].m_Size,
k_VertexTypeInfo[attrib.type].m_Type,
stride,
reinterpret_cast<void*>(offset)
);
break;
}
case 5: {
glSecondaryColorPointer(
k_VertexTypeInfo[attrib.type].m_Size,
k_VertexTypeInfo[attrib.type].m_Type,
stride,
reinterpret_cast<void*>(offset)
);
break;
}
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13: {
auto tmu = attrib.slot - 6;
auto texCoordIndex = device->m_States.fixedFunc.texCoordIndex[tmu];
glClientActiveTextureARB(GL_TEXTURE0 + texCoordIndex);
glTexCoordPointer(
k_VertexTypeInfo[attrib.type].m_Size,
k_VertexTypeInfo[attrib.type].m_Type,
stride,
reinterpret_cast<void*>(offset)
);
break;
}
}
}
}
}
for (int32_t s = 0; s < 16; s++) {
// Shader
if (useVertexShader) {
auto prevAttribEnable = &this->m_GLStates.vertexAttribs[s].enable;
if (*prevAttribEnable != attribEnable[s]) {
if (attribEnable[s]) {
glEnableVertexAttribArrayARB(s);
} else {
glDisableVertexAttribArrayARB(s);
}
}
*prevAttribEnable = attribEnable[s];
// FFP
} else {
bool* prevAttribEnable = nullptr;
GLenum glArray = GL_NONE;
switch (s) {
case 0: {
prevAttribEnable = &this->m_GLStates.position.enable;
glArray = GL_VERTEX_ARRAY;
break;
}
case 3: {
prevAttribEnable = &this->m_GLStates.normal.enable;
glArray = GL_NORMAL_ARRAY;
break;
}
case 4: {
prevAttribEnable = &this->m_GLStates.color0.enable;
glArray = GL_COLOR_ARRAY;
break;
}
case 5: {
prevAttribEnable = &this->m_GLStates.color1.enable;
glArray = GL_SECONDARY_COLOR_ARRAY;
break;
}
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13: {
auto tmu = s - 6;
auto texCoordIndex = device->m_States.fixedFunc.texCoordIndex[tmu];
prevAttribEnable = &this->m_GLStates.texCoord[texCoordIndex].enable;
glArray = GL_TEXTURE_COORD_ARRAY;
glClientActiveTextureARB(GL_TEXTURE0 + texCoordIndex);
break;
}
default:
break;
}
if (prevAttribEnable) {
if (*prevAttribEnable != attribEnable[s]) {
if (attribEnable[s]) {
glEnableClientState(glArray);
} else {
glDisableClientState(glArray);
}
}
*prevAttribEnable = attribEnable[s];
}
}
}
if (!useVertexShader) {
// TODO device->SetColorMaterial(this->m_GLStates.color0.enable);
}
}
GLVertexArray::Properties& GLVertexArray::GetProperties() {
return this->m_Properties;
}
void GLVertexArray::ReleaseObject() {
// TODO
}

View File

@ -0,0 +1,46 @@
#ifndef GX_GL_SDL_GL_VERTEX_ARRAY_HPP
#define GX_GL_SDL_GL_VERTEX_ARRAY_HPP
#include "gx/glsdl/GLBuffer.hpp"
#include "gx/glsdl/GLObject.hpp"
#include "gx/glsdl/GLVertexFormat.hpp"
#include <cstdint>
class GLSDLDevice;
class GLVertexArray : public GLObject {
public:
// Types
struct Properties {
GLVertexFormat* m_VertexBufferFormat = nullptr;
GLBuffer* m_IndexBuffer = nullptr;
GLBuffer* m_PixelPackBuffer = nullptr;
GLBuffer* m_PixelUnpackBuffer = nullptr;
GLBuffer* m_VertexBuffer[4] = {};
uint32_t m_VertexBase = 0;
uint32_t m_VertexBufferOffset[4] = {};
uint32_t m_VertexBufferStride[4] = {};
};
// Static variables
static bool s_VertexArrayEnable;
// Static functions
static void FindVertexArray(GLSDLDevice*, GLVertexArray&);
// Member variables
Properties m_Properties;
GLStates::VertexArrayObject m_GLStates;
uint32_t m_VertexArrayID = 0;
// Virtual member functions
virtual void ReleaseObject();
// Member functions
GLVertexArray(bool);
void ApplyGLStates(GLStates::VertexArrayObject&);
void ApplyVertexFormat(GLSDLDevice*);
Properties& GetProperties(void);
};
#endif

View File

@ -0,0 +1,13 @@
#ifndef GX_GL_SDL_GL_VERTEX_FORMAT_HPP
#define GX_GL_SDL_GL_VERTEX_FORMAT_HPP
#include "gx/glsdl/GLTypes.hpp"
#include <cstdint>
class GLVertexFormat {
public:
uint32_t m_Size;
GLVertexAttrib m_Attribs[16];
};
#endif

View File

@ -0,0 +1,17 @@
#include "gx/glsdl/GLVertexShader.hpp"
#include "gx/glsdl/GL.hpp"
GLVertexShader* GLVertexShader::Create() {
// TODO
// GLPool stuff
GLVertexShader* shader = new GLVertexShader();
shader->m_ShaderID = 0;
shader->m_RefCount = 1;
shader->m_ShaderType = eVertexShader;
shader->m_UsingGLSL = 0;
shader->var5 = GL_VERTEX_PROGRAM_ARB;
return shader;
}

View File

@ -0,0 +1,12 @@
#ifndef GX_GL_SDL_GL_VERTEX_SHADER_HPP
#define GX_GL_SDL_GL_VERTEX_SHADER_HPP
#include "gx/glsdl/GLShader.hpp"
class GLVertexShader : public GLShader {
public:
// Static functions
static GLVertexShader* Create(void);
};
#endif