Skip to content

Scene::prepareFrame clear loop leaves bottom-half un-cleared when HALF_WIDTH_BUFFERS=1 and FIELD_BUFFERS=0 #5

@jetpax

Description

@jetpax

Summary

When HALF_WIDTH_BUFFERS=1 and FIELD_BUFFERS=0, Scene::prepareFrame's framebuffer clear loop only writes the top half of the buffer. The bottom half retains last-frame's pixels and the rasteriser then overdraws on top of ghost geometry.

Reproduction

JetConfig with HALF_WIDTH_BUFFERS 1, FIELD_BUFFERS 0, any rasterised content, full-screen render (rasterizeBand(0, screenHeight)). Visible result: a vertical-half ghost copy of the previous frame's geometry appears in the lower half of the display.

Root cause

src/Scene.cpp ~line 340 (non-interlaced, non-checkerboard clear branch):

#if HALF_WIDTH_BUFFERS
const int rowPixels = screenWidth / 2;
const int rowCount  = screenHeight / 2;     // <- halved unconditionally
#else
const int rowPixels = screenWidth;
const int rowCount  = screenHeight;
#endif

However the rasteriser's bufferIndex math at src/Renderer.cpp:~1053 walks y over the full [0, screenHeight) range when FIELD_BUFFERS=0:

#if FIELD_BUFFERS
int32_t bufferIndex = (y >> 1) * (screenWidth / 2) + (xStart / 2);
#else
int32_t bufferIndex = y * (screenWidth / 2) + (xStart / 2);   // full y range
#endif

So the buffer is half-width but FULL-height in this combination. The /2 on rowCount is only correct when FIELD_BUFFERS=1 also halves the buffer height. The default Config.example.hpp ships both flags on together (intended as a quarter-area mode) so this combination wasn't exercised upstream.

Suggested fix

Gate the height halve on FIELD_BUFFERS:

#if HALF_WIDTH_BUFFERS
const int rowPixels = screenWidth / 2;
#if FIELD_BUFFERS
const int rowCount  = screenHeight / 2;
#else
const int rowCount  = screenHeight;
#endif
#else
const int rowPixels = screenWidth;
const int rowCount  = screenHeight;
#endif

Context

Found while porting Jet to a Raspberry Pi Zero 2 W on Zephyr RTOS at 912x492 RGB565. Happy to file a PR if useful — flagging the bug first since the CLA grant is broad. Tested locally with the above patch and the artifact is fully gone.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions