Pass through draw_fb optimization metadata to Display class

The JS implementation does content hashing to not blit unchanged
framebuffer contents (see mihaip/dingusppc@171ff2d407).
However, that is not necessary for the ATI adapters that already track
this and only set draw_fb if the framebuffer has actually changed.

Pass through a fb_known_to_be_changed for these cases, and also add an
optional update_skipped method (since the JS still wants to know when
the last logical screen update was).
This commit is contained in:
Mihai Parparita 2024-07-27 11:34:15 -07:00
parent 7d6e87a0d3
commit dab9334c3a
6 changed files with 30 additions and 3 deletions

View File

@ -164,6 +164,8 @@ AtiMach64Gx::AtiMach64Gx()
insert_bits<uint32_t>(this->regs[ATI_GUI_STAT], 32, ATI_FIFO_CNT, ATI_FIFO_CNT_size);
set_bit(regs[ATI_CRTC_GEN_CNTL], ATI_CRTC_DISPLAY_DIS); // because blank_on is true
this->draw_fb_is_dynamic = true;
}
void AtiMach64Gx::change_one_bar(uint32_t &aperture, uint32_t aperture_size,

View File

@ -144,6 +144,8 @@ ATIRage::ATIRage(uint16_t dev_id)
this->regs[ATI_GP_IO] = ((mon_code & 6) << 11) | ((mon_code & 1) << 8);
insert_bits<uint32_t>(this->regs[ATI_GUI_STAT], 32, ATI_FIFO_CNT, ATI_FIFO_CNT_size);
set_bit(regs[ATI_CRTC_GEN_CNTL], ATI_CRTC_DISPLAY_DIS); // because blank_on is true
this->draw_fb_is_dynamic = true;
}
void ATIRage::change_one_bar(uint32_t &aperture, uint32_t aperture_size,

View File

@ -41,9 +41,19 @@ public:
// Clears the display
void blank();
// Update the host framebuffer display. If the display adapter does its own
// dirty tracking, fb_known_to_be_changed will be set to true, so that the
// implementation can take that into account.
void update(std::function<void(uint8_t *dst_buf, int dst_pitch)> convert_fb_cb,
std::function<void(uint8_t *dst_buf, int dst_pitch)> cursor_ovl_cb,
bool draw_hw_cursor, int cursor_x, int cursor_y);
bool draw_hw_cursor, int cursor_x, int cursor_y,
bool fb_known_to_be_changed);
// Called in cases where the framebuffer contents have not changed, so a
// normal update() call is not happening. Allows implementations that need
// to do per-frame bookkeeping to still do that.
void update_skipped();
void handle_events(const WindowEvent& wnd_event);
void setup_hw_cursor(std::function<void(uint8_t *dst_buf, int dst_pitch)> draw_hw_cursor,

View File

@ -107,7 +107,8 @@ void Display::blank() {
void Display::update(std::function<void(uint8_t *dst_buf, int dst_pitch)> convert_fb_cb,
std::function<void(uint8_t *dst_buf, int dst_pitch)> cursor_ovl_cb,
bool draw_hw_cursor, int cursor_x, int cursor_y) {
bool draw_hw_cursor, int cursor_x, int cursor_y,
bool fb_known_to_be_changed) {
if (impl->resizing)
return;
@ -137,6 +138,10 @@ void Display::update(std::function<void(uint8_t *dst_buf, int dst_pitch)> conver
SDL_RenderPresent(impl->renderer);
}
void Display::update_skipped() {
// SDL implementation does not care about skipped updates.
}
void Display::setup_hw_cursor(std::function<void(uint8_t *dst_buf, int dst_pitch)> draw_hw_cursor,
int cursor_width, int cursor_height) {
uint8_t* dst_buf;

View File

@ -81,7 +81,10 @@ void VideoCtrlBase::update_screen()
}
this->display.update(
this->convert_fb_cb, this->cursor_ovl_cb,
this->cursor_on, cursor_x, cursor_y);
this->cursor_on, cursor_x, cursor_y,
this->draw_fb_is_dynamic);
} else if (this->draw_fb_is_dynamic) {
this->display.update_skipped();
}
}

View File

@ -86,7 +86,12 @@ protected:
int pixel_format;
float pixel_clock;
float refresh_rate;
// Implementations may choose to track framebuffer writes and set draw_fb
// to false if updates can be skipped. If the do this, they should set
// draw_fb_is_dynamic at initialization time.
bool draw_fb = true;
bool draw_fb_is_dynamic = false;
uint32_t palette[256] = {0}; // internal DAC palette in RGBA format