/*******************************************************
$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()