Make OpenGL 1.1 renderer work under PSP

This commit is contained in:
Anders Jenbo 2025-07-01 23:59:29 +02:00
parent 87072cc230
commit 6668d185d4
6 changed files with 107 additions and 37 deletions

View File

@ -665,7 +665,9 @@ MxResult IsleApp::SetupWindow()
#if defined(MINIWIN) && !defined(__3DS__)
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_OPENGL_BOOLEAN, true);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
#ifndef __PSP__
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
#endif
#endif
window = SDL_CreateWindowWithProperties(props);

View File

@ -42,12 +42,26 @@ void GL11_DestroyTexture(GLuint 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;
glGenTextures(1, &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);
return texId;
}
@ -111,7 +125,6 @@ void GL11_BeginFrame(const Matrix4x4* projection)
glDepthMask(GL_TRUE);
glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
// Disable all lights and reset global ambient
for (int i = 0; i < 8; ++i) {
@ -198,7 +211,18 @@ void GL11_SubmitDraw(
glLoadMatrixf(&modelViewMatrix[0][0]);
glEnable(GL_NORMALIZE);
#ifndef __PSP__
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glColor4ub(appearance.color.r, appearance.color.g, appearance.color.b, appearance.color.a);
#else
GLfloat color[4] = {
appearance.color.r / 255.0f,
appearance.color.g / 255.0f,
appearance.color.b / 255.0f,
appearance.color.a / 255.0f
};
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color);
#endif
if (appearance.shininess != 0.0f) {
GLfloat whiteSpec[] = {1.f, 1.f, 1.f, 1.f};
@ -220,8 +244,6 @@ void GL11_SubmitDraw(
// Bind texture if present
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);
glBindTexture(GL_TEXTURE_2D, texId);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
@ -279,7 +301,7 @@ void GL11_Clear(float r, float g, float b)
}
void GL11_Draw2DImage(
GLuint texId,
GLTextureCacheEntry& cache,
const SDL_Rect& srcRect,
const SDL_Rect& dstRect,
float left,
@ -305,24 +327,17 @@ void GL11_Draw2DImage(
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texId);
glBindTexture(GL_TEXTURE_2D, cache.glTextureId);
glEnable(GL_BLEND);
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;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTexture);
GLfloat texW, texH;
glGetTexLevelParameterfv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &texW);
glGetTexLevelParameterfv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &texH);
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 u1 = srcRect.x / cache.width;
float v1 = srcRect.y / cache.height;
float u2 = (srcRect.x + srcRect.w) / cache.width;
float v2 = (srcRect.y + srcRect.h) / cache.height;
float x1 = (float) dstRect.x;
float y1 = (float) dstRect.y;

View File

@ -39,6 +39,8 @@ struct GLTextureCacheEntry {
IDirect3DRMTexture* texture;
Uint32 version;
GLuint glTextureId;
float width;
float height;
};
struct GLMeshCacheEntry {
@ -62,7 +64,7 @@ struct GLMeshCacheEntry {
void GL11_InitState();
void GL11_LoadExtensions();
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_DestroyMesh(GLMeshCacheEntry& cache);
void GL11_BeginFrame(const Matrix4x4* projection);
@ -77,7 +79,7 @@ void GL11_SubmitDraw(
void GL11_Resize(int width, int height);
void GL11_Clear(float r, float g, float b);
void GL11_Draw2DImage(
GLuint texId,
GLTextureCacheEntry& cache,
const SDL_Rect& srcRect,
const SDL_Rect& dstRect,
float left,

View File

@ -23,7 +23,9 @@ Direct3DRMRenderer* OpenGL1Renderer::Create(DWORD width, DWORD height)
// call below when on an EGL-based backend, and crashes with EGL_BAD_MATCH.
SDL_GL_ResetAttributes();
// But ResetAttributes resets it to 16.
#ifndef __PSP__
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
#endif
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
@ -58,6 +60,8 @@ OpenGL1Renderer::OpenGL1Renderer(DWORD width, DWORD height, SDL_GLContext contex
m_virtualHeight = height;
m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32);
GL11_LoadExtensions();
m_useVBOs = SDL_GL_ExtensionSupported("GL_ARB_vertex_buffer_object");
m_useNPOT = SDL_GL_ExtensionSupported("GL_ARB_vertex_buffer_object");
}
OpenGL1Renderer::~OpenGL1Renderer()
@ -108,6 +112,59 @@ 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;
// Resize to next power-of-two if needed and NPOT isn't supported
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)
{
auto texture = static_cast<Direct3DRMTextureImpl*>(iTexture);
@ -118,28 +175,16 @@ Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi)
if (tex.texture == texture) {
if (tex.version != texture->m_version) {
GL11_DestroyTexture(tex.glTextureId);
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.glTextureId = UploadTextureData(surface->m_surface, m_useNPOT, isUi);
tex.version = texture->m_version;
tex.width = surface->m_surface->w;
tex.height = surface->m_surface->h;
}
return i;
}
}
GLuint texId;
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);
GLuint texId = UploadTextureData(surface->m_surface, m_useNPOT, isUi);
for (Uint32 i = 0; i < m_textures.size(); ++i) {
auto& tex = m_textures[i];
@ -147,12 +192,14 @@ Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUi)
tex.texture = texture;
tex.version = texture->m_version;
tex.glTextureId = texId;
tex.width = surface->m_surface->w;
tex.height = surface->m_surface->h;
AddTextureDestroyCallback(i, texture);
return i;
}
}
m_textures.push_back({texture, texture->m_version, texId});
m_textures.push_back({texture, texture->m_version, texId, surface->m_surface->w, surface->m_surface->h});
AddTextureDestroyCallback((Uint32) (m_textures.size() - 1), texture);
return (Uint32) (m_textures.size() - 1);
}
@ -331,7 +378,7 @@ void OpenGL1Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, con
float top = -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)

View File

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

View File

@ -46,6 +46,7 @@ class OpenGL1Renderer : public Direct3DRMRenderer {
D3DRMMATRIX4D m_projection;
SDL_Surface* m_renderedImage;
bool m_useVBOs;
bool m_useNPOT;
bool m_dirty = false;
std::vector<SceneLight> m_lights;
SDL_GLContext m_context;
@ -54,11 +55,13 @@ class OpenGL1Renderer : public Direct3DRMRenderer {
inline static void OpenGL1Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
{
#ifndef __PSP__
Direct3DRMRenderer* device = OpenGL1Renderer::Create(640, 480);
if (!device) {
return;
}
delete device;
#endif
D3DDEVICEDESC halDesc = {};
halDesc.dcmColorModel = D3DCOLORMODEL::RGB;