Skip to content

Commit 41aa23f

Browse files
authored
Merge pull request #1676 from marauder2k9-torque/OPENGL_DEBUG_MAC
OpenGL Fix mac rendering
2 parents 29aa5c6 + 6449d22 commit 41aa23f

6 files changed

Lines changed: 274 additions & 88 deletions

File tree

Engine/source/gfx/gl/gfxGLDevice.cpp

Lines changed: 92 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -91,19 +91,74 @@ void loadGLExtensions(void *context)
9191
GL::gglPerformExtensionBinds(context);
9292
}
9393

94-
void STDCALL glDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
95-
const GLchar *message, const void *userParam)
94+
void APIENTRY glDebugCallback(
95+
GLenum source,
96+
GLenum type,
97+
GLuint id,
98+
GLenum severity,
99+
GLsizei length,
100+
const GLchar* message,
101+
const void* userParam)
96102
{
97-
// JTH [11/24/2016]: This is a temporary fix so that we do not get spammed for redundant fbo changes.
98-
// This only happens on Intel cards. This should be looked into sometime in the near future.
99-
if (dStrStartsWith(message, "API_ID_REDUNDANT_FBO"))
103+
// Ignore non-significant notifications (optional)
104+
if (severity == GL_DEBUG_SEVERITY_NOTIFICATION)
100105
return;
106+
107+
const char* srcStr = "UNKNOWN";
108+
const char* typeStr = "UNKNOWN";
109+
const char* sevStr = "UNKNOWN";
110+
111+
switch (source)
112+
{
113+
case GL_DEBUG_SOURCE_API: srcStr = "API"; break;
114+
case GL_DEBUG_SOURCE_WINDOW_SYSTEM: srcStr = "WINDOW"; break;
115+
case GL_DEBUG_SOURCE_SHADER_COMPILER: srcStr = "SHADER"; break;
116+
case GL_DEBUG_SOURCE_THIRD_PARTY: srcStr = "THIRD_PARTY"; break;
117+
case GL_DEBUG_SOURCE_APPLICATION: srcStr = "APP"; break;
118+
case GL_DEBUG_SOURCE_OTHER: srcStr = "OTHER"; break;
119+
}
120+
121+
switch (type)
122+
{
123+
case GL_DEBUG_TYPE_ERROR: typeStr = "ERROR"; break;
124+
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: typeStr = "DEPRECATED"; break;
125+
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: typeStr = "UNDEFINED"; break;
126+
case GL_DEBUG_TYPE_PORTABILITY: typeStr = "PORTABILITY"; break;
127+
case GL_DEBUG_TYPE_PERFORMANCE: typeStr = "PERFORMANCE"; break;
128+
case GL_DEBUG_TYPE_MARKER: typeStr = "MARKER"; break;
129+
case GL_DEBUG_TYPE_PUSH_GROUP: typeStr = "PUSH"; break;
130+
case GL_DEBUG_TYPE_POP_GROUP: typeStr = "POP"; break;
131+
case GL_DEBUG_TYPE_OTHER: typeStr = "OTHER"; break;
132+
}
133+
134+
switch (severity)
135+
{
136+
case GL_DEBUG_SEVERITY_HIGH: sevStr = "HIGH"; break;
137+
case GL_DEBUG_SEVERITY_MEDIUM: sevStr = "MEDIUM"; break;
138+
case GL_DEBUG_SEVERITY_LOW: sevStr = "LOW"; break;
139+
case GL_DEBUG_SEVERITY_NOTIFICATION: sevStr = "NOTIFY"; break;
140+
}
141+
142+
// Filter known noisy IDs here if needed
143+
// Example:
144+
// if (id == 131185) return;
145+
101146
if (severity == GL_DEBUG_SEVERITY_HIGH)
102-
Con::errorf("OPENGL: %s", message);
147+
{
148+
Con::errorf("OPENGL [%s][%s][%s][%u]: %s",
149+
sevStr, srcStr, typeStr, id, message);
150+
AssertFatal(false, "OpenGL HIGH severity error.");
151+
}
103152
else if (severity == GL_DEBUG_SEVERITY_MEDIUM)
104-
Con::warnf("OPENGL: %s", message);
105-
else if (severity == GL_DEBUG_SEVERITY_LOW)
106-
Con::printf("OPENGL: %s", message);
153+
{
154+
Con::warnf("OPENGL [%s][%s][%s][%u]: %s",
155+
sevStr, srcStr, typeStr, id, message);
156+
}
157+
else
158+
{
159+
Con::printf("OPENGL [%s][%s][%s][%u]: %s",
160+
sevStr, srcStr, typeStr, id, message);
161+
}
107162
}
108163

109164
void STDCALL glAmdDebugCallback(GLuint id, GLenum category, GLenum severity, GLsizei length,
@@ -157,27 +212,34 @@ void GFXGLDevice::initGLState()
157212
#endif
158213

159214
#if TORQUE_DEBUG
160-
if( gglHasExtension(ARB_debug_output) )
161-
{
162-
glEnable(GL_DEBUG_OUTPUT);
163-
glDebugMessageCallbackARB(glDebugCallback, NULL);
164-
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
165-
GLuint unusedIds = 0;
166-
glDebugMessageControlARB(GL_DONT_CARE,
167-
GL_DONT_CARE,
168-
GL_DONT_CARE,
169-
0,
170-
&unusedIds,
171-
GL_TRUE);
172-
}
173-
else if(gglHasExtension(AMD_debug_output))
174-
{
175-
glEnable(GL_DEBUG_OUTPUT);
176-
glDebugMessageCallbackAMD(glAmdDebugCallback, NULL);
177-
//glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
178-
GLuint unusedIds = 0;
179-
glDebugMessageEnableAMD(GL_DONT_CARE, GL_DONT_CARE, 0,&unusedIds, GL_TRUE);
180-
}
215+
216+
bool debugInitialized = false;
217+
int flags;
218+
glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
219+
if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
220+
{
221+
glEnable(GL_DEBUG_OUTPUT);
222+
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
223+
224+
glDebugMessageCallback(glDebugCallback, nullptr);
225+
226+
glDebugMessageControl(
227+
GL_DONT_CARE,
228+
GL_DONT_CARE,
229+
GL_DONT_CARE,
230+
0,
231+
nullptr,
232+
GL_TRUE);
233+
234+
Con::printf("OpenGL debug output enabled.");
235+
debugInitialized = true;
236+
}
237+
238+
if (!debugInitialized)
239+
{
240+
Con::warnf("OpenGL debug output NOT available.");
241+
}
242+
181243
#endif
182244

183245
PlatformGL::setVSync(smEnableVSync);

Engine/source/gfx/gl/gfxGLTextureManager.cpp

Lines changed: 74 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex,
175175
//calculate num mipmaps
176176
if(retTex->mMipLevels == 0)
177177
retTex->mMipLevels = getMaxMipmaps(width, height, 1);
178-
178+
179179
glTexParameteri(binding, GL_TEXTURE_MAX_LEVEL, retTex->mMipLevels-1 );
180180

181181
bool hasTexStorage = false;
@@ -364,34 +364,83 @@ void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex,
364364
// loadTexture - GBitmap
365365
//-----------------------------------------------------------------------------
366366

367-
static void _textureUpload(const S32 width, const S32 height,const S32 bytesPerPixel,const GFXGLTextureObject* texture, const GFXFormat fmt, const U8* data,const S32 mip=0, const U32 face = 0, Swizzle<U8, 4> *pSwizzle = NULL)
367+
static void _textureUpload(
368+
const S32 width,
369+
const S32 height,
370+
const S32 bytesPerPixel,
371+
const GFXGLTextureObject* texture,
372+
const GFXFormat fmt,
373+
const U8* data,
374+
const S32 mip = 0,
375+
const U32 face = 0,
376+
Swizzle<U8, 4>* pSwizzle = NULL)
368377
{
369-
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, texture->getBuffer());
370-
U32 bufSize = width * height * bytesPerPixel;
371-
glBufferData(GL_PIXEL_UNPACK_BUFFER, bufSize, NULL, GL_STREAM_DRAW);
378+
const GLenum target = texture->getBinding();
372379

373-
if(pSwizzle)
374-
{
375-
PROFILE_SCOPE(Swizzle32_Upload);
376-
U8* pboMemory = (U8*)dMalloc(bufSize);
377-
pSwizzle->ToBuffer(pboMemory, data, bufSize);
378-
glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, bufSize, pboMemory);
379-
dFree(pboMemory);
380-
}
381-
else
382-
{
383-
PROFILE_SCOPE(SwizzleNull_Upload);
384-
glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, bufSize, data);
385-
}
380+
// Save pixel store state
381+
GLint prevUnpackAlign;
382+
glGetIntegerv(GL_UNPACK_ALIGNMENT, &prevUnpackAlign);
386383

387-
if(texture->getBinding() == GL_TEXTURE_CUBE_MAP)
388-
glTexSubImage2D(GFXGLFaceType[face], mip, 0, 0, width, height, GFXGLTextureFormat[fmt], GFXGLTextureType[fmt], NULL);
389-
else if (texture->getBinding() == GL_TEXTURE_2D)
390-
glTexSubImage2D(texture->getBinding(), mip, 0, 0, width, height, GFXGLTextureFormat[fmt], GFXGLTextureType[fmt], NULL);
391-
else
392-
glTexSubImage1D(texture->getBinding(), mip, 0, (width > 1 ? width : height), GFXGLTextureFormat[fmt], GFXGLTextureType[fmt], NULL);
384+
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
385+
386+
const U32 bufSize = width * height * bytesPerPixel;
393387

394-
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
388+
const U8* uploadPtr = data;
389+
U8* tempBuffer = nullptr;
390+
391+
if (pSwizzle)
392+
{
393+
tempBuffer = (U8*)dMalloc(bufSize);
394+
pSwizzle->ToBuffer(tempBuffer, data, bufSize);
395+
uploadPtr = tempBuffer;
396+
}
397+
398+
if (target == GL_TEXTURE_CUBE_MAP)
399+
{
400+
glTexSubImage2D(
401+
GFXGLFaceType[face],
402+
mip,
403+
0, 0,
404+
width, height,
405+
GFXGLTextureFormat[fmt],
406+
GFXGLTextureType[fmt],
407+
uploadPtr
408+
);
409+
}
410+
else if (target == GL_TEXTURE_2D)
411+
{
412+
glTexSubImage2D(
413+
GL_TEXTURE_2D,
414+
mip,
415+
0, 0,
416+
width, height,
417+
GFXGLTextureFormat[fmt],
418+
GFXGLTextureType[fmt],
419+
uploadPtr
420+
);
421+
}
422+
else if (target == GL_TEXTURE_1D)
423+
{
424+
glTexSubImage1D(
425+
GL_TEXTURE_1D,
426+
mip,
427+
0,
428+
width,
429+
GFXGLTextureFormat[fmt],
430+
GFXGLTextureType[fmt],
431+
uploadPtr
432+
);
433+
}
434+
435+
if (tempBuffer)
436+
dFree(tempBuffer);
437+
438+
// Restore state
439+
glPixelStorei(GL_UNPACK_ALIGNMENT, prevUnpackAlign);
440+
441+
#ifdef TORQUE_DEBUG
442+
glCheckErrors();
443+
#endif
395444
}
396445

397446
bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, GBitmap *pDL)

Engine/source/gfx/gl/gfxGLTextureObject.cpp

Lines changed: 72 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -102,36 +102,79 @@ GFXLockedRect* GFXGLTextureObject::lock(U32 mipLevel /*= 0*/, RectI* inRect /*=
102102

103103
void GFXGLTextureObject::unlock(U32 mipLevel /*= 0*/, U32 faceIndex /*= 0*/)
104104
{
105-
if(!mLockedRect.bits)
106-
return;
107-
108-
// I know this is in unlock, but in GL we actually do our submission in unlock.
109-
PROFILE_SCOPE(GFXGLTextureObject_lockRT);
110-
111-
PRESERVE_TEXTURE(mBinding);
112-
glBindTexture(mBinding, mHandle);
113-
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mBuffer);
114-
glBufferData(GL_PIXEL_UNPACK_BUFFER, (mLockedRectRect.extent.x + 1) * (mLockedRectRect.extent.y + 1) * mBytesPerTexel, mFrameAllocatorPtr, GL_STREAM_DRAW);
115-
S32 z = getDepth();
116-
if (mBinding == GL_TEXTURE_3D)
117-
glTexSubImage3D(mBinding, mipLevel, mLockedRectRect.point.x, mLockedRectRect.point.y, z,
118-
mLockedRectRect.extent.x, mLockedRectRect.extent.y, z, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], NULL);
119-
else if(mBinding == GL_TEXTURE_2D)
120-
glTexSubImage2D(mBinding, mipLevel, mLockedRectRect.point.x, mLockedRectRect.point.y,
121-
mLockedRectRect.extent.x, mLockedRectRect.extent.y, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], NULL);
122-
else if(mBinding == GL_TEXTURE_1D)
123-
glTexSubImage1D(mBinding, mipLevel, (mLockedRectRect.point.x > 1 ? mLockedRectRect.point.x : mLockedRectRect.point.y),
124-
(mLockedRectRect.extent.x > 1 ? mLockedRectRect.extent.x : mLockedRectRect.extent.y), GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], NULL);
125-
126-
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
127-
128-
mLockedRect.bits = NULL;
129-
#if TORQUE_DEBUG
130-
AssertFatal(mFrameAllocatorMarkGuard == FrameAllocator::getWaterMark(), "");
105+
if (!mLockedRect.bits)
106+
return;
107+
108+
PROFILE_SCOPE(GFXGLTextureObject_unlock);
109+
110+
PRESERVE_TEXTURE(mBinding);
111+
glBindTexture(mBinding, mHandle);
112+
113+
// --- Save pixel store state ---
114+
GLint prevUnpackAlign;
115+
glGetIntegerv(GL_UNPACK_ALIGNMENT, &prevUnpackAlign);
116+
117+
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
118+
119+
const U32 width = mLockedRectRect.extent.x;
120+
const U32 height = mLockedRectRect.extent.y;
121+
const U32 depth = getDepth();
122+
123+
if (mBinding == GL_TEXTURE_3D)
124+
{
125+
glTexSubImage3D(
126+
mBinding,
127+
mipLevel,
128+
mLockedRectRect.point.x,
129+
mLockedRectRect.point.y,
130+
0,
131+
width,
132+
height,
133+
depth,
134+
GFXGLTextureFormat[mFormat],
135+
GFXGLTextureType[mFormat],
136+
mLockedRect.bits
137+
);
138+
}
139+
else if (mBinding == GL_TEXTURE_2D)
140+
{
141+
glTexSubImage2D(
142+
mBinding,
143+
mipLevel,
144+
mLockedRectRect.point.x,
145+
mLockedRectRect.point.y,
146+
width,
147+
height,
148+
GFXGLTextureFormat[mFormat],
149+
GFXGLTextureType[mFormat],
150+
mLockedRect.bits
151+
);
152+
}
153+
else if (mBinding == GL_TEXTURE_1D)
154+
{
155+
glTexSubImage1D(
156+
mBinding,
157+
mipLevel,
158+
mLockedRectRect.point.x,
159+
width,
160+
GFXGLTextureFormat[mFormat],
161+
GFXGLTextureType[mFormat],
162+
mLockedRect.bits
163+
);
164+
}
165+
166+
// --- Restore state ---
167+
glPixelStorei(GL_UNPACK_ALIGNMENT, prevUnpackAlign);
168+
169+
mLockedRect.bits = NULL;
170+
171+
FrameAllocator::setWaterMark(mFrameAllocatorMark);
172+
mFrameAllocatorMark = 0;
173+
mFrameAllocatorPtr = NULL;
174+
175+
#ifdef TORQUE_DEBUG
176+
glCheckErrors();
131177
#endif
132-
FrameAllocator::setWaterMark(mFrameAllocatorMark);
133-
mFrameAllocatorMark = 0;
134-
mFrameAllocatorPtr = NULL;
135178
}
136179

137180
void GFXGLTextureObject::release()

Engine/source/gfx/gl/gfxGLUtils.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,32 @@
2828
#include "gfx/gl/gfxGLStateCache.h"
2929
#include "gfx/bitmap/imageUtils.h"
3030

31+
inline const char* glGetErrorString(GLenum error)
32+
{
33+
switch (error)
34+
{
35+
case GL_NO_ERROR: return "No Error";
36+
case GL_INVALID_ENUM: return "Invalid Enum";
37+
case GL_INVALID_VALUE: return "Invalid Value";
38+
case GL_INVALID_OPERATION: return "Invalid Operation";
39+
case GL_INVALID_FRAMEBUFFER_OPERATION: return "Invalid Framebuffer Operation";
40+
case GL_OUT_OF_MEMORY: return "Out of Memory";
41+
case GL_STACK_UNDERFLOW: return "Stack Underflow";
42+
case GL_STACK_OVERFLOW: return "Stack Overflow";
43+
case GL_CONTEXT_LOST: return "Context Lost";
44+
default: return "Unknown Error";
45+
}
46+
}
47+
48+
inline void _glCheckErrors(const char *filename, int line)
49+
{
50+
GLenum err;
51+
while ((err = glGetError()) != GL_NO_ERROR)
52+
Con::printf("OpenGL Error: %s (%d) [%u] %s\n", filename, line, err, glGetErrorString(err));
53+
}
54+
55+
#define glCheckErrors() _glCheckErrors(__FILE__, __LINE__)
56+
3157
inline U32 getMaxMipmaps(U32 width, U32 height, U32 depth)
3258
{
3359
return getMax( getBinLog2(depth), getMax(getBinLog2(width), getBinLog2(height))) + 1;

0 commit comments

Comments
 (0)