Refuse to capture on old contexts, warn on compat profiles. Closes #125

* If CreateContextAttribs is not used to create the context, the overlay
  will run in super-duper old mode using immediate mode calls and fixed
  function pipeline. This way it should display on (in theory) any GL
  app. Capturing will be prevented.
* Compatibility profile contexts are still allowed, but a warning is
  displayed in the overlay.
* If CreateContextAttribs is used to create a < 3.2 version context, we
  go down the same path as for legacy contexts, except with an accurate
  overlay message (just that the version isn't supported).
This commit is contained in:
baldurk
2015-04-08 21:42:40 +01:00
parent 6fa7d47097
commit 35fa1ce2bf
8 changed files with 716 additions and 241 deletions
+22
View File
@@ -341,5 +341,27 @@
</para>
</content>
</section>
<section address="FAQ11">
<title>RenderDoc is complaining about my OpenGL app in the overlay - what gives?</title>
<content>
<para>
The first thing to remember is that <legacyBold>RenderDoc only supports Core 3.2 and above OpenGL</legacyBold>.
If your app is using features from before 3.2 it almost certainly won't work as most functionality
is not supported. A couple of things like not creating a VAO (which are required in core profile) and
luminance textures (which don't exist in core profile) are allowed, but none of the fixed function
pipeline will work, etc etc.
</para>
<para>
If your app is not using the CreateContextAttribs API then RenderDoc will completely refuse to capture,
and will display overlay text to this effect using the simplest fixed-function pipeline code, so it will
run on any OpenGL app, even on a 1.4 context or similar.
</para>
<para>
If your app did use the CreateContextAttribs API, RenderDoc will allow you to capture, but compatibility
profiles will have a warning displayed in the overlay - this is because you could easily use old functionality
as it is all still available in the context.
</para>
</content>
</section>
</developerConceptualDocument>
</topic>
+2 -4
View File
@@ -3074,13 +3074,11 @@ HRESULT WrappedID3D11Device::Present(IDXGISwapChain *swap, UINT SyncInterval, UI
if(overlay & eOverlay_FrameNumber)
{
if(!overlayText.empty()) overlayText += " ";
overlayText += StringFormat::Fmt("Frame: %d.", m_FrameCounter);
overlayText += StringFormat::Fmt(" Frame: %d.", m_FrameCounter);
}
if(overlay & eOverlay_FrameRate)
{
if(!overlayText.empty()) overlayText += " ";
overlayText += StringFormat::Fmt("%.2lf ms (%.2lf .. %.2lf) (%.0lf FPS)",
overlayText += StringFormat::Fmt(" %.2lf ms (%.2lf .. %.2lf) (%.0lf FPS)",
m_AvgFrametime, m_MinFrametime, m_MaxFrametime, 1000.0f/m_AvgFrametime);
}
+7
View File
@@ -71,6 +71,13 @@ struct GLWindowingData
#define IMPLEMENT_FUNCTION_SERIALISED(ret, func) ret func; bool CONCAT(Serialise_, func);
// no longer in glcorearb.h or glext.h
const GLenum eGL_LUMINANCE = (GLenum)0x1909;
const GLenum eGL_LUMINANCE_ALPHA = (GLenum)0x190A;
const GLenum eGL_INTENSITY = (GLenum)0x8049;
const GLenum eGL_LIGHTING = (GLenum)0x0B50;
const GLenum eGL_ALPHA_TEST = (GLenum)0x0BC0;
class WrappedOpenGL;
struct GLHookSet;
+494 -226
View File
@@ -39,6 +39,13 @@
#include <algorithm>
const int firstChar = int(' ') + 1;
const int lastChar = 127;
const int numChars = lastChar-firstChar;
const float charPixelHeight = 20.0f;
stbtt_bakedchar chardata[numChars];
const char *GLChunkNames[] =
{
"WrappedOpenGL::Initialisation",
@@ -915,6 +922,11 @@ WrappedOpenGL::ContextData &WrappedOpenGL::GetCtxData()
// defined in gl_<platform>_hooks.cpp
void MakeContextCurrent(GLWindowingData data);
// for 'backwards compatible' overlay rendering
bool immediateBegin(GLenum mode, float width, float height);
void immediateVert(float x, float y, float u, float v);
void immediateEnd();
////////////////////////////////////////////////////////////////
// Windowing/setup/etc
////////////////////////////////////////////////////////////////
@@ -940,13 +952,14 @@ void WrappedOpenGL::DeleteContext(void *contextHandle)
m_ContextData.erase(contextHandle);
}
void WrappedOpenGL::CreateContext(GLWindowingData winData, void *shareContext, GLInitParams initParams, bool core)
void WrappedOpenGL::CreateContext(GLWindowingData winData, void *shareContext, GLInitParams initParams, bool core, bool attribsCreate)
{
// TODO: support multiple GL contexts more explicitly
m_InitParams = initParams;
ContextData &ctxdata = m_ContextData[winData.ctx];
ctxdata.isCore = core;
ctxdata.attribsCreate = attribsCreate;
}
void WrappedOpenGL::ActivateContext(GLWindowingData winData)
@@ -1051,6 +1064,8 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData)
int ver = mj*10 + mn;
ctxdata.version = ver;
if(ver > GLCoreVersion || (!GLIsCore && ctxdata.isCore))
{
GLCoreVersion = ver;
@@ -1059,37 +1074,20 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData)
}
}
if(gl.glGenTextures && gl.glTextureStorage2DEXT && gl.glTextureSubImage2DEXT &&
gl.glGenVertexArrays && gl.glBindVertexArray &&
gl.glGenBuffers && gl.glNamedBufferStorageEXT &&
gl.glCreateShader && gl.glShaderSource && gl.glCompileShader && gl.glGetShaderiv && gl.glGetShaderInfoLog && gl.glDeleteShader &&
gl.glCreateProgram && gl.glAttachShader && gl.glLinkProgram && gl.glGetProgramiv && gl.glGetProgramInfoLog)
// to let us display the overlay on old GL contexts, use as simple a subset of functionality as possible
// to upload the texture. VAO and shaders are used optionally on modern contexts, otherwise we fall back
// to immediate mode rendering by hand
if(gl.glGetIntegerv && gl.glGenTextures && gl.glBindTexture && gl.glTexImage2D && gl.glTexParameteri)
{
gl.glGenTextures(1, &ctxdata.GlyphTexture);
gl.glTextureStorage2DEXT(ctxdata.GlyphTexture, eGL_TEXTURE_2D, 1, eGL_R8, FONT_TEX_WIDTH, FONT_TEX_HEIGHT);
GLuint curvao = 0;
gl.glGetIntegerv(eGL_VERTEX_ARRAY_BINDING, (GLint *)&curvao);
gl.glGenVertexArrays(1, &ctxdata.DummyVAO);
gl.glBindVertexArray(ctxdata.DummyVAO);
string ttfstring = GetEmbeddedResource(sourcecodepro_ttf);
byte *ttfdata = (byte *)ttfstring.c_str();
const int firstChar = int(' ') + 1;
const int lastChar = 127;
const int numChars = lastChar-firstChar;
byte *buf = new byte[FONT_TEX_WIDTH * FONT_TEX_HEIGHT];
const float pixelHeight = 20.0f;
stbtt_BakeFontBitmap(ttfdata, 0, charPixelHeight, buf, FONT_TEX_WIDTH, FONT_TEX_HEIGHT, firstChar, numChars, chardata);
stbtt_bakedchar chardata[numChars];
int ret = stbtt_BakeFontBitmap(ttfdata, 0, pixelHeight, buf, FONT_TEX_WIDTH, FONT_TEX_HEIGHT, firstChar, numChars, chardata);
ctxdata.CharSize = pixelHeight;
ctxdata.CharAspect = chardata->xadvance / pixelHeight;
ctxdata.CharSize = charPixelHeight;
ctxdata.CharAspect = chardata->xadvance / charPixelHeight;
stbtt_fontinfo f = {0};
stbtt_InitFont(&f, ttfdata, 0);
@@ -1097,10 +1095,24 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData)
int ascent = 0;
stbtt_GetFontVMetrics(&f, &ascent, NULL, NULL);
float maxheight = float(ascent)*stbtt_ScaleForPixelHeight(&f, pixelHeight);
float maxheight = float(ascent)*stbtt_ScaleForPixelHeight(&f, charPixelHeight);
gl.glTextureSubImage2DEXT(ctxdata.GlyphTexture, eGL_TEXTURE_2D, 0, 0, 0, FONT_TEX_WIDTH, FONT_TEX_HEIGHT,
eGL_RED, eGL_UNSIGNED_BYTE, (void *)buf);
{
GLuint curtex = 0;
gl.glGetIntegerv(eGL_TEXTURE_BINDING_2D, (GLint *)&curtex);
GLenum texFmt = eGL_R8;
if(ctxdata.Legacy())
texFmt = eGL_LUMINANCE;
gl.glGenTextures(1, &ctxdata.GlyphTexture);
gl.glBindTexture(eGL_TEXTURE_2D, ctxdata.GlyphTexture);
gl.glTexImage2D(eGL_TEXTURE_2D, 0, texFmt, FONT_TEX_WIDTH, FONT_TEX_HEIGHT, 0, eGL_RED, eGL_UNSIGNED_BYTE, buf);
gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_MAG_FILTER, eGL_LINEAR);
gl.glTexParameteri(eGL_TEXTURE_2D, eGL_TEXTURE_MIN_FILTER, eGL_LINEAR);
gl.glBindTexture(eGL_TEXTURE_2D, curtex);
}
delete[] buf;
@@ -1113,72 +1125,97 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData)
float x = b->xoff;
float y = b->yoff + maxheight;
glyphData[(i+1)*2 + 0] = Vec4f(x/b->xadvance, y/pixelHeight, b->xadvance/float(b->x1 - b->x0), pixelHeight/float(b->y1 - b->y0));
glyphData[(i+1)*2 + 0] = Vec4f(x/b->xadvance, y/charPixelHeight, b->xadvance/float(b->x1 - b->x0), charPixelHeight/float(b->y1 - b->y0));
glyphData[(i+1)*2 + 1] = Vec4f(b->x0, b->y0, b->x1, b->y1);
}
gl.glGenBuffers(1, &ctxdata.GlyphUBO);
gl.glNamedBufferStorageEXT(ctxdata.GlyphUBO, sizeof(glyphData), glyphData, 0);
gl.glGenBuffers(1, &ctxdata.GeneralUBO);
gl.glNamedBufferStorageEXT(ctxdata.GeneralUBO, sizeof(FontUniforms), NULL, GL_MAP_WRITE_BIT);
gl.glGenBuffers(1, &ctxdata.StringUBO);
gl.glNamedBufferStorageEXT(ctxdata.StringUBO, sizeof(uint32_t)*4*FONT_MAX_CHARS, NULL, GL_MAP_WRITE_BIT);
string textvs = "#version 420 core\n\n";
textvs += GetEmbeddedResource(debuguniforms_h);
textvs += GetEmbeddedResource(text_vert);
string textfs = GetEmbeddedResource(text_frag);
GLuint vs = gl.glCreateShader(eGL_VERTEX_SHADER);
GLuint fs = gl.glCreateShader(eGL_FRAGMENT_SHADER);
const char *src = textvs.c_str();
gl.glShaderSource(vs, 1, &src, NULL);
src = textfs.c_str();
gl.glShaderSource(fs, 1, &src, NULL);
gl.glCompileShader(vs);
gl.glCompileShader(fs);
char buffer[1024] = {0};
GLint status = 0;
gl.glGetShaderiv(vs, eGL_COMPILE_STATUS, &status);
if(status == 0)
if(ctxdata.Modern() && gl.glGenVertexArrays && gl.glBindVertexArray)
{
gl.glGetShaderInfoLog(vs, 1024, NULL, buffer);
RDCERR("Shader error: %s", buffer);
GLuint curvao = 0;
gl.glGetIntegerv(eGL_VERTEX_ARRAY_BINDING, (GLint *)&curvao);
gl.glGenVertexArrays(1, &ctxdata.DummyVAO);
gl.glBindVertexArray(ctxdata.DummyVAO);
gl.glBindVertexArray(curvao);
}
gl.glGetShaderiv(fs, eGL_COMPILE_STATUS, &status);
if(status == 0)
if(ctxdata.Modern() && gl.glGenBuffers && gl.glBufferData && gl.glBindBuffer)
{
gl.glGetShaderInfoLog(fs, 1024, NULL, buffer);
RDCERR("Shader error: %s", buffer);
GLuint curubo = 0;
gl.glGetIntegerv(eGL_UNIFORM_BUFFER_BINDING, (GLint *)&curubo);
gl.glGenBuffers(1, &ctxdata.GlyphUBO);
gl.glBindBuffer(eGL_UNIFORM_BUFFER, ctxdata.GlyphUBO);
gl.glBufferData(eGL_UNIFORM_BUFFER, sizeof(glyphData), glyphData, eGL_STATIC_DRAW);
gl.glGenBuffers(1, &ctxdata.GeneralUBO);
gl.glBindBuffer(eGL_UNIFORM_BUFFER, ctxdata.GeneralUBO);
gl.glBufferData(eGL_UNIFORM_BUFFER, sizeof(FontUniforms), NULL, eGL_DYNAMIC_DRAW);
gl.glGenBuffers(1, &ctxdata.StringUBO);
gl.glBindBuffer(eGL_UNIFORM_BUFFER, ctxdata.StringUBO);
gl.glBufferData(eGL_UNIFORM_BUFFER, sizeof(uint32_t)*4*FONT_MAX_CHARS, NULL, eGL_DYNAMIC_DRAW);
gl.glBindBuffer(eGL_UNIFORM_BUFFER, curubo);
}
ctxdata.Program = gl.glCreateProgram();
gl.glAttachShader(ctxdata.Program, vs);
gl.glAttachShader(ctxdata.Program, fs);
gl.glLinkProgram(ctxdata.Program);
gl.glGetProgramiv(ctxdata.Program, eGL_LINK_STATUS, &status);
if(status == 0)
if(ctxdata.Modern() &&
gl.glCreateShader && gl.glShaderSource && gl.glCompileShader && gl.glGetShaderiv && gl.glGetShaderInfoLog && gl.glDeleteShader &&
gl.glCreateProgram && gl.glAttachShader && gl.glLinkProgram && gl.glGetProgramiv && gl.glGetProgramInfoLog)
{
gl.glGetProgramInfoLog(ctxdata.Program, 1024, NULL, buffer);
RDCERR("Link error: %s", buffer);
}
string textvs = "#version 420 core\n\n";
textvs += GetEmbeddedResource(debuguniforms_h);
textvs += GetEmbeddedResource(text_vert);
string textfs = GetEmbeddedResource(text_frag);
gl.glDeleteShader(vs);
gl.glDeleteShader(fs);
GLuint vs = gl.glCreateShader(eGL_VERTEX_SHADER);
GLuint fs = gl.glCreateShader(eGL_FRAGMENT_SHADER);
const char *src = textvs.c_str();
gl.glShaderSource(vs, 1, &src, NULL);
src = textfs.c_str();
gl.glShaderSource(fs, 1, &src, NULL);
gl.glCompileShader(vs);
gl.glCompileShader(fs);
char buffer[1024] = {0};
GLint status = 0;
gl.glGetShaderiv(vs, eGL_COMPILE_STATUS, &status);
if(status == 0)
{
gl.glGetShaderInfoLog(vs, 1024, NULL, buffer);
RDCERR("Shader error: %s", buffer);
}
gl.glGetShaderiv(fs, eGL_COMPILE_STATUS, &status);
if(status == 0)
{
gl.glGetShaderInfoLog(fs, 1024, NULL, buffer);
RDCERR("Shader error: %s", buffer);
}
ctxdata.Program = gl.glCreateProgram();
gl.glAttachShader(ctxdata.Program, vs);
gl.glAttachShader(ctxdata.Program, fs);
gl.glLinkProgram(ctxdata.Program);
gl.glGetProgramiv(ctxdata.Program, eGL_LINK_STATUS, &status);
if(status == 0)
{
gl.glGetProgramInfoLog(ctxdata.Program, 1024, NULL, buffer);
RDCERR("Link error: %s", buffer);
}
gl.glDeleteShader(vs);
gl.glDeleteShader(fs);
}
ctxdata.ready = true;
gl.glBindVertexArray(curvao);
}
}
}
@@ -1202,23 +1239,46 @@ struct RenderTextState
GLenum SourceRGB, SourceAlpha;
GLenum DestinationRGB, DestinationAlpha;
GLenum PolygonMode;
GLfloat Viewport[4];
GLfloat Viewportf[4];
GLint Viewport[4];
GLenum ActiveTexture;
GLuint tex0;
GLuint ubo[3];
GLuint prog;
GLuint pipe;
GLuint VAO;
void Push(const GLHookSet &gl)
// if this context wasn't created with CreateContextAttribs we
// do an immediate mode render, so fewer states are pushed/popped.
// note we don't assume a 1.0 context since that would be painful to
// handle. Instead we just skip bits of state we're not going to mess
// with. In some cases this might cause problems e.g. we don't use
// indexed enable states for blend and scissor test because we're
// assuming there's no separate blending.
//
// In the end, this is just a best-effort to keep going without
// crashing. Old GL versions aren't supported.
void Push(const GLHookSet &gl, bool modern)
{
enableBits[0] = gl.glIsEnabledi(eGL_BLEND, 0) != 0;
enableBits[1] = gl.glIsEnabled(eGL_DEPTH_TEST) != 0;
enableBits[2] = gl.glIsEnabled(eGL_DEPTH_CLAMP) != 0;
enableBits[3] = gl.glIsEnabled(eGL_STENCIL_TEST) != 0;
enableBits[4] = gl.glIsEnabled(eGL_CULL_FACE) != 0;
enableBits[5] = gl.glIsEnabledi(eGL_SCISSOR_TEST, 0) != 0;
if(GLCoreVersion >= 45 || ExtensionSupported[ExtensionSupported_ARB_clip_control])
enableBits[0] = gl.glIsEnabled(eGL_DEPTH_TEST) != 0;
enableBits[1] = gl.glIsEnabled(eGL_STENCIL_TEST) != 0;
enableBits[2] = gl.glIsEnabled(eGL_CULL_FACE) != 0;
if(modern)
{
enableBits[3] = gl.glIsEnabled(eGL_DEPTH_CLAMP) != 0;
enableBits[4] = gl.glIsEnabledi(eGL_BLEND, 0) != 0;
enableBits[5] = gl.glIsEnabledi(eGL_SCISSOR_TEST, 0) != 0;
}
else
{
enableBits[3] = gl.glIsEnabled(eGL_BLEND) != 0;
enableBits[4] = gl.glIsEnabled(eGL_SCISSOR_TEST) != 0;
enableBits[5] = gl.glIsEnabled(eGL_TEXTURE_2D) != 0;
enableBits[6] = gl.glIsEnabled(eGL_LIGHTING) != 0;
enableBits[7] = gl.glIsEnabled(eGL_ALPHA_TEST) != 0;
}
if(modern && (GLCoreVersion >= 45 || ExtensionSupported[ExtensionSupported_ARB_clip_control]))
{
gl.glGetIntegerv(eGL_CLIP_ORIGIN, (GLint *)&ClipOrigin);
gl.glGetIntegerv(eGL_CLIP_DEPTH_MODE, (GLint *)&ClipDepth);
@@ -1229,15 +1289,29 @@ struct RenderTextState
ClipDepth = eGL_NEGATIVE_ONE_TO_ONE;
}
gl.glGetIntegeri_v(eGL_BLEND_EQUATION_RGB, 0, (GLint*)&EquationRGB);
gl.glGetIntegeri_v(eGL_BLEND_EQUATION_ALPHA, 0, (GLint*)&EquationAlpha);
if(modern)
{
gl.glGetIntegeri_v(eGL_BLEND_EQUATION_RGB, 0, (GLint*)&EquationRGB);
gl.glGetIntegeri_v(eGL_BLEND_EQUATION_ALPHA, 0, (GLint*)&EquationAlpha);
gl.glGetIntegeri_v(eGL_BLEND_SRC_RGB, 0, (GLint*)&SourceRGB);
gl.glGetIntegeri_v(eGL_BLEND_SRC_ALPHA, 0, (GLint*)&SourceAlpha);
gl.glGetIntegeri_v(eGL_BLEND_SRC_RGB, 0, (GLint*)&SourceRGB);
gl.glGetIntegeri_v(eGL_BLEND_SRC_ALPHA, 0, (GLint*)&SourceAlpha);
gl.glGetIntegeri_v(eGL_BLEND_DST_RGB, 0, (GLint*)&DestinationRGB);
gl.glGetIntegeri_v(eGL_BLEND_DST_ALPHA, 0, (GLint*)&DestinationAlpha);
}
else
{
gl.glGetIntegerv(eGL_BLEND_EQUATION_RGB, (GLint*)&EquationRGB);
gl.glGetIntegerv(eGL_BLEND_EQUATION_ALPHA, (GLint*)&EquationAlpha);
gl.glGetIntegerv(eGL_BLEND_SRC_RGB, (GLint*)&SourceRGB);
gl.glGetIntegerv(eGL_BLEND_SRC_ALPHA, (GLint*)&SourceAlpha);
gl.glGetIntegerv(eGL_BLEND_DST_RGB, (GLint*)&DestinationRGB);
gl.glGetIntegerv(eGL_BLEND_DST_ALPHA, (GLint*)&DestinationAlpha);
}
gl.glGetIntegeri_v(eGL_BLEND_DST_RGB, 0, (GLint*)&DestinationRGB);
gl.glGetIntegeri_v(eGL_BLEND_DST_ALPHA, 0, (GLint*)&DestinationAlpha);
if(!VendorCheck[VendorCheck_AMD_polygon_mode_query])
{
GLenum dummy[2] = { eGL_FILL, eGL_FILL };
@@ -1250,52 +1324,99 @@ struct RenderTextState
{
PolygonMode = eGL_FILL;
}
gl.glGetFloati_v(eGL_VIEWPORT, 0, &Viewport[0]);
if(modern)
gl.glGetFloati_v(eGL_VIEWPORT, 0, &Viewportf[0]);
else
gl.glGetIntegerv(eGL_VIEWPORT, &Viewport[0]);
gl.glGetIntegerv(eGL_ACTIVE_TEXTURE, (GLint *)&ActiveTexture);
gl.glActiveTexture(eGL_TEXTURE0);
gl.glGetIntegerv(eGL_TEXTURE_BINDING_2D, (GLint*)&tex0);
gl.glGetIntegeri_v(eGL_UNIFORM_BUFFER_BINDING, 0, (GLint*)&ubo[0]);
gl.glGetIntegeri_v(eGL_UNIFORM_BUFFER_BINDING, 1, (GLint*)&ubo[1]);
gl.glGetIntegeri_v(eGL_UNIFORM_BUFFER_BINDING, 2, (GLint*)&ubo[2]);
// we get the current program but only try to restore it if it's non-0
prog = 0;
gl.glGetIntegerv(eGL_CURRENT_PROGRAM, (GLint *)&prog);
gl.glGetIntegerv(eGL_VERTEX_ARRAY_BINDING, (GLint *)&VAO);
// since we will use the fixed function pipeline, also need to check for
// program pipeline bindings (if we weren't, our program would override)
pipe = 0;
gl.glGetIntegerv(eGL_PROGRAM_PIPELINE_BINDING, (GLint *)&pipe);
if(modern)
{
gl.glGetIntegeri_v(eGL_UNIFORM_BUFFER_BINDING, 0, (GLint*)&ubo[0]);
gl.glGetIntegeri_v(eGL_UNIFORM_BUFFER_BINDING, 1, (GLint*)&ubo[1]);
gl.glGetIntegeri_v(eGL_UNIFORM_BUFFER_BINDING, 2, (GLint*)&ubo[2]);
gl.glGetIntegerv(eGL_VERTEX_ARRAY_BINDING, (GLint *)&VAO);
}
}
void Pop(const GLHookSet &gl)
void Pop(const GLHookSet &gl, bool modern)
{
if(enableBits[0]) gl.glEnablei(eGL_BLEND, 0); else gl.glDisablei(eGL_BLEND, 0);
if(enableBits[1]) gl.glEnable(eGL_DEPTH_TEST); else gl.glDisable(eGL_DEPTH_TEST);
if(enableBits[2]) gl.glEnable(eGL_DEPTH_CLAMP); else gl.glDisable(eGL_DEPTH_CLAMP);
if(enableBits[3]) gl.glEnable(eGL_STENCIL_TEST); else gl.glDisable(eGL_STENCIL_TEST);
if(enableBits[4]) gl.glEnable(eGL_CULL_FACE); else gl.glDisable(eGL_CULL_FACE);
if(enableBits[5]) gl.glEnablei(eGL_SCISSOR_TEST, 0); else gl.glDisablei(eGL_SCISSOR_TEST, 0);
if(enableBits[0]) gl.glEnable(eGL_DEPTH_TEST); else gl.glDisable(eGL_DEPTH_TEST);
if(enableBits[1]) gl.glEnable(eGL_STENCIL_TEST); else gl.glDisable(eGL_STENCIL_TEST);
if(enableBits[2]) gl.glEnable(eGL_CULL_FACE); else gl.glDisable(eGL_CULL_FACE);
if(gl.glClipControl && (GLCoreVersion >= 45 || ExtensionSupported[ExtensionSupported_ARB_clip_control])) // only available in 4.5+
if(modern)
{
if(enableBits[3]) gl.glEnable(eGL_DEPTH_CLAMP); else gl.glDisable(eGL_DEPTH_CLAMP);
if(enableBits[4]) gl.glEnablei(eGL_BLEND, 0); else gl.glDisablei(eGL_BLEND, 0);
if(enableBits[5]) gl.glEnablei(eGL_SCISSOR_TEST, 0); else gl.glDisablei(eGL_SCISSOR_TEST, 0);
}
else
{
if(enableBits[3]) gl.glEnable(eGL_BLEND); else gl.glDisable(eGL_BLEND);
if(enableBits[4]) gl.glEnable(eGL_SCISSOR_TEST); else gl.glDisable(eGL_SCISSOR_TEST);
if(enableBits[5]) gl.glEnable(eGL_TEXTURE_2D); else gl.glDisable(eGL_TEXTURE_2D);
if(enableBits[6]) gl.glEnable(eGL_LIGHTING); else gl.glDisable(eGL_LIGHTING);
if(enableBits[7]) gl.glEnable(eGL_ALPHA_TEST); else gl.glDisable(eGL_ALPHA_TEST);
}
if(modern && gl.glClipControl && (GLCoreVersion >= 45 || ExtensionSupported[ExtensionSupported_ARB_clip_control])) // only available in 4.5+
gl.glClipControl(ClipOrigin, ClipDepth);
gl.glBlendFuncSeparatei(0, SourceRGB, DestinationRGB, SourceAlpha, DestinationAlpha);
gl.glBlendEquationSeparatei(0, EquationRGB, EquationAlpha);
if(modern)
{
gl.glBlendFuncSeparatei(0, SourceRGB, DestinationRGB, SourceAlpha, DestinationAlpha);
gl.glBlendEquationSeparatei(0, EquationRGB, EquationAlpha);
}
else
{
gl.glBlendFuncSeparate(SourceRGB, DestinationRGB, SourceAlpha, DestinationAlpha);
gl.glBlendEquationSeparate(EquationRGB, EquationAlpha);
}
gl.glPolygonMode(eGL_FRONT_AND_BACK, PolygonMode);
gl.glViewportIndexedf(0, Viewport[0], Viewport[1], Viewport[2], Viewport[3]);
if(modern)
gl.glViewportIndexedf(0, Viewportf[0], Viewportf[1], Viewportf[2], Viewportf[3]);
else
gl.glViewport(Viewport[0], Viewport[1], (GLsizei)Viewport[2], (GLsizei)Viewport[3]);
gl.glActiveTexture(eGL_TEXTURE0);
gl.glBindTexture(eGL_TEXTURE_2D, tex0);
gl.glActiveTexture(ActiveTexture);
gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 0, ubo[0]);
gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 1, ubo[1]);
gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 2, ubo[2]);
gl.glUseProgram(prog);
gl.glBindVertexArray(VAO);
if(modern)
{
gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 0, ubo[0]);
gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 1, ubo[1]);
gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 2, ubo[2]);
gl.glUseProgram(prog);
gl.glBindVertexArray(VAO);
}
else
{
// only restore these if there was a setting and the function pointer exists
if(gl.glUseProgram && prog != 0)
gl.glUseProgram(prog);
if(gl.glBindProgramPipeline && pipe != 0)
gl.glBindProgramPipeline(pipe);
}
}
};
@@ -1334,106 +1455,220 @@ void WrappedOpenGL::RenderOverlayStr(float x, float y, const char *text)
if(!ctxdata.built || !ctxdata.ready) return;
gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 0, ctxdata.GeneralUBO);
FontUniforms *ubo = (FontUniforms *)gl.glMapBufferRange(eGL_UNIFORM_BUFFER, 0, sizeof(FontUniforms), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
ubo->TextPosition.x = x;
ubo->TextPosition.y = y;
ubo->FontScreenAspect.x = 1.0f/float(m_InitParams.width);
ubo->FontScreenAspect.y = 1.0f/float(m_InitParams.height);
ubo->TextSize = ctxdata.CharSize;
ubo->FontScreenAspect.x *= ctxdata.CharAspect;
ubo->CharacterSize.x = 1.0f/float(FONT_TEX_WIDTH);
ubo->CharacterSize.y = 1.0f/float(FONT_TEX_HEIGHT);
gl.glUnmapBuffer(eGL_UNIFORM_BUFFER);
size_t len = strlen(text);
if((int)len > FONT_MAX_CHARS)
// if it's reasonably modern context, assume we can use buffers and UBOs
if(ctxdata.Modern())
{
static bool printedWarning = false;
gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 0, ctxdata.GeneralUBO);
// this could be called once a frame, don't want to spam the log
if(!printedWarning)
FontUniforms *ubo = (FontUniforms *)gl.glMapBufferRange(eGL_UNIFORM_BUFFER, 0, sizeof(FontUniforms), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
ubo->TextPosition.x = x;
ubo->TextPosition.y = y;
ubo->FontScreenAspect.x = 1.0f/float(m_InitParams.width);
ubo->FontScreenAspect.y = 1.0f/float(m_InitParams.height);
ubo->TextSize = ctxdata.CharSize;
ubo->FontScreenAspect.x *= ctxdata.CharAspect;
ubo->CharacterSize.x = 1.0f/float(FONT_TEX_WIDTH);
ubo->CharacterSize.y = 1.0f/float(FONT_TEX_HEIGHT);
gl.glUnmapBuffer(eGL_UNIFORM_BUFFER);
size_t len = strlen(text);
if((int)len > FONT_MAX_CHARS)
{
printedWarning = true;
RDCWARN("log string '%s' is too long", text, (int)len);
static bool printedWarning = false;
// this could be called once a frame, don't want to spam the log
if(!printedWarning)
{
printedWarning = true;
RDCWARN("log string '%s' is too long", text, (int)len);
}
len = FONT_MAX_CHARS;
}
len = FONT_MAX_CHARS;
}
gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 0, ctxdata.StringUBO);
uint32_t *texs = (uint32_t *)gl.glMapBufferRange(eGL_UNIFORM_BUFFER, 0, len*4*sizeof(uint32_t), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 0, ctxdata.StringUBO);
uint32_t *texs = (uint32_t *)gl.glMapBufferRange(eGL_UNIFORM_BUFFER, 0, len*4*sizeof(uint32_t), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
if(texs)
{
for(size_t i=0; i < len; i++)
if(texs)
{
texs[i*4+0] = text[i] - ' ';
texs[i*4+1] = text[i] - ' ';
texs[i*4+2] = text[i] - ' ';
texs[i*4+3] = text[i] - ' ';
for(size_t i=0; i < len; i++)
{
texs[i*4+0] = text[i] - ' ';
texs[i*4+1] = text[i] - ' ';
texs[i*4+2] = text[i] - ' ';
texs[i*4+3] = text[i] - ' ';
}
}
else
{
static bool printedWarning = false;
// this could be called once a frame, don't want to spam the log
if(!printedWarning)
{
printedWarning = true;
RDCWARN("failed to map %d characters for '%s' (%d)", (int)len, text, ctxdata.StringUBO);
}
}
gl.glUnmapBuffer(eGL_UNIFORM_BUFFER);
//////////////////////////////////////////////////////////////////////////////////
// Make sure if you change any other state in here, that you also update the push
// and pop functions above (RenderTextState)
// set blend state
gl.glEnablei(eGL_BLEND, 0);
gl.glBlendFuncSeparatei(0, eGL_SRC_ALPHA, eGL_ONE_MINUS_SRC_ALPHA, eGL_SRC_ALPHA, eGL_SRC_ALPHA);
gl.glBlendEquationSeparatei(0, eGL_FUNC_ADD, eGL_FUNC_ADD);
// set depth & stencil
gl.glDisable(eGL_DEPTH_TEST);
gl.glDisable(eGL_DEPTH_CLAMP);
gl.glDisable(eGL_STENCIL_TEST);
gl.glDisable(eGL_CULL_FACE);
// set viewport & scissor
gl.glViewportIndexedf(0, 0.0f, 0.0f, (float)m_InitParams.width, (float)m_InitParams.height);
gl.glDisablei(eGL_SCISSOR_TEST, 0);
gl.glPolygonMode(eGL_FRONT_AND_BACK, eGL_FILL);
if(gl.glClipControl && (GLCoreVersion >= 45 || ExtensionSupported[ExtensionSupported_ARB_clip_control])) // only available in 4.5+
gl.glClipControl(eGL_LOWER_LEFT, eGL_NEGATIVE_ONE_TO_ONE);
// bind UBOs
gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 0, ctxdata.GeneralUBO);
gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 1, ctxdata.GlyphUBO);
gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 2, ctxdata.StringUBO);
// bind empty VAO just for valid rendering
gl.glBindVertexArray(ctxdata.DummyVAO);
// bind textures
gl.glActiveTexture(eGL_TEXTURE0);
gl.glBindTexture(eGL_TEXTURE_2D, ctxdata.GlyphTexture);
// bind program
gl.glUseProgram(ctxdata.Program);
// draw string
gl.glDrawArraysInstanced(eGL_TRIANGLE_STRIP, 0, 4, (GLsizei)len);
}
else
{
static bool printedWarning = false;
// if it wasn't created in modern fashion with createattribs, assume the worst
// and draw with immediate mode (since it's impossible that the context is core
// profile, this will always work)
//
// This isn't perfect since without a lot of fiddling we'd need to check if e.g.
// indexed blending should be used or not. Since we're not too worried about
// working in this situation, just doing something reasonable, we just assume
// roughly ~2.0 functionality
//////////////////////////////////////////////////////////////////////////////////
// Make sure if you change any other state in here, that you also update the push
// and pop functions above (RenderTextState)
// this could be called once a frame, don't want to spam the log
if(!printedWarning)
// disable blending and some old-style fixed function features
gl.glDisable(eGL_BLEND);
gl.glDisable(eGL_LIGHTING);
gl.glDisable(eGL_ALPHA_TEST);
// set depth & stencil
gl.glDisable(eGL_DEPTH_TEST);
gl.glDisable(eGL_STENCIL_TEST);
gl.glDisable(eGL_CULL_FACE);
// set viewport & scissor
gl.glViewport(0, 0, (GLsizei)m_InitParams.width, (GLsizei)m_InitParams.height);
gl.glDisable(eGL_SCISSOR_TEST);
gl.glPolygonMode(eGL_FRONT_AND_BACK, eGL_FILL);
// bind textures
gl.glActiveTexture(eGL_TEXTURE0);
gl.glBindTexture(eGL_TEXTURE_2D, ctxdata.GlyphTexture);
gl.glEnable(eGL_TEXTURE_2D);
// just in case, try to disable the programmable pipeline
if(gl.glUseProgram)
gl.glUseProgram(0);
if(gl.glBindProgramPipeline)
gl.glBindProgramPipeline(0);
// draw string (based on sample code from stb_truetype.h)
if(immediateBegin(eGL_QUADS, (float)m_InitParams.width, (float)m_InitParams.height))
{
printedWarning = true;
RDCWARN("failed to map %d characters for '%s' (%d)", (int)len, text, ctxdata.StringUBO);
y += 1.0f;
y *= charPixelHeight;
float startx = x;
float starty = y;
float maxx = x, minx = x;
float maxy = y, miny = y - charPixelHeight;
stbtt_aligned_quad q;
const char *prepass = text;
while (*prepass)
{
char c = *prepass;
if (c >= firstChar && c <= lastChar)
{
stbtt_GetBakedQuad(chardata, FONT_TEX_WIDTH, FONT_TEX_HEIGHT, c-firstChar, &x, &y, &q, 1);
maxx = RDCMAX(maxx, RDCMAX(q.x0, q.x1));
maxy = RDCMAX(maxy, RDCMAX(q.y0, q.y1));
minx = RDCMIN(minx, RDCMIN(q.x0, q.x1));
miny = RDCMIN(miny, RDCMIN(q.y0, q.y1));
}
else
{
x += chardata[0].xadvance;
}
prepass++;
}
x = startx;
y = starty;
// draw black bar behind text
immediateVert(minx, maxy, 0.0f, 0.0f);
immediateVert(maxx, maxy, 0.0f, 0.0f);
immediateVert(maxx, miny, 0.0f, 0.0f);
immediateVert(minx, miny, 0.0f, 0.0f);
while (*text)
{
char c = *text;
if (c >= firstChar && c <= lastChar)
{
stbtt_GetBakedQuad(chardata, FONT_TEX_WIDTH, FONT_TEX_HEIGHT, c-firstChar, &x, &y, &q, 1);
immediateVert(q.x0, q.y0, q.s0, q.t0);
immediateVert(q.x1, q.y0, q.s1, q.t0);
immediateVert(q.x1, q.y1, q.s1, q.t1);
immediateVert(q.x0, q.y1, q.s0, q.t1);
maxx = RDCMAX(maxx, RDCMAX(q.x0, q.x1));
maxy = RDCMAX(maxy, RDCMAX(q.y0, q.y1));
}
else
{
x += chardata[0].xadvance;
}
++text;
}
immediateEnd();
}
}
gl.glUnmapBuffer(eGL_UNIFORM_BUFFER);
//////////////////////////////////////////////////////////////////////////////////
// Make sure if you change any other state in here, that you also update the push
// and pop functions above (RenderTextState)
// set blend state
gl.glEnablei(eGL_BLEND, 0);
gl.glBlendFuncSeparatei(0, eGL_SRC_ALPHA, eGL_ONE_MINUS_SRC_ALPHA, eGL_SRC_ALPHA, eGL_SRC_ALPHA);
gl.glBlendEquationSeparatei(0, eGL_FUNC_ADD, eGL_FUNC_ADD);
// set depth & stencil
gl.glDisable(eGL_DEPTH_TEST);
gl.glDisable(eGL_DEPTH_CLAMP);
gl.glDisable(eGL_STENCIL_TEST);
gl.glDisable(eGL_CULL_FACE);
// set viewport & scissor
gl.glViewportIndexedf(0, 0.0f, 0.0f, (float)m_InitParams.width, (float)m_InitParams.height);
gl.glDisablei(eGL_SCISSOR_TEST, 0);
gl.glPolygonMode(eGL_FRONT_AND_BACK, eGL_FILL);
if(gl.glClipControl && (GLCoreVersion >= 45 || ExtensionSupported[ExtensionSupported_ARB_clip_control])) // only available in 4.5+
gl.glClipControl(eGL_LOWER_LEFT, eGL_NEGATIVE_ONE_TO_ONE);
// bind UBOs
gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 0, ctxdata.GeneralUBO);
gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 1, ctxdata.GlyphUBO);
gl.glBindBufferBase(eGL_UNIFORM_BUFFER, 2, ctxdata.StringUBO);
// bind empty VAO just for valid rendering
gl.glBindVertexArray(ctxdata.DummyVAO);
// bind textures
gl.glActiveTexture(eGL_TEXTURE0);
gl.glBindTexture(eGL_TEXTURE_2D, ctxdata.GlyphTexture);
// bind program
gl.glUseProgram(ctxdata.Program);
// draw string
gl.glDrawArraysInstanced(eGL_TRIANGLE_STRIP, 0, 4, (GLsizei)len);
}
struct ReplacementSearch
@@ -1714,35 +1949,41 @@ void WrappedOpenGL::Present(void *windowHandle)
{
RenderTextState textState;
textState.Push(m_Real);
ContextData &ctxdata = GetCtxData();
textState.Push(m_Real, ctxdata.Modern());
// TODO: handle selecting active window amongst many
{
vector<KeyButton> keys = RenderDoc::Inst().GetCaptureKeys();
string overlayText = "OpenGL. ";
string overlayText = "OpenGL.";
for(size_t i=0; i < keys.size(); i++)
if(ctxdata.Modern())
{
if(i > 0)
overlayText += ", ";
overlayText += " ";
overlayText += ToStr::Get(keys[i]);
for(size_t i=0; i < keys.size(); i++)
{
if(i > 0)
overlayText += ", ";
overlayText += ToStr::Get(keys[i]);
}
if(!keys.empty())
overlayText += " to capture.";
}
if(!keys.empty())
overlayText += " to capture.";
if(overlay & eOverlay_FrameNumber)
{
if(!overlayText.empty()) overlayText += " ";
overlayText += StringFormat::Fmt("Frame: %d.", m_FrameCounter);
overlayText += StringFormat::Fmt(" Frame: %d.", m_FrameCounter);
}
if(overlay & eOverlay_FrameRate)
{
if(!overlayText.empty()) overlayText += " ";
overlayText += StringFormat::Fmt("%.2lf ms (%.2lf .. %.2lf) (%.0lf FPS)",
m_AvgFrametime, m_MinFrametime, m_MaxFrametime, 1000.0f/m_AvgFrametime);
overlayText += StringFormat::Fmt(" %.2lf ms (%.2lf .. %.2lf) (%.0lf FPS)",
m_AvgFrametime, m_MinFrametime, m_MaxFrametime,
m_AvgFrametime <= 0.0f ? 0.0f : 1000.0f/m_AvgFrametime);
}
float y=0.0f;
@@ -1753,7 +1994,23 @@ void WrappedOpenGL::Present(void *windowHandle)
y += 1.0f;
}
if(overlay & eOverlay_CaptureList)
if(ctxdata.Legacy())
{
if(!ctxdata.attribsCreate)
{
RenderOverlayText(0.0f, y, "Context not created via CreateContextAttribs. Capturing disabled.");
y += 1.0f;
}
RenderOverlayText(0.0f, y, "Only OpenGL 3.2+ contexts are supported.");
y += 1.0f;
}
else if(!ctxdata.isCore)
{
RenderOverlayText(0.0f, y, "WARNING: Non-core context in use. Compatibility profile not supported.");
y += 1.0f;
}
if(ctxdata.Modern() && (overlay & eOverlay_CaptureList))
{
RenderOverlayText(0.0f, y, "%d Captures saved.\n", (uint32_t)m_FrameRecord.size());
y += 1.0f;
@@ -1775,7 +2032,17 @@ void WrappedOpenGL::Present(void *windowHandle)
#endif
}
textState.Pop(m_Real);
textState.Pop(m_Real, ctxdata.Modern());
// swallow all errors we might have inadvertantly caused. This is
// better than letting an error propagate and maybe screw up the
// app (although it means we might swallow an error from before the
// SwapBuffers call, it can't be helped.
if(ctxdata.Legacy() && m_Real.glGetError)
{
GLenum err = m_Real.glGetError();
while(err) err = m_Real.glGetError();
}
}
}
@@ -1936,7 +2203,8 @@ void WrappedOpenGL::Present(void *windowHandle)
}
}
if(RenderDoc::Inst().ShouldTriggerCapture(m_FrameCounter) && m_State == WRITING_IDLE && m_FrameRecord.empty())
// only allow capturing on 'modern' created contexts
if(GetCtxData().Modern() && RenderDoc::Inst().ShouldTriggerCapture(m_FrameCounter) && m_State == WRITING_IDLE && m_FrameRecord.empty())
{
m_State = WRITING_CAPFRAME;
+8 -1
View File
@@ -313,6 +313,8 @@ class WrappedOpenGL
ContextData()
{
built = ready = false;
attribsCreate = false;
version = 0;
isCore = false;
Program = GeneralUBO = StringUBO = GlyphUBO = 0;
GlyphTexture = DummyVAO = 0;
@@ -329,8 +331,13 @@ class WrappedOpenGL
bool built;
bool ready;
int version;
bool attribsCreate;
bool isCore;
bool Legacy() { return !attribsCreate || version < 32; }
bool Modern() { return !Legacy(); }
GLuint Program;
GLuint GeneralUBO, StringUBO, GlyphUBO;
GLuint GlyphTexture;
@@ -427,7 +434,7 @@ class WrappedOpenGL
const FetchDrawcall *GetDrawcall(uint32_t frameID, uint32_t eventID);
void CreateContext(GLWindowingData winData, void *shareContext, GLInitParams initParams, bool core);
void CreateContext(GLWindowingData winData, void *shareContext, GLInitParams initParams, bool core, bool attribsCreate);
void DeleteContext(void *contextHandle);
void ActivateContext(GLWindowingData winData);
void WindowSize(void *windowHandle, uint32_t w, uint32_t h);
-5
View File
@@ -36,11 +36,6 @@ GLenum GetBaseFormat(GLenum internalFormat);
GLenum GetDataType(GLenum internalFormat);
GLenum GetSizedFormat(const GLHookSet &gl, GLenum target, GLenum internalFormat);
// no longer in glcorearb.h or glext.h
const GLenum eGL_LUMINANCE = (GLenum)0x1909;
const GLenum eGL_LUMINANCE_ALPHA = (GLenum)0x190A;
const GLenum eGL_INTENSITY = (GLenum)0x8049;
void EmulateLuminanceFormat(const GLHookSet &gl, GLuint tex, GLenum target, GLenum &internalFormat, GLenum &dataFormat);
int GetNumMips(const GLHookSet &gl, GLenum target, GLuint tex, GLuint w, GLuint h, GLuint d);
+89 -2
View File
@@ -593,7 +593,7 @@ GLXContext glXCreateContext(Display *dpy, XVisualInfo *vis, GLXContext shareList
data.wnd = (GLXDrawable)NULL;
data.ctx = ret;
OpenGLHook::glhooks.GetDriver()->CreateContext(data, shareList, init, false);
OpenGLHook::glhooks.GetDriver()->CreateContext(data, shareList, init, false, false);
return ret;
}
@@ -691,7 +691,7 @@ GLXContext glXCreateContextAttribsARB(Display *dpy, GLXFBConfig config, GLXConte
data.wnd = (GLXDrawable)NULL;
data.ctx = ret;
OpenGLHook::glhooks.GetDriver()->CreateContext(data, shareList, init, core);
OpenGLHook::glhooks.GetDriver()->CreateContext(data, shareList, init, core, true);
return ret;
}
@@ -876,3 +876,90 @@ void DeleteContext(GLWindowingData context)
OpenGLHook::glhooks.DeleteContext(context);
}
// dirty immediate mode rendering functions for backwards compatible
// rendering of overlay text
typedef void (*GLGETINTEGERVPROC)(GLenum,GLint*);
typedef void (*GLPUSHMATRIXPROC)();
typedef void (*GLLOADIDENTITYPROC)();
typedef void (*GLMATRIXMODEPROC)(GLenum);
typedef void (*GLORTHOPROC)(GLdouble,GLdouble,GLdouble,GLdouble,GLdouble,GLdouble);
typedef void (*GLPOPMATRIXPROC)();
typedef void (*GLBEGINPROC)(GLenum);
typedef void (*GLVERTEX2FPROC)(float,float);
typedef void (*GLTEXCOORD2FPROC)(float,float);
typedef void (*GLENDPROC)();
static GLGETINTEGERVPROC getInt = NULL;
static GLPUSHMATRIXPROC pushm = NULL;
static GLLOADIDENTITYPROC loadident = NULL;
static GLMATRIXMODEPROC matMode = NULL;
static GLORTHOPROC ortho = NULL;
static GLPOPMATRIXPROC popm = NULL;
static GLBEGINPROC begin = NULL;
static GLVERTEX2FPROC v2f = NULL;
static GLTEXCOORD2FPROC t2f = NULL;
static GLENDPROC end = NULL;
const GLenum MAT_MODE = (GLenum)0x0BA0;
const GLenum MAT_MDVW = (GLenum)0x1700;
const GLenum MAT_PROJ = (GLenum)0x1701;
static bool immediateInited = false;
bool immediateBegin(GLenum mode, float width, float height)
{
if(!immediateInited)
{
getInt = (GLGETINTEGERVPROC)dlsym(RTLD_NEXT, "glGetIntegerv"); if(!getInt) return false;
pushm = (GLPUSHMATRIXPROC)dlsym(RTLD_NEXT, "glPushMatrix"); if(!pushm) return false;
loadident = (GLLOADIDENTITYPROC)dlsym(RTLD_NEXT, "glLoadIdentity"); if(!loadident) return false;
matMode = (GLMATRIXMODEPROC)dlsym(RTLD_NEXT, "glMatrixMode"); if(!matMode) return false;
ortho = (GLORTHOPROC)dlsym(RTLD_NEXT, "glOrtho"); if(!ortho) return false;
popm = (GLPOPMATRIXPROC)dlsym(RTLD_NEXT, "glPopMatrix"); if(!popm) return false;
begin = (GLBEGINPROC)dlsym(RTLD_NEXT, "glBegin"); if(!begin) return false;
v2f = (GLVERTEX2FPROC)dlsym(RTLD_NEXT, "glVertex2f"); if(!v2f) return false;
t2f = (GLTEXCOORD2FPROC)dlsym(RTLD_NEXT, "glTexCoord2f"); if(!t2f) return false;
end = (GLENDPROC)dlsym(RTLD_NEXT, "glEnd"); if(!end) return false;
immediateInited = true;
}
GLenum prevMatMode = eGL_NONE;
getInt(MAT_MODE, (GLint *)&prevMatMode);
matMode(MAT_PROJ);
pushm();
loadident();
ortho(0.0, width, height, 0.0, -1.0, 1.0);
matMode(MAT_MDVW);
pushm();
loadident();
matMode(prevMatMode);
begin(mode);
return true;
}
void immediateVert(float x, float y, float u, float v)
{
t2f(u,v); v2f(x,y);
}
void immediateEnd()
{
end();
GLenum prevMatMode = eGL_NONE;
getInt(MAT_MODE, (GLint *)&prevMatMode);
matMode(MAT_PROJ);
popm();
matMode(MAT_MDVW);
popm();
matMode(prevMatMode);
}
+94 -3
View File
@@ -379,7 +379,7 @@ class OpenGLHook : LibraryHook
data.wnd = WindowFromDC(dc);
data.ctx = ret;
glhooks.GetDriver()->CreateContext(data, NULL, GetInitParamsForDC(dc), false);
glhooks.GetDriver()->CreateContext(data, NULL, GetInitParamsForDC(dc), false, false);
return ret;
}
@@ -400,7 +400,7 @@ class OpenGLHook : LibraryHook
data.wnd = WindowFromDC(dc);
data.ctx = ret;
glhooks.GetDriver()->CreateContext(data, NULL, GetInitParamsForDC(dc), false);
glhooks.GetDriver()->CreateContext(data, NULL, GetInitParamsForDC(dc), false, false);
return ret;
}
@@ -468,7 +468,7 @@ class OpenGLHook : LibraryHook
data.wnd = WindowFromDC(dc);
data.ctx = ret;
glhooks.GetDriver()->CreateContext(data, hShareContext, GetInitParamsForDC(dc), core);
glhooks.GetDriver()->CreateContext(data, hShareContext, GetInitParamsForDC(dc), core, true);
return ret;
}
@@ -865,3 +865,94 @@ void DeleteContext(GLWindowingData context)
{
OpenGLHook::glhooks.DeleteContext(context);
}
// dirty immediate mode rendering functions for backwards compatible
// rendering of overlay text
typedef void (WINAPI *GLGETINTEGERVPROC)(GLenum,GLint*);
typedef void (WINAPI *GLPUSHMATRIXPROC)();
typedef void (WINAPI *GLLOADIDENTITYPROC)();
typedef void (WINAPI *GLMATRIXMODEPROC)(GLenum);
typedef void (WINAPI *GLORTHOPROC)(GLdouble,GLdouble,GLdouble,GLdouble,GLdouble,GLdouble);
typedef void (WINAPI *GLPOPMATRIXPROC)();
typedef void (WINAPI *GLBEGINPROC)(GLenum);
typedef void (WINAPI *GLVERTEX2FPROC)(float,float);
typedef void (WINAPI *GLTEXCOORD2FPROC)(float,float);
typedef void (WINAPI *GLENDPROC)();
static GLGETINTEGERVPROC getInt = NULL;
static GLPUSHMATRIXPROC pushm = NULL;
static GLLOADIDENTITYPROC loadident = NULL;
static GLMATRIXMODEPROC matMode = NULL;
static GLORTHOPROC ortho = NULL;
static GLPOPMATRIXPROC popm = NULL;
static GLBEGINPROC begin = NULL;
static GLVERTEX2FPROC v2f = NULL;
static GLTEXCOORD2FPROC t2f = NULL;
static GLENDPROC end = NULL;
const GLenum MAT_MODE = (GLenum)0x0BA0;
const GLenum MAT_MDVW = (GLenum)0x1700;
const GLenum MAT_PROJ = (GLenum)0x1701;
static bool immediateInited = false;
bool immediateBegin(GLenum mode, float width, float height)
{
if(!immediateInited)
{
HMODULE mod = GetModuleHandleA("opengl32.dll");
if(mod == NULL) return false;
getInt = (GLGETINTEGERVPROC)GetProcAddress(mod, "glGetIntegerv"); if(!getInt) return false;
pushm = (GLPUSHMATRIXPROC)GetProcAddress(mod, "glPushMatrix"); if(!pushm) return false;
loadident = (GLLOADIDENTITYPROC)GetProcAddress(mod, "glLoadIdentity"); if(!loadident) return false;
matMode = (GLMATRIXMODEPROC)GetProcAddress(mod, "glMatrixMode"); if(!matMode) return false;
ortho = (GLORTHOPROC)GetProcAddress(mod, "glOrtho"); if(!ortho) return false;
popm = (GLPOPMATRIXPROC)GetProcAddress(mod, "glPopMatrix"); if(!popm) return false;
begin = (GLBEGINPROC)GetProcAddress(mod, "glBegin"); if(!begin) return false;
v2f = (GLVERTEX2FPROC)GetProcAddress(mod, "glVertex2f"); if(!v2f) return false;
t2f = (GLTEXCOORD2FPROC)GetProcAddress(mod, "glTexCoord2f"); if(!t2f) return false;
end = (GLENDPROC)GetProcAddress(mod, "glEnd"); if(!end) return false;
immediateInited = true;
}
GLenum prevMatMode = eGL_NONE;
getInt(MAT_MODE, (GLint *)&prevMatMode);
matMode(MAT_PROJ);
pushm();
loadident();
ortho(0.0, width, height, 0.0, -1.0, 1.0);
matMode(MAT_MDVW);
pushm();
loadident();
matMode(prevMatMode);
begin(mode);
return true;
}
void immediateVert(float x, float y, float u, float v)
{
t2f(u,v); v2f(x,y);
}
void immediateEnd()
{
end();
GLenum prevMatMode = eGL_NONE;
getInt(MAT_MODE, (GLint *)&prevMatMode);
matMode(MAT_PROJ);
popm();
matMode(MAT_MDVW);
popm();
matMode(prevMatMode);
}