diff options
author | Richard Wilson <rjw@netsurf-browser.org> | 2004-07-19 23:35:12 +0000 |
---|---|---|
committer | Richard Wilson <rjw@netsurf-browser.org> | 2004-07-19 23:35:12 +0000 |
commit | d18f4397c7906880facdf7dc533d663e086771e6 (patch) | |
tree | 0677d7be5b57a18192f4ac8c5560ebf7419644b1 /riscos/buffer.c | |
parent | 2fedec98f917f221e228f71df62670a8e43c4d6a (diff) | |
download | netsurf-d18f4397c7906880facdf7dc533d663e086771e6.tar.gz netsurf-d18f4397c7906880facdf7dc533d663e086771e6.tar.bz2 |
[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
Diffstat (limited to 'riscos/buffer.c')
-rw-r--r-- | riscos/buffer.c | 168 |
1 files changed, 168 insertions, 0 deletions
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 <not_ginger_matt@users.sourceforge.net> + */ + +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#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; +} |