From 4204599fb949fa7eaea9b21213bc09861c7f14bf Mon Sep 17 00:00:00 2001 From: Ole Loots Date: Thu, 19 Apr 2012 22:44:49 +0000 Subject: Optimized bitmap blitting: cache native (converted) bitmaps. This required an change to the convert and blit routines - for opaque images, they convert the whole image. Transparent images are still converted on demand and still only the clipped area is converted. This is incomplete - native buffers should be stored in the well known bitmap buffer, but currently the bitmap struct holds a second buffer which contains converted data. svn path=/trunk/netsurf/; revision=13886 --- atari/plot/font_freetype.c | 2 +- atari/plot/plotter_vdi.c | 528 ++++++++++++++++++++++++++++----------------- 2 files changed, 327 insertions(+), 203 deletions(-) (limited to 'atari/plot') diff --git a/atari/plot/font_freetype.c b/atari/plot/font_freetype.c index 551302e79..917f20b5e 100755 --- a/atari/plot/font_freetype.c +++ b/atari/plot/font_freetype.c @@ -419,7 +419,7 @@ static void draw_glyph8(FONT_PLOTTER self, GRECT * loc, uint8_t * pixdata, int p linebuf[xloop] = (uint32_t)(colour | fontpix); } } - self->plotter->bitmap( self->plotter, fontbmp, loc->g_x, loc->g_y, 0, 0); + self->plotter->bitmap( self->plotter, fontbmp, loc->g_x, loc->g_y, 0, BITMAPF_MONOGLYPH); } static void draw_glyph1(FONT_PLOTTER self, GRECT * loc, uint8_t * pixdata, int pitch, uint32_t colour) diff --git a/atari/plot/plotter_vdi.c b/atari/plot/plotter_vdi.c index 92731719d..59411a140 100755 --- a/atari/plot/plotter_vdi.c +++ b/atari/plot/plotter_vdi.c @@ -87,6 +87,7 @@ static HermesHandle hermes_cnv_h; /* hermes converter instance handle */ static HermesHandle hermes_res_h; static short prev_vdi_clip[4]; +static struct bitmap snapshot; #ifdef WITH_8BPP_SUPPORT static unsigned short sys_pal[256][3]; /*RGB*/ @@ -151,11 +152,10 @@ static int get_clip( GEM_PLOTTER self, struct rect * out ) */ static inline void plotter_get_visible_grect( GEM_PLOTTER self, GRECT * out ) { - /*todo: !!! */ - out->g_x = VIEW( self ).clipping.x0; - out->g_y = VIEW( self ).clipping.y0; - out->g_w = VIEW( self ).clipping.x1 - VIEW( self ).clipping.x0; - out->g_h = VIEW( self ).clipping.y1 - VIEW( self ).clipping.y0; + out->g_x = VIEW( self ).vis_x; + out->g_y = VIEW( self ).vis_y; + out->g_w = VIEW( self ).vis_w; + out->g_h = VIEW( self ).vis_h; } @@ -163,9 +163,10 @@ static inline void plotter_get_visible_grect( GEM_PLOTTER self, GRECT * out ) 1. calculate visible area of framebuffer in coords relative to framebuffer position result: - this function should calc offsets into x,y coords of the framebuffer which - can be drawn. If the framebuffer coords do not fall within the screen region, - all values of visible region are set to zero. + this function should calculates an rectangle relative to the plot origin and + size. + If the ploter coords do not fall within the screen region, + all values of the region are set to zero. */ static inline void update_visible_rect( GEM_PLOTTER p ) { @@ -408,8 +409,10 @@ static int dtor( GEM_PLOTTER self ) free( VIEW(self).mem ); #ifdef WITH_8BPP_SUPPORT - for( i=OFFSET_WEB_PAL; ivdi_handle, i, &sys_pal[i][0] ); + if( DUMMY_PRIV(self)->vfmt.indexed ){ + for( i=OFFSET_WEB_PAL; ivdi_handle, i, &sys_pal[i][0] ); + } } #endif @@ -910,13 +913,26 @@ static MFDB * snapshot_create_std_mfdb(GEM_PLOTTER self, int x, int y, int w, in /* This will create an snapshot of the screen in netsurf ABGR format */ + static struct bitmap * snapshot_create(GEM_PLOTTER self, int x, int y, int w, int h) { int err; MFDB * native; + uint32_t start = clock(); + + // FIXME: This can be optimized a lot. + // 1. do not copy the snapshot to the bitmap buffer + // when the format of screen and bitmap equals. + // just point the bitmap to the native mfdb. + // 2. if we have eddi 1.1, we could optimize that further + // make snapshot_create_native_mfdb just returning a pointer + // to the screen. native = snapshot_create_native_mfdb( self, x, y, w, h ); + if( DUMMY_PRIV(self)->vfmt.bits == 32 ) + goto no_copy; + /* allocate buffer for result bitmap: */ if( DUMMY_PRIV(self)->buf_scr_compat == NULL ) { DUMMY_PRIV(self)->buf_scr_compat = bitmap_create(w, h, 0); @@ -948,6 +964,24 @@ static struct bitmap * snapshot_create(GEM_PLOTTER self, int x, int y, int w, in ); assert( err != 0 ); return( (struct bitmap * )DUMMY_PRIV(self)->buf_scr_compat ); + +no_copy: + + snapshot.width = w; + snapshot.height = h; + snapshot.pixdata = native->fd_addr; + snapshot.native = *native; + snapshot.rowstride = MFDB_STRIDE( w )*4; + + uint32_t row, col; + for( row = 0; rowfd_addr + ((row*native->fd_w))); + for( col=0; colbuf_scr_compat ) > CONV_KEEP_LIMIT ) { - int w = 0; - int h = 1; - w = (CONV_KEEP_LIMIT / DUMMY_PRIV(self)->buf_scr_compat->bpp); - assert( CONV_KEEP_LIMIT == w*DUMMY_PRIV(self)->buf_scr_compat->bpp ); - DUMMY_PRIV(self)->buf_scr_compat = bitmap_realloc( w, h, - DUMMY_PRIV(self)->buf_scr_compat->bpp, - CONV_KEEP_LIMIT, BITMAP_SHRINK, DUMMY_PRIV(self)->buf_scr_compat - ); + if( DUMMY_PRIV(self)->buf_scr_compat != NULL ) { + size_t bs = bitmap_buffer_size( DUMMY_PRIV(self)->buf_scr_compat ); + if( bs > CONV_KEEP_LIMIT ) { + int w = 0; + int h = 1; + w = (CONV_KEEP_LIMIT / DUMMY_PRIV(self)->buf_scr_compat->bpp); + assert( CONV_KEEP_LIMIT == w*DUMMY_PRIV(self)->buf_scr_compat->bpp ); + DUMMY_PRIV(self)->buf_scr_compat = bitmap_realloc( w, h, + DUMMY_PRIV(self)->buf_scr_compat->bpp, + CONV_KEEP_LIMIT, BITMAP_SHRINK, DUMMY_PRIV(self)->buf_scr_compat + ); + } } } static void snapshot_destroy( GEM_PLOTTER self ) { - if( DUMMY_PRIV(self)->buf_scr.fd_addr ) { - free( DUMMY_PRIV(self)->buf_scr.fd_addr ); - DUMMY_PRIV(self)->buf_scr.fd_addr = NULL; - } - if( DUMMY_PRIV(self)->buf_std.fd_addr ) { - free( DUMMY_PRIV(self)->buf_std.fd_addr ); - DUMMY_PRIV(self)->buf_std.fd_addr = NULL; - } - - if( DUMMY_PRIV(self)->buf_scr_compat ) { + free( DUMMY_PRIV(self)->buf_scr.fd_addr ); + if( DUMMY_PRIV(self)->buf_scr_compat != NULL ) { bitmap_destroy( DUMMY_PRIV(self)->buf_scr_compat ); - DUMMY_PRIV(self)->buf_scr_compat = NULL; } + + DUMMY_PRIV(self)->buf_scr.fd_addr = NULL; + DUMMY_PRIV(self)->buf_scr_compat = NULL; + +#ifdef WITH_8BPP_SUPPORT + free( DUMMY_PRIV(self)->buf_std.fd_addr ); + DUMMY_PRIV(self)->buf_std.fd_addr = NULL; +#endif } @@ -1082,94 +1118,129 @@ static inline unsigned char get_stdpx(MFDB * dst, int wdplanesz, int x, int y ) return( ret ); } -static int bitmap_convert_8( GEM_PLOTTER self, - struct bitmap * img, - int x, - int y, - GRECT * clip, - uint32_t bg, - uint32_t flags, - MFDB *out ) +static int bitmap_convert_8( GEM_PLOTTER self, struct bitmap * img, int x, + int y, GRECT * clip, uint32_t bg, uint32_t flags, + MFDB *out ) { - - int dststride; /* stride of dest. image */ - int dstsize; /* size of dest. in byte */ - int err; - int bw; + MFDB native; + MFDB stdform; + int dststride; /* stride of dest. image */ + int dstsize; /* size of dest. in byte */ + int err; + int bw, bh; + int process_w, process_h; struct bitmap * scrbuf = NULL; - struct bitmap * bm; - bool transp = ( ( (img->opaque == false) || ( (flags & BITMAPF_MONOGLYPH) != 0) ) - && ((self->flags & PLOT_FLAG_TRANS) != 0) ); + struct bitmap * source; + bool cache = ( flags & BITMAPF_BUFFER_NATIVE ); + bool opaque = bitmap_get_opaque( img ); + + if( opaque == false ){ + if( ( (self->flags & PLOT_FLAG_TRANS) == 0) + && + ((flags & (BITMAPF_MONOGLYPH|BITMAPF_BUFFER_NATIVE))==0) ){ + opaque = true; + } + } assert( clip->g_h > 0 ); assert( clip->g_w > 0 ); - bm = img; - bw = bitmap_get_width( img ); + process_w = bw = bitmap_get_width( img ); + process_h = bh = bitmap_get_height( img ); - dststride = MFDB_STRIDE( clip->g_w ); - dstsize = ( ((dststride >> 3) * clip->g_h) * self->bpp_virt ); + // The converted bitmap can be saved for subsequent blits, when + // the bitmap is fully opaque + + if( (opaque == true) || (flags & BITMAPF_BUFFER_NATIVE ) ){ + if( img->converted == true ){ + *out = img->native; + return( 0 ); + } + if( ( flags & BITMAPF_MONOGLYPH ) == 0 ){ + cache = true; + } + } + if( ( flags & BITMAPF_MONOGLYPH ) != 0 ){ + assert(cache == false); + } /* (re)allocate buffer for out image: */ /* altough the buffer is named "buf_packed" on 8bit systems */ /* it's not... */ - if( dstsize > DUMMY_PRIV(self)->size_buf_packed) { - int blocks = (dstsize / (CONV_BLOCK_SIZE-1))+1; - if( DUMMY_PRIV(self)->buf_packed == NULL ) - DUMMY_PRIV(self)->buf_packed =(void*)malloc( blocks * CONV_BLOCK_SIZE ); - else - DUMMY_PRIV(self)->buf_packed =(void*)realloc( - DUMMY_PRIV(self)->buf_packed, - blocks * CONV_BLOCK_SIZE - ); - assert( DUMMY_PRIV(self)->buf_packed ); - if( DUMMY_PRIV(self)->buf_packed == NULL ) { + if( cache == false ){ + // the size of the output will match the size of the clipping: + dststride = MFDB_STRIDE( clip->g_w ); + dstsize = ( ((dststride >> 3) * clip->g_h) * self->bpp_virt ); + if( dstsize > DUMMY_PRIV(self)->size_buf_packed) { + int blocks = (dstsize / (CONV_BLOCK_SIZE-1))+1; + if( DUMMY_PRIV(self)->buf_packed == NULL ) + DUMMY_PRIV(self)->buf_packed =(void*)malloc( blocks * CONV_BLOCK_SIZE ); + else + DUMMY_PRIV(self)->buf_packed =(void*)realloc( + DUMMY_PRIV(self)->buf_packed, + blocks * CONV_BLOCK_SIZE + ); + assert( DUMMY_PRIV(self)->buf_packed ); + if( DUMMY_PRIV(self)->buf_packed == NULL ) { + return( 0-ERR_NO_MEM ); + } + DUMMY_PRIV(self)->size_buf_packed = blocks * CONV_BLOCK_SIZE; + } + native.fd_addr = DUMMY_PRIV(self)->buf_packed; + } + else { + // the output image will be completly saved, so size of the output + // image will match the input image size. + dststride = MFDB_STRIDE( bw ); + dstsize = ( ((dststride >> 3) * bh) * self->bpp_virt ); + assert( out->fd_addr == NULL ); + native.fd_addr = (void*)malloc( dstsize ); + if( native.fd_addr == NULL ){ + if( scrbuf != NULL ) + bitmap_destroy( scrbuf ); return( 0-ERR_NO_MEM ); } - DUMMY_PRIV(self)->size_buf_packed = blocks * CONV_BLOCK_SIZE; } /* on 8 bit systems we must convert the TC (ABGR) image to vdi standard format. ( only tested for 256 colors ) - and then convert it to native format + and then convert it to native format with v_trnfm() */ - // realloc mem for stdform - MFDB stdform; - if( transp ){ - if( ((self->flags & PLOT_FLAG_TRANS) != 0) || ( (flags & BITMAPF_MONOGLYPH) != 0) ) { - // point image to snapshot buffer, otherwise allocate mem - MFDB * bg = snapshot_create_std_mfdb( self, x+clip->g_x,y+clip->g_y, clip->g_w, clip->g_h ); - stdform.fd_addr = bg->fd_addr; - } else { - if( dstsize > DUMMY_PRIV(self)->size_buf_planar) { - int blocks = (dstsize / (CONV_BLOCK_SIZE-1))+1; - if( DUMMY_PRIV(self)->buf_planar == NULL ) - DUMMY_PRIV(self)->buf_planar =(void*)malloc( blocks * CONV_BLOCK_SIZE ); - else - DUMMY_PRIV(self)->buf_planar =(void*)realloc( - DUMMY_PRIV(self)->buf_planar, - blocks * CONV_BLOCK_SIZE - ); - assert( DUMMY_PRIV(self)->buf_planar ); - if( DUMMY_PRIV(self)->buf_planar == NULL ) { - return( 0-ERR_NO_MEM ); - } - DUMMY_PRIV(self)->size_buf_planar = blocks * CONV_BLOCK_SIZE; + if( opaque == false ){ + // point image to snapshot buffer, otherwise allocate mem + MFDB * bg = snapshot_create_std_mfdb( self, x, y, clip->g_w, + clip->g_h ); + stdform.fd_addr = bg->fd_addr; + bh = clip->g_h; + } else { + if( dstsize > DUMMY_PRIV(self)->size_buf_planar) { + int blocks = (dstsize / (CONV_BLOCK_SIZE-1))+1; + if( DUMMY_PRIV(self)->buf_planar == NULL ) + DUMMY_PRIV(self)->buf_planar =(void*)malloc( blocks * CONV_BLOCK_SIZE ); + else + DUMMY_PRIV(self)->buf_planar =(void*)realloc( + DUMMY_PRIV(self)->buf_planar, + blocks * CONV_BLOCK_SIZE + ); + assert( DUMMY_PRIV(self)->buf_planar ); + if( DUMMY_PRIV(self)->buf_planar == NULL ) { + return( 0-ERR_NO_MEM ); } - stdform.fd_addr = DUMMY_PRIV(self)->buf_planar; + DUMMY_PRIV(self)->size_buf_planar = blocks * CONV_BLOCK_SIZE; } + stdform.fd_addr = DUMMY_PRIV(self)->buf_planar; } stdform.fd_w = dststride; - stdform.fd_h = clip->g_h; + stdform.fd_h = bh; stdform.fd_wdwidth = dststride >> 4; stdform.fd_stand = 1; stdform.fd_nplanes = (short)self->bpp_virt; stdform.fd_r1 = stdform.fd_r2 = stdform.fd_r3 = 0; - int img_stride = bitmap_get_rowstride(bm); + int img_stride = bitmap_get_rowstride(img); uint32_t prev_pixel = 0x12345678; unsigned long col = 0; unsigned char val = 0; @@ -1177,25 +1248,17 @@ static int bitmap_convert_8( GEM_PLOTTER self, uint32_t pixel; int wdplanesize = stdform.fd_wdwidth*stdform.fd_h; - - // apply transparency. - if( transp ){ + if( opaque == false ){ + // apply transparency and convert to vdi std format unsigned long bgcol = 0; unsigned char prev_col = 0; - - for( y=0; yg_h; y++ ){ - - row = (uint32_t *)(bm->pixdata + (img_stride * (y+clip->g_y))); - + row = (uint32_t *)(img->pixdata + (img_stride * (y+clip->g_y))); for( x=0; xg_w; x++ ){ - pixel = row[x+clip->g_x]; - if( (pixel&0xFF) == 0 ){ continue; } - if( (pixel&0xFF) < 0xF0 ){ col = get_stdpx( &stdform, wdplanesize,x,y ); if( (col != prev_col) || (y == 0) ) @@ -1211,7 +1274,7 @@ static int bitmap_convert_8( GEM_PLOTTER self, | ((pixel&0xFF0000)>>16) ); val = RGB_TO_VDI( col ); } - set_stdpx( &stdform, wdplanesize, x,y, val ); + set_stdpx( &stdform, wdplanesize, x, y, val ); } else { if( pixel != prev_pixel ){ /* convert pixel value to vdi color index: */ @@ -1222,18 +1285,19 @@ static int bitmap_convert_8( GEM_PLOTTER self, val = RGB_TO_VDI( col ); prev_pixel = pixel; } - set_stdpx( &stdform, wdplanesize, x,y, val ); + set_stdpx( &stdform, wdplanesize, x, y, val ); } } } + // adjust output position: + clip->g_x = 0; + clip->g_y = 0; } else { - for( y=0; yg_h; y++ ){ - - row = (uint32_t *)(bm->pixdata + (img_stride * (y+clip->g_y))); - - for( x=0; xg_w; x++ ){ - - pixel = row[x+clip->g_x]; + // convert the whole image data to vdi std format. + for( y=0; y < bh; y++ ){ + row = (uint32_t *)(img->pixdata + (img_stride * y)); + for( x=0; x < bw; x++ ){ + pixel = row[x]; if( pixel != prev_pixel ){ /* convert pixel value to vdi color index: */ pixel = pixel >> 8; @@ -1243,22 +1307,24 @@ static int bitmap_convert_8( GEM_PLOTTER self, val = RGB_TO_VDI( col ); prev_pixel = pixel; } - set_stdpx( &stdform, wdplanesize, x,y, val ); + set_stdpx( &stdform, wdplanesize, x, y, val ); } } } // convert into native format: - MFDB native; - native.fd_addr = DUMMY_PRIV(self)->buf_packed; - native.fd_w = dststride; - native.fd_h = clip->g_h; - native.fd_wdwidth = dststride >> 4; + native.fd_w = stdform.fd_w; + native.fd_h = stdform.fd_h; + native.fd_wdwidth = stdform.fd_wdwidth; native.fd_stand = 0; native.fd_nplanes = (short)self->bpp_virt; native.fd_r1 = native.fd_r2 = native.fd_r3 = 0; vr_trnfm( self->vdi_handle, &stdform, &native ); *out = native; + if( cache == true ){ + img->native = native; + img->converted = true; + } return(0); } @@ -1266,81 +1332,122 @@ static int bitmap_convert_8( GEM_PLOTTER self, /* * -* Convert bitmap to the virutal (chunked) framebuffer format -* +* Convert bitmap to the native screen format +* self: the plotter instance +* img: the bitmap +* x: coordinate where the bitmap REGION (described in clip) +* shall be drawn (screen coords) +* y: coordinate where the bitmap REGION (described in clip) +* shall be drawn (screen coords) +* clip: which area of the bitmap shall be drawn +* bg: background color +* flags: blit flags +* out: the result MFDB */ -static int bitmap_convert( GEM_PLOTTER self, - struct bitmap * img, - int x, - int y, - GRECT * clip, - uint32_t bg, - uint32_t flags, - MFDB *out ) +static int bitmap_convert( GEM_PLOTTER self, struct bitmap * img, int x, int y, + GRECT * clip, uint32_t bg, uint32_t flags, MFDB *out ) { int dststride; /* stride of dest. image */ int dstsize; /* size of dest. in byte */ int err; - int bw, bh; - struct bitmap * scrbuf = NULL; - struct bitmap * bm; - bool cache = ( flags & BITMAPF_BUFFER_NATIVE ); + int bw, bh; + struct bitmap * scrbuf = NULL; + struct bitmap * source; + bool cache = ( flags & BITMAPF_BUFFER_NATIVE ); + bool opaque = bitmap_get_opaque( img ); + + if( opaque == false ){ + if( ( (self->flags & PLOT_FLAG_TRANS) == 0) + && + ((flags & (BITMAPF_MONOGLYPH|BITMAPF_BUFFER_NATIVE))==0) ){ + opaque = true; + } + } + assert( clip->g_h > 0 ); assert( clip->g_w > 0 ); - bm = img; bw = bitmap_get_width( img ); - bh = bitmap_get_height( img ); - - if( cache ){ - assert( clip->g_w >= bw && clip->g_h >= bh ); - if( img->native.fd_addr != NULL ){ + bh = bitmap_get_height( img ); + + // The converted bitmap can be saved for subsequent blits, WHEN: + // A.) the bitmap is fully opaque OR + // B.) the bitmap is completly inside the window + // the latter one is important for alpha blits, + // because we must get the window background to apply transparency + // If the image is not completly within the window, + // we can't get the whole background for the image. + // this only works if the image isn't used at several different places. + // In fact in case of alpha bitmap caching it is only used for the + // toolbar buttons right now. + + if( (opaque == true) || (flags & BITMAPF_BUFFER_NATIVE ) ){ + if( img->converted == true ){ *out = img->native; return( 0 ); } + if( ( flags & BITMAPF_MONOGLYPH ) == 0 ){ + cache = true; + } } - + /* rem. if eddi xy is installed, we could directly access the screen! */ /* apply transparency to the image: */ - if( ( img->opaque == false ) - && ( (self->flags & PLOT_FLAG_TRANS) != 0) - && ( - (vdi_sysinfo.vdiformat == VDI_FORMAT_PACK ) - || - ( (flags & BITMAPF_MONOGLYPH) != 0) - ) ) { - uint32_t * imgpixel; - uint32_t * screenpixel; + if( ( opaque == false ) ) { + uint32_t * imgrow; + uint32_t * screenrow; int img_x, img_y; /* points into old bitmap */ int screen_x, screen_y; /* pointers into new bitmap */ - /* copy the screen to an temp buffer: */ + + /* copy the screen to an temp buffer: */ scrbuf = snapshot_create(self, x, y, clip->g_w, clip->g_h ); if( scrbuf != NULL ) { - /* copy blended pixels the new buffer (which contains screen content): */ - int img_stride = bitmap_get_rowstride(bm); + // copy blended pixels to the new buffer (which contains screen content): + int img_stride = bitmap_get_rowstride(img); int screen_stride = bitmap_get_rowstride(scrbuf); for( img_y = clip->g_y, screen_y = 0; screen_y < clip->g_h; screen_y++, img_y++) { - imgpixel = (uint32_t *)(bm->pixdata + (img_stride * img_y)); - screenpixel = (uint32_t *)(scrbuf->pixdata + (screen_stride * screen_y)); - for( img_x = clip->g_x, screen_x = 0; screen_x < clip->g_w; screen_x++, img_x++ ) { - if( (imgpixel[img_x] & 0xFF) == 0xFF ) { - screenpixel[screen_x] = imgpixel[img_x]; - } else { - if( (imgpixel[img_x] & 0x0FF) != 0 ) { - screenpixel[screen_x] = ablend( imgpixel[img_x], screenpixel[screen_x]); - } - } + imgrow = (uint32_t *)(img->pixdata + (img_stride * img_y)); + screenrow = (uint32_t *)(scrbuf->pixdata + (screen_stride * screen_y)); + for( img_x = clip->g_x, screen_x = 0; screen_x < clip->g_w; screen_x++, img_x++ ) { + + // when the pixel isn't fully opaque,...: + if( (imgrow[img_x] & 0x0FF) != 0 ){ + screenrow[screen_x] = ablend( imgrow[img_x], screenrow[screen_x]); + } + + // FIXME, maybe this loop would be faster??: + // --- + //if( (imgrow[img_x] & 0x0FF) != 0xFF ){ + // imgrow[screen_x] = ablend( imgrow[img_x], screenrow[screen_x]); + //} + + // or maybe even this??? + // --- + //if( (imgrow[img_x] & 0x0FF) == 0xFF ){ + // screenrow[screen_x] = imgrow[img_x]; + //} else if( (imgrow[img_x] & 0x0FF) != 0x00 ) { + // screenrow[screen_x] = ablend( imgrow[img_x], screenrow[screen_x]); + //} } - } - clip->g_x = 0; - clip->g_y = 0; - bm = scrbuf; + } + assert( clip->g_w <= bw ); + assert( clip->g_h <= bh ); + /* adjust size which gets converted: */ + bw = clip->g_w; + bh = clip->g_h; + /* adjust output position: */ + clip->g_x = 0; + clip->g_y = 0; + /* set the source of conversion: */ + source = scrbuf; } + } else { + source = img; } - /* (re)allocate buffer for framebuffer image: */ - dststride = MFDB_STRIDE( clip->g_w ); - dstsize = ( ((dststride >> 3) * clip->g_h) * self->bpp_virt); + /* (re)allocate buffer for converted image: */ + dststride = MFDB_STRIDE( bw ); + dstsize = ( ((dststride >> 3) * bh) * self->bpp_virt ); if( cache == false ){ if( dstsize > DUMMY_PRIV(self)->size_buf_packed) { int blocks = (dstsize / (CONV_BLOCK_SIZE-1))+1; @@ -1371,7 +1478,7 @@ static int bitmap_convert( GEM_PLOTTER self, } out->fd_w = dststride; - out->fd_h = clip->g_h; + out->fd_h = bh; out->fd_wdwidth = dststride >> 4; out->fd_stand = 0; out->fd_nplanes = (short)self->bpp_virt; @@ -1382,23 +1489,29 @@ static int bitmap_convert( GEM_PLOTTER self, &DUMMY_PRIV(self)->nsfmt, &DUMMY_PRIV(self)->vfmt ); - assert( err != 0 ); + assert( err != 0 ); + + // FIXME: here we can use the same optimization which is used for + // the snapshot creation. + /* convert image to virtual format: */ err = Hermes_ConverterCopy( hermes_cnv_h, - bm->pixdata, - clip->g_x, /* x src coord of top left in pixel coords */ - clip->g_y, /* y src coord of top left in pixel coords */ - clip->g_w, clip->g_h, - bm->rowstride, /* stride as bytes */ + source->pixdata, + 0, /* x src coord of top left in pixel coords */ + 0, /* y src coord of top left in pixel coords */ + bw, bh, + source->rowstride, /* stride as bytes */ out->fd_addr, - 0, /* x dst coord of top left in pixel coords */ - 0, /* y dst coord of top left in pixel coords */ - clip->g_w, clip->g_h, - (dststride >> 3) * self->bpp_virt /* stride as bytes */ - ); + 0, /* x dst coord of top left in pixel coords */ + 0, /* y dst coord of top left in pixel coords */ + bw, bh, + (dststride >> 3) * self->bpp_virt /* stride as bytes */ + ); assert( err != 0 ); + if( cache == true ){ img->native = *out; + img->converted = true; } return( 0 ); @@ -1421,7 +1534,8 @@ static int bitmap( GEM_PLOTTER self, struct bitmap * bmp, int x, int y, MFDB src_mf; MFDB scrmf; short pxy[8]; - GRECT off, clip, loc, vis; + GRECT off, clip, vis; + int screen_x, screen_y; src_mf.fd_addr = NULL; scrmf.fd_addr = NULL; @@ -1430,44 +1544,54 @@ static int bitmap( GEM_PLOTTER self, struct bitmap * bmp, int x, int y, off.g_y = y; off.g_h = bmp->height; off.g_w = bmp->width; - + + // clip plotter clip rectangle: clip.g_x = VIEW( self ).clipping.x0; clip.g_y = VIEW( self ).clipping.y0; clip.g_w = VIEW( self ).clipping.x1 - VIEW( self ).clipping.x0; clip.g_h = VIEW( self ).clipping.y1 - VIEW( self ).clipping.y0; if( !rc_intersect( &clip, &off) ) { - return( true ); + return( 1 ); } - + + // clip the visible rectangle of the plot area + // this is the area of the plotter which falls into + // screen region: plotter_get_visible_grect( self, &vis ); if( !rc_intersect( &vis, &off) ) { - return( true ); + return( 1 ); } + + screen_x = VIEW(self).x + off.g_x; + screen_y = VIEW(self).y + off.g_y; + + // convert the clipping relative to bitmap: + off.g_x = off.g_x - x; + off.g_y = off.g_y - y; + assert( (off.g_x >= 0) && (off.g_y >= 0) ); + + /* Convert the Bitmap to native screen format - ready for output. */ + /* This includes blending transparent pixels: */ + if( self->bitmap_convert( self, bmp, screen_x, screen_y, &off, bg, flags, &src_mf) != 0 ) { + return( 1 ); + } - loc = off; - off.g_x = MAX(0, off.g_x - x); - off.g_y = MAX(0, off.g_y - y); - loc.g_x = MAX(0, loc.g_x); - loc.g_y = MAX(0, loc.g_y); - - pxy[0] = 0; - pxy[1] = 0; - pxy[2] = off.g_w-1; - pxy[3] = off.g_h-1; - pxy[4] = VIEW(self).x + loc.g_x; - pxy[5] = VIEW(self).y + loc.g_y; - pxy[6] = VIEW(self).x + loc.g_x + off.g_w-1; - pxy[7] = VIEW(self).y + loc.g_y + off.g_h-1; - /* Convert the Bitmap to native screen format - ready for output*/ - /* This includes blending transparent pixels */ - - if( self->bitmap_convert( self, bmp, pxy[4], pxy[5], &off, bg, flags, &src_mf) != 0 ) { - return( true ); - } + // setup the src region: + pxy[0] = off.g_x; + pxy[1] = off.g_y; + pxy[2] = off.g_x + off.g_w-1; + pxy[3] = off.g_y + off.g_h-1; + + // setup the target region: + pxy[4] = screen_x; + pxy[5] = screen_y; + pxy[6] = screen_x + off.g_w-1; + pxy[7] = screen_y + off.g_h-1; + vro_cpyfm( self->vdi_handle, S_ONLY, (short*)&pxy, &src_mf, &scrmf); convert_bitmap_done( self ); - return( true ); + return( 1 ); } static int plot_mfdb (GEM_PLOTTER self, GRECT * loc, MFDB * insrc, unsigned char fgcolor, uint32_t flags) -- cgit v1.2.3