From 090cd031850dadc0a61c97315bd7383a3f42e7c3 Mon Sep 17 00:00:00 2001 From: Alexandros Frantzis Date: Thu, 10 Oct 2019 16:03:13 +0300 Subject: [PATCH] Introduce GLPlatform::CanCreateGLContext() Introduce a method to check if a platform supports desktop GL. Most platforms support desktop GL by default, so for them the implementation of this method is trivial. For EGL, though, we have to implement a proper check, since EGL support for non GLES APIs is optional. --- renderdoc/driver/gl/cgl_platform.cpp | 1 + renderdoc/driver/gl/egl_dispatch_table.h | 2 ++ renderdoc/driver/gl/egl_platform.cpp | 24 ++++++++++++++++++++++++ renderdoc/driver/gl/gl_common.h | 2 ++ renderdoc/driver/gl/gl_replay.cpp | 6 ++++++ renderdoc/driver/gl/glx_platform.cpp | 7 +++++++ renderdoc/driver/gl/wgl_platform.cpp | 1 + 7 files changed, 43 insertions(+) diff --git a/renderdoc/driver/gl/cgl_platform.cpp b/renderdoc/driver/gl/cgl_platform.cpp index dd528fe31..7fe8174e5 100644 --- a/renderdoc/driver/gl/cgl_platform.cpp +++ b/renderdoc/driver/gl/cgl_platform.cpp @@ -182,6 +182,7 @@ class CGLPlatform : public GLPlatform return NULL; } + bool CanCreateGLContext() { return true; } bool CanCreateGLESContext() { return false; } bool PopulateForReplay() { return CGL.PopulateForReplay(); } GLWindowingData MakeOutputWindow(WindowingData window, bool depth, GLWindowingData share_context) diff --git a/renderdoc/driver/gl/egl_dispatch_table.h b/renderdoc/driver/gl/egl_dispatch_table.h index 357024325..189c6f752 100644 --- a/renderdoc/driver/gl/egl_dispatch_table.h +++ b/renderdoc/driver/gl/egl_dispatch_table.h @@ -27,6 +27,7 @@ #include "gl_common.h" typedef EGLBoolean(EGLAPIENTRY *PFN_eglBindAPI)(EGLenum api); +typedef EGLenum(EGLAPIENTRY *PFN_eglQueryAPI)(); typedef EGLDisplay(EGLAPIENTRY *PFN_eglGetDisplay)(EGLNativeDisplayType display_id); typedef EGLDisplay(EGLAPIENTRY *PFN_eglGetPlatformDisplay)(EGLenum platform, void *native_display, const EGLAttrib *attrib_list); @@ -90,6 +91,7 @@ typedef PFNEGLSWAPBUFFERSWITHDAMAGEKHRPROC PFN_eglSwapBuffersWithDamageKHR; FUNC(GetCurrentSurface, false, true); \ FUNC(GetError, false, true); \ FUNC(Initialize, false, true); \ + FUNC(QueryAPI, false, true); \ FUNC(QueryString, false, true); \ FUNC(QuerySurface, false, true); diff --git a/renderdoc/driver/gl/egl_platform.cpp b/renderdoc/driver/gl/egl_platform.cpp index 5c5b05de6..75291050e 100644 --- a/renderdoc/driver/gl/egl_platform.cpp +++ b/renderdoc/driver/gl/egl_platform.cpp @@ -326,6 +326,30 @@ class EGLPlatform : public GLPlatform return ret; } + bool CanCreateGLContext() + { +#if ENABLED(RDOC_ANDROID) + // we don't trust the EGL API query to work reliably on Android, so treat + // it as special case + return false; +#else + bool success = EGL.PopulateForReplay(); + + // if we can't populate our functions we bail now. + if(!success) + return false; + + EGLenum previousAPI = EGL.QueryAPI(); + EGLBoolean supportsGL = EGL.BindAPI(EGL_OPENGL_API); + + // restore previous API + if(previousAPI != EGL_NONE) + EGL.BindAPI(previousAPI); + + return supportsGL == EGL_TRUE; +#endif + } + bool CanCreateGLESContext() { // as long as we can get libEGL we're fine diff --git a/renderdoc/driver/gl/gl_common.h b/renderdoc/driver/gl/gl_common.h index 2c31fbd36..37e4d14a0 100644 --- a/renderdoc/driver/gl/gl_common.h +++ b/renderdoc/driver/gl/gl_common.h @@ -280,6 +280,7 @@ struct GLPlatform virtual void DrawQuads(float width, float height, const std::vector &vertices) = 0; // for initialisation at replay time + virtual bool CanCreateGLContext() = 0; virtual bool CanCreateGLESContext() = 0; virtual bool PopulateForReplay() = 0; virtual ReplayStatus InitialiseAPI(GLWindowingData &replayContext, RDCDriver api, bool debug) = 0; @@ -304,6 +305,7 @@ class GLDummyPlatform : public GLPlatform virtual void DrawQuads(float width, float height, const std::vector &vertices) {} virtual void *GetReplayFunction(const char *funcname) { return NULL; } // for initialisation at replay time + virtual bool CanCreateGLContext() { return true; } virtual bool CanCreateGLESContext() { return true; } virtual bool PopulateForReplay() { return true; } virtual ReplayStatus InitialiseAPI(GLWindowingData &replayContext, RDCDriver api, bool debug) diff --git a/renderdoc/driver/gl/gl_replay.cpp b/renderdoc/driver/gl/gl_replay.cpp index 226d3e958..69997d5de 100644 --- a/renderdoc/driver/gl/gl_replay.cpp +++ b/renderdoc/driver/gl/gl_replay.cpp @@ -3607,6 +3607,12 @@ ReplayStatus GL_CreateReplayDevice(RDCFile *rdc, const ReplayOptions &opts, IRep #endif } + if(!gl_platform->CanCreateGLContext()) + { + RDCERR("Platform doesn't support GL contexts"); + return ReplayStatus::APIInitFailed; + } + RDCDEBUG("Creating an OpenGL replay device"); bool load_ok = gl_platform->PopulateForReplay(); diff --git a/renderdoc/driver/gl/glx_platform.cpp b/renderdoc/driver/gl/glx_platform.cpp index 2558fa656..430fa60d7 100644 --- a/renderdoc/driver/gl/glx_platform.cpp +++ b/renderdoc/driver/gl/glx_platform.cpp @@ -304,6 +304,13 @@ class GLXPlatform : public GLPlatform return ret; } + bool CanCreateGLContext() + { + Display *dpy = RenderDoc::Inst().GetGlobalEnvironment().xlibDisplay; + + return GetGLHandle() != NULL && dpy != NULL; + } + bool CanCreateGLESContext() { bool success = GLX.PopulateForReplay(); diff --git a/renderdoc/driver/gl/wgl_platform.cpp b/renderdoc/driver/gl/wgl_platform.cpp index c5e3f0e59..6bef0d9b3 100644 --- a/renderdoc/driver/gl/wgl_platform.cpp +++ b/renderdoc/driver/gl/wgl_platform.cpp @@ -245,6 +245,7 @@ class WGLPlatform : public GLPlatform return Process::GetFunctionAddress(Process::LoadModule("opengl32.dll"), funcname); } + bool CanCreateGLContext() { return true; } bool CanCreateGLESContext() { bool success = WGL.PopulateForReplay();