daedalus/Source/SysGLES/Graphics/GraphicsContextGL.cpp
2025-02-02 20:56:30 -05:00

263 lines
6.7 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "Base/Types.h"
#include <stdio.h>
#include "SysGLES/GL.h"
#include <SDL2/SDL_ttf.h>
#include <iostream>
#include "Graphics/GraphicsContext.h"
#include "Graphics/ColourValue.h"
#include "UI/DrawText.h"
#include "UI/Menu.h"
SDL_Window* gWindow = nullptr;
SDL_Renderer* gSdlRenderer = nullptr;
SDL_GLContext gContext = nullptr;
extern void HandleEndOfFrame();
class GraphicsContextGL : public CGraphicsContext
{
public:
virtual ~GraphicsContextGL();
virtual bool Initialise();
virtual bool IsInitialised() const { return true; }
virtual void ClearAllSurfaces();
virtual void ClearZBuffer();
virtual void ClearColBuffer(const c32 & colour);
virtual void ClearToBlack();
virtual void ClearColBufferAndDepth(const c32 & colour);
virtual void BeginFrame();
virtual void EndFrame();
virtual void UpdateFrame( bool wait_for_vbl );
virtual void GetScreenSize(u32 * width, u32 * height) const;
virtual void ViewportType(u32 * width, u32 * height) const;
virtual void SetDebugScreenTarget( ETargetSurface buffer [[maybe_unused]] ) {}
virtual void DumpNextScreen() {}
virtual void DumpScreenShot() {}
virtual void UItoGL();
};
template<> bool CSingleton< CGraphicsContext >::Create()
{
DAEDALUS_ASSERT_Q(mpInstance == nullptr);
mpInstance = std::make_shared<GraphicsContextGL>();
return mpInstance->Initialise();
}
GraphicsContextGL::~GraphicsContextGL()
{
// Destroy context and window
if (gContext)
{
SDL_GL_DeleteContext(gContext);
gContext = nullptr;
}
if (gWindow)
{
SDL_DestroyWindow(gWindow);
gWindow = nullptr;
}
// Shutdown SDL
SDL_Quit();
}
extern bool initgl();
bool GraphicsContextGL::Initialise()
{
//Initialize SDL
if ( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_EVENTS | SDL_INIT_GAMECONTROLLER) < 0 )
{
printf( "SDL could not initialize! SDL Error: %s\n", SDL_GetError() );
return false;
}
if (TTF_Init() < 0)
{
printf( "SDL could not initialize TTF Font! SDL Error: %s\n", SDL_GetError() );
return false;
}
// Request an OpenGL ES 3.1 context
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
#ifdef DAEDALUS_DEBUG_CONSOLE
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
#endif
// 24-bit depth, double buffer
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
// Create the window
gWindow = SDL_CreateWindow(
"Daedalus - GLES 3.1",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
SCREEN_WIDTH,
SCREEN_HEIGHT,
SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI
);
if (!gWindow)
{
printf("Failed to create SDL Window! SDL Error: %s\n", SDL_GetError());
return false;
}
// Create the GL ES context
gContext = SDL_GL_CreateContext(gWindow);
if (!gContext)
{
printf("Failed to create GL Context! SDL Error: %s\n", SDL_GetError());
SDL_DestroyWindow(gWindow);
gWindow = nullptr;
return false;
}
// Make the context current
SDL_GL_MakeCurrent(gWindow, gContext);
// Enable vsync (if desired)
SDL_GL_SetSwapInterval(1);
// Now that we have an ES context, initialize your function loader if needed
// If 'initgl()' is just a stub or calls a custom loader, do it here:
if (!initgl())
{
printf("initgl() reported failure.\n");
SDL_DestroyWindow(gWindow);
gWindow = nullptr;
return false;
}
// If you have an extension check or custom setup, do it here.
// E.g., glGetString(GL_VERSION), etc.
// printf("GL_VERSION: %s\n", glGetString(GL_VERSION));
// Initialize text rendering
CDrawText::Initialise();
// Clear + swap once
UpdateFrame(false);
return true;
}
void GraphicsContextGL::UItoGL()
{
if (gSdlRenderer != nullptr)
{
SDL_RenderPresent(gSdlRenderer);
SDL_RenderFlush(gSdlRenderer);
SDL_DestroyRenderer(gSdlRenderer);
gSdlRenderer = nullptr;
// If you destroyed the window, re-initialize context
if (gWindow)
{
SDL_DestroyWindow(gWindow);
SDL_GL_DeleteContext(gContext);
gContext = nullptr;
gWindow = nullptr;
}
GraphicsContextGL::Initialise();
}
}
void GraphicsContextGL::GetScreenSize(u32* width, u32* height) const
{
int window_width = 0;
int window_height = 0;
SDL_GL_GetDrawableSize(gWindow, &window_width, &window_height);
*width = static_cast<u32>(window_width);
*height = static_cast<u32>(window_height);
}
void GraphicsContextGL::ViewportType(u32* width, u32* height) const
{
GetScreenSize(width, height);
}
void GraphicsContextGL::ClearAllSurfaces()
{
// FIXME: this should clear/flip a couple of times to ensure
// the front and backbuffers are cleared.
// Not sure if it's necessary...
GraphicsContextGL::UItoGL();
ClearToBlack();
}
void GraphicsContextGL::ClearToBlack()
{
glDepthMask(GL_TRUE);
glClearDepthf(1.0f);
glClearColor(0.f, 0.f, 0.f, 0.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void GraphicsContextGL::ClearZBuffer()
{
glDepthMask(GL_TRUE);
glClearDepthf(1.0f);
glClear(GL_DEPTH_BUFFER_BIT);
}
void GraphicsContextGL::ClearColBuffer(const c32 & colour)
{
glClearColor(colour.GetRf(), colour.GetGf(), colour.GetBf(), colour.GetAf());
glClear(GL_COLOR_BUFFER_BIT);
}
void GraphicsContextGL::ClearColBufferAndDepth(const c32 & colour)
{
glDepthMask(GL_TRUE);
glClearDepthf(1.0f);
glClearColor(colour.GetRf(), colour.GetGf(), colour.GetBf(), colour.GetAf());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void GraphicsContextGL::BeginFrame()
{
// Get window size (may be different than the requested size)
u32 width, height;
GetScreenSize(&width, &height);
// Special case: avoid division by zero below
height = height > 0 ? height : 1;
glViewport(0, 0, width, height);
glScissor(0, 0, width, height);
}
void GraphicsContextGL::EndFrame()
{
HandleEndOfFrame();
}
void GraphicsContextGL::UpdateFrame(bool wait_for_vbl [[maybe_unused]])
{
// Bind default framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// If no SDL renderer is active, swap the window
if (!gSdlRenderer)
{
SDL_GL_SwapWindow(gWindow);
}
// else: If gSdlRenderer != nullptr, youre likely rendering via SDL2, not GL.
}