wsi: get rid of static graphics contexts

This commit is contained in:
Flyinghead committed 2026-07-04 17:34:11 +02:00
1 parent 02a335e2dd
commit 08c63bd39b
39 files changed
+417 -292

No files matched your search

@@ -166,10 +166,10 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
io.BackendRendererName = "imgui_impl_opengl3";
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures;
// Flycast: Detect version using theGLContext
// Flycast: Detect version using GL context
if (glsl_version == nullptr)
{
if (theGLContext.isGLES())
if (GLGraphicsContext::Instance()->isGLES())
glsl_version = "#version 100"; // OpenGL ES 2.0
else
#if defined(__APPLE__)
@@ -183,10 +183,18 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
strcat(bd->GlslVersionString, "\n");
// Detect extensions we support
bd->HasPolygonMode = !theGLContext.isGLES();
bd->HasBindSampler = (theGLContext.getMajorVersion() >= 3 && !theGLContext.isGLES()) || (theGLContext.isGLES() && theGLContext.getMajorVersion() >= 3);
const bool isGLES = GLGraphicsContext::Instance()->isGLES();
const int majorVer = GLGraphicsContext::Instance()->getMajorVersion();
bd->HasPolygonMode = !isGLES;
if (isGLES)
// GLES 3.0+
bd->HasBindSampler = majorVer >= 3;
else
// OpenGL 3.3+
bd->HasBindSampler = majorVer > 3
|| (majorVer == 3 && GLGraphicsContext::Instance()->getMinorVersion() >= 3);
#ifdef GL_CLIP_ORIGIN
bd->HasClipOrigin = (theGLContext.getMajorVersion() >= 4 && glClipControl != NULL);
bd->HasClipOrigin = (majorVer >= 4 && glClipControl != NULL);
#endif
return true;
@@ -272,7 +280,7 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
#endif
vertex_array_object = 0;
#ifndef GLES2
if (theGLContext.getMajorVersion() >= 3)
if (GLGraphicsContext::Instance()->getMajorVersion() >= 3)
{
// Recreate the VAO every time
// (This is to easily allow multiple GL contexts. VAO are not shared among GL contexts, and we don't track creation/deletion of windows so we don't have an obvious key to use to cache them.)
@@ -390,7 +398,7 @@ void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex)
if (tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantUpdates)
{
if (theGLContext.getMajorVersion() >= 3)
if (GLGraphicsContext::Instance()->getMajorVersion() >= 3)
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
}
@@ -410,7 +418,7 @@ void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex)
{
GLuint gl_tex_id = (GLuint)(intptr_t)tex->TexID;
glcache.BindTexture(GL_TEXTURE_2D, gl_tex_id);
if (theGLContext.getMajorVersion() >= 3)
if (GLGraphicsContext::Instance()->getMajorVersion() >= 3)
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->Width);
for (auto& r : tex->Updates)
+5 -5
View File
@@ -39,14 +39,14 @@ public:
}
void renderDrawData(ImDrawData *drawData, bool gui_open) override {
theDX11Context.EndImGuiFrame();
DX11Context::Instance()->EndImGuiFrame();
if (gui_open)
frameRendered = true;
}
void present() override {
if (frameRendered)
theDX11Context.Present();
DX11Context::Instance()->Present();
frameRendered = false;
}
@@ -77,15 +77,15 @@ public:
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.MipLevels = 1;
theDX11Context.getDevice()->CreateTexture2D(&desc, nullptr, &texture.texture.get());
DX11Context::Instance()->getDevice()->CreateTexture2D(&desc, nullptr, &texture.texture.get());
D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc{};
viewDesc.Format = desc.Format;
viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
viewDesc.Texture2D.MipLevels = desc.MipLevels;
theDX11Context.getDevice()->CreateShaderResourceView(texture.texture, &viewDesc, &texture.textureView.get());
DX11Context::Instance()->getDevice()->CreateShaderResourceView(texture.texture, &viewDesc, &texture.textureView.get());
theDX11Context.getDeviceContext()->UpdateSubresource(texture.texture, 0, nullptr, data, width * 4, width * 4 * height);
DX11Context::Instance()->getDeviceContext()->UpdateSubresource(texture.texture, 0, nullptr, data, width * 4, width * 4 * height);
texture.imTexture.shaderResourceView = texture.textureView.get();
texture.imTexture.pointSampling = nearestSampling;
+17 -17
View File
@@ -43,16 +43,16 @@ const D3D11_INPUT_ELEMENT_DESC ModVolLayout[]
bool DX11Renderer::Init()
{
NOTICE_LOG(RENDERER, "DX11 renderer initializing");
device = theDX11Context.getDevice();
deviceContext = theDX11Context.getDeviceContext();
device = DX11Context::Instance()->getDevice();
deviceContext = DX11Context::Instance()->getDeviceContext();
if (!device || !deviceContext)
{
WARN_LOG(RENDERER, "Null device or device context. Aborting");
return false;
}
shaders = &theDX11Context.getShaders();
samplers = &theDX11Context.getSamplers();
shaders = &DX11Context::Instance()->getShaders();
samplers = &DX11Context::Instance()->getSamplers();
bool success = (bool)shaders->getVertexShader(true, true);
ComPtr<ID3DBlob> blob = shaders->getVertexShaderBlob();
success = success && SUCCEEDED(device->CreateInputLayout(MainLayout, std::size(MainLayout), blob->GetBufferPointer(), blob->GetBufferSize(), &mainInputLayout.get()));
@@ -325,7 +325,7 @@ void DX11Renderer::Process(TA_context* ctx)
}
texCache.Cleanup();
if (!ctx->rend.isRTT && ctx->rend.swapInterval > 0)
theDX11Context.setSwapInterval(ctx->rend.swapInterval);
DX11Context::Instance()->setSwapInterval(ctx->rend.swapInterval);
ta_parse(ctx, true);
}
@@ -514,15 +514,15 @@ bool DX11Renderer::Render()
{
aspectRatio = getOutputFramebufferAspectRatio();
#ifndef LIBRETRO
deviceContext->OMSetRenderTargets(1, &theDX11Context.getRenderTarget().get(), nullptr);
deviceContext->OMSetRenderTargets(1, &DX11Context::Instance()->getRenderTarget().get(), nullptr);
displayFramebuffer();
drawOSD();
renderVideoRouting();
theDX11Context.setFrameRendered();
DX11Context::Instance()->setFrameRendered();
#else
ID3D11RenderTargetView *nullView = nullptr;
deviceContext->OMSetRenderTargets(1, &nullView, nullptr);
theDX11Context.presentFrame(fbTextureView, width, height);
DX11Context::Instance()->presentFrame(fbTextureView, width, height);
#endif
frameRendered = true;
frameRenderedOnce = true;
@@ -547,7 +547,7 @@ void DX11Renderer::displayFramebuffer()
float colors[4];
VO_BORDER_COL.getRGBColor(colors);
colors[3] = 1.f;
deviceContext->ClearRenderTargetView(theDX11Context.getRenderTarget(), colors);
deviceContext->ClearRenderTargetView(DX11Context::Instance()->getRenderTarget(), colors);
float shiftX, shiftY;
getVideoShift(shiftX, shiftY);
@@ -1031,15 +1031,15 @@ void DX11Renderer::RenderFramebuffer(const FramebufferInfo& info)
aspectRatio = getDCFramebufferAspectRatio();
deviceContext->OMSetRenderTargets(1, &theDX11Context.getRenderTarget().get(), nullptr);
deviceContext->OMSetRenderTargets(1, &DX11Context::Instance()->getRenderTarget().get(), nullptr);
displayFramebuffer();
drawOSD();
renderVideoRouting();
theDX11Context.setFrameRendered();
DX11Context::Instance()->setFrameRendered();
#else
ID3D11RenderTargetView *nullView = nullptr;
deviceContext->OMSetRenderTargets(1, &nullView, nullptr);
theDX11Context.presentFrame(dcfbTextureView, width, height);
DX11Context::Instance()->presentFrame(dcfbTextureView, width, height);
#endif
frameRendered = true;
frameRenderedOnce = true;
@@ -1196,9 +1196,9 @@ void DX11Renderer::updateFogTexture()
void DX11Renderer::drawOSD()
{
#ifndef LIBRETRO
theDX11Context.setOverlay(true);
DX11Context::Instance()->setOverlay(true);
gui_display_osd();
theDX11Context.setOverlay(false);
DX11Context::Instance()->setOverlay(false);
#endif
}
@@ -1348,7 +1348,7 @@ bool DX11Renderer::GetLastFrame(std::vector<u8>& data, int& width, int& height)
quad->draw(fbTextureView, samplers->getSampler(true), nullptr, -1.f, -1.f, 2.f, 2.f, config::Rotate90);
#ifndef LIBRETRO
deviceContext->OMSetRenderTargets(1, &theDX11Context.getRenderTarget().get(), nullptr);
deviceContext->OMSetRenderTargets(1, &DX11Context::Instance()->getRenderTarget().get(), nullptr);
#else
ID3D11RenderTargetView *nullView = nullptr;
deviceContext->OMSetRenderTargets(1, &nullView, nullptr);
@@ -1399,7 +1399,7 @@ void DX11Renderer::renderVideoRouting()
{
extern void os_VideoRoutingPublishFrameTexture(ID3D11Texture2D* pTexture);
ID3D11RenderTargetView* pRenderTargetView = theDX11Context.getRenderTarget().get();
ID3D11RenderTargetView* pRenderTargetView = DX11Context::Instance()->getRenderTarget().get();
// Backbuffer texture would be different after resizing, fetching new address everytime
ID3D11Resource* pResource = nullptr;
@@ -1458,7 +1458,7 @@ void DX11Renderer::renderVideoRouting()
quad->draw(vrStagingTextureSRV, samplers->getSampler(true));
os_VideoRoutingPublishFrameTexture(vrScaledTexture);
deviceContext->OMSetRenderTargets(1, &theDX11Context.getRenderTarget().get(), nullptr);
deviceContext->OMSetRenderTargets(1, &DX11Context::Instance()->getRenderTarget().get(), nullptr);
} else {
os_VideoRoutingPublishFrameTexture(backBufferTexture);
+1 -1
View File
@@ -48,7 +48,7 @@ struct DX11Renderer : public Renderer
#ifndef LIBRETRO
imguiDriver->setFrameRendered();
#else
theDX11Context.present();
DX11Context::Instance()->present();
#endif
return true;
}
+2 -2
View File
@@ -21,10 +21,10 @@
HRESULT DepthStencilStates::createDepthStencilState(const D3D11_DEPTH_STENCIL_DESC *desc, ID3D11DepthStencilState **state)
{
return theDX11Context.getDevice()->CreateDepthStencilState(desc, state);
return DX11Context::Instance()->getDevice()->CreateDepthStencilState(desc, state);
}
HRESULT BlendStates::createBlendState(const D3D11_BLEND_DESC *desc, ID3D11BlendState **state)
{
return theDX11Context.getDevice()->CreateBlendState(desc, state);
return DX11Context::Instance()->getDevice()->CreateBlendState(desc, state);
}
+1 -1
View File
@@ -716,7 +716,7 @@ void DX11Shaders::init(const ComPtr<ID3D11Device>& device, pD3DCompile D3DCompil
{
this->device = device;
this->D3DCompile = D3DCompile;
enableCache(!theDX11Context.hasShaderCache());
enableCache(!DX11Context::Instance()->hasShaderCache());
loadCache(CacheFile);
}
+6 -6
View File
@@ -86,13 +86,13 @@ void DX11Texture::UploadToGPU(int width, int height, const u8* temp_tex_buffer,
desc.BindFlags |= D3D11_BIND_RENDER_TARGET;
mipmapLevels = 1;
}
if (SUCCEEDED(theDX11Context.getDevice()->CreateTexture2D(&desc, nullptr, &texture.get())))
if (SUCCEEDED(DX11Context::Instance()->getDevice()->CreateTexture2D(&desc, nullptr, &texture.get())))
{
D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc{};
viewDesc.Format = desc.Format;
viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
viewDesc.Texture2D.MipLevels = desc.MipLevels == 0 ? -1 : desc.MipLevels;
theDX11Context.getDevice()->CreateShaderResourceView(texture, &viewDesc, &textureView.get());
DX11Context::Instance()->getDevice()->CreateShaderResourceView(texture, &viewDesc, &textureView.get());
}
else
{
@@ -106,17 +106,17 @@ void DX11Texture::UploadToGPU(int width, int height, const u8* temp_tex_buffer,
{
u32 w = mipmapLevels == 1 ? width : 1 << i;
u32 h = mipmapLevels == 1 ? height : 1 << i;
theDX11Context.getDeviceContext()->UpdateSubresource(texture, mipmapLevels - i - 1, nullptr, temp_tex_buffer, w * bpp, w * bpp * h);
DX11Context::Instance()->getDeviceContext()->UpdateSubresource(texture, mipmapLevels - i - 1, nullptr, temp_tex_buffer, w * bpp, w * bpp * h);
temp_tex_buffer += (1 << (2 * i)) * bpp;
}
if (mipmapped && !mipmapsIncluded)
theDX11Context.getDeviceContext()->GenerateMips(textureView);
DX11Context::Instance()->getDeviceContext()->GenerateMips(textureView);
}
#ifndef TARGET_UWP
bool DX11Texture::Force32BitTexture(TextureType type) const
{
if (!theDX11Context.textureFormatSupported(type))
if (!DX11Context::Instance()->textureFormatSupported(type))
return true;
if (IsWindows8OrGreater())
return false;
@@ -151,5 +151,5 @@ void DX11Texture::loadCustomTexture()
HRESULT Samplers::createSampler(const D3D11_SAMPLER_DESC *desc, ID3D11SamplerState **sampler)
{
return theDX11Context.getDevice()->CreateSamplerState(desc, sampler);
return DX11Context::Instance()->getDevice()->CreateSamplerState(desc, sampler);
}
+14 -3
View File
@@ -34,12 +34,24 @@
#include "nowide/stackstring.hpp"
DX11Context theDX11Context;
void DX11Context::Create(void *window, void *display) {
new DX11Context(window, display);
}
DX11Context::DX11Context(void *window, void *display)
: GraphicsContext(window, display)
{
if (!init())
throw FlycastException("DX11 initialization failed");
}
DX11Context::~DX11Context() {
term();
}
bool DX11Context::init(bool keepCurrentWindow)
{
NOTICE_LOG(RENDERER, "DX11 Context initializing");
GraphicsContext::instance = this;
#ifdef USE_SDL
if (!keepCurrentWindow && !sdl_recreate_window(0))
return false;
@@ -199,7 +211,6 @@ bool DX11Context::init(bool keepCurrentWindow)
void DX11Context::term()
{
NOTICE_LOG(RENDERER, "DX11 Context terminating");
GraphicsContext::instance = nullptr;
overlay.term();
samplers.term();
shaders.term();
+7 -3
View File
@@ -33,8 +33,9 @@
class DX11Context : public GraphicsContext
{
public:
bool init(bool keepCurrentWindow = false);
void term() override;
static void Create(void *window, void *display = nullptr);
static DX11Context *Instance() { return static_cast<DX11Context *>(GraphicsContext::Instance()); }
void EndImGuiFrame();
void Present();
const ComPtr<ID3D11Device>& getDevice() const { return pDevice; }
@@ -80,6 +81,10 @@ public:
}
private:
DX11Context(void *window, void *display);
~DX11Context();
bool init(bool keepCurrentWindow = false);
void term();
void handleDeviceLost();
bool checkTextureSupport();
@@ -109,5 +114,4 @@ private:
static constexpr UINT VENDOR_ATI = 0x1002;
static constexpr UINT VENDOR_AMD = 0x1022;
};
extern DX11Context theDX11Context;
#endif
+13 -3
View File
@@ -22,7 +22,19 @@
#include "rend/osd.h"
#include "rend/transform_matrix.h"
DX11Context theDX11Context;
void DX11Context::Create(ID3D11Device *device, ID3D11DeviceContext *deviceContext, pD3DCompile D3DCompile, D3D_FEATURE_LEVEL featureLevel) {
new DX11Context(device, deviceContext, D3DCompile, featureLevel);
}
DX11Context::DX11Context(ID3D11Device *device, ID3D11DeviceContext *deviceContext, pD3DCompile D3DCompile, D3D_FEATURE_LEVEL featureLevel)
{
if (!init(device, deviceContext, D3DCompile, featureLevel))
throw FlycastException("DX11 initialization failed");
}
DX11Context::~DX11Context() {
term();
}
bool DX11Context::init(ID3D11Device *device, ID3D11DeviceContext *deviceContext, pD3DCompile D3DCompile, D3D_FEATURE_LEVEL featureLevel)
{
@@ -33,7 +45,6 @@ bool DX11Context::init(ID3D11Device *device, ID3D11DeviceContext *deviceContext,
pDeviceContext.reset(deviceContext);
this->D3DCompile = D3DCompile;
this->featureLevel = featureLevel;
GraphicsContext::instance = this;
ComPtr<IDXGIDevice2> dxgiDevice;
pDevice.as(dxgiDevice);
@@ -66,7 +77,6 @@ bool DX11Context::init(ID3D11Device *device, ID3D11DeviceContext *deviceContext,
void DX11Context::term()
{
NOTICE_LOG(RENDERER, "DX11 Context terminating");
GraphicsContext::instance = nullptr;
blendStates.term();
quad.reset();
textureView.reset();
+6 -3
View File
@@ -33,8 +33,9 @@
class DX11Context : public GraphicsContext
{
public:
bool init(ID3D11Device *device, ID3D11DeviceContext *deviceContext, pD3DCompile D3DCompile, D3D_FEATURE_LEVEL featureLevel);
void term() override;
static void Create(ID3D11Device *device, ID3D11DeviceContext *deviceContext, pD3DCompile D3DCompile, D3D_FEATURE_LEVEL featureLevel);
static DX11Context *Instance() { return static_cast<DX11Context *>(GraphicsContext::Instance()); }
~DX11Context();
void present();
const ComPtr<ID3D11Device>& getDevice() const { return pDevice; }
@@ -71,6 +72,9 @@ public:
}
private:
DX11Context(ID3D11Device *device, ID3D11DeviceContext *deviceContext, pD3DCompile D3DCompile, D3D_FEATURE_LEVEL featureLevel);
bool init(ID3D11Device *device, ID3D11DeviceContext *deviceContext, pD3DCompile D3DCompile, D3D_FEATURE_LEVEL featureLevel);
void term();
bool checkTextureSupport();
ComPtr<ID3D11RenderTargetView>& getRenderTarget(int width, int height);
@@ -97,5 +101,4 @@ private:
static constexpr UINT VENDOR_ATI = 0x1002;
static constexpr UINT VENDOR_AMD = 0x1022;
};
extern DX11Context theDX11Context;
#endif
+5 -5
View File
@@ -75,7 +75,7 @@ struct DX11OITRenderer : public DX11Renderer
desc.ByteWidth = (((desc.ByteWidth - 1) >> 4) + 1) << 4;
bool success = SUCCEEDED(device->CreateBuffer(&desc, nullptr, &pxlPolyConstants.get()));
shaders.init(device, theDX11Context.getCompiler());
shaders.init(device, DX11Context::Instance()->getCompiler());
buffers.init(device, deviceContext);
pixelBufferSize = config::PixelBufferSize;
ComPtr<ID3DBlob> blob = shaders.getVertexShaderBlob();
@@ -579,7 +579,7 @@ struct DX11OITRenderer : public DX11Renderer
drawList<ListType_Translucent, true, DX11OITShaders::OIT>(rendContext->global_param_tr, previous_pass.tr_count, tr_count);
// unbind depth tex
deviceContext->PSSetShaderResources(4, 1, &nullView);
if (!theDX11Context.isIntel())
if (!DX11Context::Instance()->isIntel())
{
// Intel Iris Plus 640 just crashes
if (current_pass.mv_op_tr_shared)
@@ -681,15 +681,15 @@ struct DX11OITRenderer : public DX11Renderer
{
aspectRatio = getOutputFramebufferAspectRatio();
#ifndef LIBRETRO
deviceContext->OMSetRenderTargets(1, &theDX11Context.getRenderTarget().get(), nullptr);
deviceContext->OMSetRenderTargets(1, &DX11Context::Instance()->getRenderTarget().get(), nullptr);
displayFramebuffer();
drawOSD();
renderVideoRouting();
theDX11Context.setFrameRendered();
DX11Context::Instance()->setFrameRendered();
#else
ID3D11RenderTargetView *nullView = nullptr;
deviceContext->OMSetRenderTargets(1, &nullView, nullptr);
theDX11Context.presentFrame(fbTextureView, width, height);
DX11Context::Instance()->presentFrame(fbTextureView, width, height);
#endif
frameRendered = true;
frameRenderedOnce = true;
+1 -1
View File
@@ -1078,6 +1078,6 @@ void DX11OITShaders::init(const ComPtr<ID3D11Device>& device, pD3DCompile D3DCom
{
this->device = device;
this->D3DCompile = D3DCompile;
enableCache(!theDX11Context.hasShaderCache());
enableCache(!DX11Context::Instance()->hasShaderCache());
loadCache(CacheFile);
}
+12 -12
View File
@@ -113,7 +113,7 @@ bool D3DRenderer::ensureIndexBufferSize(ComPtr<IDirect3DIndexBuffer9>& buffer, u
bool D3DRenderer::Init()
{
ComPtr<IDirect3D9> d3d9 = theDXContext.getD3D();
ComPtr<IDirect3D9> d3d9 = DXContext::Instance()->getD3D();
D3DCAPS9 caps;
d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
if (caps.VertexShaderVersion < D3DVS_VERSION(1, 0))
@@ -128,7 +128,7 @@ bool D3DRenderer::Init()
}
maxAnisotropy = caps.MaxAnisotropy;
device = theDXContext.getDevice();
device = DXContext::Instance()->getDevice();
devCache.setDevice(device);
bool success = ensureVertexBufferSize(vertexBuffer, vertexBufferSize, 4_MB);
@@ -215,7 +215,7 @@ void D3DRenderer::Term()
BaseTextureCacheData *D3DRenderer::GetTexture(TSP tsp, TCW tcw, int area)
{
if (!theDXContext.isReady())
if (!DXContext::Instance()->isReady())
return nullptr;
//lookup texture
D3DTexture* tf = texCache.getTextureCacheData(tsp, tcw, area);
@@ -237,7 +237,7 @@ BaseTextureCacheData *D3DRenderer::GetTexture(TSP tsp, TCW tcw, int area)
void D3DRenderer::RenderFramebuffer(const FramebufferInfo& info)
{
if (!theDXContext.isReady()) {
if (!DXContext::Instance()->isReady()) {
// force a Present
frameRendered = true;
return;
@@ -306,12 +306,12 @@ void D3DRenderer::RenderFramebuffer(const FramebufferInfo& info)
frameRendered = true;
frameRenderedOnce = true;
clearLastFrame = false;
theDXContext.setFrameRendered();
DXContext::Instance()->setFrameRendered();
}
void D3DRenderer::Process(TA_context* ctx)
{
if (!theDXContext.isReady()) {
if (!DXContext::Instance()->isReady()) {
// force a Present
frameRendered = true;
return;
@@ -953,7 +953,7 @@ void D3DRenderer::readRttRenderTarget(u32 texAddress)
bool D3DRenderer::Render()
{
if (!theDXContext.isReady())
if (!DXContext::Instance()->isReady())
return false;
bool is_rtt = rendContext->isRTT;
@@ -1139,7 +1139,7 @@ bool D3DRenderer::Render()
frameRendered = true;
frameRenderedOnce = true;
clearLastFrame = false;
theDXContext.setFrameRendered();
DXContext::Instance()->setFrameRendered();
}
return !is_rtt;
@@ -1236,7 +1236,7 @@ void D3DRenderer::displayFramebuffer()
bool D3DRenderer::RenderLastFrame()
{
if (clearLastFrame || !frameRenderedOnce || !theDXContext.isReady())
if (clearLastFrame || !frameRenderedOnce || !DXContext::Instance()->isReady())
return false;
backbuffer.reset();
bool rc = SUCCEEDED(device->GetRenderTarget(0, &backbuffer.get()));
@@ -1298,9 +1298,9 @@ void D3DRenderer::updateFogTexture()
void D3DRenderer::drawOSD()
{
theDXContext.setOverlay(true);
DXContext::Instance()->setOverlay(true);
gui_display_osd();
theDXContext.setOverlay(false);
DXContext::Instance()->setOverlay(false);
}
void D3DRenderer::writeFramebufferToVRAM()
@@ -1376,7 +1376,7 @@ void D3DRenderer::writeFramebufferToVRAM()
bool D3DRenderer::GetLastFrame(std::vector<u8>& data, int& width, int& height)
{
if (!frameRenderedOnce || !theDXContext.isReady())
if (!frameRenderedOnce || !DXContext::Instance()->isReady())
return false;
if (width != 0) {
+1 -1
View File
@@ -68,7 +68,7 @@ void D3DTexture::UploadToGPU(int width, int height, const u8* temp_tex_buffer, b
levels = 0;
usage = D3DUSAGE_AUTOGENMIPMAP;
}
theDXContext.getDevice()->CreateTexture(width, height, levels, usage, d3dFormat, D3DPOOL_MANAGED, &texture.get(), 0); // TODO the managed pool persists between device resets
DXContext::Instance()->getDevice()->CreateTexture(width, height, levels, usage, d3dFormat, D3DPOOL_MANAGED, &texture.get(), 0); // TODO the managed pool persists between device resets
verify(texture != nullptr);
}
if (SUCCEEDED(texture->LockRect(mipmapLevels - 1, &rect, nullptr, 0)))
+3 -3
View File
@@ -38,14 +38,14 @@ public:
}
void renderDrawData(ImDrawData *drawData, bool gui_open) override {
theDXContext.EndImGuiFrame();
DXContext::Instance()->EndImGuiFrame();
if (gui_open)
frameRendered = true;
}
void present() override {
if (frameRendered)
theDXContext.Present();
DXContext::Instance()->Present();
frameRendered = false;
}
@@ -66,7 +66,7 @@ public:
{
Texture& texture = textures[name];
texture.tex.reset();
HRESULT hr = theDXContext.getDevice()->CreateTexture(width, height, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture.tex.get(), 0);
HRESULT hr = DXContext::Instance()->getDevice()->CreateTexture(width, height, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture.tex.get(), 0);
if (FAILED(hr) || !texture.tex)
{
WARN_LOG(RENDERER, "CreateTexture failed (%d x %d): error %x", width, height, hr);
+14 -3
View File
@@ -27,12 +27,24 @@
#include "dx9_driver.h"
#include "imgui_impl_dx9.h"
DXContext theDXContext;
void DXContext::Create(void *window, void *display) {
new DXContext(window, display);
}
DXContext::DXContext(void *window, void *display)
: GraphicsContext(window, display)
{
if (!init())
throw FlycastException("DX9 initialization failed");
}
DXContext::~DXContext() {
term();
}
bool DXContext::init(bool keepCurrentWindow)
{
NOTICE_LOG(RENDERER, "DX9 Context initializing");
GraphicsContext::instance = this;
#ifdef USE_SDL
if (!keepCurrentWindow && !sdl_recreate_window(0)) {
term();
@@ -93,7 +105,6 @@ bool DXContext::init(bool keepCurrentWindow)
void DXContext::term()
{
NOTICE_LOG(RENDERER, "DX9 Context terminating");
GraphicsContext::instance = nullptr;
overlay.term();
imguiDriver.reset();
pDevice.reset();
+6 -3
View File
@@ -30,8 +30,9 @@
class DXContext : public GraphicsContext
{
public:
bool init(bool keepCurrentWindow = false);
void term() override;
static void Create(void *window, void *display);
static DXContext *Instance() { return static_cast<DXContext *>(GraphicsContext::Instance()); }
~DXContext();
void EndImGuiFrame();
void Present();
void resize() override;
@@ -62,6 +63,9 @@ public:
}
private:
DXContext(void *window, void *display);
bool init(bool keepCurrentWindow = false);
void term();
void resetDevice();
WinLibLoader d3d9Library{ "D3D9.DLL" };
@@ -77,5 +81,4 @@ private:
bool amd = false;
bool deviceReady = false;
};
extern DXContext theDXContext;
#endif
+4 -4
View File
@@ -505,9 +505,9 @@ bool testBlitFramebuffer();
void findGLVersion()
{
gl.index_type = GL_UNSIGNED_INT;
gl.gl_major = theGLContext.getMajorVersion();
gl.gl_minor = theGLContext.getMinorVersion();
gl.is_gles = theGLContext.isGLES();
gl.gl_major = GLGraphicsContext::Instance()->getMajorVersion();
gl.gl_minor = GLGraphicsContext::Instance()->getMinorVersion();
gl.is_gles = GLGraphicsContext::Instance()->isGLES();
if (gl.is_gles)
{
gl.border_clamp_supported = false;
@@ -1079,7 +1079,7 @@ void OpenGLRenderer::Process(TA_context* ctx)
updatePalette = false;
}
if (!ctx->rend.isRTT && ctx->rend.swapInterval > 0)
theGLContext.setSwapInterval(ctx->rend.swapInterval);
GraphicsContext::Instance()->setSwapInterval(ctx->rend.swapInterval);
ta_parse(ctx, gl.prim_restart_fixed_supported || gl.prim_restart_supported);
}
+1 -1
View File
@@ -72,7 +72,7 @@ void OpenGLDriver::renderDrawData(ImDrawData* drawData, bool gui_open)
void OpenGLDriver::present()
{
if (frameRendered)
theGLContext.swap();
GLGraphicsContext::Instance()->swap();
frameRendered = false;
}
+23 -32
View File
@@ -30,7 +30,10 @@
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
#endif
VulkanContext *VulkanContext::contextInstance;
bool VulkanContext::fragmentStoresAndAtomics = false;
bool VulkanContext::samplerAnisotropy = false;
bool VulkanContext::dedicatedAllocationSupported = false;
bool VulkanContext::provokingVertexSupported = false;
const VkApplicationInfo* VkGetApplicationInfo()
{
@@ -156,18 +159,15 @@ bool VkCreateDevice(retro_vulkan_context* context, VkInstance instance, VkPhysic
tryAddDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
// Enable VK_KHR_dedicated_allocation if available
if (physicalDeviceProperties.apiVersion >= VK_API_VERSION_1_1)
{
if (physicalDeviceProperties.apiVersion >= VK_API_VERSION_1_1) {
// Core in Vulkan 1.1
VulkanContext::Instance()->dedicatedAllocationSupported = true;
VulkanContext::dedicatedAllocationSupported = true;
}
else
{
const bool getMemReq2Supported = tryAddDeviceExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
if (getMemReq2Supported)
{
VulkanContext::Instance()->dedicatedAllocationSupported = tryAddDeviceExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
}
VulkanContext::dedicatedAllocationSupported = tryAddDeviceExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
}
// Check for VK_KHR_get_physical_device_properties2
@@ -177,10 +177,8 @@ bool VkCreateDevice(retro_vulkan_context* context, VkInstance instance, VkPhysic
? true : tryAddDeviceExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
if (getPhysicalDeviceProperties2Supported)
{
// Enable VK_EXT_provoking_vertex if available
VulkanContext::Instance()->provokingVertexSupported = tryAddDeviceExtension(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
}
VulkanContext::provokingVertexSupported = tryAddDeviceExtension(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
// Get device features
@@ -188,28 +186,20 @@ bool VkCreateDevice(retro_vulkan_context* context, VkInstance instance, VkPhysic
vk::PhysicalDeviceFeatures& features = featuresChain.features;
vk::PhysicalDeviceProvokingVertexFeaturesEXT provokingVertexFeatures{};
if (VulkanContext::Instance()->provokingVertexSupported)
{
if (VulkanContext::provokingVertexSupported)
featuresChain.pNext = &provokingVertexFeatures;
}
// Get the physical device's features
if (getPhysicalDeviceProperties2Supported && featuresChain.pNext)
{
physicalDevice.getFeatures2(&featuresChain);
}
else
{
physicalDevice.getFeatures(&features);
}
if (VulkanContext::Instance()->provokingVertexSupported)
{
VulkanContext::Instance()->provokingVertexSupported &= provokingVertexFeatures.provokingVertexLast;
}
if (VulkanContext::provokingVertexSupported)
VulkanContext::provokingVertexSupported &= provokingVertexFeatures.provokingVertexLast;
VulkanContext::Instance()->samplerAnisotropy = features.samplerAnisotropy;
VulkanContext::Instance()->fragmentStoresAndAtomics = features.fragmentStoresAndAtomics;
VulkanContext::samplerAnisotropy = features.samplerAnisotropy;
VulkanContext::fragmentStoresAndAtomics = features.fragmentStoresAndAtomics;
// create a Device
float queuePriority = 1.0f;
@@ -248,7 +238,6 @@ bool VulkanContext::init(retro_hw_render_interface_vulkan *retro_render_if)
|| retro_render_if->interface_version != RETRO_HW_RENDER_INTERFACE_VULKAN_VERSION)
return false;
this->retro_render_if = retro_render_if;
GraphicsContext::instance = this;
instance = vk::Instance(retro_render_if->instance);
physicalDevice = vk::PhysicalDevice(retro_render_if->gpu);
@@ -510,7 +499,6 @@ void VulkanContext::endFrame(vk::Image barrierImage)
void VulkanContext::term()
{
GraphicsContext::instance = nullptr;
if (device)
{
device.waitIdle();
@@ -544,14 +532,17 @@ void VulkanContext::term()
pipelineCache.reset();
}
VulkanContext::VulkanContext()
{
assert(contextInstance == nullptr);
contextInstance = this;
void VulkanContext::Create(retro_hw_render_interface_vulkan *render_if) {
new VulkanContext(render_if);
}
VulkanContext::~VulkanContext()
VulkanContext::VulkanContext(retro_hw_render_interface_vulkan *render_if)
: GraphicsContext(nullptr, nullptr)
{
assert(contextInstance == this);
contextInstance = nullptr;
if (!init(render_if))
throw FlycastException("Vulkan initialization failed");
}
VulkanContext::~VulkanContext() {
term();
}
+10 -12
View File
@@ -36,11 +36,8 @@ class FramebufferAttachment;
class VulkanContext : public GraphicsContext, public FlightManager
{
public:
VulkanContext();
~VulkanContext() override;
bool init(retro_hw_render_interface_vulkan *render_if);
void term() override;
~VulkanContext();
static void Create(retro_hw_render_interface_vulkan *render_if);
u32 GetGraphicsQueueFamilyIndex() const { return retro_render_if->queue_index; }
void PresentFrame(vk::Image image, vk::ImageView imageView, const vk::Extent2D& extent, float aspectRatio);
@@ -88,7 +85,7 @@ public:
return vendorID == VENDOR_ATI || vendorID == VENDOR_AMD;
}
vk::Format GetDepthFormat() const { return depthFormat; }
static VulkanContext *Instance() { return contextInstance; }
static VulkanContext *Instance() { return static_cast<VulkanContext *>(GraphicsContext::Instance()); }
bool SupportsSamplerAnisotropy() const { return samplerAnisotropy; }
bool SupportsDedicatedAllocation() const { return dedicatedAllocationSupported; }
bool hasPerPixel() override { return fragmentStoresAndAtomics; }
@@ -117,6 +114,9 @@ public:
constexpr static int VENDOR_MESA = 0x10005;
private:
VulkanContext(retro_hw_render_interface_vulkan *render_if);
bool init(retro_hw_render_interface_vulkan *render_if);
void term();
void beginFrame(vk::Extent2D extent, vk::Image barrierImage);
void endFrame(vk::Image barrierImage);
@@ -130,11 +130,11 @@ private:
bool optimalTilingSupported1555 = false;
bool optimalTilingSupported4444 = false;
public:
bool fragmentStoresAndAtomics = false;
bool samplerAnisotropy = false;
static bool fragmentStoresAndAtomics;
static bool samplerAnisotropy;
f32 maxSamplerAnisotropy = 0.f;
bool dedicatedAllocationSupported = false;
bool provokingVertexSupported = false;
static bool dedicatedAllocationSupported;
static bool provokingVertexSupported;
private:
u32 vendorID = 0;
@@ -162,8 +162,6 @@ private:
std::unique_ptr<VulkanOverlay> overlay;
retro_vulkan_image retro_image;
static VulkanContext *contextInstance;
};
const VkApplicationInfo* VkGetApplicationInfo();
+11 -13
View File
@@ -50,8 +50,6 @@ VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
void ReInitOSD();
VulkanContext *VulkanContext::contextInstance;
#ifdef VK_DEBUG
#ifndef __ANDROID__
VKAPI_ATTR static VkBool32 VKAPI_CALL debugUtilsMessengerCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes,
@@ -370,7 +368,7 @@ void VulkanContext::InitImgui()
#if VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1
ImGui_ImplVulkan_LoadFunctions(0, [](const char *function_name, void *) {
return VULKAN_HPP_DEFAULT_DISPATCHER.vkGetInstanceProcAddr((VkInstance) *contextInstance->instance, function_name);
return VULKAN_HPP_DEFAULT_DISPATCHER.vkGetInstanceProcAddr((VkInstance) *Instance()->instance, function_name);
});
#endif
@@ -875,8 +873,6 @@ void VulkanContext::CreateSwapChain()
bool VulkanContext::init()
{
GraphicsContext::instance = this;
std::vector<const char *> extensions;
extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
#if defined(USE_SDL)
@@ -1183,7 +1179,6 @@ void VulkanContext::PresentLastFrame()
void VulkanContext::term()
{
GraphicsContext::instance = nullptr;
lastFrameView = nullptr;
if (device && graphicsQueue)
WaitIdle();
@@ -1415,16 +1410,19 @@ void VulkanContext::SetWindowSize(u32 width, u32 height)
}
}
VulkanContext::VulkanContext()
{
assert(contextInstance == nullptr);
contextInstance = this;
void VulkanContext::Create(void *window, void *display) {
new VulkanContext(window, display);
}
VulkanContext::~VulkanContext()
VulkanContext::VulkanContext(void *window, void *display)
: GraphicsContext(window, display)
{
assert(contextInstance == this);
contextInstance = nullptr;
if (!init())
throw FlycastException("Vulkan initialization failed");
}
VulkanContext::~VulkanContext() {
term();
}
bool VulkanContext::GetLastFrame(std::vector<u8>& data, int& width, int& height)
+5 -6
View File
@@ -97,12 +97,9 @@ struct ImDrawData;
class VulkanContext : public GraphicsContext, public FlightManager
{
public:
VulkanContext();
static void Create(void *window, void *display);
~VulkanContext() override;
bool init();
void term() override;
VkInstance GetInstance() const { return static_cast<VkInstance>(instance.get()); }
u32 GetGraphicsQueueFamilyIndex() const { return graphicsQueueIndex; }
void resize() override { resized = true; }
@@ -153,7 +150,7 @@ public:
return vendorID == VENDOR_ATI || vendorID == VENDOR_AMD;
}
vk::Format GetDepthFormat() const { return depthFormat; }
static VulkanContext *Instance() { return contextInstance; }
static VulkanContext *Instance() { return static_cast<VulkanContext *>(GraphicsContext::Instance()); }
bool SupportsSamplerAnisotropy() const { return samplerAnisotropy; }
float GetMaxSamplerAnisotropy() const { return samplerAnisotropy ? maxSamplerAnisotropy : 1.f; }
bool SupportsDedicatedAllocation() const { return dedicatedAllocationSupported; }
@@ -197,6 +194,9 @@ public:
constexpr static int VENDOR_MESA = 0x10005;
private:
VulkanContext(void *window, void *display);
bool init();
void term();
void CreateSwapChain();
bool InitDevice();
bool InitInstance(const char** extensions, uint32_t extensions_count);
@@ -286,7 +286,6 @@ private:
vk::UniqueDebugReportCallbackEXT debugReportCallback;
#endif
#endif
static VulkanContext *contextInstance;
};
#endif // !LIBRETRO
-3
View File
@@ -51,7 +51,6 @@
#endif
#include "vgamepad.h"
#include "settings.h"
#include "wsi/context.h"
#include "oslib/i18n.h"
#include "gui_font.h"
using namespace i18n;
@@ -111,8 +110,6 @@ static void emuEventCallback(Event event, void *)
case Event::Terminate:
GamepadDevice::load_system_mappings();
game_started = false;
if (GraphicsContext::Instance() != nullptr)
GraphicsContext::Instance()->setSwapInterval(1);
break;
default:
break;
+1 -1
View File
@@ -1,6 +1,6 @@
target_sources(${PROJECT_NAME} PRIVATE
context.cpp
context.h
libretro.cpp
libretro.h
switcher.cpp)
+22 -12
View File
@@ -1,7 +1,7 @@
/*
Copyright 2021 flyinghead
Copyright 2026 flyinghead
This file is part of Flycast.
This file is part of Flycast.
Flycast is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,16 +15,26 @@
You should have received a copy of the GNU General Public License
along with Flycast. If not, see <https://www.gnu.org/licenses/>.
*/
#include "libretro.h"
#ifdef LIBRETRO
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES)
LibretroGraphicsContext theGLContext;
#endif
*/
#include "context.h"
GraphicsContext *GraphicsContext::instance;
#endif
GraphicsContext::GraphicsContext(void *window, void *display)
: window(window), display(display)
{
instance = this;
EventManager::listen(Event::Pause, GraphicsContext::onEvent, this);
EventManager::listen(Event::Terminate, GraphicsContext::onEvent, this);
}
GraphicsContext::~GraphicsContext() {
EventManager::unlisten(Event::Pause, GraphicsContext::onEvent, this);
EventManager::unlisten(Event::Terminate, GraphicsContext::onEvent, this);
instance = nullptr;
}
void GraphicsContext::onEvent(Event event, void *arg) {
GraphicsContext *self = (GraphicsContext *)arg;
self->setSwapInterval(1);
}
+15 -2
View File
@@ -19,7 +19,9 @@
along with Flycast. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include "emulator.h"
#include <string>
#include <cassert>
void initRenderApi(void *window = nullptr, void *display = nullptr);
void termRenderApi();
@@ -28,8 +30,7 @@ void switchRenderApi();
class GraphicsContext
{
public:
virtual ~GraphicsContext() = default;
virtual void term() = 0;
virtual ~GraphicsContext();
virtual void resize() {}
virtual std::string getDriverName() = 0;
virtual std::string getDriverVersion() = 0;
@@ -50,9 +51,21 @@ public:
static GraphicsContext *Instance() {
return instance;
}
static void Term()
{
if (instance != nullptr) {
delete instance;
assert(instance == nullptr);
}
}
protected:
GraphicsContext(void *window, void *display = nullptr);
void *window = nullptr;
void *display = nullptr;
private:
static void onEvent(Event event, void *arg);
static GraphicsContext *instance;
};
+14 -2
View File
@@ -18,7 +18,7 @@
You should have received a copy of the GNU General Public License
along with Flycast. If not, see <https://www.gnu.org/licenses/>.
*/
#include "gl_context.h"
#include "egl.h"
#ifdef USE_EGL
#include "types.h"
@@ -28,7 +28,19 @@
#include <android/native_window.h> // requires ndk r5 or newer
#endif
EGLGraphicsContext theGLContext;
#ifndef SWAPPY
void EGLGraphicsContext::Create(void *window, void *display)
{
new EGLGraphicsContext(window, display);
}
#endif
EGLGraphicsContext::EGLGraphicsContext(void *window, void *display)
: GLGraphicsContext(window, display)
{
if (!init())
throw FlycastException("OpenGL initialization failed");
}
bool EGLGraphicsContext::makeCurrent()
{
+9 -7
View File
@@ -21,19 +21,22 @@
#pragma once
#include "gl_context.h"
#if !defined(USE_SDL) && !defined(LIBRETRO) && (defined(__ANDROID__) || defined(SUPPORT_X11))
#define USE_EGL
#include <glad/egl.h>
class EGLGraphicsContext : public GLGraphicsContext
{
public:
~EGLGraphicsContext() override { term(); }
~EGLGraphicsContext() { term(); }
void swap() override;
static void Create(void *window, void *display);
protected:
EGLGraphicsContext(void *window, void *display);
bool init();
void term() override;
void swap();
private:
void term();
bool makeCurrent();
void changeSwapInterval();
@@ -44,5 +47,4 @@ private:
int maxSwapInterval = 1;
int currentSwapInterval = 1;
};
extern EGLGraphicsContext theGLContext;
#endif
+24 -2
View File
@@ -19,6 +19,17 @@
along with Flycast. If not, see <https://www.gnu.org/licenses/>.
*/
#include "gl_context.h"
#if defined(LIBRETRO)
#include "libretro.h"
#elif defined(TARGET_IPHONE)
#include "osx.h"
#elif defined(USE_SDL)
#include "sdl.h"
#elif defined(__ANDROID__) || defined(SUPPORT_X11)
#include "egl.h"
#else
#error Unsupported window system
#endif
#ifndef LIBRETRO
#include "rend/gles/opengl_driver.h"
@@ -60,7 +71,6 @@ void GLGraphicsContext::findGLVersion()
void GLGraphicsContext::postInit()
{
instance = this;
findGLVersion();
resetUIDriver();
}
@@ -70,7 +80,6 @@ void GLGraphicsContext::preTerm()
#ifndef LIBRETRO
imguiDriver.reset();
#endif
instance = nullptr;
}
void GLGraphicsContext::resetUIDriver()
@@ -88,3 +97,16 @@ void GLGraphicsContext::setSwapInterval(int interval)
gameSwapInterval = interval;
gameSwapIntervalChanged = true;
}
void GLGraphicsContext::Create(void *window, void *display)
{
#if defined(LIBRETRO)
LibretroGraphicsContext::Create(window, display);
#elif defined(TARGET_IPHONE)
OSXGraphicsContext::Create(window, display);
#elif defined(USE_SDL)
SDLGLGraphicsContext::Create(window, display);
#elif defined(__ANDROID__) || defined(SUPPORT_X11)
EGLGraphicsContext::Create(window, display);
#endif
}
+39 -24
View File
@@ -22,8 +22,37 @@
#include "types.h"
#include "context.h"
#if defined(USE_OPENGL) && !defined(LIBRETRO) && !defined(TARGET_IPHONE)
#include <glad/gl.h>
#if defined(TARGET_IPHONE)
#include <OpenGLES/ES3/gl.h>
#include <OpenGLES/ES3/glext.h>
#elif defined(LIBRETRO)
#include <libretro.h>
#include <glsm/glsm.h>
#include <glsm/glsmsym.h>
#ifndef GL_MAJOR_VERSION
#define GL_MAJOR_VERSION 0x821B
#endif
#ifndef GL_MINOR_VERSION
#define GL_MINOR_VERSION 0x821C
#endif
#ifndef GL_DEBUG_SEVERITY_NOTIFICATION
#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
#endif
#ifndef GL_DEBUG_SEVERITY_HIGH
#define GL_DEBUG_SEVERITY_HIGH 0x9146
#endif
#ifndef GL_DEBUG_SEVERITY_MEDIUM
#define GL_DEBUG_SEVERITY_MEDIUM 0x9147
#endif
#ifndef GL_DEBUG_SEVERITY_LOW
#define GL_DEBUG_SEVERITY_LOW 0x9148
#endif
#elif defined(USE_OPENGL)
#include <glad/gl.h>
#endif
#ifdef TEST_AUTOMATION
@@ -35,6 +64,7 @@ static inline void do_swap_automation() {}
class GLGraphicsContext : public GraphicsContext
{
public:
virtual void swap() = 0;
int getMajorVersion() const {
return majorVersion;
}
@@ -63,7 +93,14 @@ public:
}
void setSwapInterval(int interval) override;
static GLGraphicsContext *Instance() {
return static_cast<GLGraphicsContext*>(GraphicsContext::Instance());
}
static void Create(void *window, void *display = nullptr);
protected:
GLGraphicsContext(void *window, void *display)
: GraphicsContext(window, display) {}
void postInit();
void preTerm();
void findGLVersion();
@@ -79,25 +116,3 @@ private:
std::string driverVersion;
bool amd = false;
};
#if defined(LIBRETRO)
#include "libretro.h"
#elif defined(TARGET_IPHONE)
#include "osx.h"
#elif defined(USE_SDL)
#include "sdl.h"
#elif defined(__ANDROID__) || defined(SUPPORT_X11)
#include "egl.h"
#else
#error Unsupported window system
#endif
+13 -36
View File
@@ -18,49 +18,26 @@
*/
#pragma once
#if defined(LIBRETRO) && (defined(HAVE_OPENGL) || defined(HAVE_OPENGLES))
#if defined(TARGET_IPHONE) //apple-specific ogles3 headers
#include <OpenGLES/ES3/gl.h>
#include <OpenGLES/ES3/glext.h>
#endif
#include "gl_context.h"
#include <libretro.h>
#include <glsm/glsm.h>
#include <glsm/glsmsym.h>
#ifndef GL_MAJOR_VERSION
#define GL_MAJOR_VERSION 0x821B
#endif
#ifndef GL_MINOR_VERSION
#define GL_MINOR_VERSION 0x821C
#endif
#ifndef GL_DEBUG_SEVERITY_NOTIFICATION
#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
#endif
#ifndef GL_DEBUG_SEVERITY_HIGH
#define GL_DEBUG_SEVERITY_HIGH 0x9146
#endif
#ifndef GL_DEBUG_SEVERITY_MEDIUM
#define GL_DEBUG_SEVERITY_MEDIUM 0x9147
#endif
#ifndef GL_DEBUG_SEVERITY_LOW
#define GL_DEBUG_SEVERITY_LOW 0x9148
#endif
class LibretroGraphicsContext : public GLGraphicsContext
{
public:
bool init() {
postInit();
return true;
}
void term() override {
~LibretroGraphicsContext() {
preTerm();
}
void swap() {}
};
void swap() override {}
extern LibretroGraphicsContext theGLContext;
static void Create(void *window, void *display) {
new LibretroGraphicsContext(window, display);
}
private:
LibretroGraphicsContext(void *window, void *display)
: GLGraphicsContext(window, display)
{
postInit();
}
};
#endif
+14 -3
View File
@@ -19,12 +19,23 @@
along with Flycast. If not, see <https://www.gnu.org/licenses/>.
*/
#if defined(TARGET_IPHONE) && !defined(LIBRETRO)
#include "gl_context.h"
#include "osx.h"
OSXGraphicsContext theGLContext;
void OSXGraphicsContext::Create(void *window, void *display) {
new OSXGraphicsContext();
}
void OSXGraphicsContext::swap()
OSXGraphicsContext::OSXGraphicsContext()
: GLGraphicsContext(nullptr, nullptr)
{
postInit();
}
OSXGraphicsContext::~OSXGraphicsContext() {
preTerm();
}
void OSXGraphicsContext::swap() {
do_swap_automation();
}
+6 -7
View File
@@ -21,16 +21,15 @@
#pragma once
#if defined(TARGET_IPHONE)
#include "gl_context.h"
#include <OpenGLES/ES3/gl.h>
#include <OpenGLES/ES3/glext.h>
class OSXGraphicsContext : public GLGraphicsContext
{
public:
bool init() { postInit(); return true; }
void term() override { preTerm(); }
void swap();
};
~OSXGraphicsContext();
void swap() override;
static void Create(void *window = nullptr, void *display = nullptr);
extern OSXGraphicsContext theGLContext;
private:
OSXGraphicsContext();
};
#endif
+15 -3
View File
@@ -19,7 +19,7 @@
along with Flycast. If not, see <https://www.gnu.org/licenses/>.
*/
#if defined(USE_SDL)
#include "gl_context.h"
#include "sdl.h"
#include "ui/gui.h"
#include "sdl/sdl.h"
#include "cfg/option.h"
@@ -27,11 +27,19 @@
#include <algorithm>
#include <cmath>
SDLGLGraphicsContext theGLContext;
SDLGLGraphicsContext::SDLGLGraphicsContext(void *window, void *display)
: GLGraphicsContext(window, display)
{
if (!init())
throw FlycastException("OpenGL initialization failed");
}
SDLGLGraphicsContext::~SDLGLGraphicsContext() {
term();
}
bool SDLGLGraphicsContext::init()
{
instance = this;
#ifdef GLES
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
@@ -167,5 +175,9 @@ void SDLGLGraphicsContext::term()
}
}
void SDLGLGraphicsContext::Create(void *window, void *display) {
new SDLGLGraphicsContext(window, display);
}
#endif
+6 -5
View File
@@ -26,15 +26,16 @@
class SDLGLGraphicsContext : public GLGraphicsContext
{
public:
bool init();
void term() override;
void swap();
~SDLGLGraphicsContext();
void swap() override;
static void Create(void *window, void *display);
private:
SDLGLGraphicsContext(void *window, void *display);
bool init();
void term();
void changeGLSwapInterval();
SDL_GLContext glcontext = nullptr;
bool swapOnVSync = false;
};
extern SDLGLGraphicsContext theGLContext;
+32 -28
View File
@@ -28,54 +28,59 @@
#include "rend/dx11/dx11context.h"
#ifdef USE_VULKAN
#include "rend/vulkan/vulkan_context.h"
VulkanContext theVulkanContext;
#endif
GraphicsContext *GraphicsContext::instance;
void initRenderApi(void *window, void *display)
{
#ifdef USE_VULKAN
if (isVulkan(config::RendererType))
{
theVulkanContext.setWindow(window, display);
if (theVulkanContext.init())
try {
VulkanContext::Create(window, display);
return;
// Fall back to OpenGL
WARN_LOG(RENDERER, "Vulkan init failed. Falling back to OpenGL.");
config::RendererType = RenderType::OpenGL;
} catch (const std::exception& e) {
// Fall back to OpenGL
WARN_LOG(RENDERER, "Vulkan init failed. Falling back to OpenGL (%s)", e.what());
config::RendererType = RenderType::OpenGL;
}
}
#endif
#ifdef USE_DX11
bool dx11Failed = false;
if (config::RendererType == RenderType::DirectX11 || config::RendererType == RenderType::DirectX11_OIT)
{
theDX11Context.setWindow(window, display);
if (theDX11Context.init())
try {
DX11Context::Create(window, display);
return;
dx11Failed = true;
WARN_LOG(RENDERER, "DirectX 11 init failed. Falling back to DirectX 9.");
config::RendererType = RenderType::DirectX9;
} catch (const std::exception& e) {
dx11Failed = true;
WARN_LOG(RENDERER, "DirectX 11 init failed. Falling back to DirectX 9 (%s)", e.what());
config::RendererType = RenderType::DirectX9;
}
}
#endif
#ifdef USE_DX9
if (config::RendererType == RenderType::DirectX9)
{
theDXContext.setWindow(window, display);
if (theDXContext.init())
try {
DXContext::Create(window, display);
return;
// Fall back to OpenGL
WARN_LOG(RENDERER, "DirectX 9 init failed. Falling back to OpenGL.");
config::RendererType = RenderType::OpenGL;
} catch (const std::exception& e) {
// Fall back to OpenGL
WARN_LOG(RENDERER, "DirectX 9 init failed. Falling back to OpenGL (%s)", e.what());
config::RendererType = RenderType::OpenGL;
}
}
#endif
#ifdef USE_OPENGL
if (!isOpenGL(config::RendererType))
config::RendererType = RenderType::OpenGL;
theGLContext.setWindow(window, display);
if (theGLContext.init())
try {
GLGraphicsContext::Create(window, display);
return;
} catch (const std::exception& e) {
WARN_LOG(RENDERER, "OpenGL init failed: %s", e.what());
}
#endif
#ifdef USE_DX11
if (!dx11Failed)
@@ -83,19 +88,18 @@ void initRenderApi(void *window, void *display)
// Try dx11 as a last resort if it hasn't been tried before
WARN_LOG(RENDERER, "OpenGL init failed. Trying DirectX 11.");
config::RendererType = RenderType::DirectX11;
theDX11Context.setWindow(window, display);
if (theDX11Context.init())
try {
DX11Context::Create(window, display);
return;
} catch (const std::exception& e) {
}
}
#endif
throw FlycastException(i18n::T("Cannot initialize the graphics API"));
}
void termRenderApi()
{
if (GraphicsContext::Instance() != nullptr)
GraphicsContext::Instance()->term();
verify(GraphicsContext::Instance() == nullptr);
void termRenderApi() {
GraphicsContext::Term();
}
void switchRenderApi()
+23 -9
View File
@@ -39,7 +39,7 @@
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES)
#include <glsm/glsm.h>
#include "wsi/gl_context.h"
#include "wsi/libretro.h"
#endif
#ifdef HAVE_VULKAN
#include "rend/vulkan/vulkan_context.h"
@@ -1369,7 +1369,13 @@ static void context_reset()
glsm_ctl(GLSM_CTL_STATE_CONTEXT_RESET, NULL);
glsm_ctl(GLSM_CTL_STATE_SETUP, NULL);
rend_term_renderer();
theGLContext.init();
GraphicsContext::Term();
try {
GLGraphicsContext::Create(nullptr, nullptr);
} catch (const std::exception& e) {
ERROR_LOG(RENDERER, "%s", e.what());
return;
}
rend_init_renderer();
#ifdef HAVE_OIT
if (!perPixelChecked)
@@ -1382,6 +1388,7 @@ static void context_destroy()
gl_ctx_resetting = true;
rend_term_renderer();
glsm_ctl(GLSM_CTL_STATE_CONTEXT_DESTROY, NULL);
GraphicsContext::Term();
}
#endif
@@ -1946,8 +1953,6 @@ static void remove_extension(char *buf, const char *path, size_t size)
}
#ifdef HAVE_VULKAN
static VulkanContext theVulkanContext;
static void retro_vk_context_reset()
{
NOTICE_LOG(RENDERER, "retro_vk_context_reset");
@@ -1957,8 +1962,12 @@ static void retro_vk_context_reset()
ERROR_LOG(RENDERER, "Get Vulkan HW interface failed");
return;
}
if (!theVulkanContext.init((retro_hw_render_interface_vulkan *)vulkan))
try {
VulkanContext::Create((retro_hw_render_interface_vulkan *)vulkan);
} catch (const std::exception& e) {
ERROR_LOG(RENDERER, "%s", e.what());
return;
}
rend_term_renderer();
rend_init_renderer();
if (!perPixelChecked)
@@ -1969,7 +1978,7 @@ static void retro_vk_context_destroy()
{
NOTICE_LOG(RENDERER, "retro_vk_context_destroy");
rend_term_renderer();
theVulkanContext.term();
GraphicsContext::Term();
}
static bool set_vulkan_hw_render()
@@ -2091,9 +2100,14 @@ static void dx11_context_reset()
return;
}
rend_term_renderer();
theDX11Context.term();
GraphicsContext::Term();
theDX11Context.init(hw_render->device, hw_render->context, hw_render->D3DCompile, hw_render->featureLevel);
try {
DX11Context::Create(hw_render->device, hw_render->context, hw_render->D3DCompile, hw_render->featureLevel);
} catch (const std::exception& e) {
ERROR_LOG(RENDERER, "%s", e.what());
return;
}
if (config::RendererType == RenderType::OpenGL_OIT || config::RendererType == RenderType::Vulkan_OIT)
config::RendererType = RenderType::DirectX11_OIT;
else if (config::RendererType != RenderType::DirectX11_OIT)
@@ -2107,7 +2121,7 @@ static void dx11_context_destroy()
{
NOTICE_LOG(RENDERER, "DX11 context destroyed");
rend_term_renderer();
theDX11Context.term();
GraphicsContext::Term();
}
#endif