diff options
author | Ole Loots <ole@monochrom.net> | 2012-04-19 22:44:49 +0000 |
---|---|---|
committer | Ole Loots <ole@monochrom.net> | 2012-04-19 22:44:49 +0000 |
commit | 4204599fb949fa7eaea9b21213bc09861c7f14bf (patch) | |
tree | a754bb6ef88abee75811490111130944ceb42354 /atari | |
parent | f6b15c1061327076d28a8438ff5baf0ab7bfe4d8 (diff) | |
download | netsurf-4204599fb949fa7eaea9b21213bc09861c7f14bf.tar.gz netsurf-4204599fb949fa7eaea9b21213bc09861c7f14bf.tar.bz2 |
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
Diffstat (limited to 'atari')
-rwxr-xr-x | atari/plot/font_freetype.c | 2 | ||||
-rwxr-xr-x | atari/plot/plotter_vdi.c | 528 |
2 files changed, 327 insertions, 203 deletions
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; i<OFFSET_CUST_PAL+16; i++){ - vs_color( self->vdi_handle, i, &sys_pal[i][0] ); + if( DUMMY_PRIV(self)->vfmt.indexed ){ + for( i=OFFSET_WEB_PAL; i<OFFSET_CUST_PAL+16; i++){ + vs_color( self->vdi_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; row<h; row++ ){ + // fd_w matches stride! + uint32_t *rowptr = ((uint32_t*)native->fd_addr + ((row*native->fd_w))); + for( col=0; col<w; col++){ + *(rowptr+col) = (*(rowptr+col)<<8); + } + } + return( &snapshot ); } static void snapshot_suspend(GEM_PLOTTER self ) @@ -974,34 +1008,36 @@ static void snapshot_suspend(GEM_PLOTTER self ) } } - if( bitmap_buffer_size( DUMMY_PRIV(self)->buf_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; y<clip->g_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; x<clip->g_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; y<clip->g_h; y++ ){ - - row = (uint32_t *)(bm->pixdata + (img_stride * (y+clip->g_y))); - - for( x=0; x<clip->g_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)
|