From fb1db30c09b083bebe33b81f4f6771aed21399f7 Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Mon, 30 Mar 2015 04:26:56 -0700 Subject: sr: Fix all the graphics issues * Get rid of all the jank and flicker. * Fix preserved backbuffer * Simplify the code, all drawing happens on a single thread now. Change-Id: I36e1deee0663defd8aea1eba985e3ecbd408eac0 --- recovery.cpp | 8 ++--- screen_ui.cpp | 93 ++++++++++++++++++++++++++++------------------------------- screen_ui.h | 5 +++- 3 files changed, 52 insertions(+), 54 deletions(-) diff --git a/recovery.cpp b/recovery.cpp index a4a4a64..cdf1de3 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -557,6 +557,9 @@ static bool erase_volume(const char* volume, bool force = false) { saved_log_file* head = NULL; + ui->SetBackground(RecoveryUI::ERASING); + ui->SetProgressType(RecoveryUI::INDETERMINATE); + if (!force && is_cache) { // If we're reformatting /cache, we load any past logs // (i.e. "/cache/recovery/last_*") and the current log @@ -604,9 +607,6 @@ static bool erase_volume(const char* volume, bool force = false) { ui->Print("Formatting %s...\n", volume); - ui->SetBackground(RecoveryUI::ERASING); - ui->SetProgressType(RecoveryUI::INDETERMINATE); - if (volume[0] == '/') { ensure_path_unmounted(volume); } @@ -1038,7 +1038,7 @@ prompt_and_wait(Device* device, int status) { switch (status) { case INSTALL_SUCCESS: case INSTALL_NONE: - ui->SetBackground(RecoveryUI::NO_COMMAND); + ui->SetBackground(RecoveryUI::NONE); break; case INSTALL_ERROR: diff --git a/screen_ui.cpp b/screen_ui.cpp index 992210b..f87e298 100644 --- a/screen_ui.cpp +++ b/screen_ui.cpp @@ -87,6 +87,7 @@ ScreenRecoveryUI::ScreenRecoveryUI() : backgroundIcon[i] = nullptr; } pthread_mutex_init(&updateMutex, nullptr); + pthread_cond_init(&progressCondition, NULL); } // Clear the screen and draw the currently selected background icon (if any). @@ -129,6 +130,8 @@ void ScreenRecoveryUI::draw_background_locked(Icon icon) { } } + LOGV("textX=%d textY=%d iconX=%d iconY=%d", textX, textY, iconX, iconY); + gr_color(255, 255, 255, 255); gr_texticon(textX, textY, text_surface); } @@ -139,9 +142,6 @@ void ScreenRecoveryUI::draw_background_locked(Icon icon) { void ScreenRecoveryUI::draw_progress_locked() { if (currentIcon == D_ERROR) return; - gr_color(0, 0, 0, 255); - gr_clear(); - if (currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) { GRSurface* icon = installation[installingFrame]; gr_blit(icon, 0, 0, gr_get_width(icon), gr_get_height(icon), iconX, iconY); @@ -153,7 +153,7 @@ void ScreenRecoveryUI::draw_progress_locked() { int height = gr_get_height(progressBarEmpty); int dx = (gr_fb_width() - width)/2; - int dy = (3*gr_fb_height() + iconHeight - 2*height)/4; + int dy = (gr_fb_height() / 2) + (iconHeight / 2); // Erase behind the progress bar (in case this was a progress-only update) gr_color(0, 0, 0, 255); @@ -277,14 +277,8 @@ void ScreenRecoveryUI::draw_dialog() { int x, y, w, h; - if (dialog_show_log) { - draw_background_locked(NONE); - } - else { - draw_background_locked(dialog_icon); - if (dialog_icon == HEADLESS) { - return; - } + if (dialog_icon == HEADLESS) { + return; } draw_header_icon(); @@ -341,23 +335,17 @@ void ScreenRecoveryUI::draw_dialog() // Redraw everything on the screen. Does not flip pages. // Should only be called with updateMutex locked. void ScreenRecoveryUI::draw_screen_locked() { - if (!show_text) { - draw_background_locked(currentIcon); - draw_progress_locked(); - } else { + draw_background_locked(currentIcon); - if (DialogShowing()) { - draw_dialog(); - return; - } - gr_color(0, 0, 0, 255); - gr_clear(); + if (DialogShowing()) { + draw_dialog(); + return; + } - if (currentIcon == INSTALLING_UPDATE || currentIcon == VIEWING_LOG) { + if (show_text) { + if (currentIcon == ERASING || currentIcon == INSTALLING_UPDATE || currentIcon == VIEWING_LOG) { size_t y = header_height_ + 4; - draw_background_locked(currentIcon); - SetColor(LOG); int cx, cy; gr_set_font("log"); @@ -393,15 +381,9 @@ void ScreenRecoveryUI::draw_screen_locked() { // Redraw everything on the screen and flip the screen (make it visible). // Should only be called with updateMutex locked. void ScreenRecoveryUI::update_screen_locked() { - draw_screen_locked(); - gr_flip(); -} - -// Updates only the progress bar, if possible, otherwise redraws the screen. -// Should only be called with updateMutex locked. -void ScreenRecoveryUI::update_progress_locked() { - draw_progress_locked(); - gr_flip(); + update_waiting = true; + pthread_cond_signal(&progressCondition); + LOGV("%s: %p\n", __func__, __builtin_return_address(0)); } // Keeps the progress bar updated, even when the process is otherwise busy. @@ -419,17 +401,21 @@ void ScreenRecoveryUI::OMGRainbows() void ScreenRecoveryUI::ProgressThreadLoop() { double interval = 1.0 / animation_fps; while (true) { - double start = now(); pthread_mutex_lock(&updateMutex); + if (progressBarType == EMPTY && !update_waiting) + pthread_cond_wait(&progressCondition, &updateMutex); + + bool redraw = false; + double start = now(); - int redraw = 0; + LOGV("loop %f show_text=%d progressBarType=%d waiting=%d\n", start, show_text, progressBarType, update_waiting ); // update the installation animation, if active // skip this if we have a text overlay (too expensive to update) if ((currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) && installing_frames > 0) { installingFrame = (installingFrame + 1) % installing_frames; - redraw = 1; + redraw = true; } // move the progress bar forward on timed intervals, if configured @@ -440,23 +426,31 @@ void ScreenRecoveryUI::ProgressThreadLoop() { if (p > 1.0) p = 1.0; if (p > progress) { progress = p; - redraw = 1; + redraw = true; } } - if (redraw) update_progress_locked(); + if (update_waiting || !pagesIdentical) { + LOGV("call draw_screen_locked\n"); + draw_screen_locked(); + if (!update_waiting) + pagesIdentical = true; + } - pthread_mutex_unlock(&updateMutex); + if (redraw) { + LOGV("call draw_progress_locked\n"); + draw_progress_locked(); + } + gr_flip(); - if (progressBarType == EMPTY) - break; + update_waiting = false; + pthread_mutex_unlock(&updateMutex); double end = now(); // minimum of 20ms delay between frames double delay = interval - (end-start); if (delay < 0.02) delay = 0.02; usleep((long)(delay * 1000000)); - } } @@ -537,6 +531,8 @@ void ScreenRecoveryUI::Init() { LoadLocalizedBitmap("no_command_text", &backgroundText[NO_COMMAND]); LoadLocalizedBitmap("error_text", &backgroundText[D_ERROR]); + pthread_create(&progress_thread_, nullptr, ProgressThreadStartRoutine, this); + RecoveryUI::Init(); } @@ -579,14 +575,12 @@ void ScreenRecoveryUI::SetProgressType(ProgressType type) { pthread_mutex_lock(&updateMutex); if (progressBarType != type) { progressBarType = type; - if (progressBarType != EMPTY) { - pthread_create(&progress_thread_, nullptr, ProgressThreadStartRoutine, this); - } } progressScopeStart = 0; progressScopeSize = 0; progress = 0; - update_progress_locked(); + + update_screen_locked(); pthread_mutex_unlock(&updateMutex); } @@ -598,7 +592,8 @@ void ScreenRecoveryUI::ShowProgress(float portion, float seconds) { progressScopeTime = now(); progressScopeDuration = seconds; progress = 0; - update_progress_locked(); + + update_screen_locked(); pthread_mutex_unlock(&updateMutex); } @@ -612,7 +607,7 @@ void ScreenRecoveryUI::SetProgress(float fraction) { float scale = width * progressScopeSize; if ((int) (progress * scale) != (int) (fraction * scale)) { progress = fraction; - update_progress_locked(); + update_screen_locked(); } } pthread_mutex_unlock(&updateMutex); diff --git a/screen_ui.h b/screen_ui.h index b03b6ef..df77e8b 100644 --- a/screen_ui.h +++ b/screen_ui.h @@ -84,6 +84,8 @@ class ScreenRecoveryUI : public RecoveryUI { bool rtl_locale; pthread_mutex_t updateMutex; + pthread_cond_t progressCondition; + GRSurface* headerIcon; GRSurface* backgroundIcon[NR_ICONS]; GRSurface* backgroundText[NR_ICONS]; @@ -146,6 +148,8 @@ class ScreenRecoveryUI : public RecoveryUI { int header_height_, header_width_; int text_first_row_; + bool update_waiting; + void draw_background_locked(Icon icon); void draw_progress_locked(); int draw_header_icon(); @@ -153,7 +157,6 @@ class ScreenRecoveryUI : public RecoveryUI { void draw_dialog(); void draw_screen_locked(); void update_screen_locked(); - void update_progress_locked(); static void* ProgressThreadStartRoutine(void* data); void ProgressThreadLoop(); -- cgit v1.1