2005-04-17 02:20:36 +04:00
/*
* Fast C2P ( Chunky - to - Planar ) Conversion
*
2009-01-04 13:43:00 +03:00
* Copyright ( C ) 2003 - 2008 Geert Uytterhoeven
2005-04-17 02:20:36 +04:00
*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file COPYING in the main directory of this archive
* for more details .
*/
2008-07-17 23:16:20 +04:00
# include <linux/module.h>
2005-04-17 02:20:36 +04:00
# include <linux/string.h>
2009-01-04 13:43:00 +03:00
# include <asm/unaligned.h>
2005-04-17 02:20:36 +04:00
# include "c2p.h"
2009-01-04 13:58:20 +03:00
# include "c2p_core.h"
2005-04-17 02:20:36 +04:00
/*
* Perform a full C2P step on 32 8 - bit pixels , stored in 8 32 - bit words
* containing
* - 32 8 - bit chunky pixels on input
2009-01-04 13:43:00 +03:00
* - permutated planar data ( 1 plane per 32 - bit word ) on output
2005-04-17 02:20:36 +04:00
*/
2009-01-04 13:43:00 +03:00
static void c2p_32x8 ( u32 d [ 8 ] )
2005-04-17 02:20:36 +04:00
{
2009-01-04 13:43:00 +03:00
transp8 ( d , 16 , 4 ) ;
transp8 ( d , 8 , 2 ) ;
transp8 ( d , 4 , 1 ) ;
transp8 ( d , 2 , 4 ) ;
transp8 ( d , 1 , 2 ) ;
2005-04-17 02:20:36 +04:00
}
/*
2009-01-04 13:43:00 +03:00
* Array containing the permutation indices of the planar data after c2p
2005-04-17 02:20:36 +04:00
*/
2009-01-04 13:43:00 +03:00
static const int perm_c2p_32x8 [ 8 ] = { 7 , 5 , 3 , 1 , 6 , 4 , 2 , 0 } ;
2005-04-17 02:20:36 +04:00
/*
* Store a full block of planar data after c2p conversion
*/
2009-01-04 13:43:00 +03:00
static inline void store_planar ( void * dst , u32 dst_inc , u32 bpp , u32 d [ 8 ] )
2005-04-17 02:20:36 +04:00
{
2009-01-04 13:42:16 +03:00
int i ;
2005-04-17 02:20:36 +04:00
2009-01-04 13:42:16 +03:00
for ( i = 0 ; i < bpp ; i + + , dst + = dst_inc )
2009-01-04 13:43:00 +03:00
put_unaligned_be32 ( d [ perm_c2p_32x8 [ i ] ] , dst ) ;
2005-04-17 02:20:36 +04:00
}
/*
* Store a partial block of planar data after c2p conversion
*/
2009-01-04 13:43:00 +03:00
static inline void store_planar_masked ( void * dst , u32 dst_inc , u32 bpp ,
2005-04-17 02:20:36 +04:00
u32 d [ 8 ] , u32 mask )
{
2009-01-04 13:42:16 +03:00
int i ;
2005-04-17 02:20:36 +04:00
2009-01-04 13:42:16 +03:00
for ( i = 0 ; i < bpp ; i + + , dst + = dst_inc )
2009-01-04 13:43:00 +03:00
put_unaligned_be32 ( comp ( d [ perm_c2p_32x8 [ i ] ] ,
get_unaligned_be32 ( dst ) , mask ) ,
dst ) ;
2005-04-17 02:20:36 +04:00
}
/*
2008-12-21 17:48:13 +03:00
* c2p_planar - Copy 8 - bit chunky image data to a planar frame buffer
2005-04-17 02:20:36 +04:00
* @ dst : Starting address of the planar frame buffer
* @ dx : Horizontal destination offset ( in pixels )
* @ dy : Vertical destination offset ( in pixels )
* @ width : Image width ( in pixels )
* @ height : Image height ( in pixels )
* @ dst_nextline : Frame buffer offset to the next line ( in bytes )
* @ dst_nextplane : Frame buffer offset to the next plane ( in bytes )
* @ src_nextline : Image offset to the next line ( in bytes )
* @ bpp : Bits per pixel of the planar frame buffer ( 1 - 8 )
*/
2008-12-21 17:48:13 +03:00
void c2p_planar ( void * dst , const void * src , u32 dx , u32 dy , u32 width ,
u32 height , u32 dst_nextline , u32 dst_nextplane ,
u32 src_nextline , u32 bpp )
2005-04-17 02:20:36 +04:00
{
2009-01-04 13:43:00 +03:00
union {
u8 pixels [ 32 ] ;
u32 words [ 8 ] ;
} d ;
u32 dst_idx , first , last , w ;
2009-01-04 13:42:16 +03:00
const u8 * c ;
2009-01-04 13:43:00 +03:00
void * p ;
2009-01-04 13:42:16 +03:00
dst + = dy * dst_nextline + ( dx & ~ 31 ) ;
dst_idx = dx % 32 ;
2009-01-04 13:43:00 +03:00
first = 0xffffffffU > > dst_idx ;
last = ~ ( 0xffffffffU > > ( ( dst_idx + width ) % 32 ) ) ;
2009-01-04 13:42:16 +03:00
while ( height - - ) {
c = src ;
p = dst ;
w = width ;
if ( dst_idx + width < = 32 ) {
/* Single destination word */
first & = last ;
2009-01-04 13:43:00 +03:00
memset ( d . pixels , 0 , sizeof ( d ) ) ;
memcpy ( d . pixels + dst_idx , c , width ) ;
2009-01-04 13:42:16 +03:00
c + = width ;
2009-01-04 13:43:00 +03:00
c2p_32x8 ( d . words ) ;
store_planar_masked ( p , dst_nextplane , bpp , d . words ,
first ) ;
2009-01-04 13:42:16 +03:00
p + = 4 ;
} else {
/* Multiple destination words */
w = width ;
/* Leading bits */
if ( dst_idx ) {
w = 32 - dst_idx ;
2009-01-04 13:43:00 +03:00
memset ( d . pixels , 0 , dst_idx ) ;
memcpy ( d . pixels + dst_idx , c , w ) ;
2009-01-04 13:42:16 +03:00
c + = w ;
2009-01-04 13:43:00 +03:00
c2p_32x8 ( d . words ) ;
store_planar_masked ( p , dst_nextplane , bpp ,
d . words , first ) ;
2009-01-04 13:42:16 +03:00
p + = 4 ;
w = width - w ;
}
/* Main chunk */
while ( w > = 32 ) {
2009-01-04 13:43:00 +03:00
memcpy ( d . pixels , c , 32 ) ;
2009-01-04 13:42:16 +03:00
c + = 32 ;
2009-01-04 13:43:00 +03:00
c2p_32x8 ( d . words ) ;
store_planar ( p , dst_nextplane , bpp , d . words ) ;
2009-01-04 13:42:16 +03:00
p + = 4 ;
w - = 32 ;
}
/* Trailing bits */
w % = 32 ;
if ( w > 0 ) {
2009-01-04 13:43:00 +03:00
memcpy ( d . pixels , c , w ) ;
memset ( d . pixels + w , 0 , 32 - w ) ;
c2p_32x8 ( d . words ) ;
store_planar_masked ( p , dst_nextplane , bpp ,
d . words , last ) ;
2009-01-04 13:42:16 +03:00
}
}
src + = src_nextline ;
dst + = dst_nextline ;
2005-04-17 02:20:36 +04:00
}
}
2008-12-21 17:48:13 +03:00
EXPORT_SYMBOL_GPL ( c2p_planar ) ;
2005-04-17 02:20:36 +04:00
2008-07-17 23:16:20 +04:00
MODULE_LICENSE ( " GPL " ) ;