LCOV - code coverage report
Current view: top level - drivers/video/fbdev/core - sysimgblt.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 158 0.0 %
Date: 2023-08-24 13:40:31 Functions: 0 4 0.0 %

          Line data    Source code
       1             : /*
       2             :  *  Generic 1-bit or 8-bit source to 1-32 bit destination expansion
       3             :  *  for frame buffer located in system RAM with packed pixels of any depth.
       4             :  *
       5             :  *  Based almost entirely on cfbimgblt.c
       6             :  *
       7             :  *      Copyright (C)  April 2007 Antonino Daplas <adaplas@pol.net>
       8             :  *
       9             :  *  This file is subject to the terms and conditions of the GNU General Public
      10             :  *  License.  See the file COPYING in the main directory of this archive for
      11             :  *  more details.
      12             :  */
      13             : #include <linux/module.h>
      14             : #include <linux/string.h>
      15             : #include <linux/fb.h>
      16             : #include <asm/types.h>
      17             : 
      18             : #define DEBUG
      19             : 
      20             : #ifdef DEBUG
      21             : #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt,__func__,## args)
      22             : #else
      23             : #define DPRINTK(fmt, args...)
      24             : #endif
      25             : 
      26             : static const u32 cfb_tab8_be[] = {
      27             :     0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
      28             :     0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
      29             :     0xff000000,0xff0000ff,0xff00ff00,0xff00ffff,
      30             :     0xffff0000,0xffff00ff,0xffffff00,0xffffffff
      31             : };
      32             : 
      33             : static const u32 cfb_tab8_le[] = {
      34             :     0x00000000,0xff000000,0x00ff0000,0xffff0000,
      35             :     0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00,
      36             :     0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff,
      37             :     0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff
      38             : };
      39             : 
      40             : static const u32 cfb_tab16_be[] = {
      41             :     0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
      42             : };
      43             : 
      44             : static const u32 cfb_tab16_le[] = {
      45             :     0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
      46             : };
      47             : 
      48             : static const u32 cfb_tab32[] = {
      49             :         0x00000000, 0xffffffff
      50             : };
      51             : 
      52           0 : static void color_imageblit(const struct fb_image *image, struct fb_info *p,
      53             :                             void *dst1, u32 start_index, u32 pitch_index)
      54             : {
      55             :         /* Draw the penguin */
      56             :         u32 *dst, *dst2;
      57           0 :         u32 color = 0, val, shift;
      58           0 :         int i, n, bpp = p->var.bits_per_pixel;
      59           0 :         u32 null_bits = 32 - bpp;
      60           0 :         u32 *palette = (u32 *) p->pseudo_palette;
      61           0 :         const u8 *src = image->data;
      62             : 
      63           0 :         dst2 = dst1;
      64           0 :         for (i = image->height; i--; ) {
      65           0 :                 n = image->width;
      66           0 :                 dst = dst1;
      67           0 :                 shift = 0;
      68           0 :                 val = 0;
      69             : 
      70           0 :                 if (start_index) {
      71           0 :                         u32 start_mask = ~(FB_SHIFT_HIGH(p, ~(u32)0,
      72             :                                                          start_index));
      73           0 :                         val = *dst & start_mask;
      74           0 :                         shift = start_index;
      75             :                 }
      76           0 :                 while (n--) {
      77           0 :                         if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
      78             :                             p->fix.visual == FB_VISUAL_DIRECTCOLOR )
      79           0 :                                 color = palette[*src];
      80             :                         else
      81           0 :                                 color = *src;
      82           0 :                         color <<= FB_LEFT_POS(p, bpp);
      83           0 :                         val |= FB_SHIFT_HIGH(p, color, shift);
      84           0 :                         if (shift >= null_bits) {
      85           0 :                                 *dst++ = val;
      86             : 
      87           0 :                                 val = (shift == null_bits) ? 0 :
      88           0 :                                         FB_SHIFT_LOW(p, color, 32 - shift);
      89             :                         }
      90           0 :                         shift += bpp;
      91           0 :                         shift &= (32 - 1);
      92           0 :                         src++;
      93             :                 }
      94           0 :                 if (shift) {
      95           0 :                         u32 end_mask = FB_SHIFT_HIGH(p, ~(u32)0, shift);
      96             : 
      97           0 :                         *dst &= end_mask;
      98           0 :                         *dst |= val;
      99             :                 }
     100           0 :                 dst1 += p->fix.line_length;
     101           0 :                 if (pitch_index) {
     102           0 :                         dst2 += p->fix.line_length;
     103           0 :                         dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1));
     104             : 
     105           0 :                         start_index += pitch_index;
     106           0 :                         start_index &= 32 - 1;
     107             :                 }
     108             :         }
     109           0 : }
     110             : 
     111           0 : static void slow_imageblit(const struct fb_image *image, struct fb_info *p,
     112             :                                   void *dst1, u32 fgcolor, u32 bgcolor,
     113             :                                   u32 start_index, u32 pitch_index)
     114             : {
     115           0 :         u32 shift, color = 0, bpp = p->var.bits_per_pixel;
     116             :         u32 *dst, *dst2;
     117           0 :         u32 val, pitch = p->fix.line_length;
     118           0 :         u32 null_bits = 32 - bpp;
     119           0 :         u32 spitch = (image->width+7)/8;
     120           0 :         const u8 *src = image->data, *s;
     121             :         u32 i, j, l;
     122             : 
     123           0 :         dst2 = dst1;
     124           0 :         fgcolor <<= FB_LEFT_POS(p, bpp);
     125           0 :         bgcolor <<= FB_LEFT_POS(p, bpp);
     126             : 
     127           0 :         for (i = image->height; i--; ) {
     128           0 :                 shift = val = 0;
     129           0 :                 l = 8;
     130           0 :                 j = image->width;
     131           0 :                 dst = dst1;
     132           0 :                 s = src;
     133             : 
     134             :                 /* write leading bits */
     135           0 :                 if (start_index) {
     136           0 :                         u32 start_mask = ~(FB_SHIFT_HIGH(p, ~(u32)0,
     137             :                                                          start_index));
     138           0 :                         val = *dst & start_mask;
     139           0 :                         shift = start_index;
     140             :                 }
     141             : 
     142           0 :                 while (j--) {
     143           0 :                         l--;
     144           0 :                         color = (*s & (1 << l)) ? fgcolor : bgcolor;
     145           0 :                         val |= FB_SHIFT_HIGH(p, color, shift);
     146             : 
     147             :                         /* Did the bitshift spill bits to the next long? */
     148           0 :                         if (shift >= null_bits) {
     149           0 :                                 *dst++ = val;
     150           0 :                                 val = (shift == null_bits) ? 0 :
     151           0 :                                         FB_SHIFT_LOW(p, color, 32 - shift);
     152             :                         }
     153           0 :                         shift += bpp;
     154           0 :                         shift &= (32 - 1);
     155           0 :                         if (!l) { l = 8; s++; }
     156             :                 }
     157             : 
     158             :                 /* write trailing bits */
     159           0 :                 if (shift) {
     160           0 :                         u32 end_mask = FB_SHIFT_HIGH(p, ~(u32)0, shift);
     161             : 
     162           0 :                         *dst &= end_mask;
     163           0 :                         *dst |= val;
     164             :                 }
     165             : 
     166           0 :                 dst1 += pitch;
     167           0 :                 src += spitch;
     168           0 :                 if (pitch_index) {
     169           0 :                         dst2 += pitch;
     170           0 :                         dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1));
     171           0 :                         start_index += pitch_index;
     172           0 :                         start_index &= 32 - 1;
     173             :                 }
     174             : 
     175             :         }
     176           0 : }
     177             : 
     178             : /*
     179             :  * fast_imageblit - optimized monochrome color expansion
     180             :  *
     181             :  * Only if:  bits_per_pixel == 8, 16, or 32
     182             :  *           image->width is divisible by pixel/dword (ppw);
     183             :  *           fix->line_legth is divisible by 4;
     184             :  *           beginning and end of a scanline is dword aligned
     185             :  */
     186           0 : static void fast_imageblit(const struct fb_image *image, struct fb_info *p,
     187             :                                   void *dst1, u32 fgcolor, u32 bgcolor)
     188             : {
     189           0 :         u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel;
     190           0 :         u32 ppw = 32/bpp, spitch = (image->width + 7)/8;
     191             :         u32 bit_mask, eorx, shift;
     192           0 :         const u8 *s = image->data, *src;
     193             :         u32 *dst;
     194             :         const u32 *tab;
     195             :         size_t tablen;
     196             :         u32 colortab[16];
     197             :         int i, j, k;
     198             : 
     199           0 :         switch (bpp) {
     200             :         case 8:
     201             :                 tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le;
     202             :                 tablen = 16;
     203             :                 break;
     204             :         case 16:
     205           0 :                 tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le;
     206           0 :                 tablen = 4;
     207             :                 break;
     208             :         case 32:
     209           0 :                 tab = cfb_tab32;
     210           0 :                 tablen = 2;
     211             :                 break;
     212             :         default:
     213           0 :                 return;
     214             :         }
     215             : 
     216           0 :         for (i = ppw-1; i--; ) {
     217           0 :                 fgx <<= bpp;
     218           0 :                 bgx <<= bpp;
     219           0 :                 fgx |= fgcolor;
     220           0 :                 bgx |= bgcolor;
     221             :         }
     222             : 
     223           0 :         bit_mask = (1 << ppw) - 1;
     224           0 :         eorx = fgx ^ bgx;
     225           0 :         k = image->width/ppw;
     226             : 
     227           0 :         for (i = 0; i < tablen; ++i)
     228           0 :                 colortab[i] = (tab[i] & eorx) ^ bgx;
     229             : 
     230           0 :         for (i = image->height; i--; ) {
     231           0 :                 dst = dst1;
     232           0 :                 shift = 8;
     233           0 :                 src = s;
     234             : 
     235             :                 /*
     236             :                  * Manually unroll the per-line copying loop for better
     237             :                  * performance. This works until we processed the last
     238             :                  * completely filled source byte (inclusive).
     239             :                  */
     240           0 :                 switch (ppw) {
     241             :                 case 4: /* 8 bpp */
     242           0 :                         for (j = k; j >= 2; j -= 2, ++src) {
     243           0 :                                 *dst++ = colortab[(*src >> 4) & bit_mask];
     244           0 :                                 *dst++ = colortab[(*src >> 0) & bit_mask];
     245             :                         }
     246             :                         break;
     247             :                 case 2: /* 16 bpp */
     248           0 :                         for (j = k; j >= 4; j -= 4, ++src) {
     249           0 :                                 *dst++ = colortab[(*src >> 6) & bit_mask];
     250           0 :                                 *dst++ = colortab[(*src >> 4) & bit_mask];
     251           0 :                                 *dst++ = colortab[(*src >> 2) & bit_mask];
     252           0 :                                 *dst++ = colortab[(*src >> 0) & bit_mask];
     253             :                         }
     254             :                         break;
     255             :                 case 1: /* 32 bpp */
     256           0 :                         for (j = k; j >= 8; j -= 8, ++src) {
     257           0 :                                 *dst++ = colortab[(*src >> 7) & bit_mask];
     258           0 :                                 *dst++ = colortab[(*src >> 6) & bit_mask];
     259           0 :                                 *dst++ = colortab[(*src >> 5) & bit_mask];
     260           0 :                                 *dst++ = colortab[(*src >> 4) & bit_mask];
     261           0 :                                 *dst++ = colortab[(*src >> 3) & bit_mask];
     262           0 :                                 *dst++ = colortab[(*src >> 2) & bit_mask];
     263           0 :                                 *dst++ = colortab[(*src >> 1) & bit_mask];
     264           0 :                                 *dst++ = colortab[(*src >> 0) & bit_mask];
     265             :                         }
     266             :                         break;
     267             :                 }
     268             : 
     269             :                 /*
     270             :                  * For image widths that are not a multiple of 8, there
     271             :                  * are trailing pixels left on the current line. Print
     272             :                  * them as well.
     273             :                  */
     274           0 :                 for (; j--; ) {
     275           0 :                         shift -= ppw;
     276           0 :                         *dst++ = colortab[(*src >> shift) & bit_mask];
     277           0 :                         if (!shift) {
     278           0 :                                 shift = 8;
     279           0 :                                 ++src;
     280             :                         }
     281             :                 }
     282             : 
     283           0 :                 dst1 += p->fix.line_length;
     284           0 :                 s += spitch;
     285             :         }
     286             : }
     287             : 
     288           0 : void sys_imageblit(struct fb_info *p, const struct fb_image *image)
     289             : {
     290           0 :         u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0;
     291           0 :         u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel;
     292           0 :         u32 width = image->width;
     293           0 :         u32 dx = image->dx, dy = image->dy;
     294             :         void *dst1;
     295             : 
     296           0 :         if (p->state != FBINFO_STATE_RUNNING)
     297             :                 return;
     298             : 
     299           0 :         bitstart = (dy * p->fix.line_length * 8) + (dx * bpp);
     300           0 :         start_index = bitstart & (32 - 1);
     301           0 :         pitch_index = (p->fix.line_length & (bpl - 1)) * 8;
     302             : 
     303           0 :         bitstart /= 8;
     304           0 :         bitstart &= ~(bpl - 1);
     305           0 :         dst1 = (void __force *)p->screen_base + bitstart;
     306             : 
     307           0 :         if (p->fbops->fb_sync)
     308           0 :                 p->fbops->fb_sync(p);
     309             : 
     310           0 :         if (image->depth == 1) {
     311           0 :                 if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
     312             :                     p->fix.visual == FB_VISUAL_DIRECTCOLOR) {
     313           0 :                         fgcolor = ((u32*)(p->pseudo_palette))[image->fg_color];
     314           0 :                         bgcolor = ((u32*)(p->pseudo_palette))[image->bg_color];
     315             :                 } else {
     316           0 :                         fgcolor = image->fg_color;
     317           0 :                         bgcolor = image->bg_color;
     318             :                 }
     319             : 
     320           0 :                 if (32 % bpp == 0 && !start_index && !pitch_index &&
     321           0 :                     ((width & (32/bpp-1)) == 0) &&
     322           0 :                     bpp >= 8 && bpp <= 32)
     323           0 :                         fast_imageblit(image, p, dst1, fgcolor, bgcolor);
     324             :                 else
     325           0 :                         slow_imageblit(image, p, dst1, fgcolor, bgcolor,
     326             :                                         start_index, pitch_index);
     327             :         } else
     328           0 :                 color_imageblit(image, p, dst1, start_index, pitch_index);
     329             : }
     330             : 
     331             : EXPORT_SYMBOL(sys_imageblit);
     332             : 
     333             : MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>");
     334             : MODULE_DESCRIPTION("1-bit/8-bit to 1-32 bit color expansion (sys-to-sys)");
     335             : MODULE_LICENSE("GPL");
     336             : 

Generated by: LCOV version 1.14