From d18f4397c7906880facdf7dc533d663e086771e6 Mon Sep 17 00:00:00 2001 From: Richard Wilson Date: Mon, 19 Jul 2004 23:35:12 +0000 Subject: [project @ 2004-07-19 23:35:12 by rjw] Double buffering for animations to remove flicker. Background font blending turned on by default. svn path=/import/netsurf/; revision=1121 --- riscos/buffer.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 riscos/buffer.c (limited to 'riscos/buffer.c') diff --git a/riscos/buffer.c b/riscos/buffer.c new file mode 100644 index 000000000..bc3c2cc72 --- /dev/null +++ b/riscos/buffer.c @@ -0,0 +1,168 @@ +/* + * This file is part of NetSurf, http://netsurf.sourceforge.net/ + * Licensed under the GNU General Public License, + * http://www.opensource.org/licenses/gpl-license + * Copyright 2004 Richard Wilson + */ + +#include +#include +#include +#include "oslib/colourtrans.h" +#include "oslib/os.h" +#include "oslib/osspriteop.h" +#include "oslib/wimp.h" +#include "netsurf/riscos/buffer.h" +#include "netsurf/riscos/wimp.h" +#include "netsurf/utils/log.h" + +/* SCREEN BUFFERING + ================ + + Because RISC OS provides no native way for windows to be buffered (ie + the contents is only updated when the task has finished doing any + drawing) certain situation cause the window contents to flicker in an + undesirable manner. Examples of this are GIF and MNG animations, and + web pages with fixed backgrounds. + + To overcome this, a very simple, transparent, interface is provided here + to allow for output to be buffered. It should be noted that screen + buffering can lower the perceived client response time as the user is + unable to see that the application is doing anything. + + [rjw] - Mon 19th July 2004 +*/ + + +/** The current buffer +*/ +static osspriteop_area *buffer = NULL; + +/** The current clip area +*/ +static os_box clipping; + +/** The current save area +*/ +static osspriteop_save_area *save_area; +static osspriteop_area *context1; +static osspriteop_id context2; +static osspriteop_save_area *context3; + + +/** + * Opens a buffer for writing to. + * + * \param redraw the current WIMP redraw area to buffer + */ +void ro_gui_buffer_open(wimp_draw *redraw) { + int size; + int orig_x0, orig_y0; + int buffer_size; + os_coord sprite_size; + os_error *error; + + /* Close any open buffer + */ + if (buffer) ro_gui_buffer_close(); + + /* Store our clipping region + */ + clipping = redraw->clip; + + /* Work out how much buffer we need + */ + sprite_size.x = clipping.x1 - clipping.x0 + 1; + sprite_size.y = clipping.y1 - clipping.y0 + 1; + ro_convert_os_units_to_pixels(&sprite_size, (os_mode)-1); + + /* Create our buffer (assume 32bpp for now (!)) + */ + buffer_size = sizeof(osspriteop_area) + sizeof(osspriteop_header) + + (sprite_size.x * sprite_size.y * 4) + 2048; + if (!(buffer = (osspriteop_area *)malloc(buffer_size))) return; + + /* Fill in the sprite area details + */ + buffer->size = buffer_size; + buffer->sprite_count = 0; + buffer->first = 16; + buffer->used = 16; + + /* Fill in the sprite header details + */ + if (xosspriteop_get_sprite_user_coords(osspriteop_NAME, buffer, + "buffer", (osbool)1, + clipping.x0, clipping.y0, clipping.x1, clipping.y1)) { + free(buffer); + buffer = NULL; + return; + } + + /* Allocate OS_SpriteOp save area + */ + if ((error = xosspriteop_read_save_area_size(osspriteop_NAME, buffer, + (osspriteop_id)"buffer", &size))) { + LOG(("Save error: %s", error->errmess)); + free(buffer); + buffer = NULL; + return; + } + if (!(save_area = malloc((unsigned)size))) { + free(buffer); + buffer = NULL; + return; + } + save_area->a[0] = 0; + + /* Switch output to sprite + */ + if ((error = xosspriteop_switch_output_to_sprite(osspriteop_NAME, buffer, + (osspriteop_id)"buffer", save_area, + 0, (int *)&context1, (int *)&context2, (int *)&context3))) { + LOG(("Switching error: %s", error->errmess)); + free(save_area); + free(buffer); + buffer = NULL; + return; + } + + /* Move the origin such that (x0, y0) becomes (0, 0). To do this + we use VDU 29,(1 << 16) - x0; (1 << 16) - y0; because RISC OS + is so insanely legacy driven. + */ + orig_x0 = (1 << 16) - clipping.x0; + orig_y0 = (1 << 16) - clipping.y0; + os_writec((char)29); + os_writec(orig_x0 & 0xff); os_writec(orig_x0 >> 8); + os_writec(orig_y0 & 0xff); os_writec(orig_y0 >> 8); +} + + +/** + * Closes any open buffer and flushes the contents to screen + */ +void ro_gui_buffer_close(void) { + + /* Check we have an open buffer + */ + if (!buffer) return; + + /* Remove any redirection and origin hacking + */ + xosspriteop_switch_output_to_sprite(osspriteop_PTR, + context1, context2, context3, + 0, 0, 0, 0); + free(save_area); + + /* Plot the contents to screen + */ + xosspriteop_put_sprite_user_coords(osspriteop_NAME, + buffer, (osspriteop_id)"buffer", + clipping.x0, clipping.y0, (os_action)0); + + /* Free our memory + */ + free(buffer); + buffer = NULL; +} -- cgit v1.2.3