From 0fe0a709ceeae77cc5d91aab318aec27320e09af Mon Sep 17 00:00:00 2001 From: Richard Wilson Date: Sun, 9 Jul 2006 17:38:34 +0000 Subject: Join update boxes if possible to decrease rendering time (optimise bouncing bunny testcase.) svn path=/trunk/netsurf/; revision=2724 --- riscos/gui.c | 3 +- riscos/gui.h | 1 + riscos/window.c | 276 +++++++++++++++++++++++++++++++++++--------------------- 3 files changed, 177 insertions(+), 103 deletions(-) (limited to 'riscos') diff --git a/riscos/gui.c b/riscos/gui.c index 53fd4ea74..3e8efca12 100644 --- a/riscos/gui.c +++ b/riscos/gui.c @@ -862,7 +862,8 @@ void gui_poll(bool active) gui_last_poll = clock(); ro_gui_handle_event(event, &block); schedule_run(); - + ro_gui_window_update_boxes(); + if (gui_reformat_pending && event == wimp_NULL_REASON_CODE) ro_gui_window_process_reformats(); else if (bitmap_maintenance_priority || diff --git a/riscos/gui.h b/riscos/gui.h index f7338c42d..b5665dcda 100644 --- a/riscos/gui.h +++ b/riscos/gui.h @@ -162,6 +162,7 @@ void ro_gui_window_set_scale(struct gui_window *g, float scale); void ro_gui_window_iconise(struct gui_window *g, wimp_full_message_window_info *wi); bool ro_gui_window_navigate_up(struct gui_window *g, const char *url); +void ro_gui_window_update_boxes(void); /* in history.c */ void ro_gui_history_init(void); diff --git a/riscos/window.c b/riscos/window.c index 255cee5c0..aa917f9d4 100644 --- a/riscos/window.c +++ b/riscos/window.c @@ -86,7 +86,19 @@ static browser_mouse_state ro_gui_mouse_drag_state(wimp_mouse_state buttons); static bool ro_gui_window_import_text(struct gui_window *g, const char *filename, bool toolbar); +struct update_box { + int x0; + int y0; + int x1; + int y1; + bool use_buffer; + struct gui_window *g; + union content_msg_data data; + struct update_box *next; +}; +struct update_box *pending_updates; +#define MARGIN 4 /** * Create and open a new browser window. @@ -561,128 +573,188 @@ void ro_gui_window_redraw(struct gui_window *g, wimp_draw *redraw) /** - * Redraw an area of a window. - * - * \param g gui_window - * \param data content_msg_data union with filled in redraw data + * Redraw any pending update boxes. */ - -void gui_window_update_box(struct gui_window *g, - const union content_msg_data *data) -{ - struct content *c = g->bw->current_content; +void ro_gui_window_update_boxes(void) { + struct content *c; osbool more; bool clear_background = false; bool use_buffer; wimp_draw update; int clip_x0, clip_y0, clip_x1, clip_y1; os_error *error; + struct update_box *cur; + struct gui_window *g; + const union content_msg_data *data; + + for (cur = pending_updates; cur != NULL; cur = cur->next) { + g = cur->g; + c = g->bw->current_content; + data = &cur->data; + use_buffer = cur->use_buffer; + if (!c) + continue; - /* in some cases an update can be triggered before a content has fully - * loaded, so current_content is 0 */ - if (!c) - return; - - update.w = g->window; - update.box.x0 = floorf(data->redraw.x * 2 * g->option.scale); - update.box.y0 = -ceilf((data->redraw.y + data->redraw.height) * 2 * - g->option.scale); - update.box.x1 = ceilf((data->redraw.x + data->redraw.width) * 2 * - g->option.scale) + 1; - update.box.y1 = -floorf(data->redraw.y * 2 * g->option.scale) + 1; + update.w = g->window; + update.box.x0 = cur->x0; + update.box.y0 = cur->y0; + update.box.x1 = cur->x1; + update.box.y1 = cur->y1; - error = xwimp_update_window(&update, &more); - if (error) { - LOG(("xwimp_update_window: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - return; - } - - /* Set the current redraw gui_window to get options from - */ - ro_gui_current_redraw_gui = g; - current_redraw_browser = g->bw; - use_buffer = (data->redraw.full_redraw) && - (g->option.buffer_everything || g->option.buffer_animations); + error = xwimp_update_window(&update, &more); + if (error) { + LOG(("xwimp_update_window: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + continue; + } - plot = ro_plotters; - ro_plot_origin_x = update.box.x0 - update.xscroll; - ro_plot_origin_y = update.box.y1 - update.yscroll; - ro_plot_set_scale(g->option.scale); + /* Set the current redraw gui_window to get options from + */ + ro_gui_current_redraw_gui = g; + current_redraw_browser = g->bw; - /* We should clear the background, except for HTML. - */ - if (c->type != CONTENT_HTML) - clear_background = true; + plot = ro_plotters; + ro_plot_origin_x = update.box.x0 - update.xscroll; + ro_plot_origin_y = update.box.y1 - update.yscroll; + ro_plot_set_scale(g->option.scale); - while (more) { - clip_x0 = (update.clip.x0 - ro_plot_origin_x) / 2; - clip_y0 = (ro_plot_origin_y - update.clip.y1) / 2; - clip_x1 = (update.clip.x1 - ro_plot_origin_x) / 2; - clip_y1 = (ro_plot_origin_y - update.clip.y0) / 2; - - if (use_buffer) - ro_gui_buffer_open(&update); - if (data->redraw.full_redraw) { - if (clear_background) { - error = xcolourtrans_set_gcol(os_COLOUR_WHITE, - colourtrans_SET_BG, - os_ACTION_OVERWRITE, 0, 0); - if (error) { - LOG(("xcolourtrans_set_gcol: 0x%x: %s", - error->errnum, - error->errmess)); - warn_user("MiscError", error->errmess); + /* We should clear the background, except for HTML. + */ + if (c->type != CONTENT_HTML) + clear_background = true; + + while (more) { + clip_x0 = (update.clip.x0 - ro_plot_origin_x) / 2; + clip_y0 = (ro_plot_origin_y - update.clip.y1) / 2; + clip_x1 = (update.clip.x1 - ro_plot_origin_x) / 2; + clip_y1 = (ro_plot_origin_y - update.clip.y0) / 2; + + if (use_buffer) + ro_gui_buffer_open(&update); + if (data->redraw.full_redraw) { + if (clear_background) { + error = xcolourtrans_set_gcol(os_COLOUR_WHITE, + colourtrans_SET_BG, + os_ACTION_OVERWRITE, 0, 0); + if (error) { + LOG(("xcolourtrans_set_gcol: 0x%x: %s", + error->errnum, + error->errmess)); + warn_user("MiscError", error->errmess); + } + os_clg(); } - os_clg(); - } - content_redraw(c, 0, 0, - c->width, c->height, - clip_x0, clip_y0, clip_x1, clip_y1, - g->option.scale, - 0xFFFFFF); - } else { - assert(data->redraw.object); - content_redraw(data->redraw.object, - floorf(data->redraw.object_x * - g->option.scale), - ceilf(data->redraw.object_y * - g->option.scale), - data->redraw.object_width * + content_redraw(c, 0, 0, + c->width, c->height, + clip_x0, clip_y0, clip_x1, clip_y1, g->option.scale, - data->redraw.object_height * + 0xFFFFFF); + } else { + assert(data->redraw.object); + content_redraw(data->redraw.object, + floorf(data->redraw.object_x * + g->option.scale), + ceilf(data->redraw.object_y * + g->option.scale), + data->redraw.object_width * + g->option.scale, + data->redraw.object_height * + g->option.scale, + clip_x0, clip_y0, clip_x1, clip_y1, g->option.scale, - clip_x0, clip_y0, clip_x1, clip_y1, - g->option.scale, - 0xFFFFFF); - } + 0xFFFFFF); + } - if (use_buffer) - ro_gui_buffer_close(); - error = xwimp_get_rectangle(&update, &more); - /* RISC OS 3.7 returns an error here if enough buffer was - claimed to cause a new dynamic area to be created. It - doesn't actually stop anything working, so we mask it out - for now until a better fix is found. This appears to be a - bug in RISC OS. */ - if (error && !(use_buffer && - error->errnum == error_WIMP_GET_RECT)) { - LOG(("xwimp_get_rectangle: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - ro_gui_current_redraw_gui = NULL; - current_redraw_browser = NULL; - return; + if (use_buffer) + ro_gui_buffer_close(); + error = xwimp_get_rectangle(&update, &more); + /* RISC OS 3.7 returns an error here if enough buffer was + claimed to cause a new dynamic area to be created. It + doesn't actually stop anything working, so we mask it out + for now until a better fix is found. This appears to be a + bug in RISC OS. */ + if (error && !(use_buffer && + error->errnum == error_WIMP_GET_RECT)) { + LOG(("xwimp_get_rectangle: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + ro_gui_current_redraw_gui = NULL; + current_redraw_browser = NULL; + continue; + } } + + /* Reset the current redraw gui_window to prevent thumbnails from + retaining options + */ + ro_gui_current_redraw_gui = NULL; + current_redraw_browser = NULL; + } + while (pending_updates) { + cur = pending_updates; + pending_updates = pending_updates->next; + free(cur); } + +} +/** + * Redraw an area of a window. + * + * \param g gui_window + * \param data content_msg_data union with filled in redraw data + */ - /* Reset the current redraw gui_window to prevent thumbnails from - retaining options - */ - ro_gui_current_redraw_gui = NULL; - current_redraw_browser = NULL; +void gui_window_update_box(struct gui_window *g, + const union content_msg_data *data) +{ + struct content *c = g->bw->current_content; + bool use_buffer; + int x0, y0, x1, y1; + struct update_box *cur; + + if (!c) + return; + + x0 = floorf(data->redraw.x * 2 * g->option.scale); + y0 = -ceilf((data->redraw.y + data->redraw.height) * 2 * g->option.scale); + x1 = ceilf((data->redraw.x + data->redraw.width) * 2 * g->option.scale) + 1; + y1 = -floorf(data->redraw.y * 2 * g->option.scale) + 1; + use_buffer = (data->redraw.full_redraw) && + (g->option.buffer_everything || g->option.buffer_animations); + + /* try to optimise buffered redraws */ + if (use_buffer) { + for (cur = pending_updates; cur != NULL; cur = cur->next) { + if ((cur->g != g) || (!cur->use_buffer)) + continue; + if ((((cur->x0 - x1) < MARGIN) || ((cur->x1 - x0) < MARGIN)) && + (((cur->y0 - y1) < MARGIN) || ((cur->y1 - y0) < MARGIN))) { + cur->x0 = min(cur->x0, x0); + cur->y0 = min(cur->y0, y0); + cur->x1 = max(cur->x1, x1); + cur->y1 = max(cur->y1, y1); + return; + } + + } + } + cur = malloc(sizeof(struct update_box)); + if (!cur) { + LOG(("No memory for malloc.")); + warn_user("NoMemory", 0); + return; + } + cur->x0 = x0; + cur->y0 = y0; + cur->x1 = x1; + cur->y1 = y1; + cur->next = pending_updates; + pending_updates = cur; + cur->g = g; + cur->use_buffer = use_buffer; + cur->data = *data; } -- cgit v1.2.3