📄 blit_arm_yuv.c
字号:
/*****************************************************************************
*
* 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_yuv.c 375 2005-12-02 09:34:27Z picard $
*
* The Core Pocket Media Player
* Copyright (c) 2004-2005 Gabor Kovacs
*
****************************************************************************/
#include "../common.h"
#include "../dyncode/dyncode.h"
#include "blit_soft.h"
// DstAlignSize 8
// DstAlignPos 8
// SrcAlignPos 8
#if defined(ARM)
// R0..R4 temporary
// R5 DiffMask (when Diff)
// R6 Src2SrcLast (when Diff)
// R5 7F7F7F7F (when !Diff and HalfY and !HalfX)
// R7 Src
// R8 MaskCarry (when Brightness != 0)
// R9 Add32 (when Brightness != 0)
// R10 EndOfLine (Src)
// R11 Dst
// R12 DstPitch
// R14 SrcPitch
typedef struct stack
{
int Dst[3];
int Src[3];
int EndOfRect;
int DstNext[2];
int SrcNext[2];
int SaveR0;
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;
static void NOINLINE SetDither(blit_soft* p,int Pos,int Part,int Plane)
{
if (Plane==0 && (p->FX.Flags & BLITFX_DITHER) && p->SrcYUV)
{
// dither matrix:
// 0 2
// 3 1
int Ofs;
if (Pos & 8)
Ofs = Part?2:0;
else
Ofs = Part?1:3;
if (Ofs != p->LookUpOfs)
{
I2C(ADD,R8,R8,Ofs-p->LookUpOfs);
p->LookUpOfs = Ofs;
}
}
}
static NOINLINE int YUV_4(blit_soft* p, int Reg,int Pos,int Plane)
{
reg RA = (reg)Reg;
reg RB = R4;
reg RC = R0;
reg RD = R9;
if (p->SwapXY)
{
if (Reg != R0)
{
if (!p->SrcYUV || (Plane!=0 && (p->HalfX || p->HalfY)))
I2C(LDR,R0,SP,OFS(stack,SaveR0));
else
I2(LDR,R0,R7);
}
if (p->LookUp)
{
I2C(AND,RB,R2,0xFF << Pos);
I2C(AND,RC,R0,0xFF << Pos);
SetDither(p,Pos,1,Plane);
Byte(); I3S(LDR,RB,R8,RB,LSR,Pos);
I2C(AND,RD,R1,0xFF << Pos);
Byte(); I3S(LDR,RC,R8,RC,LSR,Pos);
I3S(MOV,RB,NONE,RB,LSR,-(p->DirX<0?8:16));
I3S(ORR,RB,RB,RC,LSR,-(p->DirX<0?24:0));
I2C(AND,RC,R3,0xFF << Pos);
SetDither(p,Pos,0,Plane);
Byte(); I3S(LDR,RD,R8,RD,LSR,Pos);
Byte(); I3S(LDR,RC,R8,RC,LSR,Pos);
I3S(ORR,RB,RB,RD,LSR,-(p->DirX<0?16:8));
I3S(ORR,RB,RB,RC,LSR,-(p->DirX<0?0:24));
}
else
{
I2C(AND,RB,R2,0xFF << Pos);
I3S(MOV,RB,NONE,RB,LSR,Pos-(p->DirX<0?8:16));
I2C(AND,RC,R0,0xFF << Pos);
I3S(ORR,RB,RB,RC,LSR,Pos-(p->DirX<0?24:0));
I2C(AND,RC,R1,0xFF << Pos);
I3S(ORR,RB,RB,RC,LSR,Pos-(p->DirX<0?16:8));
I2C(AND,RC,R3,0xFF << Pos);
I3S(ORR,RB,RB,RC,LSR,Pos-(p->DirX<0?0:24));
}
RA=RB;
}
else
if (p->DirX<0)
{
if (p->LookUp)
{
I2C(AND,RB,RA,0xFF00);
SetDither(p,Pos,1,Plane);
Byte(); I3S(LDR,RD,R8,RA,LSR,24);
Byte(); I3S(LDR,RB,R8,RB,LSR,8);
I3S(MOV,RA,NONE,RA,ROR,24);
I3S(ORR,RD,RD,RB,LSL,16);
SetDither(p,Pos,0,Plane);
Byte(); I3S(LDR,RB,R8,RA,LSR,24);
I2C(AND,RA,RA,0xFF00);
Byte(); I3S(LDR,RA,R8,RA,LSR,8);
I3S(ORR,RD,RD,RB,LSL,8);
I3S(ORR,RD,RD,RA,LSL,24);
RA = RD;
}
else
if (RA == RC)
{
// only RA and RB
I3S(MOV,RB,NONE,RA,LSR,24);
I3S(ORR,RB,RB,RA,LSL,24);
I3S(MOV,RA,NONE,RA,ROR,16);
I3S(MOV,RB,NONE,RB,ROR,16);
I3S(ORR,RB,RB,RA,LSR,24);
I3S(ORR,RB,RB,RA,LSL,24);
I3S(MOV,RA,NONE,RB,ROR,16);
}
else
{
I2C(AND,RC,RA,0xFF00);
I3S(MOV,RB,NONE,RA,LSL,24);
I3S(ORR,RB,RB,RC,LSL,8);
I2C(AND,RC,RA,0xFF0000);
I3S(ORR,RB,RB,RA,LSR,24);
I3S(ORR,RA,RB,RC,LSR,8);
}
}
else
{
if (p->LookUp)
{
I2C(AND,RB,RA,0xFF00);
SetDither(p,Pos,1,Plane);
Byte(); I3S(LDR,RD,R8,RA,LSR,24);
Byte(); I3S(LDR,RB,R8,RB,LSR,8);
I3S(MOV,RA,NONE,RA,ROR,24);
I3S(ORR,RB,RB,RD,LSL,16);
SetDither(p,Pos,0,Plane);
Byte(); I3S(LDR,RD,R8,RA,LSR,24);
I2C(AND,RA,RA,0xFF00);
Byte(); I3S(LDR,RA,R8,RA,LSR,8);
I3S(ORR,RB,RB,RD,LSL,8);
I3S(ORR,RA,RA,RB,LSL,8);
}
else
{
RB = R0;
RC = R4;
}
}
if (Plane==0 && p->FX.Brightness && !p->LookUp && p->SrcYUV)
{
if (p->FX.Brightness < 0)
{
I3(MVN,RB,NONE,RA);
RA=RB;
}
I3(ADD,RC,RA,R9); //add32
I3(BIC,RB,RA,RC);
I3(AND,RB,RB,R8); //maskcarry
I3S(MOV,RB,NONE,RB,LSR,7);
I3S(SUB,RC,RC,RB,LSL,8);
I3S(RSB,RB,RB,RB,LSL,8);
I3(ORR,RB,RB,RC);
if (p->FX.Brightness < 0)
I3(MVN,RB,NONE,RB);
RA=RB;
}
return RA;
}
static NOINLINE void YUV_4X4(blit_soft* p, int Plane)
{
int y;
int UV = Plane != 0;
int Rows = 2;
int HalfX = UV ? p->HalfX:0;
int HalfY = UV ? p->HalfY:0;
int SrcUVX = UV?p->SrcUVX2:0;
int SrcUVPitch = UV?p->SrcUVPitch2:0;
int DstUVPitch = UV?p->DstUVPitch2:0;
if (UV) Rows >>= p->SrcUVY2+p->HalfY;
I2C(LDR,R7,SP,OFS(stack,Src[Plane]));
I2C(LDR,R11,SP,OFS(stack,Dst[Plane]));
for (y=0;y<Rows;++y)
{
reg RA,RWidth=R0;
dyninst* LoopX = Label(0);
MB(); I2C(LDR,R0,SP,OFS(stack,Width));
if (p->SrcBPP2>0)
{
IMul(R1,R0,p->SrcBPP/8);
RWidth = R1;
}
I3S(ADD,R10,R7,RWidth,LSR,SrcUVX); //end of line
//preload
if (!p->Slices)
{
dyninst* PreLoad1;
dyninst* PreLoad2;
dyninst* PreLoad3;
dyninst* PreLoad4;
I2C(ADD,R0,R7,32);
I3(CMP,NONE,R0,R10);
I0P(B,CS,LoopX);
PreLoad1 = Label(1);
Byte(); I2C(LDR,R2,R0,-32);
I2C(ADD,R0,R0,64);
I3(CMP,NONE,R0,R10);
Byte(); I2C(LDR,R3,R0,-64);
I0P(B,CC,PreLoad1);
I3S(ADD,R7,R7,R14,ASR,SrcUVPitch-1);
I3S(ADD,R10,R10,R14,ASR,SrcUVPitch-1);
I2C(ADD,R0,R7,32);
PreLoad2 = Label(1);
Byte(); I2C(LDR,R2,R0,-32);
I2C(ADD,R0,R0,64);
I3(CMP,NONE,R0,R10);
Byte(); I2C(LDR,R3,R0,-64);
I0P(B,CC,PreLoad2);
I3S(ADD,R7,R7,R14,ASR,SrcUVPitch);
I3S(ADD,R10,R10,R14,ASR,SrcUVPitch);
I2C(ADD,R0,R7,32);
PreLoad3 = Label(1);
Byte(); I2C(LDR,R2,R0,-32);
I2C(ADD,R0,R0,64);
I3(CMP,NONE,R0,R10);
Byte(); I2C(LDR,R3,R0,-64);
I0P(B,CC,PreLoad3);
I3S(SUB,R7,R7,R14,ASR,SrcUVPitch-1);
I3S(SUB,R10,R10,R14,ASR,SrcUVPitch-1);
I2C(ADD,R0,R7,32);
PreLoad4 = Label(1);
Byte(); I2C(LDR,R2,R0,-32);
I2C(ADD,R0,R0,64);
I3(CMP,NONE,R0,R10);
Byte(); I2C(LDR,R3,R0,-64);
I0P(B,CC,PreLoad4);
I3S(SUB,R7,R7,R14,ASR,SrcUVPitch);
I3S(SUB,R10,R10,R14,ASR,SrcUVPitch);
}
else
if (p->ARM5)
{
//preload next
I3S(ADD,R0,R7,R14,ASR,SrcUVPitch-2);
I3S(ADD,R1,R0,R14,ASR,SrcUVPitch-1);
I2(PLD,NONE,R0);
I2(PLD,NONE,R1);
I3S(PLD,NONE,R0,R14,ASR,SrcUVPitch);
I3S(PLD,NONE,R1,R14,ASR,SrcUVPitch);
}
InstPost(LoopX);
if (p->RealOnlyDiff)
{
p->Skip = Label(0);
I3(LDR,R4,R7,R6);
I3S(LDR_POST,R0,R7,R14,ASR,SrcUVPitch-1);
I3(LDR,R1,R7,R6);
I3S(LDR_POST,R2,R7,R14,ASR,SrcUVPitch);
I3(EOR,R4,R4,R0);
S(); I3(BIC,R4,R4,R5);
I3(LDR,R0,R7,R6);
I3S(LDR_POSTSUB,R3,R7,R14,ASR,SrcUVPitch-1);
I3(EOR,R1,R1,R2);
S(); C(EQ); I3(BIC,R1,R1,R5);
I3(LDR,R4,R7,R6);
I3S(LDR_POSTSUB,R1,R7,R14,ASR,SrcUVPitch);
I3(EOR,R0,R0,R3);
S(); C(EQ); I3(BIC,R0,R0,R5);
I2(LDR,R0,R7);
I3(EOR,R4,R4,R1);
S(); C(EQ); I3(BIC,R4,R4,R5);
I0P(B,EQ,p->Skip);
}
else
if (!p->SrcYUV && !p->LookUp)
{
int x,y;
// r0,r2,r3,r1 (tmp r4,r5,r6)
for (y=0;y<4;++y)
{
reg Out;
switch (y)
{
case 1: Out = R1; break;
case 2: Out = R2; break;
case 3: Out = R3; break;
default:Out = R0; break;
}
for (x=0;x<4;++x)
{
reg Val = (reg)(x?R4:Out);
int ofs = ((p->SrcBPP/8) << HalfX)*x;
switch (p->SrcBPP)
{
// 8bit handled by lookup (with normal YUV blitting)
case 16:
Half(); I2C(LDR,R4,R7,ofs);
I2C(MOV,R5,NONE,((1 << p->SrcSize[1])-1) << (8-p->SrcSize[1]));
I2C(MOV,R6,NONE,((1 << p->SrcSize[2])-1) << (8-p->SrcSize[2]));
I3S(AND,R5,R5,R4,LSR,p->SrcPos[1]+p->SrcSize[1]-8);
I3S(AND,R6,R6,R4,LSR,p->SrcPos[2]+p->SrcSize[2]-8);
I2C(AND,R4,R4,p->Src.BitMask[0]);
I3S(MOV,R4,NONE,R4,LSR,p->SrcPos[0]+p->SrcSize[0]-8);
break;
case 24:
case 32:
Byte(); I2C(LDR,R6,R7,ofs+(p->SrcPos[2]>>3));
Byte(); I2C(LDR,R4,R7,ofs+(p->SrcPos[0]>>3));
Byte(); I2C(LDR,R5,R7,ofs+(p->SrcPos[1]>>3));
break;
}
// R4,R5,R6 r,g,b
// Y = (2105*R + 4128*G + 802*B)/0x2000 + 16;
// U = (-1212*R - 2384*G + 3596*B)/0x2000 + 128;
// V = (3596*R - 3015*G - 582*B)/0x2000 + 128;
switch (Plane)
{
case 0:
// Y = (8*R + 16*G + 3*B)/32 + 16;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -