Newer
Older
UbixOS / src / lib / objgfx40 / ogPixCon.cpp
@Charlie Root Charlie Root on 31 Dec 2017 5 KB Sync
#include <objgfx40/objgfx40.h>
#include <objgfx40/ogPixCon.h>

// ogPixCon constructor
ogPixCon::ogPixCon(ogPixelFmt srcPixFmt, ogPixelFmt dstPixFmt) {
  uInt8 channelIdx[4];
  uInt8 srcFieldSize[4];
  uInt8 srcFieldPos[4];
  uInt8 dstShifters[4];

  uInt8 tmpb;
  int32 i, j;

  channelIdx[0] = 0;
  channelIdx[1] = 1;
  channelIdx[2] = 2;
  channelIdx[3] = 3;

  srcFieldSize[0] = srcPixFmt.alphaMaskSize;
  srcFieldSize[1] = srcPixFmt.redMaskSize;
  srcFieldSize[2] = srcPixFmt.greenMaskSize;
  srcFieldSize[3] = srcPixFmt.blueMaskSize;
 
  srcFieldPos[0] = srcPixFmt.alphaFieldPosition;
  srcFieldPos[1] = srcPixFmt.redFieldPosition;
  srcFieldPos[2] = srcPixFmt.greenFieldPosition;
  srcFieldPos[3] = srcPixFmt.blueFieldPosition;

  /*
   * The dest shifters are 32-(fieldPosition+fieldSize).  For things like
   * 24bpp where there is no alpha, the field position will be 0, and the
   * field size will be 0. 32-(0+0) is 32.. and when the shift takes place
   * the 32 will turn into a 0 and the shift will do nothing
   */

  dstShifters[0] = 32-(dstPixFmt.alphaFieldPosition+dstPixFmt.alphaMaskSize);
  dstShifters[1] = 32-(dstPixFmt.redFieldPosition+dstPixFmt.redMaskSize);
  dstShifters[2] = 32-(dstPixFmt.greenFieldPosition+dstPixFmt.greenMaskSize);
  dstShifters[3] = 32-(dstPixFmt.blueFieldPosition+dstPixFmt.blueMaskSize);

  i = srcPixFmt.redMaskSize - dstPixFmt.redMaskSize;
  if (i>0) 
    srcMasker = OG_MASKS[dstPixFmt.redMaskSize] << (srcPixFmt.redFieldPosition+i);
  else
    srcMasker = OG_MASKS[srcPixFmt.redMaskSize] << srcPixFmt.redFieldPosition;

  i = srcPixFmt.greenMaskSize - dstPixFmt.greenMaskSize;
  if (i>0) 
    srcMasker+= OG_MASKS[dstPixFmt.greenMaskSize] << (srcPixFmt.greenFieldPosition+i);
  else
    srcMasker+= OG_MASKS[srcPixFmt.greenMaskSize] << srcPixFmt.greenFieldPosition;

  i = srcPixFmt.blueMaskSize - dstPixFmt.blueMaskSize;
  if (i>0) 
    srcMasker+= OG_MASKS[dstPixFmt.blueMaskSize] << (srcPixFmt.blueFieldPosition+i);
  else
    srcMasker+= OG_MASKS[srcPixFmt.blueMaskSize] << srcPixFmt.blueFieldPosition;

  i = srcPixFmt.alphaMaskSize - dstPixFmt.alphaMaskSize;
  if (i>0) 
    srcMasker+= OG_MASKS[dstPixFmt.alphaMaskSize] << (srcPixFmt.alphaFieldPosition+i);
  else
    srcMasker+= OG_MASKS[srcPixFmt.alphaMaskSize] << srcPixFmt.alphaFieldPosition;

  /*
   * sort in descending order based on srcFieldPos (oth field will hold
   * highest position value)
   */
 
  for (i = 1; i < 4; i++ ) 
    for (j = 0; j < i; j++) {
      if (srcFieldPos[j] < srcFieldPos[i]) {
        tmpb = srcFieldPos[j];
        srcFieldPos[j] = srcFieldPos[i];
        srcFieldPos[i] = tmpb;
        
        tmpb = srcFieldSize[j];
        srcFieldSize[j] = srcFieldSize[i];
        srcFieldSize[i] = tmpb;
        
        tmpb = channelIdx[j];
        channelIdx[j] = channelIdx[i];
        channelIdx[i] = tmpb;
      } // if
    } // for j

  srcShifter = ((srcFieldSize[0] << 24) |
                (srcFieldSize[1] << 16) |
                (srcFieldSize[2] << 8) |
                (srcFieldSize[3]));

  dstShifter = ((dstShifters[channelIdx[0]] << 24) |
                (dstShifters[channelIdx[1]] << 16) |
                (dstShifters[channelIdx[2]] << 8) |
                (dstShifters[channelIdx[3]]));
  return;
} // ogPixCon::ogPixCon

uInt32 
ogPixCon::ConvPix(uInt32 pixel) {
  __asm__ __volatile__(
       "  xor   %%ebx, %%ebx       \n"    // xor     ebx, ebx
       "  xor   %%edi, %%edi       \n"    // xor     edi, edi
       "                           \n"
       "  push  %%eax              \n"    // push    eax
       "                           \n"
       "  and   %%edx, %%esi       \n"    // and     esi, edx
       "  xor   %%eax, %%eax       \n"    // xor     eax, eax
       "  xor   %%edx, %%edx       \n"    // xor     edx, edx
       "                           \n"
       "  shrdl %%cl, %%esi, %%eax \n"    // shrd    eax, esi, cl
       "  shr   %%cl, %%esi        \n"    // shr     esi, cl
       "  mov   %%ch, %%cl         \n"    // mov     cl, ch
       "  shrdl %%cl, %%esi, %%ebx \n"    // shrd    ebx, esi, cl
       "  shr   %%cl, %%esi        \n"    // shr     esi, cl
       "  shr   $16, %%ecx         \n"    // shr     ecx, 16
       "  shrdl %%cl, %%esi, %%edx \n"    // shrd    edx, esi, cl
       "  shr   %%cl, %%esi        \n"    // shr     esi, cl
       "  mov   %%ch, %%cl         \n"    // mov     cl, ch
       "  shrdl %%cl, %%esi, %%edi \n"    // shrd    edi, esi, cl
       "                           \n"
       "  pop   %%ecx              \n"    // pop     ecx
       "                           \n"
       "  shr   %%cl, %%eax        \n"    // shr     eax, cl
       "  shr   $8, %%ecx          \n"    // shr     ecx, 8
       "  shr   %%cl, %%ebx        \n"    // shr     ebx, cl
       "  shr   $8, %%ecx          \n"    // shr     ecx, 8
       "  shr   %%cl, %%edx        \n"    // shr     edx, cl
       "  shr   $8, %%ecx          \n"    // shr     ecx, 8
       "  shr   %%cl, %%edi        \n"    // shr     edi, cl
       "                           \n"
       "  or    %%ebx, %%eax       \n"    // or      eax, ebx
       "  or    %%edi, %%edx       \n"    // or      edx, edi
       "  nop                      \n"    // nop
       "  or    %%edx, %%eax       \n"    // or      eax, edx

  : "=a" (pixel)                        // %0
  : "S" (pixel), "d" (srcMasker),       // %1, %2
    "c" (srcShifter), "a" (dstShifter)  // %3, %4
 //   "ecx" (srcShifter), "eax" (dstShifter)    // %2, %3
  );
  return pixel;
}; // ogPixCon::ConvPix