Behavior/necessity of `playdate.display.flush()`

I'm using SDK 1.12.0 and macOS 12.4, on a 2020 M1 MacBook Air. I'm playing around with the different graphics functions, and I can't figure out exactly what playdate.display.flush() does, or when it's needed. The SDK docs say that it:

Sends the contents of the frame buffer to the display immediately. Useful if you have called playdate.stop() to disable update callbacks in, say, the case where your app updates the display only in reaction to button presses.

Based on that, I'd expect that if I call playdate.stop() and then draw in a button handler callback, the results of the drawing code won't be visible without a call to playdate.display.flush(). But I wrote a small program to do that here, and that's not the behavior I'm seeing. If I run that code in the simulator and press A repeatedly, I see a string of squares painted on the screen, whether or not the call to playdate.display.flush() is commented out.

As a followup, I tried setting a very low screen refresh rate and logging timestamps from the button handler function, in this gist. I was wondering if maybe calling playdate.display.flush() would force a screen update before the next frame was due, but that also doesn't appear to be the case. This program also seems unaffected by the presence or absence of the playdate.display.flush() call; no matter when I press the A button, the next screen update comes at a multiple of the frame length (3 seconds, in this case).

Am I misreading the implication from the docs that I quoted above? Does calling or not calling playdate.display.flush() ever cause a visible behavior change?

Could this be a behavioral difference between the simulator and the device? I can't test on the device yet since my order is in Group 5 :slight_smile:.

Based on the documentation, it sounds like playdate.stop() should no longer call the frame callback, and that any modifications to the frame buffer shouldn't become visible until playdate.display.flush() is called.

I wrote a program in C to test this (attached to this post), since in C the frame callback explicitly notifies the runtime when it should refresh the display:

flush.zip (3.8 KB)

The controls are as follows:

  • Up: Clear frame buffer to white
  • Down: Clear frame buffer to black
  • B: Clear frame buffer to 50% black/white
  • A: Flush frame buffer to display

If you don't press A, you'll never see any changes on-screen. Well, I should clarify that this is the behavior when running on the hardware.

Here's the kicker: the simulator is wrong. If you run this program in the simulator, the display will refresh immediately when pressing up, down and B. It seems like the simulator is always showing the contents of the frame buffer, not the contents of the... I was gonna say LCD, but whatever the display hardware is made of.

Try running your test on the hardware. You may find it behaves the way you expect.

It occurs to me that I triggered a display refresh by returning 1 from the update callback rather than calling playdate->graphics->display() and returning zero. I tested this locally and it works just the same.

In the code, you can replace the following:

case kButtonA:
    return 1; // 1 = Refresh the display

with the following:

case kButtonA:
    pd->graphics->display();
    break;

and the hardware and simulator will both behave the same as before.

Here's the kicker: the simulator is wrong . If you run this program in the simulator, the display will refresh immediately when pressing up, down and B.

Thanks, I was wondering that. As I said in my post, I don't have my device yet, so this is something I'll have to make sure to test when it does arrive!