I've ran into the following problem: when a render image is created in one thread it cannot be modified anymore in another thread. The render image is still there and it can e.x. be saved, but whatever modification (clear, draw, etc.) I throw at it the image won't change. Please note that I already do allocate an sf::Context in every thread.
The following minimalistic code example demonstrates the problem:
// include SFML
#include <SFML/Graphics.hpp>
// include STD
#include <iostream>
#include <fstream>
#include <sstream>
// include threads
#include <windows.h>
#include <process.h>
// global variable (for simplicity)
sf::RenderImage* g_pRenderImage = NULL;
// thread function
unsigned int _stdcall ThreadFunction(void* pParam)
{
// create SFML context in every thread
sf::Context MyContext;
// get and output thread index
int* pThreadIndex = (int*) pParam;
std::cout << "thread " << *pThreadIndex << " started" << std::endl;
// create or reuse render image
if (g_pRenderImage == NULL) {
std::cout << " creating render image" << std::endl;
g_pRenderImage = new sf::RenderImage;
g_pRenderImage->Create(300, 100);
} else {
std::cout << " reusing render image" << std::endl;
}
// loop
int ImageIndex;
for (ImageIndex = 0; ImageIndex < 2; ++ImageIndex) {
// clear render image
g_pRenderImage->Clear(sf::Color(200, 200, 200));
// create label
std::stringstream Label;
Label << "thread" << *pThreadIndex << "image" << ImageIndex;
// create SFML text from label
sf::Text MyText(Label.str());
MyText.SetColor(sf::Color(255, 0, 0));
MyText.SetPosition(20.0f, 20.0f);
// draw SFML text
g_pRenderImage->Draw(MyText);
// display (finish) render image
g_pRenderImage->Display();
// save render image
std::cout << " saving image '" << Label.str() << ".png'" << std::endl;
g_pRenderImage->GetImage().SaveToFile(Label.str() + ".png");
}
std::cout << " done" << std::endl;
return 0;
}
// main function
int main(int argc, char** argv)
{
// create SFML context in main thread
sf::Context MyContext;
// loop over threads
int ThreadIndex;
for (ThreadIndex = 0; ThreadIndex < 2; ++ThreadIndex) {
// create thread
unsigned int TempThreadID = 0;
HANDLE TempThreadHandle = (HANDLE) _beginthreadex(
NULL, // no security attributes
0, // use default stack size
ThreadFunction, // thread function
&ThreadIndex, // argument to thread function
0, // use default creation flags
&TempThreadID); // returns the thread identifier
// handle thread creation error
if (TempThreadHandle == NULL) {
std::cout << "failed to create thread " << ThreadIndex << std::endl;
return 1;
}
// wait till thread finishes
WaitForSingleObject(TempThreadHandle, INFINITE);
}
return 0;
}
This code was made with Visual C++ 2003 .NET on Windows XP 32 Bit using
https://sfml.svn.sourceforge.net/svnroot/sfml/branches/sfml2 revision 1523.
After running this code there will be 4 image files:
"thread0image0.png" containing the text "thread0image0" which is correct.
"thread0image1.png" containing the text "thread0image1" which is correct.
"thread1image0.png" containing the text "thread0image1" which is wrong.
"thread1image1.png" containing the text "thread0image1" which is wrong.
Based on my actual, big project using multiple threads seems to work for render
windows, but as the example above shows it does not work for render
images.
I'd like to know whether I'm doing something wrong, whether this is intended/expected behaviour or whether this is a bug, thanks.