Newer
Older
ubixos / src / sys / graphics / objgfx30.cpp
/*******************************************************
$Id$
*******************************************************/

#include "objgfx30.h"
#include <stdlib.h>
#include <string.h>
#include <ubixos/types.h>
// TGfx0 constructor

TGfx0::TGfx0(void) {
  DataState = og_None;
  Buffer = 0;
  LineOfs = 0;
  pal = 0;
  xRes = 0;
  yRes = 0;
  MaxX = 0;
  MaxY = 0;
  bSize = 0;
  lSize = 0;
  TransparentColor = 0;
  BPP = 0;
  RedShifter = 0;
  GreenShifter = 0;
  BlueShifter = 0;
  RedFieldPosition = 0;
  GreenFieldPosition = 0;
  BlueFieldPosition = 0;
  return;
} // TGfx0::TGfx0()


bool TGfx0::create(UInt32 _xRes, UInt32 _yRes,TPixelFmt* _pixformat) {
  /*
   *  constructor TGfx0::create()
   *  Allocates memory for a buffer of size _xRes by _yRes with
   *  the pixel format defined in _pixformat.  Allocates memory
   *  for pal and LineOfs.
   */
  UInt32 yy;
  if (DataState==og_Owner) {
    if (Buffer) free(Buffer);
    if (LineOfs) free(LineOfs);
    if (pal) free(pal);
  }  // if datastate
  BPP = _pixformat->BPP;
  bSize=_xRes*_yRes*((BPP+7) >> 3);
  Buffer = malloc(bSize);
  if (!Buffer) return FALSE;
  memset(Buffer,0,bSize);
  lSize = _yRes*sizeof(UInt32);
  LineOfs = (UInt32*)malloc(lSize);
  if (!LineOfs) return FALSE;
  pal = (TRGB*)malloc(256*sizeof(TRGB));
  if (!pal) return FALSE;
  memset(pal,0,sizeof(TRGB)*256);
  MaxX=_xRes-1;
  xRes=_xRes;
  MaxY=_yRes-1;
  yRes=_yRes;
  LineOfs[0]=0;
  for (yy=1; yy<=MaxY; yy++)
    LineOfs[yy]=LineOfs[yy-1]+xRes*((BPP+7) >> 3);
  DataState = og_Owner;
  // For 8bpp modes the next part doesn't matter 
  RedFieldPosition=_pixformat->RedFieldPosition;
  GreenFieldPosition=_pixformat->GreenFieldPosition;
  BlueFieldPosition=_pixformat->BlueFieldPosition;
  // The next part is only used by 15/16hpp 
  RedShifter=8-_pixformat->RedMaskSize;
  GreenShifter=8-_pixformat->GreenMaskSize;
  BlueShifter=8-_pixformat->BlueMaskSize; 
  Owner = this;
  return TRUE;
} // TGfx0::create

void TGfx0::copy(TGfx0* SrcObject) {
  UInt32 count, xCount, yCount;
  UInt32 xx, yy;
  UInt8  r, g, b;
  if (!Buffer) return;
  if (!SrcObject->Buffer) return;
  xCount = SrcObject->MaxX+1;
  if (xCount>MaxX+1) xCount=MaxX;
  yCount = SrcObject->MaxY+1;
  if (yCount>MaxY+1) yCount=MaxY;
  if ((BPP!=SrcObject->BPP) || (RedShifter!=SrcObject->RedShifter) ||
      (BlueShifter!=SrcObject->BlueShifter) || 
      (GreenShifter!=SrcObject->GreenShifter)) {
    for (yy=0; yy<=yCount; yy++)
      for (xx=0; xx<=xCount; xx++) {
        SrcObject->unpackRGB(SrcObject->getPixel(xx,yy),&r,&g,&b);
        putPixel(xx,yy,RGB(r,g,b));
      } // for
  }  // if
  else
  {
    xCount=xCount*((BPP+7) >> 3); // adjust for bpp 
    for (count=0; count<=yCount; count++) ;
      memcpy(((char*)Buffer+LineOfs[count]),                        // dest
             ((char*)SrcObject->Buffer+SrcObject->LineOfs[count]),  // src
             xCount);                                               // len
  } // else
} // TGfx0::copy

UInt32 TGfx0::getMaxX(void) {
  return MaxX;
} // TGfx0::getMaxX

UInt32 TGfx0::getMaxY(void) {
  return MaxY;
} // TGfx0::getMaxY

UInt32 TGfx0::getPixel(UInt32 x, UInt32 y) {
  UInt32 result;
  result = 42;
  if ((!Buffer) || (!LineOfs)) return TransparentColor;
  if ((x<0) || (x>MaxX) || (y<0) || y>MaxY) return TransparentColor;
  switch (BPP) {
  case 8:
    asm(
       "  add  (%%esi,%%ebx,4), %%edi \n" //  add     edi, [esi + ebx*4]
       "  add  %%ecx, %%edi   \n"  // add     edi, ecx
       " movzbl (%%edi),%%eax \n"  // edx,byte ptr [edi]
       "  mov  %%eax, %4      \n"  // mov     result, eax
       :
       : "D" (Buffer), "S" (LineOfs),    // %0, %1
         "c" (x), "b" (y),               // %2, %3
         "m" (result)                    // %4
       );
    break;
  case 15:
  case 16:
    asm(
       "  add  %%ecx, %%ecx   \n"  // add     ecx, ecx {adjust for pixel size}
       "  add  (%%esi,%%ebx,4), %%edi \n" //  add     edi, [esi + ebx*4]
       "  add  %%ecx, %%edi   \n"  // add     edi, ecx
       "  movzwl (%%edi),%%eax \n"  // edx,word ptr [edi]
       "  mov  %%eax, %4      \n"  // mov     result, eax
       :
       : "D" (Buffer), "S" (LineOfs),    // %0, %1
         "c" (x), "b" (y),               // %2, %3
         "m" (result)                    // %4
       );
    break;
  case 24:
    asm(
       "  mov  %%ecx, %%eax   \n"  // mov     eax, ecx  - adjust for pixel size 
       "  add  %%ecx, %%ecx   \n"  // add     ecx, ecx  - adjust for pixel size
       "  add  %%eax, %%ecx   \n"  // add     ecx, eax  - adjust for pixel size
       "  add  (%%esi,%%ebx,4), %%edi \n" //  add     edi, [esi + ebx*4]
       "  add  %%ecx, %%edi   \n"  // add     edi, ecx
       "  movzwl (%%edi),%%eax \n" // edx,word ptr [edi]
       "  xor  %%eax, %%eax   \n"  
       "  mov  2(%%edi), %%al \n"  // mov     al, [edi+2]
       "  shl  $16, %%eax     \n"  // shl     eax, 16
       "  mov  (%%edi), %%ax  \n"  // mov     ax, [edi]
       "  mov  %%eax, %4      \n"  // mov     result, eax
       :
       : "D" (Buffer), "S" (LineOfs),    // %0, %1
         "c" (x), "b" (y),               // %2, %3
         "m" (result)                    // %4
       );
    break;
  case 32:
    asm(
       "  shl  $2, %%ecx      \n"  // shl     ecx, 2 {adjust for pixel size}
       "  add  (%%esi,%%ebx,4), %%edi \n" //  add     edi, [esi + ebx*4]
       "  add  %%ecx, %%edi   \n"  // add     edi, ecx
       "  mov  (%%edi),%%eax  \n"  // edx,word ptr [edi]
       "  mov  %%eax, %4      \n"  // mov     result, eax
       :
       : "D" (Buffer), "S" (LineOfs),    // %0, %1
         "c" (x), "b" (y),               // %2, %3
         "m" (result)                    // %4
       );
  } // switch
  return result;
} // TGfx0::getPixel

void TGfx0::putPixel(UInt32 x, UInt32 y, UInt32 colour) {
  if ((!Buffer) || (!LineOfs)) return;
  if ((x<0) || (x>MaxX) || (y<0) || y>MaxY) return;
  switch (BPP) {
  case 8:
    asm(
    // { Calculate offset, prepare the pixel to be drawn }
        "  add  (%%esi,%%ebx,4), %%edi \n" // add     edi, [esi + ebx * 4]
        "  mov  %4, %%eax     \n"  // mov     eax, colour
        "  add  %%ecx, %%edi  \n"  // add     edi, ecx
    // { Draw the pixel }
        "  mov  %%al, (%%edi) \n"  // mov     [edi], al
        :
        : "D" (Buffer), "S" (LineOfs),           // %0, %1
          "c" (x), "b" (y),                      // %2, %3
          "m" (colour)                           // %4
   );
   break;
   case 15:
   case 16:
     asm(
    // { Calculate offset, prepare the pixel to be drawn }
        "  add  (%%esi,%%ebx,4), %%edi \n" // add     edi, [esi + ebx * 4]
        "  add  %%ecx, %%ecx  \n"  // add     ecx, ecx {adjust for pixel size}
        "  mov  %4, %%eax     \n"  // mov     eax, colour
        "  add  %%ecx, %%edi  \n"  // add     edi, ecx
    // { Draw the pixel }
        "  mov  %%ax, (%%edi) \n"  // mov     [edi], al
        :
        : "D" (Buffer), "S" (LineOfs),           // %0, %1
          "c" (x), "b" (y),                      // %2, %3
          "m" (colour)                           // %4
   );
     break;
   case 24:
     asm(
    // { Calculate offset, prepare the pixel to be drawn }
        "  add  (%%esi,%%ebx,4),%%edi \n" // add     edi, [esi + ebx * 4]
        "  add  %%ecx, %%edi  \n"  // add     edi, ecx
        "  add  %%ecx, %%edi  \n"  // add     edi, ecx {adjust for pixel size}
        "  add  %%ecx, %%edi  \n"  // add     edi, ecx {adjust for pixel size}
    // { Draw the pixel }
        "  mov  %%ax, (%%edi) \n"  // mov     [edi], ax
        "  shr  $16, %%eax    \n"  // shr     eax, 16
        "  mov  %%al, 2(%%edi)\n"  // mov     [edi+2],al
        :
        : "D" (Buffer), "S" (LineOfs),           // %0, %1
          "c" (x), "b" (y),                      // %2, %3
          "a" (colour)                           // %4
    );
    break;
  case 32:
     asm(
    // { Calculate offset, prepare the pixel to be drawn }
        "  shl  $2, %%ecx     \n"  // shl     eax, 2 {adjust for pixel size}
        "  add  (%%esi,%%ebx,4),%%edi \n" // add     edi, [esi + ebx * 4]
        "  add  %%ecx, %%edi  \n"  // add     edi, ecx
    // { Draw the pixel }
        "  mov  %%eax, (%%edi) \n" // mov     [edi], eax
        :
        : "D" (Buffer), "S" (LineOfs),           // %0, %1
          "c" (x), "b" (y),                      // %2, %3
          "a" (colour)                           // %4
    );
  } // switch
  return;
} // TGfx0::putPixel

UInt32 TGfx0::RGB(UInt8 red, UInt8 green, UInt8 blue) {
  UInt32 lastclr;
  lastclr=0;
  switch (BPP) {
  case 8:
    asm(
      "  movl  $256,%%ecx     \n"
      "  movl  $256*3+1,%%ebx \n"
      "  xor   %%eax,%%eax    \n"
      "lop:                   \n"
      "  pushl %%eax          \n"
      "  mov   (%%esi),%%al   \n"
      "  incl  %%esi          \n"
      "  sub   %1,%%al        \n"
      "  jns   abs1           \n"
      "  neg   %%al           \n"
      "abs1:                  \n"
      "  movl   %%eax,%%edi   \n"
      "  mov   (%%esi),%%al   \n"
      "  incl  %%esi          \n"
      "  sub   %2,%%al        \n"
      "  jns   abs2           \n"
      "  neg   %%al           \n"
      "abs2:                  \n"
      "  addl  %%eax,%%edi    \n"
      "  mov   (%%esi),%%al   \n"
      "  incl  %%esi          \n"
      "  sub   %3,%%al        \n"
      "  jns   abs3           \n"
      "  neg   %%al           \n"
      "abs3:                  \n"
      "  addl  %%eax,%%edi    \n"
      "  popl  %%eax          \n"
      "  cmpl  %%ebx,%%edi    \n"
      "  jae   no_good_match  \n"
      "  movl  %%edi,%%ebx    \n"
      "  movl  %%eax,%4       \n"
      "no_good_match:         \n"
      "  incl  %%eax          \n"
      "  decl  %%ecx          \n"
      "  jnz   lop            \n"
      : 
      : "S" (pal), "m" (red), "m" (green), "m" (blue), "m" (lastclr)
      );
    break;
  case 15:
  case 16:
    asm(
      "  xor  %%eax, %%eax    \n"
      "  xor  %%ebx, %%ebx    \n"
      "  xor  %%ecx, %%ecx    \n"
      "  mov  %0, %%al        \n"  // mov al, red
      "  mov  %3, %%cl        \n"  // mov cl, RedShifter
      "  shr  %%cl, %%al      \n"  // shr al, cl
      "  mov  %4, %%cl        \n"  // mov cl, RedFieldPosition
      "  shl  %%cl, %%eax     \n"  // shl eax, cl
      "  mov  %%eax, %%ebx    \n"  // mov ebx, eax
      "  xor  %%eax, %%eax    \n"  // xor eax, eax
      "  mov  %1, %%al        \n"  // mov al, green
      "  mov  %5, %%cl        \n"  // mov cl, GreenShifter
      "  shr  %%cl, %%al      \n"  // shr al, cl
      "  mov  %6, %%cl        \n"  // mov cl, GreenFieldPosition
      "  shl  %%cl, %%eax     \n"  // shl eax, cl
      "  or   %%eax, %%ebx    \n"  // or eax, ebx
      "  xor  %%eax, %%eax    \n"  // xor eax, eax
      "  mov  %2, %%al        \n"  // mov al, blue
      "  mov  %7, %%cl        \n"  // mov cl, BlueShifter
      "  shr  %%cl, %%al      \n"  // shr al, cl
      "  mov  %8, %%cl        \n"  // mov cl, BlueFieldPosition
      "  shl  %%cl, %%eax     \n"  // shl eax, cl
      "  or   %%ebx, %%eax    \n"  // or eax, ebx
      "  mov  %%eax, %9       \n"  // mov lastclr, eax
      : 
      : "m" (red), "m" (green), "m" (blue),           // %0, %1, %2
        "m" (RedShifter), "m" (RedFieldPosition),     // %3, %4
        "m" (GreenShifter), "m" (GreenFieldPosition), // %5, %6
        "m" (BlueShifter), "m" (BlueFieldPosition),   // %7, %8
        "m" (lastclr)                                 // %9
    );
    break;
  case 24:
  case 32:
    asm(
      "  xor  %%eax, %%eax    \n"  // xor     eax, eax
      "  xor  %%ebx, %%ebx    \n"  // xor     ebx, ebx
      "  xor  %%ecx, %%ecx    \n"  // xor     ecx, ecx

      "  mov  %0, %%al        \n"  // mov     al, red
      "  mov  %3, %%cl        \n"  // mov    cl, RedFieldPosition
      "  shl  %%cl, %%eax     \n"  // shl     eax, cl
      "  mov  %%eax, %%ebx    \n"  // mov     ebx, eax
      "  xor  %%eax, %%eax    \n"  // xor     eax, eax
      "  mov  %1, %%al        \n"  // mov     al, green
      "  mov  %4, %%cl        \n"  // mov     cl, GreenFieldPosition
      "  shl  %%cl, %%eax     \n"  // shl     eax, cl
      "  or   %%eax, %%ebx    \n"  // or      ebx, eax
      "  xor  %%eax, %%eax    \n"  // xor     eax, eax
      "  mov  %2, %%al        \n"  // mov     al, blue
      "  mov  %5, %%cl        \n"  // mov     cl, BlueFieldPosition
      "  shl  %%cl, %%eax     \n"  // shl     eax, cl
      "  or   %%ebx, %%eax    \n"  // or      eax, ebx
      "  mov  %%eax, %6       \n"  // mov     lastclr, eax
      :
      : "m" (red), "m" (green), "m" (blue),  // %0, %1, %2
        "m" (RedFieldPosition),              // %3
        "m" (GreenFieldPosition),            // %4
        "m" (BlueFieldPosition),             // %5
        "m" (lastclr)                        // %6
    );
  } // switch
  //asm("": "=a" (lastclr));
  return lastclr;
} // TGfx0::RGB

void TGfx0::setRGBPalette(UInt8 colour, UInt8 red, UInt8 green, UInt8 blue) {
  if (!pal) return;
  pal[colour].red = red;
  pal[colour].green = green;
  pal[colour].blue = blue;
  return;
} // TGfx0::setRGBPalette

void TGfx0::unpackRGB(UInt32 colour, UInt8* red, UInt8* green, UInt8* blue) {
  switch (BPP) {
  case 8:
    if (!pal) {
      *red = 0;
      *green = 0;
      *blue = 0;
      return;
    }
    if (colour>255) colour=colour & 255;
    *red   = pal[colour].red;
    *green = pal[colour].green;
    *blue  = pal[colour].blue; 
    break;
  case 15:
  case 16:
    *red   = ((colour >> RedFieldPosition) << RedShifter);
    *green = ((colour >> GreenFieldPosition) << GreenShifter);
    *blue  = ((colour >> BlueFieldPosition) << BlueShifter);
    if ((*red) && (RedShifter)) *red+=(1 << RedShifter)-1;
    if ((*green) && (GreenShifter)) *green+=(1 << GreenShifter)-1;
    if ((*blue) && (BlueShifter)) *blue+=(1 << BlueShifter)-1;
    break;
  case 24:
  case 32:
    *red   = colour >> RedFieldPosition;
    *green = colour >> GreenFieldPosition;
    *blue  = colour >> BlueFieldPosition;
    break;
  default:
    *red   = 0;
    *green = 0;
    *blue  = 0;
  }
  return;
} // TGfx0:unpackRGB

TGfx0::~TGfx0(void) {
  if (DataState == og_Owner) {
    if (pal) free(pal);
    if (Buffer) free(Buffer);
    if (LineOfs) free(LineOfs);
  }  // if datastate
  pal=0;
  LineOfs=0;
  Buffer=0;
  bSize=0;
  lSize=0;
  DataState = og_None;
  return;
} // TGfx0::~TGfx0()