Well, this was a bitch, but I found it.
It was a buffer overrun problem. The default behaviour of glReadPixels is to pack every row to a multiple of 4 bytes, even though the spec doesn't say that (you have to go look at glPixelStore for that). So when you're writing a window which is an odd size rather than the more usual power-of-2 numbers you got a buffer overrun which resulted in random behaviour (I ended up with a crash deep in ntdll.dll).
I've fixed this now, see the patch below. I've also fixed the fact that when you're using multiple windows in GL you weren't guaranteed to write the correct one previously, if another one was updated last. I've tested this in my own embedded app (wxWidgets based) and it works.
Eihort:
- Code: Select all
Index: RenderSystems/GL/src/OgreWin32Window.cpp
===================================================================
RCS file: /cvsroot/ogre/ogrenew/RenderSystems/GL/src/OgreWin32Window.cpp,v
retrieving revision 1.45.2.5
diff -u -r1.45.2.5 OgreWin32Window.cpp
--- RenderSystems/GL/src/OgreWin32Window.cpp 10 Aug 2007 10:35:27 -0000 1.45.2.5
+++ RenderSystems/GL/src/OgreWin32Window.cpp 15 Aug 2007 12:06:48 -0000
@@ -511,12 +511,22 @@
// Allocate buffer
uchar* pBuffer = new uchar[mWidth * mHeight * 3];
+ // Switch context if different from current one
+ RenderSystem* rsys = Root::getSingleton().getRenderSystem();
+ rsys->_setViewport(this->getViewport(0));
+
+ // Must change the packing to ensure no overruns!
+ glPixelStorei(GL_PACK_ALIGNMENT, 1);
+
// Read pixels
// I love GL: it does all the locking & colour conversion for us
if (mIsFullScreen)
glReadBuffer(GL_FRONT);
glReadPixels(0,0, mWidth, mHeight, GL_RGB, GL_UNSIGNED_BYTE, pBuffer);
+ // restore default alignment
+ glPixelStorei(GL_PACK_ALIGNMENT, 4);
+
// Wrap buffer in a memory stream
DataStreamPtr stream(new MemoryDataStream(pBuffer, mWidth * mHeight * 3, false));
Shoggoth:- Code: Select all
Index: RenderSystems/GL/src/OgreWin32Window.cpp
===================================================================
RCS file: /cvsroot/ogre/ogrenew/RenderSystems/GL/src/OgreWin32Window.cpp,v
retrieving revision 1.50
diff -u -r1.50 OgreWin32Window.cpp
--- RenderSystems/GL/src/OgreWin32Window.cpp 26 Jun 2007 17:56:24 -0000 1.50
+++ RenderSystems/GL/src/OgreWin32Window.cpp 15 Aug 2007 12:00:34 -0000
@@ -521,11 +521,22 @@
"Win32Window::copyContentsToMemory" );
}
+
+ // Switch context if different from current one
+ RenderSystem* rsys = Root::getSingleton().getRenderSystem();
+ rsys->_setViewport(this->getViewport(0));
+
+ // Must change the packing to ensure no overruns!
+ glPixelStorei(GL_PACK_ALIGNMENT, 1);
+
glReadBuffer((buffer == FB_FRONT)? GL_FRONT : GL_BACK);
glReadPixels((GLint)dst.left, (GLint)dst.top,
(GLsizei)dst.getWidth(), (GLsizei)dst.getHeight(),
format, type, dst.data);
+ // restore default alignment
+ glPixelStorei(GL_PACK_ALIGNMENT, 4);
+
//vertical flip
{
size_t rowSpan = dst.getWidth() * PixelUtil::getNumElemBytes(dst.format);