gps/GPSResources/tcpmp/common/blit/blit_arm_rgb16.c

541 lines
11 KiB
C
Executable File

/*****************************************************************************
*
* This program is free software ; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: blit_arm_rgb16.c 339 2005-11-15 11:22:45Z picard $
*
* The Core Pocket Media Player
* Copyright (c) 2004-2005 Gabor Kovacs
*
****************************************************************************/
#include "../common.h"
#include "../dyncode/dyncode.h"
#include "blit_soft.h"
#if defined(ARM)
// R0..R6 temporary
// R7 Pos(when Stretch)
// R8 Src2SrcLast (when Diff)
// R8 Src0 (when Stretch)
// R9 Src
// R10 EndOfLine
// R11 Dst
// R12 DstPitch
// R14 SrcPitch
// R14 Src1 (when Stretch)
typedef struct stack
{
int EndOfRect;
int DstNext;
int SrcNext;
void* Palette;
int StackFrame[STACKFRAME];
//void* this R0
//char* Dst R1
//char* Src R2
//int DstPitch R3 can be signed
int SrcPitch;
int Width;
int Height;
int Src2SrcLast;
} stack;
void RGB_4X2(blit_soft* p)
{
if (p->RealOnlyDiff)
{
p->Skip = Label(0);
I3(LDR,R4,R9,R8);
I3(LDR_POST,R0,R9,R14);
I3(LDR,R6,R9,R8);
I2C(LDR_POST,R2,R9,4);
I3(LDR,R5,R9,R8);
I3(LDR_POSTSUB,R3,R9,R14);
I3(CMP,NONE,R0,R4);
C(EQ); I3(CMP,NONE,R2,R6);
I3(LDR,R6,R9,R8);
I2C(LDR_POST,R1,R9,4);
C(EQ); I3(CMP,NONE,R3,R5);
C(EQ); I3(CMP,NONE,R1,R6);
C(EQ);
if (p->SwapXY)
I3S(ADD,R11,R11,R12,LSL,2+p->DstDoubleY);
else
I2C(ADD,R11,R11,(2*4*p->DirX)<<p->DstDoubleX);
I0P(B,EQ,p->Skip);
}
if (p->DstDoubleX && p->DstDoubleY)
{
//todo...
}
else
{
if (p->SwapXY)
{
if (p->RealOnlyDiff)
I2C(SUB,R9,R9,8);
Half(); I3(LDR_POST,R0,R9,R14);
Half(); I2C(LDR_POST,R1,R9,2);
Half(); I3(LDR_POSTSUB,R3,R9,R14);
Half(); I2C(LDR_POST,R2,R9,2);
if (p->DirX>0)
{
I3S(ORR,R4,R0,R1,LSL,16);
I3S(ORR,R5,R2,R3,LSL,16);
}
else
{
I3S(ORR,R4,R1,R0,LSL,16);
I3S(ORR,R5,R3,R2,LSL,16);
}
MB(); Half(); I3(LDR_POST,R0,R9,R14);
MB(); Half(); I2C(LDR_POST,R1,R9,2);
MB(); Half(); I3(LDR_POSTSUB,R3,R9,R14);
MB(); Half(); I2C(LDR_POST,R2,R9,2);
if (p->DirX>0)
{
I3S(ORR,R1,R0,R1,LSL,16);
I3S(ORR,R3,R2,R3,LSL,16);
}
else
{
I3S(ORR,R1,R1,R0,LSL,16);
I3S(ORR,R3,R3,R2,LSL,16);
}
I3(STR_POST,R4,R11,R12);
I3(STR_POST,R5,R11,R12);
I3(STR_POST,R1,R11,R12);
I3(STR_POST,R3,R11,R12);
}
else
{
if (!p->RealOnlyDiff)
{
I3(LDR_POST,R0,R9,R14);
I2C(LDR_POST,R2,R9,4);
I3(LDR_POSTSUB,R3,R9,R14);
I2C(LDR_POST,R1,R9,4);
}
if (p->DirX<0)
{
I3S(MOV,R0,NONE,R0,ROR,16);
I3S(MOV,R1,NONE,R1,ROR,16);
I3S(MOV,R2,NONE,R2,ROR,16);
I3S(MOV,R3,NONE,R3,ROR,16);
}
I3(STR_POST,R0,R11,R12);
I2C(STR_POST,R2,R11,4*p->DirX);
I3(STR_POSTSUB,R3,R11,R12);
I2C(STR_POST,R1,R11,4*p->DirX);
}
}
if (p->RealOnlyDiff)
InstPost(p->Skip);
}
void RGB_Read(blit_soft* p,reg RGB,reg Src,int Inc)
{
int Type[4];
int IncByte[4];
reg Tmp = R6;
int i,j;
bool_t First;
if (p->Src.BitCount==p->Dst.BitCount && (p->Src.BitCount!=8 || !p->LookUp) &&
p->Src.BitMask[0] == p->Dst.BitMask[0] &&
p->Src.BitMask[1] == p->Dst.BitMask[1] &&
p->Src.BitMask[2] == p->Dst.BitMask[2])
{
switch (p->Src.BitCount)
{
case 8:
Byte(); I2C(LDR_POST,RGB,Src,Inc);
break;
case 16:
Half(); I2C(LDR_POST,RGB,Src,Inc*2);
break;
case 32:
I2C(LDR_POST,RGB,Src,Inc*4);
break;
}
}
else
{
switch (p->Src.BitCount)
{
case 8:
if (p->LookUp)
{
I1P(MOV,Tmp,p->LookUp,0);
Byte(); I2C(LDR_POST,RGB,Src,Inc);
switch (p->Dst.BitCount)
{
case 8:
Byte(); I3(LDR,RGB,Tmp,RGB);
break;
case 16:
I3(ADD,RGB,RGB,RGB);
Half(); I3(LDR,RGB,Tmp,RGB);
break;
case 32:
I3S(LDR,RGB,Tmp,RGB,LSL,2);
break;
}
}
break;
case 16:
Half(); I2C(LDR_POST,RGB,Src,Inc*2);
for (i=0;i<3;++i)
{
j = min(p->DstSize[i],p->SrcSize[i]);
I2C(AND,Tmp,RGB,((1<<j)-1) << (p->SrcSize[i]+p->SrcPos[i]-j));
I3S(ORR,RGB,RGB,Tmp,LSL,16-p->SrcSize[i]-p->SrcPos[i]+p->DstSize[i]+p->DstPos[i]);
}
I3S(MOV,RGB,NONE,RGB,LSR,16);
break;
case 32:
case 24:
for (j=0;j<3;++j)
IncByte[j] = 1;
IncByte[3] = (Inc-1) * (p->SrcBPP/8) + (p->Src.BitCount==32);
for (j=0;j<4;++j)
{
Type[j] = -1;
for (i=0;i<3;++i)
if (p->SrcPos[i]==j*8)
Type[j] = i;
if (Type[j]<0)
{
// merge IncByte to previous
for (i=j-1;i>=0;--i)
if (Type[i]>=0 || IncByte[i])
{
IncByte[i] += IncByte[j];
IncByte[j] = 0;
break;
}
}
}
First = 1;
for (j=0;j<4;++j)
{
i = Type[j];
if (i>=0)
{
Byte(); I2C(LDR_POST,Tmp,Src,IncByte[j]);
I2C(AND,Tmp,Tmp,((1 << p->DstSize[i])-1) << (8-p->DstSize[i]));
if (First)
{
I3S(MOV,RGB,NONE,Tmp,LSR,8-p->DstPos[i]-p->DstSize[i]);
First = 0;
}
else
I3S(ORR,RGB,RGB,Tmp,LSR,8-p->DstPos[i]-p->DstSize[i]);
}
else if (IncByte[j]>0)
I2C(ADD,Src,Src,IncByte[j]);
}
break;
}
}
}
void RGB_4X2S(blit_soft* p,int* Inc)
{
if (p->SwapXY)
{
RGB_Read(p,R0,R8,Inc[0]);
RGB_Read(p,R1,R14,Inc[0]);
RGB_Read(p,R2,R8,Inc[1]);
RGB_Read(p,R3,R14,Inc[1]);
if (p->DirX>0)
{
I3S(ORR,R4,R0,R1,LSL,16);
I3S(ORR,R5,R2,R3,LSL,16);
}
else
{
I3S(ORR,R4,R1,R0,LSL,16);
I3S(ORR,R5,R3,R2,LSL,16);
}
RGB_Read(p,R0,R8,Inc[2]);
RGB_Read(p,R1,R14,Inc[2]);
RGB_Read(p,R2,R8,Inc[3]);
RGB_Read(p,R3,R14,Inc[3]);
if (p->DirX>0)
{
I3S(ORR,R1,R0,R1,LSL,16);
I3S(ORR,R3,R2,R3,LSL,16);
}
else
{
I3S(ORR,R1,R1,R0,LSL,16);
I3S(ORR,R3,R3,R2,LSL,16);
}
I3(STR_POST,R4,R11,R12);
I3(STR_POST,R5,R11,R12);
I3(STR_POST,R1,R11,R12);
I3(STR_POST,R3,R11,R12);
}
else
{
RGB_Read(p,R0,R8,Inc[0]);
RGB_Read(p,R1,R8,Inc[1]);
RGB_Read(p,R2,R8,Inc[2]);
RGB_Read(p,R3,R8,Inc[3]);
if (p->DirX>0)
{
I3S(ORR,R4,R0,R1,LSL,16);
I3S(ORR,R5,R2,R3,LSL,16);
}
else
{
I3S(ORR,R4,R1,R0,LSL,16);
I3S(ORR,R5,R3,R2,LSL,16);
}
RGB_Read(p,R0,R14,Inc[0]);
RGB_Read(p,R1,R14,Inc[1]);
RGB_Read(p,R2,R14,Inc[2]);
RGB_Read(p,R3,R14,Inc[3]);
if (p->DirX>0)
{
I3S(ORR,R1,R0,R1,LSL,16);
I3S(ORR,R3,R2,R3,LSL,16);
}
else
{
I3S(ORR,R1,R1,R0,LSL,16);
I3S(ORR,R3,R3,R2,LSL,16);
}
I3(STR_POST,R4,R11,R12);
I2C(STR_POST,R1,R11,4*p->DirX);
I3(STR_POSTSUB,R3,R11,R12);
I2C(STR_POST,R5,R11,4*p->DirX);
}
}
void Any_RGB_RGB(blit_soft* p)
{
dyninst* LoopX;
dyninst* LoopY;
dyninst* EndOfLine;
bool_t Stretch;
bool_t Same =
p->Src.BitCount==p->Dst.BitCount &&
p->Src.BitMask[0] == p->Dst.BitMask[0] &&
p->Src.BitMask[1] == p->Dst.BitMask[1] &&
p->Src.BitMask[2] == p->Dst.BitMask[2];
Stretch = p->RScaleX!=16 || p->RScaleY!=16 || !Same;
p->RealOnlyDiff = (boolmem_t)(p->OnlyDiff && !Stretch);
p->Caps = 0;
p->DstAlignSize = 4;
if (p->SrcDoubleX && !Stretch)
p->DstAlignSize = 8;
p->LookUp = NULL;
if (p->Src.Palette)
CalcPalRGBLookUp(p);
if (p->LookUp_Data)
{
p->LookUp = InstCreate(p->LookUp_Data,p->LookUp_Size,NONE,NONE,NONE,0,0);
free(p->LookUp_Data);
p->LookUp_Data = NULL;
}
CodeBegin();
I2C(SUB,SP,SP,OFS(stack,StackFrame));
I2C(LDR,R11,R1,0);//Dst[0]
I2C(LDR,R9,R2,0); //Src[0]
if (p->DirX<0)
{
//adjust reversed destination for block size
I2C(SUB,R11,R11,2);
}
I3(MOV,R12,NONE,R3); //DstPitch
I2C(LDR,R2,SP,OFS(stack,Height));
I2C(LDR,R1,SP,OFS(stack,Width));
if (!Stretch)
{
//SrcNext = 2*Src->Pitch - SrcWidth << (SrcBPP2+SrcDoubleX)
I2C(LDR,R14,SP,OFS(stack,SrcPitch));
I3S(MOV,R3,NONE,R1,LSL,p->SrcDoubleX+p->SrcBPP2);
I3S(RSB,R0,R3,R14,LSL,1);
I2C(STR,R0,SP,OFS(stack,SrcNext));
}
if (p->SwapXY)
{
//EndOfRect = Dst + Height*2*DirX
I3S(p->DirX<0?SUB:ADD,R0,R11,R2,LSL,p->DstBPP2);
I2C(STR,R0,SP,OFS(stack,EndOfRect));
//DstNext = 2*(DstBPP/8)*DirX - Width*Dst->Pitch
I3(MUL,R3,R1,R12);
I2C(MOV,R0,NONE,2*p->DirX*(p->DstBPP/8));
I3(SUB,R0,R0,R3);
I2C(STR,R0,SP,OFS(stack,DstNext));
}
else
{
I3(MUL,R0,R12,R2); //DstPitch * Height
I3(ADD,R0,R11,R0);
I2C(STR,R0,SP,OFS(stack,EndOfRect));
//DstNext = 2*Dst->Pitch - DirX*Width*(DstBPP/8)
I3(ADD,R3,R1,R1);
I3S(p->DirX<0?ADD:RSB,R0,R3,R12,LSL,p->DstBPP2);
I2C(STR,R0,SP,OFS(stack,DstNext));
}
if (p->RealOnlyDiff)
I2C(LDR,R8,SP,OFS(stack,Src2SrcLast));
if (Stretch)
I2C(MOV,R7,NONE,0); //Pos
I2C(LDR,R0,SP,OFS(stack,Width));
LoopY = Label(1);
//R0 width
if (p->SwapXY)
{
I3(MUL,R10,R12,R0); //R12=DstPitch
I3(ADD,R10,R11,R10);
}
else
I3S(p->DirX>0?ADD:SUB,R10,R11,R0,LSL,1);
if (Stretch)
{
int Col,i,ColCount;
I3(MOV,R8,NONE,R9); //Src0
I2C(LDR,R6,SP,OFS(stack,SrcPitch));
I3S(MOV,R4,NONE,R7,LSR,4);
I2C(ADD,R0,R7,p->RScaleY);
I3S(RSB,R4,R4,R0,LSR,4);
I3(MUL,R4,R6,R4);
I3(ADD,R14,R9,R4); //Src1
EndOfLine = Label(0);
LoopX = Label(1);
ColCount = 16;
for (i=1;i<4 && !(p->RScaleX & i);i<<=1)
ColCount >>= 1;
for (Col=0;Col<ColCount;Col+=4)
{
int Inc[4];
for (i=0;i<4;++i)
Inc[i] = (((Col+i+1) * p->RScaleX) >> 4) - (((Col+i) * p->RScaleX) >> 4);
RGB_4X2S(p,Inc);
I3(CMP,NONE,R10,R11);
if (Col+4 >= ColCount)
I0P(B,NE,LoopX);
else
I0P(B,EQ,EndOfLine);
}
InstPost(EndOfLine);
I2C(LDR,R6,SP,OFS(stack,SrcPitch));
I3S(MOV,R4,NONE,R7,LSR,4);
I2C(ADD,R7,R7,2*p->RScaleY);
I3S(RSB,R4,R4,R7,LSR,4);
I3(MUL,R4,R6,R4);
I3(ADD,R9,R9,R4); //add 2 lines
}
else
{
LoopX = Label(1);
RGB_4X2(p);
I3(CMP,NONE,R10,R11);
I0P(B,NE,LoopX);
I2C(LDR,R0,SP,OFS(stack,SrcNext));
I3(ADD,R9,R9,R0);
}
I2C(LDR,R1,SP,OFS(stack,DstNext));
I2C(LDR,R2,SP,OFS(stack,EndOfRect));
I2C(LDR,R0,SP,OFS(stack,Width)); // needed for next EndOfLine
I3(ADD,R11,R11,R1);
I3(CMP,NONE,R2,R11);
I0P(B,NE,LoopY);
I2C(ADD,SP,SP,OFS(stack,StackFrame));
CodeEnd();
if (p->LookUp)
{
Align(16);
InstPost(p->LookUp);
}
}
#endif