From 180295936b686d194b7b4c25b9a0dc2038ffc4cb Mon Sep 17 00:00:00 2001 From: Chris Young Date: Thu, 28 Apr 2016 19:18:06 +0100 Subject: Use guigfx.library for 8-bit image quantization This achieves speed-up on OS3/68k platforms where 8-bit modes are more likely to be used, at the expense of lower quality quantization than the former picture.datatype abuse provided. Additionally, caching of BitMaps in palette-mapped modes is now possible. NetSurf now requires guigfx.library (and render.library) in order to start, even on OS4. --- amiga/Makefile.target | 6 +- amiga/bitmap.c | 217 ++++++++++++++++++++++++++------------------------ amiga/bitmap.h | 10 --- amiga/gui.c | 1 + amiga/gui_options.c | 4 +- amiga/libs.c | 12 ++- amiga/plotters.c | 9 ++- 7 files changed, 134 insertions(+), 125 deletions(-) (limited to 'amiga') diff --git a/amiga/Makefile.target b/amiga/Makefile.target index 8e167802a..54957f778 100644 --- a/amiga/Makefile.target +++ b/amiga/Makefile.target @@ -50,10 +50,10 @@ else LDFLAGS += $(shell $(PKG_CONFIG) --libs tre) LDFLAGS += -L$(GCCSDK_INSTALL_ENV)/lib + LDFLAGS += -lpbl -liconv + ifeq ($(SUBTARGET),os3) - LDFLAGS += -lpbl -liconv -lamiga - else - LDFLAGS += -lpbl -liconv + LDFLAGS += -lamiga -lm endif endif diff --git a/amiga/bitmap.c b/amiga/bitmap.c index 9f534443a..6ef5157b2 100644 --- a/amiga/bitmap.c +++ b/amiga/bitmap.c @@ -1,5 +1,5 @@ /* - * Copyright 2008, 2009, 2012 Chris Young + * Copyright 2008, 2009, 2012, 2016 Chris Young * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -30,11 +30,20 @@ #include #include #include + +#include +#include +#include +#ifndef __amigaos4__ +#include +#endif + #ifdef __amigaos4__ #include #endif #include "assert.h" +#include "utils/log.h" #include "utils/nsoption.h" #include "utils/nsurl.h" #include "utils/messages.h" @@ -60,6 +69,8 @@ struct bitmap { int nativebmheight; PLANEPTR native_mask; Object *dto; + APTR drawhandle; + APTR psm; struct nsurl *url; /* temporary storage space */ char *title; /* temporary storage space */ ULONG *icondata; /* for appicons */ @@ -94,7 +105,8 @@ void *amiga_bitmap_create(int width, int height, unsigned int state) bitmap->nativebmwidth = 0; bitmap->nativebmheight = 0; bitmap->native_mask = NULL; - bitmap->dto = NULL; + bitmap->drawhandle = NULL; + bitmap->psm = NULL; bitmap->url = NULL; bitmap->title = NULL; bitmap->icondata = NULL; @@ -134,16 +146,13 @@ void amiga_bitmap_destroy(void *bitmap) if(bm) { - if((bm->nativebm) && (bm->native == AMI_NSBM_TRUECOLOUR)) { + if((bm->nativebm)) { // && (bm->native == AMI_NSBM_TRUECOLOUR)) { ami_rtg_freebitmap(bm->nativebm); } - if(bm->dto) { - /**\todo find out why this crashes on exit but not during normal program execution */ - DisposeDTObject(bm->dto); - } - if(bm->native_mask) FreeRaster(bm->native_mask, bm->width, bm->height); + if(bm->drawhandle) ReleaseDrawHandle(bm->drawhandle); + if(bm->psm) DeletePenShareMap(bm->psm); FreeVec(bm->pixdata); if(bm->url) nsurl_unref(bm->url); @@ -152,7 +161,8 @@ void amiga_bitmap_destroy(void *bitmap) bm->pixdata = NULL; bm->nativebm = NULL; bm->native_mask = NULL; - bm->dto = NULL; + bm->drawhandle = NULL; + bm->psm = NULL; bm->url = NULL; bm->title = NULL; @@ -192,13 +202,15 @@ void amiga_bitmap_modified(void *bitmap) { struct bitmap *bm = bitmap; - if((bm->nativebm) && (bm->native == AMI_NSBM_TRUECOLOUR)) + if((bm->nativebm)) // && (bm->native == AMI_NSBM_TRUECOLOUR)) ami_rtg_freebitmap(bm->nativebm); - if(bm->dto) DisposeDTObject(bm->dto); + if(bm->drawhandle) ReleaseDrawHandle(bm->drawhandle); + if(bm->psm) DeletePenShareMap(bm->psm); if(bm->native_mask) FreeRaster(bm->native_mask, bm->width, bm->height); bm->nativebm = NULL; - bm->dto = NULL; + bm->drawhandle = NULL; + bm->psm = NULL; bm->native_mask = NULL; bm->native = AMI_NSBM_NONE; } @@ -288,17 +300,25 @@ static size_t bitmap_get_bpp(void *vbitmap) return 4; } -#ifdef __amigaos4__ static void ami_bitmap_argb_to_rgba(struct bitmap *bm) { if(bm == NULL) return; ULONG *data = (ULONG *)amiga_bitmap_get_buffer(bm); - for(int i = 0; i < ((amiga_bitmap_get_rowstride(bm) / sizeof(ULONG)) * bm->height); i++) { + for(int i = 0; i < (bm->width * bm->height); i++) { data[i] = (data[i] << 8) | (data[i] >> 24); } } -#endif + +static void ami_bitmap_rgba_to_argb(struct bitmap *bm) +{ + if(bm == NULL) return; + + ULONG *data = (ULONG *)amiga_bitmap_get_buffer(bm); + for(int i = 0; i < (bm->width * bm->height); i++) { + data[i] = (data[i] >> 8) | (data[i] << 24); + } +} #ifdef BITMAP_DUMP void bitmap_dump(struct bitmap *bitmap) @@ -385,41 +405,64 @@ struct bitmap *ami_bitmap_from_datatype(char *filename) return bm; } -static inline struct BitMap *ami_bitmap_get_truecolour(struct bitmap *bitmap,int width,int height,struct BitMap *friendbm) +static inline struct BitMap *ami_bitmap_get_generic(struct bitmap *bitmap, int width, int height, struct BitMap *friendbm, int type) { struct BitMap *tbm = NULL; - if(!bitmap) return NULL; - - if((bitmap->native != AMI_NSBM_NONE) && (bitmap->native != AMI_NSBM_TRUECOLOUR)) { - amiga_bitmap_modified(bitmap); - } - if(bitmap->nativebm) { - if((bitmap->nativebmwidth == width) && (bitmap->nativebmheight==height)) - { + if((bitmap->nativebmwidth == width) && (bitmap->nativebmheight == height)) { tbm = bitmap->nativebm; return tbm; - } - else if((bitmap->nativebmwidth == bitmap->width) && (bitmap->nativebmheight==bitmap->height)) - { + } else if((bitmap->nativebmwidth == bitmap->width) && + (bitmap->nativebmheight == bitmap->height)) { // >= width/height ? tbm = bitmap->nativebm; - } - else - { - if(bitmap->nativebm) ami_rtg_freebitmap(bitmap->nativebm); - bitmap->nativebm = NULL; + } else { + if(bitmap->nativebm) amiga_bitmap_modified(bitmap); } } - if(!tbm) - { - if((tbm = ami_rtg_allocbitmap(bitmap->width, bitmap->height, 32, 0, - friendbm, AMI_BITMAP_FORMAT))) { - ami_rtg_writepixelarray(amiga_bitmap_get_buffer(bitmap), - tbm, bitmap->width, bitmap->height, - bitmap->width * 4, AMI_BITMAP_FORMAT); + if(tbm == NULL) { + if(type == AMI_NSBM_TRUECOLOUR) { + if((tbm = ami_rtg_allocbitmap(bitmap->width, bitmap->height, 32, 0, + friendbm, AMI_BITMAP_FORMAT))) { + ami_rtg_writepixelarray(amiga_bitmap_get_buffer(bitmap), + tbm, bitmap->width, bitmap->height, + bitmap->width * 4, AMI_BITMAP_FORMAT); + } + } else { + if((tbm = ami_rtg_allocbitmap(bitmap->width, bitmap->height, + 8, 0, friendbm, AMI_BITMAP_FORMAT))) { + + struct RastPort rp; + InitRastPort(&rp); + rp.BitMap = tbm; + ULONG dithermode = DITHERMODE_NONE; + + if(nsoption_int(dither_quality) == 1) { + dithermode = DITHERMODE_EDD; + } else if(nsoption_int(dither_quality) == 2) { + dithermode = DITHERMODE_FS; + } + + ami_bitmap_rgba_to_argb(bitmap); + bitmap->psm = CreatePenShareMap(TAG_DONE); + AddPixelArray(bitmap->psm, (ULONG *)amiga_bitmap_get_buffer(bitmap), + bitmap->width, bitmap->height, + GGFX_PixelFormat, PIXFMT_0RGB_32, TAG_DONE); + + bitmap->drawhandle = ObtainDrawHandle(bitmap->psm, &rp, scrn->ViewPort.ColorMap, + GGFX_DitherMode, dithermode, + TAG_DONE); + + APTR ddh = CreateDirectDrawHandle(bitmap->drawhandle, + bitmap->width, bitmap->height, + bitmap->width, bitmap->height, NULL); + + DirectDrawTrueColor(ddh, (ULONG *)amiga_bitmap_get_buffer(bitmap), 0, 0, TAG_DONE); + DeleteDirectDrawHandle(ddh); + ami_bitmap_argb_to_rgba(bitmap); + } } if(nsoption_int(cache_bitmaps) == 2) @@ -427,7 +470,7 @@ static inline struct BitMap *ami_bitmap_get_truecolour(struct bitmap *bitmap,int bitmap->nativebm = tbm; bitmap->nativebmwidth = bitmap->width; bitmap->nativebmheight = bitmap->height; - bitmap->native = AMI_NSBM_TRUECOLOUR; + bitmap->native = type; } } @@ -435,25 +478,29 @@ static inline struct BitMap *ami_bitmap_get_truecolour(struct bitmap *bitmap,int { struct BitMap *scaledbm; struct BitScaleArgs bsa; + int depth = 32; + if(type == AMI_NSBM_PALETTEMAPPED) depth = 8; - scaledbm = ami_rtg_allocbitmap(width, height, 32, 0, + scaledbm = ami_rtg_allocbitmap(width, height, depth, 0, friendbm, AMI_BITMAP_FORMAT); #ifdef __amigaos4__ - if(__builtin_expect(GfxBase->LibNode.lib_Version >= 53, 1)) { - /* AutoDoc says v52, but this function isn't in OS4.0, so checking for v53 (OS4.1) */ + if(__builtin_expect(((GfxBase->LibNode.lib_Version >= 53) && + (type == AMI_NSBM_TRUECOLOUR)), 1)) { + /* AutoDoc says v52, but this function isn't in OS4.0, so checking for v53 (OS4.1) + * Additionally, when we use friend BitMaps in non 32-bit modes it freezes the OS */ uint32 flags = 0; if(nsoption_bool(scale_quality)) flags |= COMPFLAG_SrcFilter; CompositeTags(COMPOSITE_Src, tbm, scaledbm, - COMPTAG_ScaleX,COMP_FLOAT_TO_FIX((float)width/bitmap->width), - COMPTAG_ScaleY,COMP_FLOAT_TO_FIX((float)height/bitmap->height), + COMPTAG_ScaleX, COMP_FLOAT_TO_FIX((float)width/bitmap->width), + COMPTAG_ScaleY, COMP_FLOAT_TO_FIX((float)height/bitmap->height), COMPTAG_Flags, flags, - COMPTAG_DestX,0, - COMPTAG_DestY,0, - COMPTAG_DestWidth,width, - COMPTAG_DestHeight,height, - COMPTAG_OffsetX,0, - COMPTAG_OffsetY,0, + COMPTAG_DestX, 0, + COMPTAG_DestY, 0, + COMPTAG_DestWidth, width, + COMPTAG_DestHeight, height, + COMPTAG_OffsetX, 0, + COMPTAG_OffsetY, 0, COMPTAG_FriendBitMap, scrn->RastPort.BitMap, TAG_DONE); } else /* Do it the old-fashioned way. This is pretty slow, even on OS4.1 */ @@ -487,13 +534,23 @@ static inline struct BitMap *ami_bitmap_get_truecolour(struct bitmap *bitmap,int bitmap->nativebm = tbm; bitmap->nativebmwidth = width; bitmap->nativebmheight = height; - bitmap->native = AMI_NSBM_TRUECOLOUR; + bitmap->native = type; } } return tbm; } + +static inline struct BitMap *ami_bitmap_get_truecolour(struct bitmap *bitmap,int width,int height,struct BitMap *friendbm) +{ + if((bitmap->native != AMI_NSBM_NONE) && (bitmap->native != AMI_NSBM_TRUECOLOUR)) { + amiga_bitmap_modified(bitmap); + } + + return ami_bitmap_get_generic(bitmap, width, height, friendbm, AMI_NSBM_TRUECOLOUR); +} + PLANEPTR ami_bitmap_get_mask(struct bitmap *bitmap, int width, int height, struct BitMap *n_bm) { @@ -525,62 +582,22 @@ PLANEPTR ami_bitmap_get_mask(struct bitmap *bitmap, int width, } static inline struct BitMap *ami_bitmap_get_palettemapped(struct bitmap *bitmap, - int width, int height) + int width, int height, struct BitMap *friendbm) { - struct BitMap *dtbm; - if((bitmap->native != AMI_NSBM_NONE) && (bitmap->native != AMI_NSBM_PALETTEMAPPED)) { amiga_bitmap_modified(bitmap); } - /* Dispose the DataTypes object if we've performed a layout already, - and we need to scale, as scaling can only be performed before - the first GM_LAYOUT */ - - if(bitmap->dto && - ((bitmap->nativebmwidth != width) || - (bitmap->nativebmheight != height))) { - DisposeDTObject(bitmap->dto); - bitmap->dto = NULL; - } - - if(bitmap->dto == NULL) { - bitmap->dto = ami_datatype_object_from_bitmap(bitmap); - - SetDTAttrs(bitmap->dto, NULL, NULL, - PDTA_Screen, scrn, - PDTA_ScaleQuality, nsoption_bool(scale_quality), - PDTA_DitherQuality, nsoption_int(dither_quality), - PDTA_FreeSourceBitMap, TRUE, - TAG_DONE); - - if((bitmap->width != width) || (bitmap->height != height)) { - IDoMethod(bitmap->dto, PDTM_SCALE, width, height, 0); - } - - if((DoDTMethod(bitmap->dto, 0, 0, DTM_PROCLAYOUT, 0, 1)) == 0) - return NULL; - } - - GetDTAttrs(bitmap->dto, - PDTA_DestBitMap, &dtbm, - TAG_END); - - bitmap->nativebmwidth = width; - bitmap->nativebmheight = height; - - /**\todo Native bitmaps are stored as DataTypes Objects here? - This is sub-optimal and they should be cached as BitMaps according to user - preferences */ - bitmap->native = AMI_NSBM_PALETTEMAPPED; - return dtbm; + return ami_bitmap_get_generic(bitmap, width, height, friendbm, AMI_NSBM_PALETTEMAPPED); } struct BitMap *ami_bitmap_get_native(struct bitmap *bitmap, int width, int height, struct BitMap *friendbm) { + if(bitmap == NULL) return NULL; + if(__builtin_expect(ami_plot_screen_is_palettemapped() == true, 0)) { - return ami_bitmap_get_palettemapped(bitmap, width, height); + return ami_bitmap_get_palettemapped(bitmap, width, height, friendbm); } else { return ami_bitmap_get_truecolour(bitmap, width, height, friendbm); } @@ -673,12 +690,6 @@ void ami_bitmap_set_icondata(struct bitmap *bm, ULONG *icondata) bm->icondata = icondata; } -bool ami_bitmap_has_dto(struct bitmap *bm) -{ - if(bm->dto) return true; - else return false; -} - bool ami_bitmap_is_nativebm(struct bitmap *bm, struct BitMap *nbm) { if(bm->nativebm == nbm) return true; diff --git a/amiga/bitmap.h b/amiga/bitmap.h index 743cd8faa..d7dd70bce 100755 --- a/amiga/bitmap.h +++ b/amiga/bitmap.h @@ -82,16 +82,6 @@ ULONG *ami_bitmap_get_icondata(struct bitmap *bm); */ void ami_bitmap_set_icondata(struct bitmap *bm, ULONG *icondata); -/** - * Test if a bitmap has an associated DataTypes object. - * - * \param bm a bitmap, as returned by bitmap_create() - * \return true if the BitMap has a DataTypes object - * - * This function probably shouldn't be used! - */ -bool ami_bitmap_has_dto(struct bitmap *bm); - /** * Test if a BitMap is owned by a bitmap. * diff --git a/amiga/gui.c b/amiga/gui.c index 9227b7044..9c8908469 100644 --- a/amiga/gui.c +++ b/amiga/gui.c @@ -3921,6 +3921,7 @@ gui_window_create(struct browser_window *bw, (strcmp(nsoption_charp(pubscreen_name), "Workbench") == 0)) iconifygadget = TRUE; + LOG("Creating menu"); struct Menu *menu = ami_menu_create(g->shared); NewList(&g->shared->tab_list); diff --git a/amiga/gui_options.c b/amiga/gui_options.c index 4ac5464e3..221b0da95 100755 --- a/amiga/gui_options.c +++ b/amiga/gui_options.c @@ -505,7 +505,7 @@ void ami_gui_opts_open(void) BOOL proxyhostdisabled = TRUE, proxyauthdisabled = TRUE, proxybypassdisabled = FALSE; BOOL disableanims, animspeeddisabled = FALSE, acceptlangdisabled = FALSE; BOOL scaleselected = nsoption_bool(scale_quality), scaledisabled = FALSE; - BOOL ditherdisable = TRUE, nativebm_disable = FALSE; + BOOL ditherdisable = TRUE; BOOL download_notify_disabled = FALSE, tab_always_show_disabled = FALSE; BOOL ptr_disable = FALSE; char animspeed[10]; @@ -554,7 +554,6 @@ void ami_gui_opts_open(void) if(ami_plot_screen_is_palettemapped() == true) { ditherdisable = FALSE; - nativebm_disable = TRUE; } if(nsoption_bool(http_proxy) == true) @@ -1022,7 +1021,6 @@ void ami_gui_opts_open(void) LAYOUT_AddChild, gow->objects[GID_OPTS_NATIVEBM] = ChooserObj, GA_ID, GID_OPTS_NATIVEBM, GA_RelVerify, TRUE, - GA_Disabled, nativebm_disable, CHOOSER_PopUp, TRUE, #ifdef __amigaos4__ CHOOSER_LabelArray, nativebmopts, diff --git a/amiga/libs.c b/amiga/libs.c index 7c130a800..2303d35e7 100644 --- a/amiga/libs.c +++ b/amiga/libs.c @@ -169,6 +169,8 @@ AMINS_LIB_STRUCT(Locale); AMINS_LIB_STRUCT(P96); AMINS_LIB_STRUCT(Workbench); +AMINS_LIB_STRUCT(GuiGFX); + AMINS_CLASS_STRUCT(ARexx); AMINS_CLASS_STRUCT(Bevel); AMINS_CLASS_STRUCT(BitMap); @@ -224,14 +226,16 @@ bool ami_libs_open(void) if(GfxBase->LibNode.lib_Version < 54) AMINS_LIB_OPEN("Picasso96API.library", 0, P96, "main", 1, false) + /* Non-OS provided libraries */ + AMINS_LIB_OPEN("guigfx.library", 9, GuiGFX, "main", 1, true) + /* NB: timer.device is opened in schedule.c (ultimately by the scheduler process). * The library base and interface are obtained there, rather than here, due to * the additional complexities of opening devices, which aren't important here * (as we only need the library interface), but are important for the scheduler * (as it also uses the device interface). We trust that the scheduler has - * initialised before any other code requires the timer's library interface - * (this is ensured by waiting for the scheduler to start up) and that it is - * OK to use a child process' timer interface, to avoid opening it twice. + * initialised before any other code requires the timer's library interface, + * to avoid opening it twice. */ /* BOOPSI classes. @@ -298,6 +302,8 @@ void ami_libs_close(void) AMINS_CLASS_CLOSE(Window) /* Libraries */ + AMINS_LIB_CLOSE(GuiGFX) + AMINS_LIB_CLOSE(Asl) AMINS_LIB_CLOSE(DataTypes) AMINS_LIB_CLOSE(Diskfont) diff --git a/amiga/plotters.c b/amiga/plotters.c index 9c4f8b068..9c3c3c7f1 100644 --- a/amiga/plotters.c +++ b/amiga/plotters.c @@ -49,6 +49,8 @@ #include "amiga/rtg.h" #include "amiga/utf8.h" +//#define AMI_PLOTTER_DEBUG 1 + HOOKF(void, ami_bitmap_tile_hook, struct RastPort *, rp, struct BackFillMessage *); struct bfbitmap { @@ -153,6 +155,8 @@ void ami_init_layers(struct gui_globals *gg, ULONG width, ULONG height, bool for /* Screen depth is reported as 24 even when it's actually 32-bit. * We get freezes and other problems on OS4 if we befriend at any * other depths, hence this check. + * \todo use friend BitMaps but avoid CompositeTags() at non-32-bit + * as that seems to be the cause of the problems. */ if((depth >= 24) && (force32bit == false)) friend = scrn->RastPort.BitMap; #endif @@ -613,8 +617,7 @@ static bool ami_bitmap(int x, int y, int width, int height, struct bitmap *bitma #endif } - if((ami_bitmap_has_dto(bitmap) == false) && (ami_bitmap_is_nativebm(bitmap, tbm) == false)) { - /**\todo is this logic logical? */ + if((ami_bitmap_is_nativebm(bitmap, tbm) == false)) { ami_rtg_freebitmap(tbm); } @@ -719,7 +722,7 @@ static bool ami_bitmap_tile(int x, int y, int width, int height, #endif FreeVec(bfh); - if((ami_bitmap_has_dto(bitmap) == false) && (ami_bitmap_is_nativebm(bitmap, tbm) == false)) { + if((ami_bitmap_is_nativebm(bitmap, tbm) == false)) { /**\todo is this logic logical? */ ami_rtg_freebitmap(tbm); } -- cgit v1.2.3