SFML community forums
Bindings - other languages => DotNet => Topic started by: Spodi on November 13, 2010, 06:57:18 pm
-
Here is a minimalist C# console app to recreate the problem:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SFML.Graphics;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
using (var rw = new RenderWindow(new SFML.Window.VideoMode(800, 600), "Test"))
{
Shape sh = Shape.Rectangle(new FloatRect(8,8,32,32), Color.Green);
RenderImage buffer = null;
while (rw.IsOpened())
{
rw.DispatchEvents();
buffer = CreateBuffer(rw, buffer);
buffer.Clear();
buffer.Draw(sh);
buffer.Display();
rw.Clear();
var s = new Sprite(buffer.Image);
rw.Draw(s);
rw.Display();
}
}
}
static RenderImage CreateBuffer(RenderWindow rw, RenderImage existingBuffer)
{
if (existingBuffer == null || existingBuffer.Width != rw.Width || existingBuffer.Height != rw.Height)
{
if (existingBuffer != null)
existingBuffer.Dispose();
return new RenderImage(rw.Width, rw.Height);
}
return existingBuffer;
}
}
}
I have been having this issue for a while, but always assumed it was my fault up until now. RenderImage doesn't seem to want to dispose properly. In my game, I use a few RenderImages to draw to, then combine them all to the screen. If the RenderWindow changes in size, the RenderImages are disposed then created again with the new size. But when disposing them, that is when the problems seem to arise.
If you take out the Dispose in the program above, it also seems to make it work just fine.
-
But when disposing them, that is when the problems seem to arise.
What happens?
-
It is hard to say exactly. One frequent problem is an AccessViolationException while the RenderImage disposes. I believe this is caused by:
myDefaultView.Dispose();
I had this commented out in my game to prevent the exception, but when calling Dispose, it still resulted in a strange issue where the RenderImage seems to refuse to update. It would continue to show the old display even though I am using a new RenderImage. On occasion, it would sometimes fix itself for no apparent reason. Recreated the RenderWindow would also fix it until you dispose of the RenderImage again.
-
I fixed the bug, should be ok now.
Thanks for your help :)
-
Thanks Laurent, that seems to fix the disposal issues. :)
I'm still getting the "screen not redrawing" issue. Though I don't know yet if its an issue on my side or SFML's. I'll look into it again when I have the chance, and if its still a problem, try to create a better example and description of the issue I am having.
-
Alright, here is a similar test program that makes it much easier to see the issue at hand:
using System;
using SFML.Graphics;
namespace ConsoleApplication2
{
class Program
{
static void Main()
{
Random rnd = new Random();
using (var rw = new RenderWindow(new SFML.Window.VideoMode(800, 600), "Test"))
{
rw.UseVerticalSync(true);
// Create shape to create test sprite
Shape sh = Shape.Rectangle(new FloatRect(8, 8, 32, 32), Color.White);
int i = 0;
RenderImage buffer = null;
while (rw.IsOpened())
{
rw.DispatchEvents();
// Update the view to fit the RenderWindow
rw.SetView(new View(new FloatRect(0, 0, rw.Width, rw.Height)));
// Change shape color
if (++i % 50 == 0)
sh.Color = new Color((byte)rnd.Next(0, 255), (byte)rnd.Next(0, 255), (byte)rnd.Next(0, 255), 255);
// Ensure the RenderImage is created with the same size of the RenderWindow
buffer = CreateBuffer(rw, buffer);
if (!rw.Input.IsKeyDown(SFML.Window.KeyCode.A))
{
// Draw with buffer
// Draw to the buffer
buffer.Clear();
buffer.Draw(sh);
buffer.Display();
// Clear the screen and draw the buffer to the screen
var s = new Sprite(buffer.Image);
rw.Draw(s);
rw.Display();
}
else
{
// Draw without buffer
rw.Clear(Color.White);
rw.Draw(sh);
rw.Display();
}
}
}
}
static RenderImage CreateBuffer(RenderWindow rw, RenderImage existingBuffer)
{
// If the buffer doesn't exist or is the wrong size, it must be created
if (existingBuffer == null || existingBuffer.Width != rw.Width || existingBuffer.Height != rw.Height)
{
// If the buffer already exists, dispose it
// NOTE: This disposal is what breaks the rendering. Remove it and it works again.
if (existingBuffer != null)
existingBuffer.Dispose();
// Return the new buffer
var ret = new RenderImage(rw.Width, rw.Height);
return ret;
}
// Existing buffer is already the correct size, so do not recreate
return existingBuffer;
}
}
}
Basically, when I resize the window, the display "freezes". Its like the RenderImage isn't recreated with the new size and retains the image that was last drawn to it. This only seems to happen when Dispose is called on the RenderImage.
Some things to note:
1. Even though the screen is "frozen", everything else seems to work fine.
2. If you draw without the buffer (press A), then go back to drawing with the buffer, it starts working again.
3. Even when the RenderImage is garbage collected (comment out the dispose, add GC.Collect() in game loop), it doesn't seem to have this issue.
Hopefully that is enough info. :)
-
Thank you for the code.
I translated it to C++, and fortunately the bug is still there. So I'll be able to debug it as deeply as I need ;)
I'll let you know when it's fixed.
-
Any updates on this, Laurent?
-
Nop, sorry. I spent two days on it and then gave up and switched to something else. I'll try to work on it again as soon as possible.