树莓派Circle框架下绘制特定ASCII字符触发屏幕闪烁故障排查求助
树莓派Circle框架下绘制特定ASCII字符触发屏幕闪烁故障排查求助
大家好,我现在在做一个基于树莓派Compute Module 4的个人项目,用Circle框架开发,遇到了一个非常奇怪的屏幕显示问题:当我绘制32个及以上特定字符时,这些字符之后的所有像素都会出现画面 glitch。
我使用的是固定宽度(2字节)的位图字体,每个字符由characterHeight行的u16数据表示,高位在前。目前测试发现,数字、?、@、所有大写字母以及小写a都会触发这个故障,但像:、`这类字符就不会出现问题。
以下是我的关键代码:
drawChar函数
void drawChar(MemoryBuffer& buffer, const Font& font, char character, u32 posX, u32 posY, u32 color) { // y represents position in character for(u32 y = 0; y < font.characterHeight; ++y) { // Current line is character * characterHeight + y because char*charHeight gets you to the correct array and + y gets you to the correct line in the array u16 currLine = font.font[character * font.characterHeight + y]; // x represents position in character for(u32 x = 0; x < font.characterWidth; ++x) { // currLine anded with 1 shifted over characterWidth - 1 - x bits because 1 << characterWidth - 1 places the 1 at the beginning of line, then - x moves it over x bits if(currLine & (1 << (font.characterWidth - 1 - x))) buffer.DrawPixel(x + posX, y + posY, color); } } }
drawPixel函数
void MemoryBuffer::DrawPixel(u32 x, u32 y, u32 color) { m_BufferPointer[y * (m_Pitch / 4) + x] = color; }
为了方便排查,我整理了最小复现示例代码:
kernel.h
#ifndef _kernel_h #define _kernel_h #include "HDMIDraw.h" #include <circle/types.h> #include <circle/bcmframebuffer.h> enum TShutdownMode { ShutdownNone, ShutdownHalt, ShutdownReboot }; class CKernel { public: CKernel (void); ~CKernel (void); boolean Initialize (void); TShutdownMode Run (void); private: CBcmFrameBuffer m_FrameBuffer; MemoryBuffer m_VirtBuffer; }; #endif
kernel.cpp
#include "kernel.h" #include "text.h" const Font FontTerminus = {.font= &font16x32norm[0][0], .characterWidth = 16, .characterHeight = 32}; CKernel::CKernel (void) : m_FrameBuffer(0, 0, 32) { } CKernel::~CKernel (void) { } boolean CKernel::Initialize (void) { if (!m_FrameBuffer.Initialize()) return FALSE; u32 width = m_FrameBuffer.GetWidth(); u32 height = m_FrameBuffer.GetHeight(); u32 pitch = m_FrameBuffer.GetPitch(); m_VirtBuffer.Allocate(width, height, pitch); return TRUE; } TShutdownMode CKernel::Run (void) { // Display loop while (true) { // Fill screen white (blank screen at start of loop) m_VirtBuffer.FillScreen(0xFFFFFF); // Draw a colored box, and test string m_VirtBuffer.DrawRect(0, 0, m_VirtBuffer.GetWidth()/2, m_VirtBuffer.GetHeight()/2, 0x00FF00); m_VirtBuffer.DrawString(FontTerminus, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0, 0, 0x000000); // Copy m_VirtBuffer (the draw buffer) to m_FrameBuffer (the display buffer), then wait for vsync to avoid tearing m_VirtBuffer.CopyToFrameBuffer(m_FrameBuffer); m_FrameBuffer.WaitForVerticalSync(); // Ensure clean display } return ShutdownHalt; }
HDMIDraw.h
#ifndef _hdmi_draw #define _hdmi_draw #include <circle/bcmframebuffer.h> #include <circle/types.h> struct Font; struct Bitmap { const u32* pixelMap; const u32 width; const u32 height; constexpr Bitmap(const u32* pixels, u32 w, u32 h) : pixelMap(pixels), width(w), height(h) {} }; class MemoryBuffer { public: MemoryBuffer(); ~MemoryBuffer(); void Allocate(u32 Width, u32 Height, u32 Pitch); u32* GetBuffer() { return m_BufferPointer; } u32 GetPitch() const { return m_Pitch; } u32 GetWidth() const { return m_Width; } u32 GetHeight() const { return m_Height; } void DrawPixel(u32 x, u32 y, u32 color); void FillScreen(u32 color); void DrawRect(u32 x1, u32 y1, u32 x2, u32 y2, u32 color); void DrawString(const Font& font, const char* string, u32 posX, u32 posY, u32 color); void CopyToFrameBuffer(CBcmFrameBuffer& frameBuffer); private: u32* m_BufferPointer{nullptr}; u32 m_Width{0}; u32 m_Height{0}; u32 m_Pitch{0}; u32 m_Size{0}; }; #endif
HDMIDraw.cpp
#include "HDMIDraw.h" #include "text.h" #include <string.h> MemoryBuffer::MemoryBuffer() : m_BufferPointer(nullptr), m_Width(0), m_Height(0), m_Pitch(0), m_Size(0) { } MemoryBuffer::~MemoryBuffer() { delete[] m_BufferPointer; } // Method to allocate the buffer in memory and set fields m_Width, m_Height, and m_Pitch void MemoryBuffer::Allocate(u32 Width, u32 Height, u32 Pitch) { m_Width = Width; m_Height = Height; m_Pitch = Pitch; }
我反复检查了字符绘制和像素绘制的逻辑,没发现明显的错误,实在搞不懂为什么只有特定字符、且绘制数量达到32个以上时才会触发这个glitch。有没有大佬能帮我分析下可能的原因,或者给我一些排查的方向?另外我已经附上了故障的效果截图(字符绘制故障效果)。
内容来源于stack exchange
相关产品推荐
相关产品推荐

