mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-24 15:36:33 +00:00
Support EGL_ANGLE_surface_orientation flipped backbuffers
This commit is contained in:
@@ -51,6 +51,7 @@ typedef EGLSurface (*PFN_eglGetCurrentSurface)(EGLint readdraw);
|
||||
typedef EGLint (*PFN_eglGetError)(void);
|
||||
typedef EGLBoolean (*PFN_eglGetConfigAttrib)(EGLDisplay dpy, EGLConfig config, EGLint attribute,
|
||||
EGLint *value);
|
||||
typedef const char *(*PFN_eglQueryString)(EGLDisplay dpy, EGLint name);
|
||||
typedef PFNEGLPOSTSUBBUFFERNVPROC PFN_eglPostSubBufferNV;
|
||||
|
||||
#define EGL_HOOKED_SYMBOLS(FUNC) \
|
||||
@@ -74,6 +75,7 @@ typedef PFNEGLPOSTSUBBUFFERNVPROC PFN_eglPostSubBufferNV;
|
||||
FUNC(GetCurrentSurface, false); \
|
||||
FUNC(GetError, false); \
|
||||
FUNC(Initialize, false); \
|
||||
FUNC(QueryString, false); \
|
||||
FUNC(QuerySurface, false);
|
||||
|
||||
struct EGLDispatchTable
|
||||
|
||||
@@ -53,6 +53,24 @@ public:
|
||||
std::set<EGLContext> contexts;
|
||||
std::map<EGLContext, EGLConfig> configs;
|
||||
std::map<EGLSurface, EGLNativeWindowType> windows;
|
||||
|
||||
bool IsYFlipped(EGLDisplay dpy, EGLSurface surface)
|
||||
{
|
||||
if(strstr(EGL.QueryString(dpy, EGL_EXTENSIONS), "ANGLE_surface_orientation"))
|
||||
{
|
||||
// https://github.com/google/angle/blob/master/extensions/EGL_ANGLE_surface_orientation.txt
|
||||
#define EGL_SURFACE_ORIENTATION_ANGLE 0x33A8
|
||||
#define EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE 0x0002
|
||||
|
||||
int mask = 0;
|
||||
EGL.QuerySurface(dpy, surface, EGL_SURFACE_ORIENTATION_ANGLE, &mask);
|
||||
|
||||
return (mask & EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE) != 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} eglhook;
|
||||
|
||||
HOOK_EXPORT EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display)
|
||||
@@ -302,6 +320,8 @@ HOOK_EXPORT EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface sur
|
||||
// GL_SRGB8_ALPHA8 is specified as color-renderable, unlike GL_SRGB8.
|
||||
init.isSRGB = init.colorBits == 32 && colorspace == EGL_GL_COLORSPACE_SRGB;
|
||||
|
||||
init.isYFlipped = eglhook.IsYFlipped(dpy, surface);
|
||||
|
||||
eglhook.driver.SetDriverType(RDCDriver::OpenGLES);
|
||||
eglhook.driver.WindowSize(surface, width, height);
|
||||
if(!eglhook.driver.UsesVRFrameMarkers())
|
||||
@@ -333,10 +353,12 @@ HOOK_EXPORT EGLBoolean EGLAPIENTRY eglPostSubBufferNV(EGLDisplay dpy, EGLSurface
|
||||
// GL_SRGB8_ALPHA8 is specified as color-renderable, unlike GL_SRGB8.
|
||||
init.isSRGB = init.colorBits == 32 && colorspace == EGL_GL_COLORSPACE_SRGB;
|
||||
|
||||
init.isYFlipped = eglhook.IsYFlipped(dpy, surface);
|
||||
|
||||
eglhook.driver.SetDriverType(RDCDriver::OpenGLES);
|
||||
eglhook.driver.WindowSize(surface, winwidth, winheight);
|
||||
eglhook.driver.WindowSize(eglhook.windows[surface], winwidth, winheight);
|
||||
if(!eglhook.driver.UsesVRFrameMarkers())
|
||||
eglhook.driver.SwapBuffers(surface);
|
||||
eglhook.driver.SwapBuffers(eglhook.windows[surface]);
|
||||
|
||||
return EGL.PostSubBufferNV(dpy, surface, x, y, width, height);
|
||||
}
|
||||
|
||||
@@ -1103,6 +1103,7 @@ GLInitParams::GLInitParams()
|
||||
multiSamples = 1;
|
||||
width = 32;
|
||||
height = 32;
|
||||
isYFlipped = false;
|
||||
}
|
||||
|
||||
bool GLInitParams::IsSupportedVersion(uint64_t ver)
|
||||
@@ -1120,6 +1121,10 @@ bool GLInitParams::IsSupportedVersion(uint64_t ver)
|
||||
if(ver == 0x1B)
|
||||
return true;
|
||||
|
||||
// 0x1C -> 0x1D - added isYFlipped init parameter for backbuffers on ANGLE.
|
||||
if(ver == 0x1C)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1133,6 +1138,8 @@ void DoSerialise(SerialiserType &ser, GLInitParams &el)
|
||||
SERIALISE_MEMBER(multiSamples);
|
||||
SERIALISE_MEMBER(width);
|
||||
SERIALISE_MEMBER(height);
|
||||
if(ser.VersionAtLeast(0x1D))
|
||||
SERIALISE_MEMBER(isYFlipped);
|
||||
}
|
||||
|
||||
INSTANTIATE_SERIALISE_TYPE(GLInitParams);
|
||||
|
||||
@@ -1636,7 +1636,7 @@ void WrappedOpenGL::SwapBuffers(void *windowHandle)
|
||||
}
|
||||
|
||||
if(!overlayText.empty())
|
||||
RenderOverlayText(0.0f, 0.0f, overlayText.c_str());
|
||||
RenderOverlayText(0.0f, 0.0f, m_InitParams.isYFlipped, overlayText.c_str());
|
||||
|
||||
// swallow all errors we might have inadvertantly caused. This is
|
||||
// better than letting an error propagate and maybe screw up the
|
||||
@@ -1939,7 +1939,8 @@ bool WrappedOpenGL::EndFrameCapture(void *dev, void *wnd)
|
||||
{
|
||||
ContextData &ctxdata = GetCtxData();
|
||||
|
||||
RenderOverlayText(0.0f, 0.0f, "Failed to capture frame %u: %s", m_FrameCounter, reasonString);
|
||||
RenderOverlayText(0.0f, 0.0f, m_InitParams.isYFlipped, "Failed to capture frame %u: %s",
|
||||
m_FrameCounter, reasonString);
|
||||
|
||||
// swallow all errors we might have inadvertantly caused. This is
|
||||
// better than letting an error propagate and maybe screw up the
|
||||
@@ -2059,24 +2060,27 @@ WrappedOpenGL::BackbufferImage *WrappedOpenGL::SaveBackbufferImage()
|
||||
}
|
||||
|
||||
// flip the image in-place
|
||||
for(uint16_t y = 0; y <= thheight / 2; y++)
|
||||
if(!m_InitParams.isYFlipped)
|
||||
{
|
||||
uint16_t flipY = (thheight - 1 - y);
|
||||
|
||||
for(uint16_t x = 0; x < thwidth; x++)
|
||||
for(uint16_t y = 0; y <= thheight / 2; y++)
|
||||
{
|
||||
byte save[3];
|
||||
save[0] = thpixels[(y * thwidth + x) * 3 + 0];
|
||||
save[1] = thpixels[(y * thwidth + x) * 3 + 1];
|
||||
save[2] = thpixels[(y * thwidth + x) * 3 + 2];
|
||||
uint16_t flipY = (thheight - 1 - y);
|
||||
|
||||
thpixels[(y * thwidth + x) * 3 + 0] = thpixels[(flipY * thwidth + x) * 3 + 0];
|
||||
thpixels[(y * thwidth + x) * 3 + 1] = thpixels[(flipY * thwidth + x) * 3 + 1];
|
||||
thpixels[(y * thwidth + x) * 3 + 2] = thpixels[(flipY * thwidth + x) * 3 + 2];
|
||||
for(uint16_t x = 0; x < thwidth; x++)
|
||||
{
|
||||
byte save[3];
|
||||
save[0] = thpixels[(y * thwidth + x) * 3 + 0];
|
||||
save[1] = thpixels[(y * thwidth + x) * 3 + 1];
|
||||
save[2] = thpixels[(y * thwidth + x) * 3 + 2];
|
||||
|
||||
thpixels[(flipY * thwidth + x) * 3 + 0] = save[0];
|
||||
thpixels[(flipY * thwidth + x) * 3 + 1] = save[1];
|
||||
thpixels[(flipY * thwidth + x) * 3 + 2] = save[2];
|
||||
thpixels[(y * thwidth + x) * 3 + 0] = thpixels[(flipY * thwidth + x) * 3 + 0];
|
||||
thpixels[(y * thwidth + x) * 3 + 1] = thpixels[(flipY * thwidth + x) * 3 + 1];
|
||||
thpixels[(y * thwidth + x) * 3 + 2] = thpixels[(flipY * thwidth + x) * 3 + 2];
|
||||
|
||||
thpixels[(flipY * thwidth + x) * 3 + 0] = save[0];
|
||||
thpixels[(flipY * thwidth + x) * 3 + 1] = save[1];
|
||||
thpixels[(flipY * thwidth + x) * 3 + 2] = save[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,9 +51,10 @@ struct GLInitParams
|
||||
uint32_t multiSamples;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
bool isYFlipped;
|
||||
|
||||
// check if a frame capture section version is supported
|
||||
static const uint64_t CurrentVersion = 0x1C;
|
||||
static const uint64_t CurrentVersion = 0x1D;
|
||||
static bool IsSupportedVersion(uint64_t ver);
|
||||
};
|
||||
|
||||
@@ -440,8 +441,8 @@ private:
|
||||
static const int FONT_TEX_HEIGHT = 128;
|
||||
static const int FONT_MAX_CHARS = 256;
|
||||
|
||||
void RenderOverlayText(float x, float y, const char *fmt, ...);
|
||||
void RenderOverlayStr(float x, float y, const char *str);
|
||||
void RenderOverlayText(float x, float y, bool yflipped, const char *fmt, ...);
|
||||
void RenderOverlayStr(float x, float y, bool yflipped, const char *str);
|
||||
|
||||
struct BackbufferImage
|
||||
{
|
||||
|
||||
@@ -257,7 +257,7 @@ void WrappedOpenGL::ContextData::CreateDebugData()
|
||||
}
|
||||
}
|
||||
|
||||
void WrappedOpenGL::RenderOverlayText(float x, float y, const char *fmt, ...)
|
||||
void WrappedOpenGL::RenderOverlayText(float x, float y, bool yflipped, const char *fmt, ...)
|
||||
{
|
||||
static char tmpBuf[4096];
|
||||
|
||||
@@ -273,18 +273,18 @@ void WrappedOpenGL::RenderOverlayText(float x, float y, const char *fmt, ...)
|
||||
|
||||
textState.Push(ctxdata.Modern());
|
||||
|
||||
RenderOverlayStr(x, y, tmpBuf);
|
||||
RenderOverlayStr(x, y, yflipped, tmpBuf);
|
||||
|
||||
textState.Pop(ctxdata.Modern());
|
||||
}
|
||||
|
||||
void WrappedOpenGL::RenderOverlayStr(float x, float y, const char *text)
|
||||
void WrappedOpenGL::RenderOverlayStr(float x, float y, bool yflipped, const char *text)
|
||||
{
|
||||
if(char *t = strchr((char *)text, '\n'))
|
||||
{
|
||||
*t = 0;
|
||||
RenderOverlayStr(x, y, text);
|
||||
RenderOverlayStr(x, y + 1.0f, t + 1);
|
||||
RenderOverlayStr(x, y, yflipped, text);
|
||||
RenderOverlayStr(x, y + 1.0f, yflipped, t + 1);
|
||||
*t = '\n';
|
||||
return;
|
||||
}
|
||||
@@ -347,7 +347,7 @@ void WrappedOpenGL::RenderOverlayStr(float x, float y, const char *text)
|
||||
pos.y -= 1.0f;
|
||||
|
||||
vertexData[(i * 6 + ch) * 5 + 0] = pos.x;
|
||||
vertexData[(i * 6 + ch) * 5 + 1] = -pos.y;
|
||||
vertexData[(i * 6 + ch) * 5 + 1] = yflipped ? pos.y : -pos.y;
|
||||
vertexData[(i * 6 + ch) * 5 + 2] = uv.x;
|
||||
vertexData[(i * 6 + ch) * 5 + 3] = uv.y;
|
||||
vertexData[(i * 6 + ch) * 5 + 4] = float(text[i] - FONT_FIRST_CHAR);
|
||||
@@ -529,6 +529,8 @@ void WrappedOpenGL::RenderOverlayStr(float x, float y, const char *text)
|
||||
vertices.push_back(Vec4f(maxx, miny, 0.0f, 0.0f));
|
||||
vertices.push_back(Vec4f(minx, miny, 0.0f, 0.0f));
|
||||
|
||||
float mul = yflipped ? -1.0f : 1.0f;
|
||||
|
||||
while(*text)
|
||||
{
|
||||
char c = *text;
|
||||
@@ -537,10 +539,10 @@ void WrappedOpenGL::RenderOverlayStr(float x, float y, const char *text)
|
||||
stbtt_GetBakedQuad(chardata, FONT_TEX_WIDTH, FONT_TEX_HEIGHT, c - FONT_FIRST_CHAR, &x, &y,
|
||||
&q, 1);
|
||||
|
||||
vertices.push_back(Vec4f(q.x0, q.y0, q.s0, q.t0));
|
||||
vertices.push_back(Vec4f(q.x1, q.y0, q.s1, q.t0));
|
||||
vertices.push_back(Vec4f(q.x1, q.y1, q.s1, q.t1));
|
||||
vertices.push_back(Vec4f(q.x0, q.y1, q.s0, q.t1));
|
||||
vertices.push_back(Vec4f(q.x0, q.y0 * mul, q.s0, q.t0));
|
||||
vertices.push_back(Vec4f(q.x1, q.y0 * mul, q.s1, q.t0));
|
||||
vertices.push_back(Vec4f(q.x1, q.y1 * mul, q.s1, q.t1));
|
||||
vertices.push_back(Vec4f(q.x0, q.y1 * mul, q.s0, q.t1));
|
||||
|
||||
maxx = RDCMAX(maxx, RDCMAX(q.x0, q.x1));
|
||||
maxy = RDCMAX(maxy, RDCMAX(q.y0, q.y1));
|
||||
|
||||
@@ -3222,6 +3222,8 @@ ReplayStatus CreateReplayDevice(RDCFile *rdc, GLPlatform &platform, IReplayDrive
|
||||
|
||||
ReadSerialiser ser(reader, Ownership::Stream);
|
||||
|
||||
ser.SetVersion(ver);
|
||||
|
||||
SystemChunk chunk = ser.ReadChunk<SystemChunk>();
|
||||
|
||||
if(chunk != SystemChunk::DriverInit)
|
||||
|
||||
Reference in New Issue
Block a user