diff --git a/devices/video/atimach64gx.cpp b/devices/video/atimach64gx.cpp index e6cab6d..8ffb01b 100644 --- a/devices/video/atimach64gx.cpp +++ b/devices/video/atimach64gx.cpp @@ -164,6 +164,8 @@ AtiMach64Gx::AtiMach64Gx() insert_bits(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, diff --git a/devices/video/atirage.cpp b/devices/video/atirage.cpp index 14d88a2..7362ec9 100644 --- a/devices/video/atirage.cpp +++ b/devices/video/atirage.cpp @@ -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(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, diff --git a/devices/video/display.h b/devices/video/display.h index fc9f737..a8900cc 100644 --- a/devices/video/display.h +++ b/devices/video/display.h @@ -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 convert_fb_cb, std::function 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 draw_hw_cursor, diff --git a/devices/video/display_sdl.cpp b/devices/video/display_sdl.cpp index b2544be..b2b7ead 100644 --- a/devices/video/display_sdl.cpp +++ b/devices/video/display_sdl.cpp @@ -107,7 +107,8 @@ void Display::blank() { void Display::update(std::function convert_fb_cb, std::function 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 conver SDL_RenderPresent(impl->renderer); } +void Display::update_skipped() { + // SDL implementation does not care about skipped updates. +} + void Display::setup_hw_cursor(std::function draw_hw_cursor, int cursor_width, int cursor_height) { uint8_t* dst_buf; diff --git a/devices/video/videoctrl.cpp b/devices/video/videoctrl.cpp index 988d20f..dcd39c3 100644 --- a/devices/video/videoctrl.cpp +++ b/devices/video/videoctrl.cpp @@ -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(); } } diff --git a/devices/video/videoctrl.h b/devices/video/videoctrl.h index 91b7b28..2a4ab2d 100644 --- a/devices/video/videoctrl.h +++ b/devices/video/videoctrl.h @@ -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