getDisplayBufferBitmap() and copyFrameBufferBitmap() returning all-black bitmaps

I'm porting some code from elsewhere to run on the Playdate, and part of the graphics layer requires us to be able to create a 'blitter': a device that copies a section of the screen away so we can either redraw it back in its original position (e.g. to redraw after something has been scrolled across the top) or elsewhere (like a sort of sprite).

To do this, I think I need to use one or other of getDisplayBufferBitmap() (for the live display) or copyFrameBufferBitmap() (for the working buffer) to grab the current contents of the screen, and then using the mask/display/unmask trick in Redrawing only a portion of LCDBitmap with the C api on linux? to draw the requested subset of the bitmap onto the requested bit of the screen.

But the trouble is, neither of these functions seems to be working for me (in the simulator; I've not tried them on a real device). They're both returning an all-black bitmap: if I fetch the bitmap and then immediately display it back on the screen, the whole screen turns black. This also happens for me in the bach.mid example code (C_API/Examples/bach.mid): this uses a similar trick to shift the display buffer left by one pixel whenever the MIDI sequence increments, but if I compile and run the code (unmodified), all I see is a black screen with one white column at the right-hand edge.

Is there something I'm missing about the operation of these functions? The example code not running makes me think that maybe it's not just me... Is the idea that you have to use the getDebugBitmap() function iff you're running in the simulator, and the other functions only if you're running on real hardware? I'm using v1.12.3 of the SDK.

That's really weird, it works for me on macOS. I'm guessing you're on Windows or Linux? That part of the code is cross-platform, though, so I'm not sure what could be causing that. :thinking:

Windows here, sorry, should have said. I'll compile up a version for the real device and see what I see there (ed: tried running it on the real device and I see the same broken behaviour).

Let me know if there's anything else useful I could do to diagnose it.

Aha! I worked it out. It wasn't actually the get-bitmap functions, but the draw-bitmap functions.

Elsewhere in the code, I had need of a function that could draw either white or black text, so I had been calling e.g. setDrawMode(kDrawModeFillWhite) or setDrawMode(kDrawModeFillBlack). However, I had failed to reset this to kDrawModeCopy before I tried to draw the bitmap back to the screen to load the blitter, so it was drawing in all-black because it had previously been asked to draw black text.

So it's all working for me now, after resetting the draw mode. Sorry for the wild goose chase! I still don't understand why I was seeing this effect in the bach.mid example code in the simulator, though, which doesn't call setDrawMode at all. Could the setting from one app persist to another one?

1 Like

Not really — when you exit to the launcher, the system fully reboots. There must be something else causing this.

@dwineman The system doesn't fully reboot in the Simulator. The drawing mode likely needs to be reset when exiting a game (edit: I verified draw mode is reset to kDrawModeCopy when games are launched in the sim... J/K that's in lua only). @lookoutjames I did find a bug in the Windows Simulator where the bach.mid example wouldn't scroll the screen correctly. That was due to the Simulator not drawing a blank white screen as the game was launched. Is that what you could be seeing?

Yep, looks like a bug in the C API "reset graphics state" code (which is only relevant in the simulator because on the device it does a reboot when you exit a game). It's restoring the context stack but it's not restoring the default values for the initial context. Nice catch! I'll file that and get a fix in the queue.

4 Likes

Excellent! Glad my ineptitude managed to lead to something useful, anyway. Thanks for chasing this up for me.

1 Like