Canvas problem with release

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
Bananicorn
Prole
Posts: 37
Joined: Thu Apr 12, 2018 9:59 am

Canvas problem with release

Post by Bananicorn »

Okay, so here's my problem, it currently only occurs in wine, I couldn't yet test it on actual windows.
If I have a canvas which I release, re-create, redraw and then draw to screen in the same frame, it seems to not make it in time, thus being rendered empty...
This isn't a huge problem if this canvas is rendered directly on-screen, then it might result in it not being there for a frame, but since the need for this is kinda rare, it's nothing major.

The real problem for me comes up when I need to draw this canvas to another canvas, (like when buffering a parallax background) which then doesn't actually get buffered and might not be replaced in quite a while...

I've put together a somewhat minimal example demonstrating the behaviour.
I just don't know how to work my way around it (or if I'm doing something fundamentally wrong)

Code: Select all

function love.load ()
	small_canvas = love.graphics.newCanvas(100, 100)
	big_canvas = love.graphics.newCanvas(400, 400)
	counter = 0
end

function draw_small_canvas ()
	love.graphics.setColor(0, 1, 0, 1)
	love.graphics.rectangle('fill', 1, 1, 100, 100)
	love.graphics.setColor(1, 0, 0, 1)
	love.graphics.circle('fill', 50, 50, 50)
	love.graphics.setCanvas()
	love.graphics.setColor(1, 1, 1, 1)
end

function love.draw ()
	counter = counter + 1
	if counter > 60 then
		small_canvas:release()
		small_canvas = love.graphics.newCanvas(100, 100)
		big_canvas:release()
		big_canvas = love.graphics.newCanvas(400, 400)

		love.graphics.setCanvas(small_canvas)
		draw_small_canvas()
		love.graphics.setCanvas()

		--save smaller canvas into bigger one
		love.graphics.setCanvas(big_canvas)
		love.graphics.draw(small_canvas, 0, 0)
		love.graphics.draw(small_canvas, 100, 0)
		love.graphics.draw(small_canvas, 100, 100)
		love.graphics.draw(small_canvas, 0, 100)
		love.graphics.setCanvas()

		counter = 0
	end
	love.graphics.draw(small_canvas, 0, 0)
	love.graphics.draw(big_canvas, 150, 0)
end

function love.update (dt)
	if love.keyboard.isDown("escape") then
		love.event.quit()
	end
end
I've added an attachment so you can see the problem right away - to test it in wine just run

Code: Select all

make win; wine win32/canvas_bug_test.exe
Well, technically you don't need the make win first, but you'll need it for a convenient build once you start messing around with it.
The problem does not occur if I run it normally on linux.

Any pointers on what I might be doing wrong, are highly appreciated, thanks in advance! :)

Edit: removed some unused code - thanks for pointing that out, zorg! :)
Attachments
canvas_problem.zip
(19.33 MiB) Downloaded 50 times
Last edited by Bananicorn on Thu Nov 22, 2018 2:44 pm, edited 1 time in total.
User avatar
zorg
Party member
Posts: 3444
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Canvas problem with release

Post by zorg »

Okay, first pointer is that it's wasteful to release and recreate those canvases each frame... why exactly are you doing that?

The sane method would be to :clear them, and to simply just render into them again, then render them onto the screen.

Code: Select all

function love.draw ()
	counter = counter + 1
	if counter > 60 then -- a heads up, nothing guarantees the screen will run at 60Hz, so this might not do what you want it to.
		small_canvas:clear()
		big_canvas:clear()

		love.graphics.setCanvas(small_canvas)
		draw_small_canvas()
		love.graphics.setCanvas()

		-- /render/ smaller canvas into bigger one
		love.graphics.setCanvas(big_canvas)
		love.graphics.draw(small_canvas, 0, 0)
		love.graphics.draw(small_canvas, 100, 0)
		love.graphics.draw(small_canvas, 100, 100)
		love.graphics.draw(small_canvas, 0, 100)
		love.graphics.setCanvas()

		counter = 0
	end
	draw_small_canvas() -- technically, this draws the stuff you put -into- small_canvas directly onto the screen... confusing terminology
	love.graphics.draw(small_canvas, 0, 0)
	love.graphics.draw(big_canvas, 150, 0)
end
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
Bananicorn
Prole
Posts: 37
Joined: Thu Apr 12, 2018 9:59 am

Re: Canvas problem with release

Post by Bananicorn »

Okay, first pointer is that it's wasteful to release and recreate those canvases each frame... why exactly are you doing that?
Okay, sorry I wasn't too clear on that - my actual problem is in another program, but this demonstrates the principle behind it.
In my actual program I have to "resize" canvases, and as far as I know that only works by throwing away the old one and creating a new one, right? (Please tell me there's another way, oh god)
All of this is done in a single function, but I thought bringing it into play here would be a bit too much overhead, but what it does is this:
  • release old canvas
  • create new canvas
  • fill new canvas with primitive shapes
  • draw new canvas on screen (which it usually doesn't)
What's even worse is that if I draw this canvas to another canvas in the same frame, it won't draw anything and then I'm left with an empty canvas which I was hoping to re-use for quite a while...
draw_small_canvas() -- technically, this draws the stuff you put -into- small_canvas directly onto the screen... confusing terminology
Sorry this makes no sense in that place, I'll edit it out of the question - the small canvas is drawn right below anyways.

And the counter at 60 was just arbitrarily chosen, it's just there so you have about a second to see the buffered canvas before the bug occurs.

Edit: formatting
Post Reply

Who is online

Users browsing this forum: Amazon [Bot] and 6 guests