summaryrefslogtreecommitdiff
path: root/atari/plot
diff options
context:
space:
mode:
authorOle Loots <ole@monochrom.net>2012-04-19 22:44:49 +0000
committerOle Loots <ole@monochrom.net>2012-04-19 22:44:49 +0000
commit4204599fb949fa7eaea9b21213bc09861c7f14bf (patch)
treea754bb6ef88abee75811490111130944ceb42354 /atari/plot
parentf6b15c1061327076d28a8438ff5baf0ab7bfe4d8 (diff)
downloadnetsurf-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/plot')
-rwxr-xr-xatari/plot/font_freetype.c2
-rwxr-xr-xatari/plot/plotter_vdi.c528
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)