Add support for POT-only GPUs, fix VBO (#468)

This commit is contained in:
Anders Jenbo 2025-07-02 00:45:25 +02:00 committed by GitHub
parent 12d4d6a89a
commit 7b06ee5ae6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 96 additions and 37 deletions

View File

@ -42,12 +42,26 @@ void GL11_DestroyTexture(GLuint texId)
glDeleteTextures(1, &texId); glDeleteTextures(1, &texId);
} }
GLuint GL11_UploadTextureData(void* pixels, int width, int height) GLuint GL11_UploadTextureData(void* pixels, int width, int height, bool isUi)
{ {
GLuint texId; GLuint texId;
glGenTextures(1, &texId); glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D, texId); glBindTexture(GL_TEXTURE_2D, texId);
if (isUi) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
return texId; return texId;
} }
@ -111,7 +125,6 @@ void GL11_BeginFrame(const Matrix4x4* projection)
glDepthMask(GL_TRUE); glDepthMask(GL_TRUE);
glEnable(GL_LIGHTING); glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL); glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
// Disable all lights and reset global ambient // Disable all lights and reset global ambient
for (int i = 0; i < 8; ++i) { for (int i = 0; i < 8; ++i) {
@ -198,6 +211,7 @@ void GL11_SubmitDraw(
glLoadMatrixf(&modelViewMatrix[0][0]); glLoadMatrixf(&modelViewMatrix[0][0]);
glEnable(GL_NORMALIZE); glEnable(GL_NORMALIZE);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glColor4ub(appearance.color.r, appearance.color.g, appearance.color.b, appearance.color.a); glColor4ub(appearance.color.r, appearance.color.g, appearance.color.b, appearance.color.a);
if (appearance.shininess != 0.0f) { if (appearance.shininess != 0.0f) {
@ -220,8 +234,6 @@ void GL11_SubmitDraw(
// Bind texture if present // Bind texture if present
if (appearance.textureId != NO_TEXTURE_ID) { if (appearance.textureId != NO_TEXTURE_ID) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texId); glBindTexture(GL_TEXTURE_2D, texId);
glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY);
@ -279,7 +291,7 @@ void GL11_Clear(float r, float g, float b)
} }
void GL11_Draw2DImage( void GL11_Draw2DImage(
GLuint texId, GLTextureCacheEntry& cache,
const SDL_Rect& srcRect, const SDL_Rect& srcRect,
const SDL_Rect& dstRect, const SDL_Rect& dstRect,
float left, float left,
@ -305,24 +317,17 @@ void GL11_Draw2DImage(
glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texId); glBindTexture(GL_TEXTURE_2D, cache.glTextureId);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GLint boundTexture = 0; GLint boundTexture = 0;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTexture); glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTexture);
GLfloat texW, texH; float u1 = srcRect.x / cache.width;
glGetTexLevelParameterfv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &texW); float v1 = srcRect.y / cache.height;
glGetTexLevelParameterfv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &texH); float u2 = (srcRect.x + srcRect.w) / cache.width;
float v2 = (srcRect.y + srcRect.h) / cache.height;
float u1 = srcRect.x / texW;
float v1 = srcRect.y / texH;
float u2 = (srcRect.x + srcRect.w) / texW;
float v2 = (srcRect.y + srcRect.h) / texH;
float x1 = (float) dstRect.x; float x1 = (float) dstRect.x;
float y1 = (float) dstRect.y; float y1 = (float) dstRect.y;

View File

@ -39,6 +39,8 @@ struct GLTextureCacheEntry {
IDirect3DRMTexture* texture; IDirect3DRMTexture* texture;
Uint32 version; Uint32 version;
GLuint glTextureId; GLuint glTextureId;
float width;
float height;
}; };
struct GLMeshCacheEntry { struct GLMeshCacheEntry {
@ -62,7 +64,7 @@ struct GLMeshCacheEntry {
void GL11_InitState(); void GL11_InitState();
void GL11_LoadExtensions(); void GL11_LoadExtensions();
void GL11_DestroyTexture(GLuint texId); void GL11_DestroyTexture(GLuint texId);
GLuint GL11_UploadTextureData(void* pixels, int width, int height); GLuint GL11_UploadTextureData(void* pixels, int width, int height, bool isUI);
void GL11_UploadMesh(GLMeshCacheEntry& cache, bool hasTexture); void GL11_UploadMesh(GLMeshCacheEntry& cache, bool hasTexture);
void GL11_DestroyMesh(GLMeshCacheEntry& cache); void GL11_DestroyMesh(GLMeshCacheEntry& cache);
void GL11_BeginFrame(const Matrix4x4* projection); void GL11_BeginFrame(const Matrix4x4* projection);
@ -77,7 +79,7 @@ void GL11_SubmitDraw(
void GL11_Resize(int width, int height); void GL11_Resize(int width, int height);
void GL11_Clear(float r, float g, float b); void GL11_Clear(float r, float g, float b);
void GL11_Draw2DImage( void GL11_Draw2DImage(
GLuint texId, GLTextureCacheEntry& cache,
const SDL_Rect& srcRect, const SDL_Rect& srcRect,
const SDL_Rect& dstRect, const SDL_Rect& dstRect,
float left, float left,

View File

@ -58,6 +58,8 @@ OpenGL1Renderer::OpenGL1Renderer(DWORD width, DWORD height, SDL_GLContext contex
m_virtualHeight = height; m_virtualHeight = height;
m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32); m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32);
GL11_LoadExtensions(); GL11_LoadExtensions();
m_useVBOs = SDL_GL_ExtensionSupported("GL_ARB_vertex_buffer_object");
m_useNPOT = SDL_GL_ExtensionSupported("GL_OES_texture_npot");
} }
OpenGL1Renderer::~OpenGL1Renderer() OpenGL1Renderer::~OpenGL1Renderer()
@ -108,6 +110,58 @@ void OpenGL1Renderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* t
); );
} }
static int NextPowerOfTwo(int v)
{
int power = 1;
while (power < v) {
power <<= 1;
}
return power;
}
static Uint32 UploadTextureData(SDL_Surface* src, bool useNPOT, bool isUi)
{
SDL_Surface* working = src;
if (src->format != SDL_PIXELFORMAT_RGBA32) {
working = SDL_ConvertSurface(src, SDL_PIXELFORMAT_RGBA32);
if (!working) {
SDL_Log("SDL_ConvertSurface failed: %s", SDL_GetError());
return NO_TEXTURE_ID;
}
}
SDL_Surface* finalSurface = working;
int newW = NextPowerOfTwo(working->w);
int newH = NextPowerOfTwo(working->h);
if (!useNPOT && (newW != working->w || newH != working->h)) {
SDL_Surface* resized = SDL_CreateSurface(newW, newH, working->format);
if (!resized) {
SDL_Log("SDL_CreateSurface (resize) failed: %s", SDL_GetError());
if (working != src) {
SDL_DestroySurface(working);
}
return NO_TEXTURE_ID;
}
SDL_Rect srcRect = {0, 0, working->w, working->h};
SDL_Rect dstRect = {0, 0, newW, newH};
SDL_BlitSurfaceScaled(working, &srcRect, resized, &dstRect, SDL_SCALEMODE_NEAREST);
if (working != src) {
SDL_DestroySurface(working);
}
finalSurface = resized;
}
Uint32 texId = GL11_UploadTextureData(finalSurface->pixels, finalSurface->w, finalSurface->h, isUi);
if (finalSurface != src) {
SDL_DestroySurface(finalSurface);
}
return texId;
}
Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi) Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi)
{ {
auto texture = static_cast<Direct3DRMTextureImpl*>(iTexture); auto texture = static_cast<Direct3DRMTextureImpl*>(iTexture);
@ -118,28 +172,16 @@ Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi)
if (tex.texture == texture) { if (tex.texture == texture) {
if (tex.version != texture->m_version) { if (tex.version != texture->m_version) {
GL11_DestroyTexture(tex.glTextureId); GL11_DestroyTexture(tex.glTextureId);
tex.glTextureId = UploadTextureData(surface->m_surface, m_useNPOT, isUi);
SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_RGBA32);
if (!surf) {
return NO_TEXTURE_ID;
}
tex.glTextureId = GL11_UploadTextureData(surf->pixels, surf->w, surf->h);
SDL_DestroySurface(surf);
tex.version = texture->m_version; tex.version = texture->m_version;
tex.width = surface->m_surface->w;
tex.height = surface->m_surface->h;
} }
return i; return i;
} }
} }
GLuint texId; GLuint texId = UploadTextureData(surface->m_surface, m_useNPOT, isUi);
SDL_Surface* surf = SDL_ConvertSurface(surface->m_surface, SDL_PIXELFORMAT_RGBA32);
if (!surf) {
return NO_TEXTURE_ID;
}
texId = GL11_UploadTextureData(surf->pixels, surf->w, surf->h);
SDL_DestroySurface(surf);
for (Uint32 i = 0; i < m_textures.size(); ++i) { for (Uint32 i = 0; i < m_textures.size(); ++i) {
auto& tex = m_textures[i]; auto& tex = m_textures[i];
@ -147,12 +189,20 @@ Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi)
tex.texture = texture; tex.texture = texture;
tex.version = texture->m_version; tex.version = texture->m_version;
tex.glTextureId = texId; tex.glTextureId = texId;
tex.width = surface->m_surface->w;
tex.height = surface->m_surface->h;
AddTextureDestroyCallback(i, texture); AddTextureDestroyCallback(i, texture);
return i; return i;
} }
} }
m_textures.push_back({texture, texture->m_version, texId}); m_textures.push_back(
{texture,
texture->m_version,
texId,
static_cast<float>(surface->m_surface->w),
static_cast<float>(surface->m_surface->h)}
);
AddTextureDestroyCallback((Uint32) (m_textures.size() - 1), texture); AddTextureDestroyCallback((Uint32) (m_textures.size() - 1), texture);
return (Uint32) (m_textures.size() - 1); return (Uint32) (m_textures.size() - 1);
} }
@ -331,7 +381,7 @@ void OpenGL1Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, con
float top = -m_viewportTransform.offsetY / m_viewportTransform.scale; float top = -m_viewportTransform.offsetY / m_viewportTransform.scale;
float bottom = (m_height - m_viewportTransform.offsetY) / m_viewportTransform.scale; float bottom = (m_height - m_viewportTransform.offsetY) / m_viewportTransform.scale;
GL11_Draw2DImage(m_textures[textureId].glTextureId, srcRect, dstRect, left, right, bottom, top); GL11_Draw2DImage(m_textures[textureId], srcRect, dstRect, left, right, bottom, top);
} }
void OpenGL1Renderer::Download(SDL_Surface* target) void OpenGL1Renderer::Download(SDL_Surface* target)

View File

@ -47,6 +47,7 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height)
SDL_GLContext context = SDL_GL_CreateContext(DDWindow); SDL_GLContext context = SDL_GL_CreateContext(DDWindow);
if (!context) { if (!context) {
SDL_Log("SDL_GL_CreateContext: %s", SDL_GetError());
return nullptr; return nullptr;
} }

View File

@ -46,6 +46,7 @@ class OpenGL1Renderer : public Direct3DRMRenderer {
D3DRMMATRIX4D m_projection; D3DRMMATRIX4D m_projection;
SDL_Surface* m_renderedImage; SDL_Surface* m_renderedImage;
bool m_useVBOs; bool m_useVBOs;
bool m_useNPOT;
bool m_dirty = false; bool m_dirty = false;
std::vector<SceneLight> m_lights; std::vector<SceneLight> m_lights;
SDL_GLContext m_context; SDL_GLContext m_context;