pushcontext(NULL) + sprite system / drawing weird behaviour

I'm testing in windows simulator, and someone had a problem discord where the sprite system would not clear the screen, i simulated the problem in playdate SDK using C api only but i don't understand why it affects it ? I use Pushcontext(NULL) all the time in the C Api and i always i assumed doing PushContext(NULL) and then doing draw commands or drawing images draws to the screen again (it sure seems to act that way).

However when using this in combination with the sprite system odd things started happening. Consider the following simplified C Example.

i create sprites to fill the screen, then draw it once then i do a pushcontext(NULL) and draw a line the screen, which is shown. When i press A Button a line is drawn and remains visible. Only when press i the B button i call drawsprites again which should theoretically clear the screen again and redraw the part of the sprites that contained the lines. But this does not happen and the cullprit seems to be the Pushcontext(NULL) call, if i leave that out it behaves as expected

can someone explain to me why the code with the pushcontext(NULL) call fails ? i assumed pushcontext(NULL) enforces rendering to the screen again and it seems to do that but when used it seems to affect the sprite system for clearing the line when pressing B

For reference this is what it does when it does work without the pushcontext call and with the push context call the line nevers get removed when pressing B Button

PlaydateSimulator_WuRQQnjZRe

And this confused me and i'd like clarifications about both pushcontext(NULL) like what it actually does and why it affects the program in this way.

That's my bug, sorry. :disappointed: For some reason in the C API pushContext() doesn't copy the previous context, which means the drawing functions don't have a reference to the sprite display list and can't mark the drawn areas as dirty. One of the things on my todo list is to move the context stuff down to the graphics layer so that we don't have separate and inconsistent implementations in both the Lua and C APIs.

About NULL contexts: This is useful if you have a utility function that wants to set a drawing parameter like color/pattern or font, do some drawing, then restore the state so that it doesn't affect the calling code. In your demo wrapping the drawLine() call in a push/popContext doesn't really do much except trigger this bug.. though I understand this is a simplified case. If you really do need to wrap your drawing code in push/popContext the easiest workaround for the display list bug is probably to call pd->sprite->addDirtyRect(LCDMakeRect(0,0,400,240)) after popping the context to force a full screen redraw. It's not optimal, but it'll do the trick.

2 Likes

While on the topic of context stuff, it would be neat if there was a way to peek the current context, to facilitate user-level custom drawing functions being able to use the context system. Over the last couple of days I wrote my own line rasterizer (as a workaround while the SDK one is still a bit broken), and since there's no way to peek the current context, I had to write wrapper functions for pushContext() and popContext() that maintain my own user-level context stack. Ditto for the clip rect functions, too.

thanks for explaining it, it makes sense now to me :slight_smile:

I do have one more question when doing for example this with nested push & pop statements (which do seem to work) does the pushcontext NULL makes it so that we are actually enforcing drawing to the screen or should it still draw to the bitmap but just undo whatever we did with the context between the pushcontext(NULL) / Popcontext call ? Basically suppose we stack pushcontext calls with bitmaps and such and at some point we want to force drawing to the screen again does pushcontext(NULL) do that ? i can't remember it exactly but i think it does, unless it just pushes a new context but remains drawing to the bitmap. Like with pseudocode below is the line drawn on the screen or bitmap ? i can easily test it i guess if i wrote a small test program but maybe it's good for reference for other people. I think if i remember correctly it will draw to the screen and not affect the bitmap

pushcontext(bitmap)
pushcontext(NULL)
//change some context stuff then
drawline
popcontext
popcontext

Edit: i wrote the test program, pushcontext(NULL) is indeed the same as pushing the screen "bitmap"

this runs at 1 fps and i pushcontext bitmap first then immediatly pushcontex(NULL) and the bitmap is unaffected because on the next drawbitmap call with texbunny it draws a bunny without a line over the bunny, which means pushcontext(null) allows drawing to the screen at any point you call that, if it would have drawn onto the bunny bitmap / image you would not see such long line on the screen either as the bitmap (of the bunny) is not that big and the line would have been clipped

PlaydateSimulator_EJi9QyB04V