| /* ------------------------------------------------------------------ |
| * Copyright (C) 2008 PacketVideo |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either |
| * express or implied. |
| * See the License for the specific language governing permissions |
| * and limitations under the License. |
| * ------------------------------------------------------------------- |
| */ |
| // // |
| // File: cczoomrotation12.cpp // |
| // // |
| ////////////////////////////////////////////////////////////////////////////////// |
| /** Class ColorConvert12, YUV to RGB12 bit with dithering. 4bit empty */ |
| #include "colorconv_config.h" |
| #include "cczoomrotation12.h" |
| |
| //for debug only |
| //#define OUTPUT_RGB_565 |
| |
| |
| OSCL_EXPORT_REF ColorConvertBase* ColorConvert12::NewL(void) |
| { |
| ColorConvert12* self = OSCL_NEW(ColorConvert12, ()); |
| return OSCL_STATIC_CAST(ColorConvertBase*, self); |
| } |
| |
| |
| ColorConvert12::ColorConvert12() |
| { |
| mErr_horz[0] = (NULL); |
| mClip = NULL; |
| } |
| |
| |
| OSCL_EXPORT_REF ColorConvert12::~ColorConvert12() |
| { |
| if (mErr_horz[0]) |
| { |
| OSCL_ARRAY_DELETE(mErr_horz[0]); |
| } |
| |
| if (mClip) |
| { |
| mClip -= 384; |
| OSCL_ARRAY_DELETE(mClip); |
| } |
| } |
| |
| |
| int32 ColorConvert12::Init(int32 Src_width, int32 Src_height, int32 Src_pitch, int32 Dst_width, int32 Dst_height, int32 Dst_pitch, int32 nRotation) |
| { |
| if (ColorConvertBase::Init(Src_width, Src_height, Src_pitch, Dst_width, Dst_height, Dst_pitch, nRotation) == 0) |
| { |
| return 0; |
| } |
| |
| //local init |
| _mInitialized = false; |
| |
| if (mErr_horz[0]) |
| { |
| OSCL_ARRAY_DELETE(mErr_horz[0]); |
| mErr_horz[0] = NULL; |
| } |
| |
| int32 leavecode = 0; |
| if (_mRotation&0x1) |
| { |
| OSCL_TRY(leavecode, mErr_horz[0] = OSCL_ARRAY_NEW(uint8, _mSrc_height * 4)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| return 0; |
| ); |
| |
| #if USE_ARM_ASM_FOR_COLORCONVERT |
| oscl_memset((void*)(mErr_horz[0]), 0, _mSrc_height*4); |
| #else |
| mErr_horz[1] = mErr_horz[0] + _mSrc_height + 1; |
| mErr_horz[2] = mErr_horz[1] + _mSrc_height + 1; |
| #endif |
| } |
| else |
| { |
| OSCL_TRY(leavecode, mErr_horz[0] = OSCL_ARRAY_NEW(uint8, _mSrc_width * 4)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| return 0; |
| ); |
| |
| #if USE_ARM_ASM_FOR_COLORCONVERT |
| oscl_memset((void*)(mErr_horz[0]), 0, _mSrc_width*4); |
| #else |
| mErr_horz[1] = mErr_horz[0] + _mSrc_width + 1; |
| mErr_horz[2] = mErr_horz[1] + _mSrc_width + 1; |
| #endif |
| } |
| |
| if (mClip) |
| { |
| mClip -= 384; |
| OSCL_ARRAY_DELETE(mClip); |
| mClip = NULL; |
| } |
| leavecode = 0; |
| OSCL_TRY(leavecode, mClip = OSCL_ARRAY_NEW(uint8, 1024)); |
| OSCL_FIRST_CATCH_ANY(leavecode, |
| return 0; |
| ); |
| mClip += 384; |
| |
| int32 tmp; |
| for (int32 i = -384; i < 640; i++) |
| { |
| tmp = (int32)(1.164 * (i - 16)); |
| mClip[i] = (tmp < 0) ? 0 : ((tmp > 255) ? 255 : (uint8)tmp); |
| } |
| |
| //default no zoom |
| _mInitialized = true; |
| |
| SetMode(0); // called after init |
| |
| return 1; |
| } |
| |
| int32 ColorConvert12::SetYuvFullRange(bool range) |
| { |
| OSCL_ASSERT(_mInitialized == true); |
| |
| if (range == true) |
| return 0; // error this mode is not supported yet |
| |
| return 1; |
| } |
| |
| |
| int32 ColorConvert12::SetMode(int32 nMode) //nMode : 0 Off, 1 On |
| { |
| OSCL_ASSERT(_mInitialized == true); |
| |
| if (nMode == 0) |
| { |
| mPtrYUV2RGB = &ColorConvert12::get_frame12; |
| _mState = 0; |
| _mDisp.src_pitch = _mSrc_pitch ; |
| _mDisp.dst_pitch = _mSrc_width ; |
| _mDisp.src_width = _mSrc_width ; |
| _mDisp.src_height = _mSrc_height ; |
| _mDisp.dst_width = _mSrc_width ; |
| _mDisp.dst_height = _mSrc_height ; |
| } |
| else |
| { |
| if (_mIsZoom) |
| { |
| if (_mRotation&0x1) /* zoom and rotate */ |
| { |
| mPtrYUV2RGB = &ColorConvert12::cc12ZoomRotate; |
| } |
| else /* zoom only */ |
| { |
| mPtrYUV2RGB = &ColorConvert12::cc12ZoomIn; |
| } |
| } |
| else |
| { |
| if (_mRotation&0x1) /* rotate only*/ |
| { |
| mPtrYUV2RGB = &ColorConvert12::cc12Rotate; |
| } |
| else /* no zoom, no rotate, SetMode(1) = SetMode(0) */ |
| { |
| mPtrYUV2RGB = &ColorConvert12::get_frame12; |
| } |
| } |
| _mState = nMode; |
| _mDisp.src_pitch = _mSrc_pitch ; |
| _mDisp.dst_pitch = _mDst_pitch ; |
| _mDisp.src_width = _mSrc_width ; |
| _mDisp.src_height = _mSrc_height ; |
| _mDisp.dst_width = _mDst_width ; |
| _mDisp.dst_height = _mDst_height ; |
| } |
| |
| return 1; |
| } |
| |
| |
| int32 ColorConvert12::GetOutputBufferSize(void) |
| { |
| OSCL_ASSERT(_mInitialized == true); |
| |
| // for zoom, need extra line of RGB buffer for processing otherwise memory will corrupt. |
| return _mState ? ((_mDst_height + 1)*_mDst_pitch*2) : (_mSrc_width*_mSrc_height*2); |
| } |
| |
| |
| int32 ColorConvert12::Convert(uint8 **yuvBuf, uint8 *rgbBuf) |
| { |
| OSCL_ASSERT(_mInitialized == true); |
| OSCL_ASSERT(yuvBuf); |
| OSCL_ASSERT(yuvBuf[0]); |
| OSCL_ASSERT(yuvBuf[1]); |
| OSCL_ASSERT(yuvBuf[2]); |
| OSCL_ASSERT(rgbBuf); |
| |
| //reset the row dither error buffer |
| if (((uint)rgbBuf)&0x3 || ((uint)yuvBuf[0])&0x3) /* address is not word align */ |
| { |
| return 0; |
| } |
| |
| if (_mRotation&0x1) |
| { |
| oscl_memset((void*)(mErr_horz[0]), 0, _mSrc_height*4); |
| } |
| else |
| { |
| oscl_memset((void*)(mErr_horz[0]), 0, _mSrc_width*4); |
| } |
| |
| (*this.*mPtrYUV2RGB)(yuvBuf, rgbBuf, &_mDisp, mClip, (uint8 *)(mErr_horz[0])); |
| |
| return 1; |
| } |
| |
| |
| int32 ColorConvert12::Convert(uint8 *yuvBuf, uint8 *rgbBuf) |
| { |
| OSCL_ASSERT(_mInitialized == true); |
| OSCL_ASSERT(yuvBuf); |
| OSCL_ASSERT(rgbBuf); |
| |
| //this conversion will cause problems when do src clipping. However, if they want, they must give more info |
| uint8 *TmpYuvBuf[3]; |
| |
| if (((uint)rgbBuf)&0x3 || ((uint)yuvBuf)&0x3) /* address is not word align */ |
| { |
| return 0; |
| } |
| |
| TmpYuvBuf[0] = yuvBuf; |
| TmpYuvBuf[1] = yuvBuf + (_mSrc_pitch) * (_mSrc_mheight); |
| TmpYuvBuf[2] = TmpYuvBuf[1] + (_mSrc_pitch * _mSrc_mheight) / 4; |
| |
| (*this.*mPtrYUV2RGB)(TmpYuvBuf, rgbBuf, &_mDisp, mClip, (uint8 *)(mErr_horz[0])); |
| |
| return 1; |
| } |
| |
| |
| #if USE_ARM_ASM_FOR_COLORCONVERT |
| int32 ColorConvert12::get_frame12(uint8 **src, uint8 *dst, |
| DisplayProperties *disp, uint8 *ClipTable, uint8 *pExtraParam) |
| { |
| { |
| asm("stmfd sp!, {r0, r4-r11, r14}"); |
| asm("mov r0, r1"); //src |
| asm("mov r1, r2"); //dst |
| asm("mov r2, r3"); //disp |
| asm("ldr r3, [sp, #40]"); //COFF_TBL |
| |
| asm("ldmfd r2, {r4-r9};"); |
| |
| asm("rsb r8, r6, r4, lsl #1;"); //r8 = src_pitch*2-src_width |
| asm("sub r9, r4, r6;"); //r9 = src_pitch - src_width |
| asm("mov r9, r9, lsr #1;"); //r9 = (src_pitch - src_width)/2 |
| asm("rsb r10,r6, r5, lsl #1;"); //r10= (dst_pitch - src_width) |
| asm("mov r10, r10, lsl #1;"); //r10= (dst_pitch - src_width)*2 |
| asm("sub r6, r6, #1;"); //r6 = src_width-1 |
| asm("orr r6, r4, r6, lsl #18;"); //r6 = src_pitch | ( (src_width-1)<<18) |
| //dst_pitch, r6, src_height, src_pitch*2-src_width, (src_pitch - src_width)/2, (dst_pitch - src_width)*2 |
| asm("stmfd sp!, {r5-r10};"); |
| asm("ldmfd r0, {r4, r5, r7};"); //pY, pCb, pCr |
| asm("stmfd sp!, { r5, r7 };"); //push pCb, pCr |
| |
| asm("LOOP_ROW:"); |
| asm("ldr r9, [sp, #76]"); //load r9 = ErrRow |
| |
| asm("mov r8, #0"); //; reset error from left pixel |
| asm("LOOP_COL:"); |
| asm("ldmfd sp!, { r5, r7 }"); //load pCb, pCr |
| asm("ldrb r0, [r5], #1"); //Cb |
| asm("ldrb r2, [r7], #1"); //Cr |
| asm("stmfd sp!, { r5, r7 }"); |
| asm("mov r10, r6, lsl #16"); //r10 = src_pitch <<16; |
| asm("ldrb r10, [r4, r10, lsr #16]");//r10 = Y (bottom left) |
| |
| asm("sub r0, r0, #128;"); //r0 = Cb-128 |
| asm("sub r2, r2, #128;"); //r2 = Cr-128 |
| |
| asm("ldr r7, =45774"); |
| asm("ldr r11, =22014"); |
| asm("mul r7, r2, r7"); //r7 = (Cr-128)*JCoeff[0]; |
| asm("mla r7, r0, r11, r7"); //r7 = (Cb-128)*22014 + (Cr-128)*JCoeff[0]; |
| asm("ldr r11, =89859"); |
| asm("mul r2, r11, r2"); //r2 = (Cr-128)*89859 |
| asm("ldr r11, =113618"); |
| asm("mul r0, r11, r0"); //r0 = (Cb-128)*113618 |
| |
| asm("add r11, r2, r10, lsl #16"); // (Cr-128)*89859 + (Y<<16) |
| asm("rsb r12, r7, r10, lsl #16"); // (Y<<16) - ((Cb-128)*22014 + (Cr-128)*JCoeff[0]) |
| asm("add r14, r0, r10, lsl #16"); // (Cb-128)*113618 + (Y<<16) |
| |
| asm("ldr r10, [r9, r6, lsr #16]"); //;load error from upper row/pixel |
| asm("add r8, r8, r10, lsr #1"); //get the bottom error, only the LSB 16 bits is meaningful |
| |
| asm("and r10, r8, #0xF"); //error B |
| asm("add r14, r14, r10"); |
| asm("and r10, r8, #0xF0"); //error G |
| asm("add r12, r12, r10, lsr #4"); |
| asm("and r10, r8, #0xF00"); //error R |
| |
| asm("add r11, r11, r10, lsr #8"); |
| |
| asm("ldrb r11, [r3, r11, asr #16]"); |
| asm("ldrb r12, [r3, r12, asr #16]"); |
| asm("ldrb r14, [r3, r14, asr #16]"); |
| |
| #ifdef OUTPUT_RGB_565 |
| // get RGB_565 |
| asm("mov r10, r11, lsr #3"); |
| asm("mov r10, r10, lsl #6"); |
| asm("orr r10, r10, r12, lsr #2"); |
| asm("mov r10, r10, lsl #5"); |
| asm("orr r10, r10, r14, lsr #3"); |
| #else |
| //RGB_444 |
| asm("and r10, r12, #0xF0"); //G |
| asm("orr r10, r10, r14, lsr #4"); //B |
| asm("and r11, r11, #0xF0"); |
| asm("orr r10, r10, r11, lsl #4"); //R |
| #endif |
| |
| asm("and r11, r11, #0xE"); |
| asm("and r12, r12, #0xE"); |
| asm("and r14, r14, #0xE"); |
| |
| asm("orr r11, r11, r12, lsl #4"); |
| |
| asm("ldr r12, [sp, #8]"); //should be det_pitch |
| asm("add r1, r1, r12, lsl #1"); //pDst move to bottom left pixel |
| |
| asm("strh r10, [r1]"); // store bottom left pixel |
| asm("sub r1, r1, r12, lsl #1"); |
| |
| //////**************************///////////////////// |
| asm("orr r10, r11, r14, lsl #8"); //RGB dither error |
| |
| asm("mov r8, r8, lsr #16"); |
| asm("mov r8, r8, lsl #16"); |
| asm("orr r8, r8, r10, lsr #1"); |
| |
| asm("ldrb r14, [r4], #1"); // p14 = Y (top left) |
| |
| asm("add r11, r2, r14, lsl #16"); |
| asm("rsb r12, r7, r14, lsl #16"); |
| asm("add r14, r0, r14, lsl #16"); |
| |
| asm("add r8, r8, r10, lsl #15"); //get the top error, only the HSB 16 bits is meaningful |
| |
| asm("and r10, r8, #0xF0000"); //error B |
| asm("add r14, r14, r10, lsr #16"); |
| asm("and r10, r8, #0xF00000"); //error G |
| asm("add r12, r12, r10, lsr #20"); |
| asm("and r10, r8, #0xF000000"); //error R |
| asm("add r11, r11, r10, lsr #24"); |
| |
| //clip |
| |
| asm("ldrb r11, [r3, r11, asr #16]"); |
| asm("ldrb r12, [r3, r12, asr #16]"); |
| asm("ldrb r14, [r3, r14, asr #16]"); |
| |
| #ifdef OUTPUT_RGB_565 |
| // get RGB_565 |
| asm("mov r10, r11, lsr #3"); |
| asm("mov r10, r10, lsl #6"); |
| asm("orr r10, r10, r12, lsr #2"); |
| asm("mov r10, r10, lsl #5"); |
| asm("orr r10, r10, r14, lsr #3"); |
| #else |
| //RGB_444 |
| asm("and r10, r12, #0xF0"); //G |
| asm("orr r10, r10, r14, lsr #4"); //B |
| asm("and r11, r11, #0xF0"); |
| asm("orr r10, r10, r11, lsl #4"); //R |
| #endif |
| |
| |
| asm("strh r10, [r1], #2"); //strore top left RGB |
| |
| asm("and r11, r11, #0xE"); |
| asm("and r12, r12, #0xE"); |
| asm("and r14, r14, #0xE"); |
| |
| asm("orr r11, r11, r12, lsl #4"); |
| asm("orr r11, r11, r14, lsl #8"); |
| |
| asm("mov r8, r8, lsl #16"); |
| asm("mov r8, r8, lsr #16"); |
| asm("orr r8, r8, r11, lsl #15"); |
| |
| asm("str r11, [r9, r6, lsr #16]"); |
| |
| asm("sub r6, r6, #0x40000"); //col |
| |
| /********************************LEFT END, RIGHT BEGIN****************/ |
| |
| asm("mov r10, r6, lsl #16"); |
| asm("ldrb r10, [r4, r10, lsr #16]"); |
| |
| asm("add r11, r2, r10, lsl #16"); |
| asm("rsb r12, r7, r10, lsl #16"); |
| asm("add r14, r0, r10, lsl #16"); |
| |
| asm("ldr r10, [r9, r6, lsr #16]"); |
| |
| asm("add r8, r8, r10, lsr #1"); |
| |
| asm("and r10, r8, #0xF"); |
| asm("add r14, r14, r10"); |
| asm("and r10, r8, #0xF0"); |
| asm("add r12, r12, r10, lsr #4"); |
| asm("and r10, r8, #0xF00"); |
| asm("add r11, r11, r10, lsr #8"); |
| |
| asm("ldrb r11, [r3, r11, asr #16]"); |
| asm("ldrb r12, [r3, r12, asr #16]"); |
| asm("ldrb r14, [r3, r14, asr #16]"); |
| |
| #ifdef OUTPUT_RGB_565 |
| // get RGB_565 |
| asm("mov r10, r11, lsr #3"); |
| asm("mov r10, r10, lsl #6"); |
| asm("orr r10, r10, r12, lsr #2"); |
| asm("mov r10, r10, lsl #5"); |
| asm("orr r10, r10, r14, lsr #3"); |
| #else |
| //RGB_444 |
| asm("and r10, r12, #0xF0"); //G |
| asm("orr r10, r10, r14, lsr #4"); //B |
| asm("and r11, r11, #0xF0"); |
| asm("orr r10, r10, r11, lsl #4"); //R |
| #endif |
| |
| asm("and r11, r11, #0xE"); |
| asm("and r12, r12, #0xE"); |
| asm("and r14, r14, #0xE"); |
| |
| asm("orr r11, r11, r12, lsl #4"); |
| |
| asm("ldr r12, [sp, #8]"); |
| |
| asm("add r1, r1, r12, lsl #1"); |
| |
| asm("strh r10, [r1]"); //store RGB bottom right |
| asm("sub r1, r1, r12, lsl #1"); |
| |
| asm("orr r10, r11, r14, lsl #8"); |
| |
| asm("mov r8, r8, lsr #16"); |
| asm("mov r8, r8, lsl #16"); |
| asm("orr r8, r8, r10, lsr #1"); |
| |
| asm("ldrb r14, [r4], #1"); //r14 = Y (top right pixel) |
| |
| asm("add r11, r2, r14, lsl #16"); |
| asm("rsb r12, r7, r14, lsl #16"); |
| asm("add r14, r0, r14, lsl #16"); |
| |
| asm("add r8, r8, r10, lsl #15"); |
| |
| asm("and r10, r8, #0xF0000"); |
| asm("add r14, r14, r10, lsr #16"); |
| asm("and r10, r8, #0xF00000"); |
| asm("add r12, r12, r10, lsr #20"); |
| asm("and r10, r8, #0xF000000"); |
| asm("add r11, r11, r10, lsr #24"); |
| |
| asm("ldrb r11, [r3, r11, asr #16]"); |
| asm("ldrb r12, [r3, r12, asr #16]"); |
| asm("ldrb r14, [r3, r14, asr #16]"); |
| #ifdef OUTPUT_RGB_565 |
| // get RGB_565 |
| asm("mov r10, r11, lsr #3"); |
| asm("mov r10, r10, lsl #6"); |
| asm("orr r10, r10, r12, lsr #2"); |
| asm("mov r10, r10, lsl #5"); |
| asm("orr r10, r10, r14, lsr #3"); |
| #else |
| //RGB_444 |
| asm("and r10, r12, #0xF0"); //G |
| asm("orr r10, r10, r14, lsr #4"); //B |
| asm("and r11, r11, #0xF0"); |
| asm("orr r10, r10, r11, lsl #4"); //R |
| #endif |
| |
| asm("strh r10, [r1], #2"); //store RGB (top right pixel) |
| |
| asm("and r11, r11, #0xE"); |
| asm("and r12, r12, #0xE"); |
| asm("and r14, r14, #0xE"); |
| |
| asm("orr r11, r11, r12, lsl #4"); |
| asm("orr r11, r11, r14, lsl #8"); |
| |
| asm("mov r8, r8, lsl #16"); |
| asm("mov r8, r8, lsr #16"); |
| asm("orr r8, r8, r11, lsl #15"); |
| |
| asm("str r11, [r9, r6, lsr #16] ; ");//Att: error left shift by 1 bit |
| |
| asm("subs r6, r6, #0x40000"); |
| |
| asm("bgt LOOP_COL"); |
| |
| asm("add sp, sp, #8"); |
| asm("ldmfd sp, {r5-r10}"); |
| asm("add r4, r4, r8"); |
| asm("add r5, r5, r9"); |
| asm("add r7, r7, r9"); |
| asm("add r1, r1, r10"); |
| asm("subs r7, r7, #2;"); |
| asm("str r7, [sp, #8]"); |
| |
| asm("sub sp, sp, #8"); |
| asm("bgt LOOP_ROW"); |
| |
| asm("mov r0, #1"); |
| asm("add sp, sp, #32"); |
| asm("ldmfd sp!, {r0, r4-r11, pc}"); |
| // asm(".ltorg"); |
| } |
| return 1; |
| } |
| |
| #else // straight C version |
| ///////////////////////////////////////////////////////////////////////////// |
| int32 ColorConvert12::get_frame12(uint8 **src, uint8 *dst, |
| DisplayProperties *disp, uint8 *clip, uint8 *pErr_horz) |
| { |
| const static uint32 JCoeff[4] = |
| { |
| 45774, //65536*0.813/1.164; |
| 89859, //65536*1.596/1.164; |
| 22014, //65536*0.391/1.164; |
| 113618 //65536*2.018/1.164; |
| }; |
| |
| uint8 *pCb, *pCr; |
| uint16 *pY; |
| uint16 *pDst; |
| int32 src_width, dst_width, display_width; |
| int32 Y, Cb, Cr, Cg; |
| uint32 left_err_t, left_err_b; /* error from the left pixels */ |
| uint32 top_err_l, top_err_r; /* error from the top pixels */ |
| int32 deltaY, deltaDst, deltaCbCr; |
| int32 row, col; |
| int32 tmp0, tmp1, tmp2; |
| uint32 rgb; |
| |
| |
| src_width = disp->src_pitch; |
| dst_width = disp->dst_pitch; |
| display_width = disp->src_width; |
| |
| deltaY = (src_width << 1) - display_width; |
| deltaCbCr = (src_width - display_width) >> 1; |
| deltaDst = (dst_width << 1) - display_width; |
| |
| pY = (uint16 *) src[0]; |
| src_width >>= 1; |
| pCb = src[1]; |
| pCr = src[2]; |
| |
| pDst = (uint16 *)dst; |
| |
| for (row = disp->src_height; row > 0; row -= 2) |
| { |
| |
| left_err_t = left_err_b = 0; /* reset left pixel errors */ |
| |
| for (col = display_width - 2; col >= 0; col -= 2) |
| { |
| |
| Cb = *pCb++; |
| Cr = *pCr++; |
| |
| //load the bottom two pixels |
| Y = pY[src_width]; |
| |
| Cb -= 128; |
| Cr -= 128; |
| Cg = Cr * JCoeff[0]; |
| Cg += Cb * JCoeff[2]; |
| |
| Cr *= JCoeff[1]; |
| Cb *= JCoeff[3]; |
| |
| tmp0 = Y & 0xFF; //Low endian left pixel |
| //tmp0 = pY[src_width]; |
| |
| tmp1 = (tmp0 << 16) - Cg; |
| tmp2 = (tmp0 << 16) + Cb; |
| tmp0 = (tmp0 << 16) + Cr; |
| |
| //add the error from top and left |
| //This is not exact error diffusion since |
| //we process the bottom two pixels first !! |
| tmp0 += ((left_err_b & 0xFF) << 16);// err_vert[0]; |
| tmp1 += (((left_err_b >> 8) & 0xFF) << 16);//err_vert[1]; |
| tmp2 += (((left_err_b >> 16) & 0xFF) << 16);//err_vert[2]; |
| |
| top_err_l = *((uint*)(pErr_horz + (col << 2))); |
| tmp0 += ((top_err_l & 0xFF) << 16);//pErr_horz[col]; |
| tmp1 += (((top_err_l >> 8) & 0xFF) << 16);//mErr_horz[1][col]; |
| tmp2 += (((top_err_l >> 16) & 0xFF) << 16);//mErr_horz[2][col]; |
| |
| tmp0 = clip[tmp0>>16]; |
| tmp1 = clip[tmp1>>16]; |
| tmp2 = clip[tmp2>>16]; |
| |
| #ifdef OUTPUT_RGB_565 |
| //RGB_565 |
| rgb = (tmp0 >> 3); |
| rgb = (tmp1 >> 2) | (rgb << 6); |
| rgb = (tmp2 >> 3) | (rgb << 5); |
| #else |
| //RGB_444 |
| rgb = (tmp0 & 0xF0) << 4; |
| rgb |= (tmp1 & 0xF0); |
| rgb |= (tmp2 >> 4); |
| #endif |
| tmp0 &= 0xE; |
| tmp1 &= 0xE; |
| tmp2 &= 0xE; |
| tmp0 >>= 1; |
| tmp1 >>= 1; |
| tmp2 >>= 1; |
| |
| //save error |
| top_err_l = tmp0 | (tmp1 << 8) | (tmp2 << 16); |
| |
| Y >>= 8; |
| //Y = pY[src_width+1]; |
| |
| // error from the left already available |
| tmp1 = (Y << 16) - Cg + (tmp1 << 16); |
| tmp2 = (Y << 16) + Cb + (tmp2 << 16); |
| tmp0 = (Y << 16) + Cr + (tmp0 << 16); |
| |
| //add the error from top |
| top_err_r = *((uint*)(pErr_horz + (col << 2) + 4)); |
| tmp0 += ((top_err_r & 0xFF) << 16);//pErr_horz[col+1]; |
| tmp1 += (((top_err_r >> 8) & 0xFF) << 16);//mErr_horz[1][col+1]; |
| tmp2 += (((top_err_r >> 16) & 0xFF) << 16);//mErr_horz[2][col+1]; |
| |
| tmp0 = clip[tmp0>>16]; |
| tmp1 = clip[tmp1>>16]; |
| tmp2 = clip[tmp2>>16]; |
| |
| #ifdef OUTPUT_RGB_565 |
| //RGB_565 |
| rgb |= ((tmp0 >> 3) << 27); |
| rgb |= ((tmp1 >> 2) << 21); |
| rgb |= ((tmp2 >> 3) << 16); |
| #else |
| //RGB_444 |
| rgb |= (tmp0 & 0xF0) << 20; |
| rgb |= (tmp1 & 0xF0) << 16; |
| rgb |= (tmp2 >> 4) << 16; |
| #endif |
| *((uint*)(pDst + dst_width)) = rgb; |
| |
| tmp0 &= 0xE; |
| tmp1 &= 0xE; |
| tmp2 &= 0xE; |
| tmp0 >>= 1; |
| tmp1 >>= 1; |
| tmp2 >>= 1; |
| |
| //save error |
| left_err_b = tmp0 | (tmp1 << 8) | (tmp2 << 16); |
| top_err_r = left_err_b; |
| |
| //load the top two pixels |
| //Y = *((uint16 *)pY)++; |
| Y = *pY++; |
| |
| tmp0 = Y & 0xFF; //Low endian left pixel |
| //tmp0 = *pY++; |
| tmp1 = (tmp0 << 16) - Cg; |
| tmp2 = (tmp0 << 16) + Cb; |
| tmp0 = (tmp0 << 16) + Cr; |
| |
| //add the error from top and left |
| tmp0 += ((left_err_t & 0xFF) << 16);// err_vert[3]; |
| tmp1 += (((left_err_t >> 8) & 0xFF) << 16);//err_vert[4]; |
| tmp2 += (((left_err_t >> 16) & 0xFF) << 16);//err_vert[5]; |
| |
| tmp0 += ((top_err_l & 0xFF) << 16);//pErr_horz[col]; |
| tmp1 += (((top_err_l >> 8) & 0xFF) << 16);//mErr_horz[1][col]; |
| tmp2 += (((top_err_l >> 8) & 0xFF) << 16);//mErr_horz[2][col]; |
| |
| tmp0 = clip[tmp0>>16]; |
| tmp1 = clip[tmp1>>16]; |
| tmp2 = clip[tmp2>>16]; |
| |
| #ifdef OUTPUT_RGB_565 |
| //RGB_565 |
| rgb = (tmp0 >> 3); |
| rgb = (tmp1 >> 2) | (rgb << 6); |
| rgb = (tmp2 >> 3) | (rgb << 5); |
| #else |
| //RGB_444 |
| rgb = (tmp0 & 0xF0) << 4; |
| rgb |= (tmp1 & 0xF0); |
| rgb |= (tmp2 >> 4); |
| #endif |
| // calculate error |
| tmp0 &= 0xE; |
| tmp1 &= 0xE; |
| tmp2 &= 0xE; |
| tmp0 >>= 1; |
| tmp1 >>= 1; |
| tmp2 >>= 1; |
| |
| top_err_l = tmp0 | (tmp1 << 8) | (tmp2 << 16); |
| *((uint*)(pErr_horz + (col << 2))) = top_err_l; |
| |
| Y >>= 8; |
| //Y = *pY++; |
| |
| //error from the left is already available |
| tmp1 = (Y << 16) - Cg + (tmp1 << 16); |
| tmp2 = (Y << 16) + Cb + (tmp2 << 16); |
| tmp0 = (Y << 16) + Cr + (tmp0 << 16); |
| |
| //add the error from top |
| tmp0 += ((top_err_r & 0xFF) << 16);//pErr_horz[col+1]; |
| tmp1 += (((top_err_r >> 8) & 0xFF) << 16);//mErr_horz[1][col+1]; |
| tmp2 += (((top_err_r >> 16) & 0xFF) << 16);//mErr_horz[2][col+1]; |
| |
| tmp0 = clip[tmp0>>16]; |
| tmp1 = clip[tmp1>>16]; |
| tmp2 = clip[tmp2>>16]; |
| |
| #ifdef OUTPUT_RGB_565 |
| //RGB_565 |
| rgb |= ((tmp0 >> 3) << 27); |
| rgb |= ((tmp1 >> 2) << 21); |
| rgb |= ((tmp2 >> 3) << 16); |
| #else |
| //RGB_444 |
| rgb |= (tmp0 & 0xF0) << 20; |
| rgb |= (tmp1 & 0xF0) << 16; |
| rgb |= (tmp2 >> 4) << 16; |
| #endif |
| |
| // *( (uint *)pDst)++ = rgb; |
| *((uint *)pDst) = rgb; |
| pDst += 2; |
| |
| tmp0 &= 0xE; |
| tmp1 &= 0xE; |
| tmp2 &= 0xE; |
| tmp0 >>= 1; |
| tmp1 >>= 1; |
| tmp2 >>= 1; |
| |
| // save error |
| left_err_t = tmp0 | (tmp1 << 8) | (tmp2 << 16); // = top_err_r |
| *((uint*)(pErr_horz + (col << 2) + 4)) = left_err_t; |
| |
| }//end of COL |
| |
| pY += (deltaY >> 1); |
| pCb += deltaCbCr; |
| pCr += deltaCbCr; |
| pDst += (deltaDst); //coz pDst defined as UINT * |
| } |
| return 1; |
| } |
| #endif // USE_ARM_ASM_FOR_COLORCONVERT |
| |
| |
| #if USE_ARM_ASM_FOR_COLORCONVERT |
| int32 ColorConvert12::cc12Rotate(uint8 **src, uint8 *dst, |
| DisplayProperties *disp, uint8 *clip, uint8 *pExtraParam) |
| { |
| #if CCROTATE |
| { |
| asm("STMFD sp!,{r0-r11,lr}"); |
| asm("SUB sp,sp,#0x3c"); |
| asm("LDR r3,[sp,#0x48]"); |
| asm("LDR r10,[sp,#0x74]"); |
| asm("LDR lr,[sp,#0x70]"); |
| asm("LDMIA r3,{r9,r11}"); |
| asm("MOV r12,r1"); |
| asm("STR r11,[sp,#0x30]"); |
| asm("LDR r3,[r3,#8]"); |
| asm("LDR r4,[sp,#0x48]"); |
| asm("MOV r5,#1"); |
| asm("LDR r1,[r4,#0x10]"); |
| asm("RSB r1,r1,r11,LSL #1"); |
| asm("STR r1,[sp,#0x24]"); |
| asm("LDR r7,[r0,#0x50]"); |
| asm("LDMIA r12,{r0,r1,r4}"); |
| asm("LDR r12,[sp,#0x48]"); |
| asm("CMP r7,#0"); |
| asm("LDR r8,[r12,#0]"); |
| asm("LDR r12,[r12,#0xc]"); |
| asm("MUL r6,r8,r12"); |
| asm("ADD r5,r5,r6,ASR #2"); |
| asm("ADD r6,r6,#2"); |
| asm("STRNE r6,[sp,#0x28]"); |
| asm("STRNE r5,[sp,#0x20]"); |
| asm("MOV r8,r8,ASR #1"); |
| asm("BNE L1.1716"); |
| asm("RSB r6,r6,#0"); |
| asm("RSB r5,r5,#0"); |
| asm("STR r5,[sp,#0x20]"); |
| asm("STR r6,[sp,#0x28]"); |
| asm("L1.1716:"); |
| asm("BEQ L1.1748"); |
| asm("SUB r5,r12,#1"); |
| asm("MLA r0,r5,r9,r0"); |
| asm("MVN r5,#0"); |
| asm("ADD r12,r5,r12,ASR #1"); |
| asm("MLA r1,r12,r8,r1"); |
| asm("MLA r12,r8,r12,r4"); |
| asm("B L1.1772"); |
| asm("L1.1748:"); |
| asm("ADD r0,r0,r3"); |
| asm("ADD r1,r1,r3,ASR #1"); |
| asm("ADD r12,r4,r3,ASR #1"); |
| asm("SUB r12,r12,#1"); |
| asm("SUB r1,r1,#1"); |
| asm("SUB r0,r0,#1"); |
| asm("L1.1772:"); |
| asm("BEQ L1.1800"); |
| asm("RSB r8,r8,#0"); |
| asm("MOV r4,#1"); |
| asm("STMIB sp,{r4,r8}"); |
| asm("RSB r9,r9,#0"); |
| asm("STR r9,[sp,#0]"); |
| asm("B L1.1812"); |
| asm("L1.1800:"); |
| asm("MVN r4,#0"); |
| asm("STMIB sp,{r4,r8}"); |
| asm("STR r9,[sp,#0]"); |
| asm("L1.1812:"); |
| asm("STR r3,[sp,#0x1c]"); |
| asm("CMP r3,#0"); |
| asm("BLE L1.2824"); |
| asm("LDR r3,[sp,#4]"); |
| asm("LDR r9,[sp,#0]"); |
| asm("ADD r3,r3,r9"); |
| asm("STR r3,[sp,#0x38]"); |
| asm("L1.1840:"); |
| asm("LDR r4,[sp,#0x48]"); |
| asm("MOV r3,#0"); |
| asm("LDR r4,[r4,#0xc]"); |
| asm("MOV r5,r3"); |
| asm("SUBS r4,r4,#2"); |
| asm("BMI L1.2776"); |
| asm("L1.1864:"); |
| asm("LDRB r6,[r1,#0]"); |
| asm("LDR r8,[sp,#8]"); |
| asm("MOV r9,#0xce"); |
| asm("LDRB r7,[r12],r8"); |
| asm("ADD r9,r9,#0xb200"); |
| asm("ADD r1,r1,r8"); |
| asm("SUB r7,r7,#0x80"); |
| asm("MOV r11,#0xff"); |
| asm("ADD r11,r11,#0x2a00"); |
| asm("MUL r8,r9,r7"); |
| asm("SUB r6,r6,#0x80"); |
| asm("MUL r9,r11,r6"); |
| asm("ADD r8,r8,r9,LSL #1"); |
| asm("LDR r9,L1.2840");//asm("LDR r9, =0x00015f03 "); |
| asm("MUL r7,r9,r7"); |
| asm("LDR r9,L1.2844");//asm("LDR r9, =0x0001bbd2"); |
| asm("MUL r6,r9,r6"); |
| asm("LDR r9,[sp,#4]"); |
| asm("LDRB r9,[r0,r9]"); |
| asm("RSB r11,r8,r9,LSL #16"); |
| asm("STR r11,[sp,#0x14]"); |
| asm("ADD r11,r6,r9,LSL #16"); |
| asm("STR r11,[sp,#0x10]"); |
| asm("AND r11,r3,#0xff"); |
| asm("ADD r9,r7,r9,LSL #16"); |
| asm("ADD r11,r9,r11,LSL #16"); |
| asm("MOV r9,#0xff0000"); |
| asm("STR r11,[sp,#0x18]"); |
| asm("LDR r11,[sp,#0x14]"); |
| asm("AND r9,r9,r3,LSL #8"); |
| asm("ADD r11,r9,r11"); |
| asm("LDR r9,[sp,#0x10]"); |
| asm("AND r3,r3,#0xff0000"); |
| asm("ADD r9,r3,r9"); |
| asm("STR r9,[sp,#0x10]"); |
| asm("STR r11,[sp,#0x14]"); |
| asm("LDR r3,[r10,r4,LSL #2]"); |
| asm("LDR r11,[sp,#0x18]"); |
| asm("AND r9,r3,#0xff"); |
| asm("ADD r9,r11,r9,LSL #16"); |
| asm("STR r9,[sp,#0x18]"); |
| asm("MOV r9,#0xff0000"); |
| asm("LDR r11,[sp,#0x14]"); |
| asm("AND r9,r9,r3,LSL #8"); |
| asm("ADD r11,r9,r11"); |
| asm("LDR r9,[sp,#0x10]"); |
| asm("AND r3,r3,#0xff0000"); |
| asm("ADD r3,r3,r9"); |
| asm("LDR r9,[sp,#0x18]"); |
| asm("LDRB r9,[lr,r9,ASR #16]"); |
| asm("STR r9,[sp,#0x18]"); |
| asm("LDRB r9,[lr,r11,ASR #16]"); |
| asm("STR r9,[sp,#0x14]"); |
| asm("LDRB r3,[lr,r3,ASR #16]"); |
| asm("LDR r9,[sp,#0x18]"); |
| asm("AND r9,r9,#0xf0"); |
| asm("MOV r11,r9,LSL #4"); |
| asm("LDR r9,[sp,#0x14]"); |
| asm("AND r9,r9,#0xf0"); |
| asm("ORR r9,r9,r11"); |
| asm("ORR r11,r9,r3,ASR #4"); |
| asm("STR r11,[sp,#0xc]"); |
| asm("LDR r11,[sp,#0x14]"); |
| asm("AND r3,r3,#0xe"); |
| asm("AND r11,r11,#0xe"); |
| asm("MOV r11,r11,LSR #1"); |
| asm("STR r11,[sp,#0x14]"); |
| asm("MOV r11,r3,LSR #1"); |
| asm("LDR r9,[sp,#0x18]"); |
| asm("STR r11,[sp,#0x10]"); |
| asm("LDR r11,[sp,#0x14]"); |
| asm("AND r9,r9,#0xe"); |
| asm("MOV r9,r9,LSR #1"); |
| asm("ORR r3,r9,r11,LSL #8"); |
| asm("LDR r11,[sp,#0x10]"); |
| asm("STR r9,[sp,#0x18]"); |
| asm("ORR r9,r3,r11,LSL #16"); |
| asm("LDR r3,[sp,#0x38]"); |
| asm("STR r9,[sp,#0x2c]"); |
| asm("LDRB r3,[r0,r3]"); |
| asm("LDR r11,[sp,#0x14]"); |
| asm("RSB r9,r8,r3,LSL #16"); |
| asm("ADD r11,r9,r11,LSL #16"); |
| asm("STR r11,[sp,#0x14]"); |
| asm("LDR r11,[sp,#0x10]"); |
| asm("ADD r9,r6,r3,LSL #16"); |
| asm("ADD r11,r9,r11,LSL #16"); |
| asm("LDR r9,[sp,#0x18]"); |
| asm("STR r11,[sp,#0x10]"); |
| asm("ADD r3,r7,r3,LSL #16"); |
| asm("ADD r11,r3,r9,LSL #16"); |
| asm("ADD r3,r10,r4,LSL #2"); |
| asm("STR r3,[sp,#0x34]"); |
| asm("LDR r9,[r3,#4]"); |
| asm("AND r3,r9,#0xff"); |
| asm("ADD r3,r11,r3,LSL #16"); |
| asm("STR r3,[sp,#0x18]"); |
| asm("MOV r3,#0xff0000"); |
| asm("LDR r11,[sp,#0x14]"); |
| asm("AND r3,r3,r9,LSL #8"); |
| asm("ADD r3,r3,r11"); |
| asm("LDR r11,[sp,#0x10]"); |
| asm("AND r9,r9,#0xff0000"); |
| asm("ADD r9,r9,r11"); |
| asm("LDR r11,[sp,#0x18]"); |
| asm("LDRB r11,[lr,r11,ASR #16]"); |
| asm("STR r11,[sp,#0x18]"); |
| asm("LDRB r3,[lr,r3,ASR #16]"); |
| asm("STR r3,[sp,#0x14]"); |
| asm("LDRB r3,[lr,r9,ASR #16]"); |
| asm("AND r9,r11,#0xf0"); |
| asm("LDR r11,[sp,#0xc]"); |
| asm("ORR r9,r11,r9,LSL #20"); |
| asm("LDR r11,[sp,#0x14]"); |
| asm("AND r11,r11,#0xf0"); |
| asm("ORR r9,r9,r11,LSL #16"); |
| asm("MOV r11,r3,LSR #4"); |
| asm("ORR r9,r9,r11,LSL #16"); |
| asm("LDR r11,[sp,#0x30]"); |
| asm("AND r3,r3,#0xe"); |
| asm("STR r9,[r2,r11,LSL #1]"); |
| asm("LDR r11,[sp,#0x18]"); |
| asm("MOV r3,r3,ASR #1"); |
| asm("AND r9,r11,#0xe"); |
| asm("LDR r11,[sp,#0x14]"); |
| asm("MOV r9,r9,ASR #1"); |
| asm("AND r11,r11,#0xe"); |
| asm("MOV r11,r11,ASR #1"); |
| asm("ORR r9,r9,r11,LSL #8"); |
| asm("ORR r3,r9,r3,LSL #16"); |
| asm("LDRB r9,[r0,#0]"); |
| asm("RSB r11,r8,r9,LSL #16"); |
| asm("STR r11,[sp,#0x14]"); |
| asm("ADD r11,r6,r9,LSL #16"); |
| asm("STR r11,[sp,#0x10]"); |
| asm("ADD r11,r7,r9,LSL #16"); |
| asm("AND r9,r5,#0xff"); |
| asm("ADD r9,r11,r9,LSL #16"); |
| asm("STR r9,[sp,#0x18]"); |
| asm("MOV r9,#0xff0000"); |
| asm("AND r9,r9,r5,LSL #8"); |
| asm("LDR r11,[sp,#0x14]"); |
| asm("AND r5,r5,#0xff0000"); |
| asm("ADD r9,r9,r11"); |
| asm("STR r9,[sp,#0x14]"); |
| asm("LDR r11,[sp,#0x10]"); |
| asm("LDR r9,[sp,#0x2c]"); |
| asm("ADD r5,r5,r11"); |
| asm("AND r11,r9,#0xff"); |
| asm("LDR r9,[sp,#0x18]"); |
| asm("ADD r9,r9,r11,LSL #16"); |
| asm("STR r9,[sp,#0x18]"); |
| asm("LDR r9,[sp,#0x2c]"); |
| asm("MOV r11,#0xff0000"); |
| asm("AND r9,r11,r9,LSL #8"); |
| asm("LDR r11,[sp,#0x14]"); |
| asm("ADD r5,r9,r5"); |
| asm("ADD r11,r9,r11"); |
| asm("LDR r9,[sp,#0x18]"); |
| asm("LDRB r9,[lr,r9,ASR #16]"); |
| asm("STR r9,[sp,#0x18]"); |
| asm("LDRB r9,[lr,r11,ASR #16]"); |
| asm("STR r9,[sp,#0x14]"); |
| asm("LDRB r5,[lr,r5,ASR #16]"); |
| asm("LDR r9,[sp,#0x18]"); |
| asm("AND r9,r9,#0xf0"); |
| asm("MOV r11,r9,LSL #4"); |
| asm("LDR r9,[sp,#0x14]"); |
| asm("AND r9,r9,#0xf0"); |
| asm("ORR r9,r9,r11"); |
| asm("ORR r9,r9,r5,ASR #4"); |
| asm("STR r9,[sp,#0xc]"); |
| asm("LDR r9,[sp,#0x18]"); |
| asm("AND r5,r5,#0xe"); |
| asm("AND r11,r9,#0xe"); |
| asm("LDR r9,[sp,#0x14]"); |
| asm("MOV r11,r11,LSR #1"); |
| asm("STR r11,[sp,#0x18]"); |
| asm("AND r9,r9,#0xe"); |
| asm("MOV r11,r9,LSR #1"); |
| asm("LDR r9,[sp,#0x18]"); |
| asm("MOV r5,r5,LSR #1"); |
| asm("ORR r9,r9,r11,LSL #8"); |
| asm("ORR r9,r9,r5,LSL #16"); |
| asm("STR r11,[sp,#0x14]"); |
| asm("STR r9,[r10,r4,LSL #2]"); |
| asm("LDR r9,[sp,#0]"); |
| asm("LDRB r9,[r0,r9]"); |
| asm("LDR r11,[sp,#0]"); |
| asm("ADD r0,r0,r11,LSL #1"); |
| asm("LDR r11,[sp,#0x14]"); |
| asm("RSB r8,r8,r9,LSL #16"); |
| asm("ADD r6,r6,r9,LSL #16"); |
| asm("ADD r5,r6,r5,LSL #16"); |
| asm("ADD r8,r8,r11,LSL #16"); |
| asm("LDR r11,[sp,#0x18]"); |
| asm("ADD r6,r7,r9,LSL #16"); |
| asm("ADD r6,r6,r11,LSL #16"); |
| asm("AND r7,r3,#0xff"); |
| asm("ADD r6,r6,r7,LSL #16"); |
| asm("MOV r9,#0xff0000"); |
| asm("AND r7,r9,r3,LSL #8"); |
| asm("ADD r7,r7,r8"); |
| asm("AND r8,r3,r9"); |
| asm("ADD r5,r8,r5"); |
| asm("LDRB r6,[lr,r6,ASR #16]"); |
| asm("LDRB r7,[lr,r7,ASR #16]"); |
| asm("LDRB r5,[lr,r5,ASR #16]"); |
| asm("AND r8,r6,#0xf0"); |
| asm("LDR r9,[sp,#0xc]"); |
| asm("AND r6,r6,#0xe"); |
| asm("ORR r8,r9,r8,LSL #20"); |
| asm("AND r9,r7,#0xf0"); |
| asm("ORR r8,r8,r9,LSL #16"); |
| asm("MOV r9,r5,ASR #4"); |
| asm("AND r7,r7,#0xe"); |
| asm("MOV r7,r7,ASR #1"); |
| asm("AND r5,r5,#0xe"); |
| asm("MOV r6,r6,ASR #1"); |
| asm("ORR r6,r6,r7,LSL #8"); |
| asm("MOV r5,r5,ASR #1"); |
| asm("ORR r8,r8,r9,LSL #16"); |
| asm("STR r8,[r2],#4"); |
| asm("ORR r5,r6,r5,LSL #16"); |
| asm("LDR r6,[sp,#0x34]"); |
| asm("SUBS r4,r4,#2"); |
| asm("STR r5,[r6,#4]"); |
| asm("BPL L1.1864"); |
| asm("L1.2776:"); |
| asm("LDR r3,[sp,#0x28]"); |
| asm("ADD r0,r0,r3"); |
| asm("LDR r3,[sp,#0x20]"); |
| asm("ADD r1,r1,r3"); |
| asm("ADD r12,r12,r3"); |
| asm("LDR r3,[sp,#0x24]"); |
| asm("ADD r2,r2,r3,LSL #1"); |
| asm("LDR r3,[sp,#0x1c]"); |
| asm("SUB r3,r3,#2"); |
| asm("STR r3,[sp,#0x1c]"); |
| asm("CMP r3,#0"); |
| asm("BGT L1.1840"); |
| asm("L1.2824:"); |
| asm("ADD sp,sp,#0x4c"); |
| asm("LDMFD sp!,{r4-r11,lr}"); |
| asm("MOV r0,#1"); |
| // asm("BX lr"); |
| asm("L1.2836:"); |
| asm(".align 0"); |
| asm("L1.2840:"); |
| asm(".word 0x00015f03"); |
| asm("L1.2844:"); |
| asm(".word 0x0001bbd2"); |
| } |
| return 1; |
| #else |
| return 0; |
| #endif // CCROTATE |
| } |
| |
| #else // straight C version |
| |
| int32 ColorConvert12::cc12Rotate(uint8 **src, uint8 *dst, |
| DisplayProperties *disp, uint8 *clip, uint8 *pErr_horz) |
| { |
| #if CCROTATE |
| const static uint32 JCoeff[4] = |
| { |
| 45774, //65536*0.813/1.164; |
| 89859, //65536*1.596/1.164; |
| 22014, //65536*0.391/1.164; |
| 113618 //65536*2.018/1.164; |
| }; |
| |
| uint8 *pCb, *pCr; |
| uint8 *pY; |
| uint16 *pDst; |
| int32 src_width, dst_width, display_width; |
| int32 Y, Cb, Cr, Cg; |
| uint32 left_err_t, left_err_b; /* error from the left pixels */ |
| uint32 top_err_l, top_err_r; /* error from the top pixels */ |
| int32 deltaY, deltaDst, deltaCbCr; |
| int32 row, col; |
| int32 tmp0, tmp1, tmp2; |
| uint32 rgb; |
| |
| |
| src_width = disp->src_pitch; |
| dst_width = disp->dst_pitch; |
| display_width = disp->src_width; |
| |
| deltaDst = (disp->dst_pitch << 1) - disp->dst_width; // (dst_pitch<<1) - src_height |
| if (_mRotation == CCROTATE_CLKWISE) |
| { // go from top-left to bottom-left |
| deltaY = src_width * disp->src_height + 2; |
| deltaCbCr = ((src_width * disp->src_height) >> 2) + 1; |
| } |
| else // rotate counterclockwise |
| { // go from bottom-right back to top-right |
| deltaY = -(src_width * disp->src_height + 2); |
| deltaCbCr = -(((src_width * disp->src_height) >> 2) + 1); |
| } |
| |
| // map origin of the destination to the source |
| if (_mRotation == CCROTATE_CLKWISE) |
| { // goto bottom-left |
| pY = src[0] + src_width * (disp->src_height - 1); |
| pCb = src[1] + ((src_width >> 1) * ((disp->src_height >> 1) - 1)); |
| pCr = src[2] + ((src_width >> 1) * ((disp->src_height >> 1) - 1)); |
| } |
| else // rotate counterclockwise |
| { // goto top-right |
| pY = src[0] + display_width - 1; |
| pCb = src[1] + (display_width >> 1) - 1; |
| pCr = src[2] + (display_width >> 1) - 1; |
| } |
| |
| pDst = (uint16 *)dst; |
| |
| int half_src_width, read_idx, tmp_src_width; |
| if (_mRotation == CCROTATE_CLKWISE) |
| { |
| half_src_width = -(src_width >> 1); |
| read_idx = 1; |
| tmp_src_width = -src_width; |
| } |
| else // rotate counterclockwise |
| { |
| half_src_width = (src_width >> 1); |
| read_idx = -1; |
| tmp_src_width = src_width; |
| } |
| |
| for (row = display_width; row > 0; row -= 2) |
| { |
| |
| left_err_t = left_err_b = 0; /* reset left pixel errors */ |
| |
| for (col = disp->src_height - 2; col >= 0; col -= 2) |
| { |
| |
| Cb = *pCb; |
| pCb += half_src_width; |
| Cr = *pCr; |
| pCr += half_src_width; |
| |
| Cb -= 128; |
| Cr -= 128; |
| Cg = Cr * JCoeff[0]; |
| Cg += Cb * JCoeff[2]; |
| |
| Cr *= JCoeff[1]; |
| Cb *= JCoeff[3]; |
| |
| //process the bottom two pixels in RGB plane |
| tmp0 = pY[read_idx]; /* top-left pixel */ |
| |
| tmp1 = (tmp0 << 16) - Cg; |
| tmp2 = (tmp0 << 16) + Cb; |
| tmp0 = (tmp0 << 16) + Cr; |
| |
| //add the error from top and left |
| //This is not exact error diffusion since |
| //we process the bottom two pixels first !! |
| tmp0 += ((left_err_b & 0xFF) << 16);// err_vert[0]; |
| tmp1 += (((left_err_b >> 8) & 0xFF) << 16);//err_vert[1]; |
| tmp2 += (((left_err_b >> 16) & 0xFF) << 16);//err_vert[2]; |
| |
| top_err_l = *((uint*)(pErr_horz + (col << 2))); |
| tmp0 += ((top_err_l & 0xFF) << 16);//pErr_horz[col]; |
| tmp1 += (((top_err_l >> 8) & 0xFF) << 16);//mErr_horz[1][col]; |
| tmp2 += (((top_err_l >> 16) & 0xFF) << 16);//mErr_horz[2][col]; |
| |
| tmp0 = clip[tmp0>>16]; |
| tmp1 = clip[tmp1>>16]; |
| tmp2 = clip[tmp2>>16]; |
| |
| #ifdef OUTPUT_RGB_565 |
| //RGB_565 |
| rgb = (tmp0 >> 3); |
| rgb = (tmp1 >> 2) | (rgb << 6); |
| rgb = (tmp2 >> 3) | (rgb << 5); |
| #else |
| //RGB_444 |
| rgb = (tmp0 & 0xF0) << 4; |
| rgb |= (tmp1 & 0xF0); |
| rgb |= (tmp2 >> 4); |
| #endif |
| tmp0 &= 0xE; |
| tmp1 &= 0xE; |
| tmp2 &= 0xE; |
| tmp0 >>= 1; |
| tmp1 >>= 1; |
| tmp2 >>= 1; |
| |
| //save error |
| top_err_l = tmp0 | (tmp1 << 8) | (tmp2 << 16); |
| |
| Y = pY[read_idx+tmp_src_width]; /* bottom-left pixel */ |
| |
| // error from the left already available |
| tmp1 = (Y << 16) - Cg + (tmp1 << 16); |
| tmp2 = (Y << 16) + Cb + (tmp2 << 16); |
| tmp0 = (Y << 16) + Cr + (tmp0 << 16); |
| |
| //add the error from top |
| top_err_r = *((uint*)(pErr_horz + (col << 2) + 4)); |
| tmp0 += ((top_err_r & 0xFF) << 16);//pErr_horz[col+1]; |
| tmp1 += (((top_err_r >> 8) & 0xFF) << 16);//mErr_horz[1][col+1]; |
| tmp2 += (((top_err_r >> 16) & 0xFF) << 16);//mErr_horz[2][col+1]; |
| |
| tmp0 = clip[tmp0>>16]; |
| tmp1 = clip[tmp1>>16]; |
| tmp2 = clip[tmp2>>16]; |
| |
| #ifdef OUTPUT_RGB_565 |
| //RGB_565 |
| rgb |= ((tmp0 >> 3) << 27); |
| rgb |= ((tmp1 >> 2) << 21); |
| rgb |= ((tmp2 >> 3) << 16); |
| #else |
| //RGB_444 |
| rgb |= (tmp0 & 0xF0) << 20; |
| rgb |= (tmp1 & 0xF0) << 16; |
| rgb |= (tmp2 >> 4) << 16; |
| #endif |
| *((uint*)(pDst + dst_width)) = rgb; |
| |
| tmp0 &= 0xE; |
| tmp1 &= 0xE; |
| tmp2 &= 0xE; |
| tmp0 >>= 1; |
| tmp1 >>= 1; |
| tmp2 >>= 1; |
| |
| //save error |
| left_err_b = tmp0 | (tmp1 << 8) | (tmp2 << 16); |
| top_err_r = left_err_b; |
| |
| //process the top two pixels in RGB plane |
| |
| tmp0 = *pY; /*upper-right pixel */ |
| tmp1 = (tmp0 << 16) - Cg; |
| tmp2 = (tmp0 << 16) + Cb; |
| tmp0 = (tmp0 << 16) + Cr; |
| |
| //add the error from top and left |
| tmp0 += ((left_err_t & 0xFF) << 16);// err_vert[3]; |
| tmp1 += (((left_err_t >> 8) & 0xFF) << 16);//err_vert[4]; |
| tmp2 += (((left_err_t >> 16) & 0xFF) << 16);//err_vert[5]; |
| |
| tmp0 += ((top_err_l & 0xFF) << 16);//pErr_horz[col]; |
| tmp1 += (((top_err_l >> 8) & 0xFF) << 16);//mErr_horz[1][col]; |
| tmp2 += (((top_err_l >> 8) & 0xFF) << 16);//mErr_horz[2][col]; |
| |
| tmp0 = clip[tmp0>>16]; |
| tmp1 = clip[tmp1>>16]; |
| tmp2 = clip[tmp2>>16]; |
| |
| #ifdef OUTPUT_RGB_565 |
| //RGB_565 |
| rgb = (tmp0 >> 3); |
| rgb = (tmp1 >> 2) | (rgb << 6); |
| rgb = (tmp2 >> 3) | (rgb << 5); |
| #else |
| //RGB_444 |
| rgb = (tmp0 & 0xF0) << 4; |
| rgb |= (tmp1 & 0xF0); |
| rgb |= (tmp2 >> 4); |
| #endif |
| |
| tmp0 &= 0xE; |
| tmp1 &= 0xE; |
| tmp2 &= 0xE; |
| tmp0 >>= 1; |
| tmp1 >>= 1; |
| tmp2 >>= 1; |
| |
| top_err_l = tmp0 | (tmp1 << 8) | (tmp2 << 16); |
| *((uint*)(pErr_horz + (col << 2))) = top_err_l; |
| |
| Y = pY[tmp_src_width]; /* bottom-right pixel */ |
| pY += (tmp_src_width << 1); |
| |
| //error from the left is already available |
| tmp1 = (Y << 16) - Cg + (tmp1 << 16); |
| tmp2 = (Y << 16) + Cb + (tmp2 << 16); |
| tmp0 = (Y << 16) + Cr + (tmp0 << 16); |
| |
| //add the error from top |
| tmp0 += ((top_err_r & 0xFF) << 16);//pErr_horz[col+1]; |
| tmp1 += (((top_err_r >> 8) & 0xFF) << 16);//mErr_horz[1][col+1]; |
| tmp2 += (((top_err_r >> 16) & 0xFF) << 16);//mErr_horz[2][col+1]; |
| |
| tmp0 = clip[tmp0>>16]; |
| tmp1 = clip[tmp1>>16]; |
| tmp2 = clip[tmp2>>16]; |
| |
| #ifdef OUTPUT_RGB_565 |
| //RGB_565 |
| rgb |= ((tmp0 >> 3) << 27); |
| rgb |= ((tmp1 >> 2) << 21); |
| rgb |= ((tmp2 >> 3) << 16); |
| #else |
| //RGB_444 |
| rgb |= (tmp0 & 0xF0) << 20; |
| rgb |= (tmp1 & 0xF0) << 16; |
| rgb |= (tmp2 >> 4) << 16; |
| #endif |
| |
| *((uint *)pDst) = rgb; |
| |
| pDst += 2; |
| |
| tmp0 &= 0xE; |
| tmp1 &= 0xE; |
| tmp2 &= 0xE; |
| tmp0 >>= 1; |
| tmp1 >>= 1; |
| tmp2 >>= 1; |
| |
| // save error |
| left_err_t = tmp0 | (tmp1 << 8) | (tmp2 << 16); // = top_err_r |
| *((uint*)(pErr_horz + (col << 2) + 4)) = left_err_t; |
| |
| }//end of COL |
| |
| pY += deltaY; |
| pCb += deltaCbCr; |
| pCr += deltaCbCr; |
| pDst += (deltaDst); //coz pDst defined as UINT * |
| } |
| return 1; |
| #else |
| return 0; |
| #endif // CCROTATE |
| } |
| #endif // USE_ARM_ASM_FOR_COLORCONVERT |
| |
| |
| // platform specific C function |
| int32 cc12scaling(uint8 **src, uint8 *dst, int *disp, |
| uint8 *clip, uint8 *pErr_horz, |
| uint8 *_mRowPix, uint8 *_mColPix); |
| |
| ///////////////////////////////////////////////////////////////////////////// |
| // Note:: This zoom algorithm needs an extra line of RGB buffer. So, users |
| // have to use GetRGBBufferSize API to get the size it needs. See GetRGBBufferSize(). |
| |
| int32 ColorConvert12::cc12ZoomIn(uint8 **src, uint8 *dst, |
| DisplayProperties *disp, uint8 *clip, uint8 *pErr_horz) |
| { |
| int32 disp_prop[6]; |
| |
| disp_prop[0] = disp->src_pitch; |
| disp_prop[1] = disp->dst_pitch; |
| disp_prop[2] = disp->src_width; |
| disp_prop[3] = disp->src_height; |
| disp_prop[4] = disp->dst_width; |
| disp_prop[5] = disp->dst_height; |
| |
| return cc12scaling(src, dst, disp_prop, clip, pErr_horz, _mRowPix, _mColPix); |
| } |
| |
| #if USE_ARM_ASM_FOR_COLORCONVERT |
| int32 cc12scaling(uint8 **src, uint8 *dst, int *disp, |
| uint8 *clip, uint8 *pErr_horz, |
| uint8 *_mRowPix, uint8 *_mColPix) |
| { |
| #if CCSCALING |
| { |
| asm("STMFD sp!,{r4-r11,lr}"); |
| asm("SUB sp,sp,#0x44"); |
| asm("LDR r7,[sp,#0x6c]"); |
| asm("LDR r12,[r2,#0]"); |
| asm("MOV r5,r3"); |
| asm("STR r12,[sp,#0x24]"); |
| asm("LDR r3,[r2,#8]"); |
| asm("LDR r4,[r2,#4]"); |
| asm("RSB r12,r3,r12,LSL #1"); |
| asm("STR r12,[sp,#0x1c]"); |
| asm("LDR r12,[sp,#0x24]"); |
| asm("SUB r12,r12,r3"); |
| asm("MOV r12,r12,ASR #1"); |
| asm("STR r12,[sp,#0x14]"); |
| asm("LDR r12,[r2,#0x10]"); |
| asm("STR r12,[sp,#0x18]"); |
| asm("LDMIA r0,{r6,lr}"); |
| asm("STR lr,[sp,#0x2c]"); |
| asm("LDR r8,[r0,#8]"); |
| asm("MOV r0,r1"); |
| asm("STR r8,[sp,#0x28]"); |
| asm("LDR r1,[r2,#0xc]"); |
| asm("SUB r2,r1,#1"); |
| asm("STR r2,[sp,#0x10]"); |
| asm("CMP r2,#0"); |
| asm("BLT L1.4684"); |
| asm("SUB r1,r3,#2"); |
| asm("STR r1,[sp,#0x40]"); |
| asm("LDR r1,[sp,#0x18]"); |
| asm("MOV r1,r1,LSL #1"); |
| asm("STR r1,[sp,#0x3c]"); |
| asm("L1.3020:"); |
| asm("LDR r1,[sp,#0x70]"); |
| asm("LDR r2,[sp,#0x10]"); |
| asm("ADD r1,r1,r2"); |
| asm("STR r1,[sp,#0x38]"); |
| asm("LDRB r1,[r1,#-1]"); |
| asm("CMP r1,#0"); |
| asm("BNE L1.3104"); |
| asm("LDR r1,[sp,#0x70]"); |
| asm("LDR r2,[sp,#0x10]"); |
| asm("LDRB r1,[r1,r2]"); |
| asm("CMP r1,#0"); |
| asm("BNE L1.3104"); |
| asm("LDR r3,[sp,#0x24]"); |
| asm("LDR lr,[sp,#0x2c]"); |
| asm("LDR r8,[sp,#0x28]"); |
| asm("ADD lr,lr,r3,ASR #1"); |
| asm("ADD r8,r8,r3,ASR #1"); |
| asm("STR r8,[sp,#0x28]"); |
| asm("STR lr,[sp,#0x2c]"); |
| asm("ADD r6,r6,r3,LSL #1"); |
| asm("B L1.4664"); |
| asm("L1.3104:"); |
| asm("LDR r1,[sp,#0x40]"); |
| asm("MOV r2,#0"); |
| asm("MOV r12,r2"); |
| asm("CMP r1,#0"); |
| asm("BLT L1.4364"); |
| asm("L1.3124:"); |
| asm("LDR lr,[sp,#0x2c]"); |
| asm("MOV r9,#0xce"); |
| asm("LDRB r3,[lr],#1"); |
| asm("LDR r8,[sp,#0x28]"); |
| asm("STR lr,[sp,#0x2c]"); |
| asm("LDRB lr,[r8],#1"); |
| asm("STR r8,[sp,#0x28]"); |
| asm("ADD r9,r9,#0xb200"); |
| asm("SUB lr,lr,#0x80"); |
| asm("MOV r10,#0xff"); |
| asm("ADD r10,r10,#0x2a00"); |
| asm("MUL r8,r9,lr"); |
| asm("SUB r3,r3,#0x80"); |
| asm("MUL r9,r10,r3"); |
| asm("LDR r10,L1.4692"); |
| asm("ADD r9,r8,r9,LSL #1"); |
| asm("MUL r8,r10,lr"); |
| asm("LDR r10,L1.4696"); |
| asm("MUL lr,r10,r3"); |
| asm("LDRB r3,[r7,r1]"); |
| asm("CMP r3,#0"); |
| asm("ADDEQ r6,r6,#1"); |
| asm("BEQ L1.3796"); |
| asm("LDR r3,[sp,#0x24]"); |
| asm("TST r0,#3"); |
| asm("LDRB r10,[r6,r3]"); |
| asm("RSB r11,r9,r10,LSL #16"); |
| asm("STR r11,[sp,#8]"); |
| asm("ADD r11,r8,r10,LSL #16"); |
| asm("ADD r3,lr,r10,LSL #16"); |
| asm("AND r10,r12,#0xff"); |
| asm("ADD r11,r11,r10,LSL #16"); |
| asm("MOV r10,#0xff0000"); |
| asm("STR r11,[sp,#0xc]"); |
| asm("LDR r11,[sp,#8]"); |
| asm("AND r10,r10,r12,LSL #8"); |
| asm("ADD r11,r10,r11"); |
| asm("STR r11,[sp,#8]"); |
| asm("LDR r10,[sp,#0x68]"); |
| asm("AND r12,r12,#0xff0000"); |
| asm("ADD r12,r12,r3"); |
| asm("LDR r3,[r10,r1,LSL #2]"); |
| asm("LDR r11,[sp,#0xc]"); |
| asm("AND r10,r3,#0xff"); |
| asm("ADD r10,r11,r10,LSL #16"); |
| asm("STR r10,[sp,#0xc]"); |
| asm("MOV r10,#0xff0000"); |
| asm("AND r10,r10,r3,LSL #8"); |
| asm("AND r3,r3,#0xff0000"); |
| asm("ADD r3,r3,r12"); |
| asm("LDR r11,[sp,#8]"); |
| asm("LDR r12,[sp,#0xc]"); |
| asm("ADD r10,r10,r11"); |
| asm("LDRB r11,[r5,r12,ASR #16]"); |
| asm("STR r11,[sp,#0xc]"); |
| asm("LDRB r10,[r5,r10,ASR #16]"); |
| asm("LDRB r12,[r5,r3,ASR #16]"); |
| asm("AND r3,r11,#0xf0"); |
| asm("MOV r11,r3,LSL #4"); |
| asm("AND r3,r10,#0xf0"); |
| asm("ORR r3,r3,r11"); |
| asm("LDR r11,[sp,#0xc]"); |
| asm("AND r10,r10,#0xe"); |
| asm("AND r11,r11,#0xe"); |
| asm("MOV r11,r11,LSR #1"); |
| asm("STR r11,[sp,#0xc]"); |
| asm("MOV r11,r10,LSR #1"); |
| asm("ORR r3,r3,r12,ASR #4"); |
| asm("AND r12,r12,#0xe"); |
| asm("STR r11,[sp,#8]"); |
| asm("MOV r11,r12,LSR #1"); |
| asm("STR r11,[sp,#4]"); |
| asm("LDR r11,[sp,#0xc]"); |
| asm("LDR r12,[sp,#8]"); |
| asm("ORR r12,r11,r12,LSL #8"); |
| asm("LDR r11,[sp,#4]"); |
| asm("LDRB r10,[r6],#1"); |
| asm("ORR r12,r12,r11,LSL #16"); |
| asm("LDR r11,[sp,#8]"); |
| asm("STR r10,[sp,#0x20]"); |
| asm("RSB r10,r9,r10,LSL #16"); |
| asm("ADD r10,r10,r11,LSL #16"); |
| asm("STR r10,[sp,#8]"); |
| asm("LDR r10,[sp,#0x20]"); |
| asm("LDR r11,[sp,#4]"); |
| asm("ADD r10,lr,r10,LSL #16"); |
| asm("ADD r10,r10,r11,LSL #16"); |
| asm("STR r10,[sp,#4]"); |
| asm("LDR r10,[sp,#0x20]"); |
| asm("LDR r11,[sp,#0xc]"); |
| asm("ADD r10,r8,r10,LSL #16"); |
| asm("ADD r10,r10,r11,LSL #16"); |
| asm("AND r11,r2,#0xff"); |
| asm("ADD r10,r10,r11,LSL #16"); |
| asm("STR r10,[sp,#0xc]"); |
| asm("MOV r10,#0xff0000"); |
| asm("AND r11,r10,r2,LSL #8"); |
| asm("LDR r10,[sp,#8]"); |
| asm("AND r2,r2,#0xff0000"); |
| asm("ADD r11,r11,r10"); |
| asm("LDR r10,[sp,#4]"); |
| asm("ADD r2,r2,r10"); |
| asm("LDR r10,[sp,#0xc]"); |
| asm("LDRB r10,[r5,r10,ASR #16]"); |
| asm("STR r10,[sp,#0xc]"); |
| asm("LDRB r11,[r5,r11,ASR #16]"); |
| asm("LDRB r10,[r5,r2,ASR #16]"); |
| asm("STR r10,[sp,#4]"); |
| asm("LDR r10,[sp,#0xc]"); |
| asm("MOV r2,r10,LSL #28"); |
| asm("MOV r2,r2,LSR #29"); |
| asm("AND r10,r11,#0xe"); |
| asm("ORR r2,r2,r10,LSL #7"); |
| asm("LDR r10,[sp,#4]"); |
| asm("AND r11,r11,#0xf0"); |
| asm("AND r10,r10,#0xe"); |
| asm("ORR r2,r2,r10,LSL #15"); |
| asm("LDR r10,[sp,#0x68]"); |
| asm("STR r2,[r10,r1,LSL #2]"); |
| asm("LDR r10,[sp,#0xc]"); |
| asm("AND r10,r10,#0xf0"); |
| asm("MOV r10,r10,LSL #4"); |
| asm("STR r10,[sp,#0xc]"); |
| asm("ORR r10,r11,r10"); |
| asm("LDR r11,[sp,#4]"); |
| asm("ORR r10,r10,r11,ASR #4"); |
| asm("LDRB r11,[r7,r1]"); |
| asm("BEQ L1.3720"); |
| asm("CMP r11,#2"); |
| asm("BNE L1.3668"); |
| asm("ADD r11,r0,r4,LSL #1"); |
| asm("STRH r3,[r11,#0]"); |
| asm("STRH r3,[r11,#2]"); |
| asm("STRH r10,[r0,#0]"); |
| asm("STRH r10,[r0,#2]"); |
| asm("B L1.3796"); |
| asm("L1.3668:"); |
| asm("CMP r11,#3"); |
| asm("ADD r11,r0,r4,LSL #1"); |
| asm("STRNEH r3,[r11,#0]"); |
| asm("STRNEH r10,[r0,#0]"); |
| asm("BNE L1.3796"); |
| asm("STRH r3,[r11],#2"); |
| asm("ORR r3,r3,r3,LSL #16"); |
| asm("STR r3,[r11,#0]"); |
| asm("STRH r10,[r0,#0]"); |
| asm("ORR r3,r10,r10,LSL #16"); |
| asm("MOV r10,#2"); |
| asm("STR r3,[r10,r0]"); |
| asm("B L1.3796"); |
| asm("L1.3720:"); |
| asm("CMP r11,#2"); |
| asm("BNE L1.3748"); |
| asm("ORR r3,r3,r3,LSL #16"); |
| asm("STR r3,[r0,r4,LSL #1]"); |
| asm("ORR r3,r10,r10,LSL #16"); |
| asm("STR r3,[r0,#0]"); |
| asm("B L1.3796"); |
| asm("L1.3748:"); |
| asm("CMP r11,#3"); |
| asm("ADDNE r11,r0,r4,LSL #1"); |
| asm("STRNEH r3,[r11,#0]"); |
| asm("STRNEH r10,[r0,#0]"); |
| asm("BNE L1.3796"); |
| asm("ORR r11,r3,r3,LSL #16"); |
| asm("STR r11,[r0,r4,LSL #1]"); |
| asm("ADD r11,r0,r4,LSL #1"); |
| asm("STRH r3,[r11,#4]"); |
| asm("ORR r3,r10,r10,LSL #16"); |
| asm("STR r3,[r0,#0]"); |
| asm("STRH r10,[r0,#4]"); |
| asm("L1.3796:"); |
| asm("LDRB r3,[r7,r1]"); |
| asm("ADD r0,r0,r3,LSL #1"); |
| asm("ADD r3,r7,r1"); |
| asm("STR r3,[sp,#0x34]"); |
| asm("LDRB r3,[r3,#1]"); |
| asm("CMP r3,#0"); |
| asm("ADDEQ r6,r6,#1"); |
| asm("BEQ L1.4344"); |
| asm("LDR r3,[sp,#0x24]"); |
| asm("TST r0,#3"); |
| asm("LDRB r10,[r6,r3]"); |
| asm("RSB r11,r9,r10,LSL #16"); |
| asm("STR r11,[sp,#8]"); |
| asm("ADD r11,r8,r10,LSL #16"); |
| asm("ADD r3,lr,r10,LSL #16"); |
| asm("AND r10,r12,#0xff"); |
| asm("ADD r11,r11,r10,LSL #16"); |
| asm("MOV r10,#0xff0000"); |
| asm("STR r11,[sp,#0xc]"); |
| asm("LDR r11,[sp,#8]"); |
| asm("AND r10,r10,r12,LSL #8"); |
| asm("ADD r11,r10,r11"); |
| asm("STR r11,[sp,#8]"); |
| asm("LDR r10,[sp,#0x68]"); |
| asm("AND r12,r12,#0xff0000"); |
| asm("ADD r12,r12,r3"); |
| asm("ADD r3,r10,r1,LSL #2"); |
| asm("STR r3,[sp,#0x30]"); |
| asm("LDR r3,[r3,#4]"); |
| asm("LDR r11,[sp,#0xc]"); |
| asm("AND r10,r3,#0xff"); |
| asm("ADD r10,r11,r10,LSL #16"); |
| asm("STR r10,[sp,#0xc]"); |
| asm("MOV r10,#0xff0000"); |
| asm("AND r10,r10,r3,LSL #8"); |
| asm("AND r3,r3,#0xff0000"); |
| asm("ADD r3,r3,r12"); |
| asm("LDR r11,[sp,#8]"); |
| asm("LDR r12,[sp,#0xc]"); |
| asm("ADD r10,r10,r11"); |
| asm("LDRB r11,[r5,r12,ASR #16]"); |
| asm("STR r11,[sp,#0xc]"); |
| asm("LDRB r10,[r5,r10,ASR #16]"); |
| asm("LDRB r12,[r5,r3,ASR #16]"); |
| asm("AND r3,r11,#0xf0"); |
| asm("AND r11,r10,#0xf0"); |
| asm("ORR r3,r11,r3,LSL #4"); |
| asm("AND r10,r10,#0xe"); |
| asm("MOV r10,r10,LSR #1"); |
| asm("ORR r3,r3,r12,ASR #4"); |
| asm("AND r12,r12,#0xe"); |
| asm("STR r10,[sp,#8]"); |
| asm("LDR r11,[sp,#0xc]"); |
| asm("MOV r10,r12,LSR #1"); |
| asm("STR r10,[sp,#4]"); |
| asm("AND r11,r11,#0xe"); |
| asm("MOV r11,r11,LSR #1"); |
| asm("LDR r10,[sp,#8]"); |
| asm("STR r11,[sp,#0xc]"); |
| asm("ORR r12,r11,r10,LSL #8"); |
| asm("LDR r10,[sp,#4]"); |
| asm("LDRB r11,[r6],#1"); |
| asm("ORR r12,r12,r10,LSL #16"); |
| asm("LDR r10,[sp,#8]"); |
| asm("RSB r9,r9,r11,LSL #16"); |
| asm("ADD r9,r9,r10,LSL #16"); |
| asm("ADD lr,lr,r11,LSL #16"); |
| asm("LDR r10,[sp,#4]"); |
| asm("ADD r8,r8,r11,LSL #16"); |
| asm("LDR r11,[sp,#0xc]"); |
| asm("ADD lr,lr,r10,LSL #16"); |
| asm("AND r10,r2,#0xff"); |
| asm("ADD r8,r8,r11,LSL #16"); |
| asm("ADD r8,r8,r10,LSL #16"); |
| asm("MOV r10,#0xff0000"); |
| asm("AND r10,r10,r2,LSL #8"); |
| asm("AND r2,r2,#0xff0000"); |
| asm("ADD r2,r2,lr"); |
| asm("LDRB lr,[r5,r8,ASR #16]"); |
| asm("ADD r9,r10,r9"); |
| asm("LDRB r8,[r5,r9,ASR #16]"); |
| asm("LDRB r9,[r5,r2,ASR #16]"); |
| asm("MOV r2,lr,LSL #28"); |
| asm("AND r10,r8,#0xe"); |
| asm("MOV r2,r2,LSR #29"); |
| asm("ORR r2,r2,r10,LSL #7"); |
| asm("AND r10,r9,#0xe"); |
| asm("ORR r2,r2,r10,LSL #15"); |
| asm("LDR r10,[sp,#0x30]"); |
| asm("AND r8,r8,#0xf0"); |
| asm("AND lr,lr,#0xf0"); |
| asm("ORR lr,r8,lr,LSL #4"); |
| asm("STR r2,[r10,#4]"); |
| asm("LDR r8,[sp,#0x34]"); |
| asm("ORR lr,lr,r9,ASR #4"); |
| asm("LDRB r8,[r8,#1]"); |
| asm("BEQ L1.4268"); |
| asm("CMP r8,#2"); |
| asm("BNE L1.4216"); |
| asm("ADD r8,r0,r4,LSL #1"); |
| asm("STRH r3,[r8,#0]"); |
| asm("STRH r3,[r8,#2]"); |
| asm("STRH lr,[r0,#0]"); |
| asm("STRH lr,[r0,#2]"); |
| asm("B L1.4344"); |
| asm("L1.4216:"); |
| asm("CMP r8,#3"); |
| asm("ADD r8,r0,r4,LSL #1"); |
| asm("STRNEH r3,[r8,#0]"); |
| asm("STRNEH lr,[r0,#0]"); |
| asm("BNE L1.4344"); |
| asm("STRH r3,[r8],#2"); |
| asm("ORR r3,r3,r3,LSL #16"); |
| asm("STR r3,[r8,#0]"); |
| asm("STRH lr,[r0,#0]"); |
| asm("ORR r3,lr,lr,LSL #16"); |
| asm("MOV lr,#2"); |
| asm("STR r3,[lr,r0]"); |
| asm("B L1.4344"); |
| asm("L1.4268:"); |
| asm("CMP r8,#2"); |
| asm("BNE L1.4296"); |
| asm("ORR r3,r3,r3,LSL #16"); |
| asm("STR r3,[r0,r4,LSL #1]"); |
| asm("ORR r3,lr,lr,LSL #16"); |
| asm("STR r3,[r0,#0]"); |
| asm("B L1.4344"); |
| asm("L1.4296:"); |
| asm("CMP r8,#3"); |
| asm("ADDNE r8,r0,r4,LSL #1"); |
| asm("STRNEH r3,[r8,#0]"); |
| asm("STRNEH lr,[r0,#0]"); |
| asm("BNE L1.4344"); |
| asm("ORR r8,r3,r3,LSL #16"); |
| asm("STR r8,[r0,r4,LSL #1]"); |
| asm("ADD r8,r0,r4,LSL #1"); |
| asm("STRH r3,[r8,#4]"); |
| asm("ORR r3,lr,lr,LSL #16"); |
| asm("STR r3,[r0,#0]"); |
| asm("STRH lr,[r0,#4]"); |
| asm("L1.4344:"); |
| asm("LDR r3,[sp,#0x34]"); |
| asm("SUBS r1,r1,#2"); |
| asm("LDRB r3,[r3,#1]"); |
| asm("ADD r0,r0,r3,LSL #1"); |
| asm("BPL L1.3124"); |
| asm("L1.4364:"); |
| asm("LDR r1,[sp,#0x1c]"); |
| asm("LDR lr,[sp,#0x2c]"); |
| asm("ADD r6,r6,r1"); |
| asm("LDR r1,[sp,#0x14]"); |
| asm("LDR r8,[sp,#0x28]"); |
| asm("ADD lr,lr,r1"); |
| asm("ADD r8,r8,r1"); |
| asm("LDR r1,[sp,#0x18]"); |
| asm("STR r8,[sp,#0x28]"); |
| asm("SUB r8,r0,r1,LSL #1"); |
| asm("LDR r1,[sp,#0x70]"); |
| asm("LDR r2,[sp,#0x10]"); |
| asm("STR lr,[sp,#0x2c]"); |
| asm("LDRB r0,[r1,r2]"); |
| asm("LDR r1,[sp,#0x38]"); |
| asm("LDRB r1,[r1,#-1]"); |
| asm("MUL r9,r4,r0"); |
| asm("CMP r1,#0"); |
| asm("BEQ L1.4552"); |
| asm("CMP r0,#1"); |
| asm("BEQ L1.4464"); |
| asm("ADD r1,r8,r4,LSL #1"); |
| asm("ADD r0,r8,r9,LSL #1"); |
| asm("LDR r2,[sp,#0x3c]"); |
| asm("BL memcpy"); |
| asm("L1.4464:"); |
| asm("LDR r1,[sp,#0x38]"); |
| asm("LDRB r0,[r1,#-1]"); |
| asm("CMP r0,#2"); |
| asm("BNE L1.4504"); |
| asm("ADD r0,r8,r9,LSL #1"); |
| asm("ADD r0,r0,r4,LSL #1"); |
| asm("ADD r1,r8,r4,LSL #1"); |
| asm("LDR r2,[sp,#0x3c]"); |
| asm("BL memcpy"); |
| asm("B L1.4552"); |
| asm("L1.4504:"); |
| asm("CMP r0,#3"); |
| asm("BNE L1.4552"); |
| asm("ADD r10,r8,r9,LSL #1"); |
| asm("ADD r9,r8,r4,LSL #1"); |
| asm("MOV r1,r9"); |
| asm("ADD r0,r10,r4,LSL #1"); |
| asm("LDR r2,[sp,#0x3c]"); |
| asm("BL memcpy"); |
| asm("ADD r0,r10,r4,LSL #2"); |
| asm("MOV r1,r9"); |
| asm("LDR r2,[sp,#0x3c]"); |
| asm("BL memcpy"); |
| asm("L1.4552:"); |
| asm("LDR r1,[sp,#0x70]"); |
| asm("LDR r2,[sp,#0x10]"); |
| asm("LDRB r0,[r1,r2]"); |
| asm("CMP r0,#2"); |
| asm("BNE L1.4592"); |
| asm("ADD r0,r8,r4,LSL #1"); |
| asm("MOV r1,r8"); |
| asm("LDR r2,[sp,#0x3c]"); |
| asm("BL memcpy"); |
| asm("B L1.4632"); |
| asm("L1.4592:"); |
| asm("CMP r0,#3"); |
| asm("BNE L1.4632"); |
| asm("ADD r0,r8,r4,LSL #1"); |
| asm("MOV r1,r8"); |
| asm("LDR r2,[sp,#0x3c]"); |
| asm("BL memcpy"); |
| asm("ADD r0,r8,r4,LSL #2"); |
| asm("MOV r1,r8"); |
| asm("LDR r2,[sp,#0x3c]"); |
| asm("BL memcpy"); |
| asm("L1.4632:"); |
| asm("LDR r1,[sp,#0x38]"); |
| asm("LDRB r0,[r1,#-1]"); |
| asm("LDR r1,[sp,#0x70]"); |
| asm("LDR r2,[sp,#0x10]"); |
| asm("LDRB r1,[r1,r2]"); |
| asm("ADD r0,r0,r1"); |
| asm("MUL r0,r4,r0"); |
| asm("ADD r0,r8,r0,LSL #1"); |
| asm("L1.4664:"); |
| asm("LDR r2,[sp,#0x10]"); |
| asm("SUB r2,r2,#2"); |
| asm("STR r2,[sp,#0x10]"); |
| asm("CMP r2,#0"); |
| asm("BGE L1.3020"); |
| asm("L1.4684:"); |
| asm("ADD sp,sp,#0x44"); |
| asm("LDMFD sp!,{r4-r11,lr}"); |
| asm("MOV r0,#1"); |
| // asm("BX lr"); |
| asm("L1.4688:"); |
| asm(".align 0"); |
| asm("L1.4692:"); |
| asm(".word 0x00015f03"); |
| asm("L1.4696:"); |
| asm(".word 0x0001bbd2"); |
| } |
| return 1; |
| #else |
| return 0; |
| #endif // CCSCALING |
| } |
| |
| #else // straight C version |
| |
| int32 cc12scaling(uint8 **src, uint8 *dst, int *disp, |
| uint8 *clip, uint8 *pErr_horz, |
| uint8 *_mRowPix, uint8 *_mColPix) |
| { |
| #if CCSCALING |
| const static uint32 JCoeff[4] = |
| { |
| 45774, //65536*0.813/1.164; |
| 89859, //65536*1.596/1.164; |
| 22014, //65536*0.391/1.164; |
| 113618 //65536*2.018/1.164; |
| }; |
| |
| uint8 *pCb, *pCr, *pY; |
| uint16 *pDst; |
| int32 src_pitch, dst_pitch, src_width; |
| int32 Y, Cb, Cr, Cg; |
| uint32 left_err_t, left_err_b; /* error from the left pixels */ |
| uint32 top_err_l, top_err_r; /* error from the top pixels */ |
| int32 deltaY, dst_width, deltaCbCr; |
| int32 row, col; |
| int32 tmp0, tmp1, tmp2; |
| uint32 rgb; |
| int32 offset; |
| |
| |
| src_pitch = disp[0]; |
| dst_pitch = disp[1]; |
| src_width = disp[2]; |
| |
| deltaY = (src_pitch << 1) - src_width; |
| deltaCbCr = (src_pitch - src_width) >> 1; |
| dst_width = disp[4]; |
| |
| pY = src[0]; |
| pCb = src[1]; |
| pCr = src[2]; |
| |
| pDst = (uint16 *)dst; |
| |
| for (row = disp[3] - 1; row >= 0; row -= 2) |
| {/* decrement index, _mColPix[.] is |
| symmetric to increment index */ |
| |
| if ((_mColPix[row-1] == 0) && (_mColPix[row] == 0)) |
| { |
| pCb += (src_pitch >> 1); |
| pCr += (src_pitch >> 1); |
| pY += (src_pitch << 1); |
| continue; |
| } |
| |
| left_err_t = left_err_b = 0; /* reset left pixel errors */ |
| |
| for (col = src_width - 2; col >= 0; col -= 2) |
| { /* decrement index, _mRowPix[.] is |
| symmetric to increment index */ |
| |
| Cb = *pCb++; |
| Cr = *pCr++; |
| |
| //load the bottom two pixels |
| //Y = *(((uint16 *)pY)+src_pitch); |
| //Y = *((uint16 *)(((uint16 *)pY) + src_pitch)); |
| |
| Cb -= 128; |
| Cr -= 128; |
| Cg = Cr * JCoeff[0]; |
| Cg += Cb * JCoeff[2]; |
| |
| Cr *= JCoeff[1]; |
| Cb *= JCoeff[3]; |
| |
| if (_mRowPix[col]) /* compute this pixel */ |
| { |
| tmp0 = pY[src_pitch]; //bottom left |
| |
| tmp1 = (tmp0 << 16) - Cg; |
| tmp2 = (tmp0 << 16) + Cb; |
| tmp0 = (tmp0 << 16) + Cr; |
| |
| tmp0 += ((left_err_b & 0xFF) << 16);// err_vert[0]; |
| tmp1 += (((left_err_b >> 8) & 0xFF) << 16);//err_vert[1]; |
| tmp2 += (((left_err_b >> 16) & 0xFF) << 16);//err_vert[2]; |
| |
| top_err_l = *((uint*)(pErr_horz + (col << 2))); |
| tmp0 += ((top_err_l & 0xFF) << 16);//pErr_horz[col]; |
| tmp1 += (((top_err_l >> 8) & 0xFF) << 16);//mErr_horz[1][col]; |
| tmp2 += (((top_err_l >> 16) & 0xFF) << 16);//mErr_horz[2][col]; |
| |
| tmp0 = clip[tmp0>>16]; |
| tmp1 = clip[tmp1>>16]; |
| tmp2 = clip[tmp2>>16]; |
| #ifdef OUTPUT_RGB_565 |
| //RGB_565 |
| rgb = (tmp0 >> 3); |
| rgb = (tmp1 >> 2) | (rgb << 6); |
| rgb = (tmp2 >> 3) | (rgb << 5); |
| #else |
| //RGB_444 |
| rgb = (tmp0 & 0xF0) << 4; |
| rgb |= (tmp1 & 0xF0); |
| rgb |= (tmp2 >> 4); |
| #endif |
| tmp0 &= 0xE; |
| tmp1 &= 0xE; |
| tmp2 &= 0xE; |
| tmp0 >>= 1; |
| tmp1 >>= 1; |
| tmp2 >>= 1; |
| |
| //save error |
| left_err_b = tmp0 | (tmp1 << 8) | (tmp2 << 16); // = top_err_l also |
| |
| Y = *pY++; //upper left |
| |
| // error from the top already available |
| tmp1 = (Y << 16) - Cg + (tmp1 << 16); |
| tmp2 = (Y << 16) + Cb + (tmp2 << 16); |
| tmp0 = (Y << 16) + Cr + (tmp0 << 16); |
| |
| //add the error from left |
| tmp0 += ((left_err_t & 0xFF) << 16);// err_vert[3]; |
| tmp1 += (((left_err_t >> 8) & 0xFF) << 16);//err_vert[4]; |
| tmp2 += (((left_err_t >> 16) & 0xFF) << 16);//err_vert[5]; |
| |
| tmp0 = clip[tmp0>>16]; |
| tmp1 = clip[tmp1>>16]; |
| tmp2 = clip[tmp2>>16]; |
| |
| //save error |
| left_err_t = ((tmp0 & 0xE) >> 1) | ((tmp1 & 0xE) << 7) | ((tmp2 & 0xE) << 15); //= top_err_l also |
| *((uint*)(pErr_horz + (col << 2))) = left_err_t; // =top_err_l; |
| |
| #ifdef OUTPUT_RGB_565 |
| //RGB_565 |
| tmp0 = (tmp0 >> 3); |
| tmp0 = (tmp1 >> 2) | (tmp0 << 6); |
| tmp0 = (tmp2 >> 3) | (tmp0 << 5); |
| #else |
| //RGB_444 |
| tmp0 = (tmp0 & 0xF0) << 4; |
| tmp0 |= (tmp1 & 0xF0); |
| tmp0 |= (tmp2 >> 4); |
| #endif |
| if (((uint)pDst) & 3) //half word aligned |
| { |
| if (_mRowPix[col] == 2) |
| { |
| *(pDst + dst_pitch) = rgb; |
| *(pDst + dst_pitch + 1) = rgb; |
| *(pDst) = tmp0; |
| *(pDst + 1) = tmp0; |
| } |
| else if (_mRowPix[col] == 3) |
| { |
| *(pDst + dst_pitch) = rgb; |
| *((uint*)(pDst + dst_pitch + 1)) = rgb | (rgb << 16); |
| |
| *(pDst) = tmp0; |
| *((uint*)(pDst + 1)) = tmp0 | (tmp0 << 16); |
| } |
| else |
| { |
| *(pDst + dst_pitch) = rgb; |
| *(pDst) = tmp0; |
| } |
| } |
| else //word aligned |
| { |
| if (_mRowPix[col] == 2) |
| { |
| *((uint*)(pDst + dst_pitch)) = rgb | (rgb << 16); |
| *((uint*)(pDst)) = tmp0 | (tmp0 << 16); |
| } |
| else if (_mRowPix[col] == 3) |
| { |
| *((uint*)(pDst + dst_pitch)) = rgb | (rgb << 16); |
| *(pDst + dst_pitch + 2) = rgb; |
| |
| *((uint*)(pDst)) = tmp0 | (tmp0 << 16); |
| *(pDst + 2) = tmp0; |
| } |
| else |
| { |
| *(pDst + dst_pitch) = rgb; |
| *(pDst) = tmp0; |
| } |
| } |
| } /* if(_mRowPix[col]) */ |
| else |
| { |
| pY++; |
| } |
| |
| pDst += _mRowPix[col]; |
| |
| if (_mRowPix[col+1]) /* compute this pixel */ |
| { |
| //load the top two pixels |
| //Y = *((uint16 *)pY)++; |
| tmp0 = pY[src_pitch]; //bottom right |
| |
| tmp1 = (tmp0 << 16) - Cg; |
| tmp2 = (tmp0 << 16) + Cb; |
| tmp0 = (tmp0 << 16) + Cr; |
| |
| //add the error from top and left |
| tmp0 += ((left_err_b & 0xFF) << 16);// err_vert[0]; |
| tmp1 += (((left_err_b >> 8) & 0xFF) << 16);//err_vert[1]; |
| tmp2 += (((left_err_b >> 16) & 0xFF) << 16);//err_vert[2]; |
| |
| top_err_r = *((uint*)(pErr_horz + (col << 2) + 4)); |
| tmp0 += ((top_err_r & 0xFF) << 16);//pErr_horz[col+1]; |
| tmp1 += (((top_err_r >> 8) & 0xFF) << 16);//mErr_horz[1][col+1]; |
| tmp2 += (((top_err_r >> 16) & 0xFF) << 16);//mErr_horz[2][col+1]; |
| |
| tmp0 = clip[tmp0>>16]; |
| tmp1 = clip[tmp1>>16]; |
| tmp2 = clip[tmp2>>16]; |
| |
| #ifdef OUTPUT_RGB_565 |
| //RGB_565 |
| rgb = (tmp0 >> 3); |
| rgb = (tmp1 >> 2) | (rgb << 6); |
| rgb = (tmp2 >> 3) | (rgb << 5); |
| #else |
| //RGB_444 |
| rgb = (tmp0 & 0xF0) << 4; |
| rgb |= (tmp1 & 0xF0); |
| rgb |= (tmp2 >> 4); |
| #endif |
| |
| tmp0 &= 0xE; |
| tmp1 &= 0xE; |
| tmp2 &= 0xE; |
| tmp0 >>= 1; |
| tmp1 >>= 1; |
| tmp2 >>= 1; |
| |
| //save error |
| left_err_b = tmp0 | (tmp1 << 8) | (tmp2 << 16); // = top_err_r also |
| |
| Y = *pY++; |
| |
| // error from the top already available |
| tmp1 = (Y << 16) - Cg + (tmp1 << 16); |
| tmp2 = (Y << 16) + Cb + (tmp2 << 16); |
| tmp0 = (Y << 16) + Cr + (tmp0 << 16); |
| |
| //add the error from left |
| tmp0 += ((left_err_t & 0xFF) << 16);// err_vert[3]; |
| tmp1 += (((left_err_t >> 8) & 0xFF) << 16);//err_vert[4]; |
| tmp2 += (((left_err_t >> 16) & 0xFF) << 16);//err_vert[5]; |
| |
| tmp0 = clip[tmp0>>16]; |
| tmp1 = clip[tmp1>>16]; |
| tmp2 = clip[tmp2>>16]; |
| |
| //save error |
| left_err_t = ((tmp0 & 0xE) >> 1) | ((tmp1 & 0xE) << 7) | ((tmp2 & 0xE) << 15);//= top_err_r also |
| *((uint*)(pErr_horz + (col << 2) + 4)) = left_err_t;// =top_err_r; |
| |
| #ifdef OUTPUT_RGB_565 |
| //RGB_565 |
| tmp0 = (tmp0 >> 3); |
| tmp0 = (tmp1 >> 2) | (tmp0 << 6); |
| tmp0 = (tmp2 >> 3) | (tmp0 << 5); |
| #else |
| //RGB_444 |
| tmp0 = (tmp0 & 0xF0) << 4; |
| tmp0 |= (tmp1 & 0xF0); |
| tmp0 |= (tmp2 >> 4); |
| #endif |
| |
| if (((uint)pDst) & 3) //half word aligned |
| { |
| if (_mRowPix[col+1] == 2) |
| { |
| *(pDst + dst_pitch) = rgb; |
| *(pDst + dst_pitch + 1) = rgb; |
| *(pDst) = tmp0; |
| *(pDst + 1) = tmp0; |
| } |
| else if (_mRowPix[col+1] == 3) |
| { |
| *(pDst + dst_pitch) = rgb; |
| *((uint*)(pDst + dst_pitch + 1)) = rgb | (rgb << 16); |
| |
| *(pDst) = tmp0; |
| *((uint*)(pDst + 1)) = tmp0 | (tmp0 << 16); |
| } |
| else |
| { |
| *(pDst + dst_pitch) = rgb; |
| *(pDst) = tmp0; |
| } |
| } |
| else //word aligned |
| { |
| if (_mRowPix[col+1] == 2) |
| { |
| *((uint*)(pDst + dst_pitch)) = rgb | (rgb << 16); |
| *((uint*)(pDst)) = tmp0 | (tmp0 << 16); |
| } |
| else if (_mRowPix[col+1] == 3) |
| { |
| *((uint*)(pDst + dst_pitch)) = rgb | (rgb << 16); |
| *(pDst + dst_pitch + 2) = rgb; |
| |
| *((uint*)(pDst)) = tmp0 | (tmp0 << 16); |
| *(pDst + 2) = tmp0; |
| } |
| else |
| { |
| *(pDst + dst_pitch) = rgb; |
| *(pDst) = tmp0; |
| } |
| } |
| } /* if(_mRowPix[col]) */ |
| else |
| { |
| pY++; |
| } |
| |
| pDst += _mRowPix[col+1]; |
| }//end of COL |
| |
| pY += (deltaY); |
| pCb += deltaCbCr; |
| pCr += deltaCbCr; |
| |
| pDst -= (dst_width); //goes back to the beginning of the line; |
| |
| //copy down |
| offset = (_mColPix[row] * dst_pitch); |
| |
| if (_mColPix[row-1] && _mColPix[row] != 1) |
| { |
| oscl_memcpy(pDst + offset, pDst + dst_pitch, dst_width*2); |
| } |
| if (_mColPix[row-1] == 2) |
| { |
| oscl_memcpy(pDst + offset + dst_pitch, pDst + dst_pitch, dst_width*2); |
| } |
| else if (_mColPix[row-1] == 3) |
| { |
| oscl_memcpy(pDst + offset + dst_pitch, pDst + dst_pitch, dst_width*2); |
| oscl_memcpy(pDst + offset + dst_pitch*2, pDst + dst_pitch, dst_width*2); |
| } |
| |
| //copy up |
| if (_mColPix[row] == 2) |
| oscl_memcpy(pDst + dst_pitch, pDst, dst_width*2); |
| else if (_mColPix[row] == 3) |
| { |
| oscl_memcpy(pDst + dst_pitch, pDst, dst_width*2); |
| oscl_memcpy(pDst + dst_pitch*2, pDst, dst_width*2); |
| } |
| |
| pDst += dst_pitch * (_mColPix[row-1] + _mColPix[row]); |
| } |
| return 1; |
| #else |
| return 0; |
| #endif // CCSCALING |
| } |
| #endif // USE_ARM_ASM_FOR_COLORCONVERT |
| |
| |
| // platform specfic function in C |
| int32 cc12sc_rotate(uint8 **src, uint8 *dst, int *disp, |
| uint8 *clip, uint8 *pErr_horz, |
| uint8 *_mRowPix, uint8 *_mColPix, |
| bool _mIsRotateClkwise); |
| |
| int32 ColorConvert12::cc12ZoomRotate(uint8 **src, uint8 *dst, |
| DisplayProperties *disp, uint8 *clip, uint8 *pErr_horz) |
| { |
| int disp_prop[6]; |
| |
| disp_prop[0] = disp->src_pitch; |
| disp_prop[1] = disp->dst_pitch; |
| disp_prop[2] = disp->src_width; |
| disp_prop[3] = disp->src_height; |
| disp_prop[4] = disp->dst_width; |
| disp_prop[5] = disp->dst_height; |
| |
| return cc12sc_rotate(src, dst, disp_prop, clip, pErr_horz, _mRowPix, _mColPix, (_mRotation == CCROTATE_CLKWISE)); |
| } |
| |
| |
| #if USE_ARM_ASM_FOR_COLORCONVERT |
| ///////////////////////////////////////////////////////////////////////////// |
| // Note:: This zoom algorithm needs an extra line of RGB buffer. So, users |
| // have to use GetRGBBufferSize API to get the size it needs. See GetRGBBufferSize(). |
| int32 cc12sc_rotate(uint8 **src, uint8 *dst, int *disp, |
| uint8 *clip, uint8 *pErr_horz, |
| uint8 *_mRowPix, uint8 *_mColPix, |
| bool _mIsRotateClkwise) |
| { |
| #if (CCROTATE && CCSCALING) |
| { |
| asm("STMFD sp!,{r0-r11,lr}"); |
| asm("SUB sp,sp,#0x4c"); |
| asm("MOV lr,r0"); |
| asm("MOV r0,r1"); |
| asm("LDR r1,[sp,#0x54]"); |
| asm("LDR r9,[sp,#0x84]"); |
| asm("LDR r11,[sp,#0x8c]"); |
| asm("LDR r2,[r1,#8]"); |
| asm("LDR r4,[r1,#4]"); |
| asm("LDR r10,[r1,#0]"); |
| asm("LDR r1,[r1,#0x10]"); |
| asm("MOV r5,r3"); |
| asm("STR r1,[sp,#0x24]"); |
| asm("LDMIA lr,{r6,r12}"); |
| asm("LDR r3,[lr,#8]"); |
| asm("LDR r1,[sp,#0x54]"); |
| asm("MOV r7,#1"); |
| asm("LDR lr,[r1,#0]"); |
| asm("LDR r1,[r1,#0xc]"); |
| asm("CMP r11,#0"); |
| asm("MUL r8,lr,r1"); |
| asm("ADD r7,r7,r8,ASR #2"); |
| asm("ADD r8,r8,#2"); |
| asm("STRNE r8,[sp,#0x28]"); |
| asm("STRNE r7,[sp,#0x20]"); |
| asm("MOV lr,lr,ASR #1"); |
| asm("BNE L1.4940"); |
| asm("RSB r8,r8,#0"); |
| asm("RSB r7,r7,#0"); |
| asm("STR r7,[sp,#0x20]"); |
| asm("STR r8,[sp,#0x28]"); |
| asm("L1.4940:"); |
| asm("BEQ L1.4972"); |
| asm("SUB r7,r1,#1"); |
| asm("MLA r6,r7,r10,r6"); |
| asm("MVN r7,#0"); |
| asm("ADD r1,r7,r1,ASR #1"); |
| asm("MLA r7,r1,lr,r12"); |
| asm("MLA r8,r1,lr,r3"); |
| asm("B L1.4996"); |
| asm("L1.4972:"); |
| asm("ADD r1,r6,r2"); |
| asm("SUB r6,r1,#1"); |
| asm("ADD r1,r12,r2,ASR #1"); |
| asm("SUB r7,r1,#1"); |
| asm("ADD r1,r3,r2,ASR #1"); |
| asm("SUB r8,r1,#1"); |
| asm("L1.4996:"); |
| asm("BEQ L1.5028"); |
| asm("RSB lr,lr,#0"); |
| asm("MOV r3,#1"); |
| asm("ADD r1,sp,#8"); |
| asm("STMIA r1,{r3,lr}"); |
| asm("RSB r10,r10,#0"); |
| asm("STR r10,[sp,#4]"); |
| asm("B L1.5044"); |
| asm("L1.5028:"); |
| asm("MVN r3,#0"); |
| asm("ADD r1,sp,#8"); |
| asm("STMIA r1,{r3,lr}"); |
| asm("STR r10,[sp,#4]"); |
| asm("L1.5044:"); |
| asm("SUB r2,r2,#1"); |
| asm("STR r2,[sp,#0x1c]"); |
| asm("CMP r2,#0"); |
| asm("BLE L1.6816"); |
| asm("LDR r1,[sp,#0x24]"); |
| asm("MOV r1,r1,LSL #1"); |
| asm("STR r1,[sp,#0x48]"); |
| asm("L1.5072:"); |
| asm("LDR r1,[sp,#0x88]"); |
| asm("LDR r2,[sp,#0x1c]"); |
| asm("ADD r1,r1,r2"); |
| asm("STR r1,[sp,#0x44]"); |
| asm("LDRB r1,[r1,#-1]"); |
| asm("CMP r1,#0"); |
| asm("BNE L1.5140"); |
| asm("LDR r1,[sp,#0x88]"); |
| asm("LDR r2,[sp,#0x1c]"); |
| asm("LDRB r1,[r1,r2]"); |
| asm("CMP r1,#0"); |
| asm("BNE L1.5140"); |
| asm("LDR r3,[sp,#8]"); |
| asm("ADD r7,r7,r3"); |
| asm("ADD r8,r8,r3"); |
| asm("ADD r6,r6,r3,LSL #1"); |
| asm("B L1.6796"); |
| asm("L1.5140:"); |
| asm("LDR r1,[sp,#0x54]"); |
| asm("MOV r2,#0"); |
| asm("LDR r1,[r1,#0xc]"); |
| asm("MOV r12,r2"); |
| asm("SUBS r1,r1,#2"); |
| asm("BMI L1.6504"); |
| asm("L1.5164:"); |
| asm("LDRB r3,[r7,#0]"); |
| asm("LDR lr,[sp,#0xc]"); |
| asm("LDRB r10,[r8],lr"); |
| asm("SUB r3,r3,#0x80"); |
| asm("STR r3,[sp,#0x30]"); |
| asm("ADD r7,r7,lr"); |
| asm("MOV lr,#0xce"); |
| asm("SUB r3,r10,#0x80"); |
| asm("ADD lr,lr,#0xb200"); |
| asm("MUL r11,lr,r3"); |
| asm("LDR lr,[sp,#0x30]"); |
| asm("MOV r10,#0xff"); |
| asm("ADD r10,r10,#0x2a00"); |
| asm("MUL lr,r10,lr"); |
| asm("LDR r10,L1.6824"); |
| asm("ADD lr,r11,lr,LSL #1"); |
| asm("MUL r11,r10,r3"); |
| asm("LDR r3,[sp,#0x30]"); |
| asm("LDR r10,L1.6828"); |
| asm("STR r11,[sp,#0x2c]"); |
| asm("MUL r11,r10,r3"); |
| asm("STR r11,[sp,#0x30]"); |
| asm("LDRB r3,[r9,r1]"); |
| asm("CMP r3,#0"); |
| asm("LDREQ r10,[sp,#4]"); |
| asm("ADDEQ r6,r6,r10"); |
| asm("BEQ L1.5880"); |
| asm("LDR r3,[sp,#8]"); |
| asm("TST r0,#3"); |
| asm("LDRB r10,[r6,r3]"); |
| asm("RSB r11,lr,r10,LSL #16"); |
| asm("STR r11,[sp,#0x14]"); |
| asm("LDR r11,[sp,#0x30]"); |
| asm("ADD r3,r11,r10,LSL #16"); |
| asm("LDR r11,[sp,#0x2c]"); |
| asm("ADD r11,r11,r10,LSL #16"); |
| asm("AND r10,r12,#0xff"); |
| asm("ADD r11,r11,r10,LSL #16"); |
| asm("MOV r10,#0xff0000"); |
| asm("AND r10,r10,r12,LSL #8"); |
| asm("STR r11,[sp,#0x18]"); |
| asm("LDR r11,[sp,#0x14]"); |
| asm("AND r12,r12,#0xff0000"); |
| asm("ADD r11,r10,r11"); |
| asm("LDR r10,[sp,#0x80]"); |
| asm("STR r11,[sp,#0x14]"); |
| asm("ADD r12,r12,r3"); |
| asm("LDR r3,[r10,r1,LSL #2]"); |
| asm("LDR r11,[sp,#0x18]"); |
| asm("AND r10,r3,#0xff"); |
| asm("ADD r10,r11,r10,LSL #16"); |
| asm("STR r10,[sp,#0x18]"); |
| asm("MOV r10,#0xff0000"); |
| asm("AND r10,r10,r3,LSL #8"); |
| asm("AND r3,r3,#0xff0000"); |
| asm("ADD r3,r3,r12"); |
| asm("LDR r11,[sp,#0x14]"); |
| asm("LDR r12,[sp,#0x18]"); |
| asm("ADD r10,r10,r11"); |
| asm("LDRB r11,[r5,r12,ASR #16]"); |
| asm("STR r11,[sp,#0x18]"); |
| asm("LDRB r10,[r5,r10,ASR #16]"); |
| asm("LDRB r12,[r5,r3,ASR #16]"); |
| asm("AND r3,r11,#0xf0"); |
| asm("MOV r11,r3,LSL #4"); |
| asm("AND r3,r10,#0xf0"); |
| asm("ORR r3,r3,r11"); |
| asm("LDR r11,[sp,#0x18]"); |
| asm("AND r10,r10,#0xe"); |
| asm("AND r11,r11,#0xe"); |
| asm("MOV r11,r11,LSR #1"); |
| asm("STR r11,[sp,#0x18]"); |
| asm("MOV r11,r10,LSR #1"); |
| asm("ORR r3,r3,r12,ASR #4"); |
| asm("AND r12,r12,#0xe"); |
| asm("STR r11,[sp,#0x14]"); |
| asm("MOV r11,r12,LSR #1"); |
| asm("STR r11,[sp,#0x10]"); |
| asm("LDR r11,[sp,#0x18]"); |
| asm("LDR r12,[sp,#0x14]"); |
| asm("ORR r12,r11,r12,LSL #8"); |
| asm("LDR r11,[sp,#0x10]"); |
| asm("LDRB r10,[r6,#0]"); |
| asm("ORR r12,r12,r11,LSL #16"); |
| asm("STR r10,[sp,#0x34]"); |
| asm("LDR r10,[sp,#4]"); |
| asm("LDR r11,[sp,#0x14]"); |
| asm("ADD r6,r6,r10"); |
| asm("LDR r10,[sp,#0x34]"); |
| asm("RSB r10,lr,r10,LSL #16"); |
| asm("ADD r10,r10,r11,LSL #16"); |
| asm("STR r10,[sp,#0x14]"); |
| asm("LDR r10,[sp,#0x34]"); |
| asm("LDR r11,[sp,#0x30]"); |
| asm("ADD r10,r11,r10,LSL #16"); |
| asm("LDR r11,[sp,#0x10]"); |
| asm("ADD r10,r10,r11,LSL #16"); |
| asm("STR r10,[sp,#0x10]"); |
| asm("LDR r10,[sp,#0x34]"); |
| asm("LDR r11,[sp,#0x2c]"); |
| asm("ADD r10,r11,r10,LSL #16"); |
| asm("LDR r11,[sp,#0x18]"); |
| asm("ADD r10,r10,r11,LSL #16"); |
| asm("AND r11,r2,#0xff"); |
| asm("ADD r10,r10,r11,LSL #16"); |
| asm("STR r10,[sp,#0x18]"); |
| asm("MOV r10,#0xff0000"); |
| asm("AND r11,r10,r2,LSL #8"); |
| asm("LDR r10,[sp,#0x14]"); |
| asm("AND r2,r2,#0xff0000"); |
| asm("ADD r11,r11,r10"); |
| asm("LDR r10,[sp,#0x10]"); |
| asm("ADD r2,r2,r10"); |
| asm("LDR r10,[sp,#0x18]"); |
| asm("LDRB r10,[r5,r10,ASR #16]"); |
| asm("STR r10,[sp,#0x18]"); |
| asm("LDRB r11,[r5,r11,ASR #16]"); |
| asm("LDRB r10,[r5,r2,ASR #16]"); |
| asm("STR r10,[sp,#0x10]"); |
| asm("LDR r10,[sp,#0x18]"); |
| asm("MOV r2,r10,LSL #28"); |
| asm("MOV r2,r2,LSR #29"); |
| asm("AND r10,r11,#0xe"); |
| asm("ORR r2,r2,r10,LSL #7"); |
| asm("LDR r10,[sp,#0x10]"); |
| asm("AND r11,r11,#0xf0"); |
| asm("AND r10,r10,#0xe"); |
| asm("ORR r2,r2,r10,LSL #15"); |
| asm("LDR r10,[sp,#0x80]"); |
| asm("STR r2,[r10,r1,LSL #2]"); |
| asm("LDR r10,[sp,#0x18]"); |
| asm("AND r10,r10,#0xf0"); |
| asm("MOV r10,r10,LSL #4"); |
| asm("STR r10,[sp,#0x18]"); |
| asm("ORR r10,r11,r10"); |
| asm("LDR r11,[sp,#0x10]"); |
| asm("ORR r10,r10,r11,ASR #4"); |
| asm("LDRB r11,[r9,r1]"); |
| asm("BEQ L1.5804"); |
| asm("CMP r11,#2"); |
| asm("BNE L1.5752"); |
| asm("ADD r11,r0,r4,LSL #1"); |
| asm("STRH r3,[r11,#0]"); |
| asm("STRH r3,[r11,#2]"); |
| asm("STRH r10,[r0,#0]"); |
| asm("STRH r10,[r0,#2]"); |
| asm("B L1.5880"); |
| asm("L1.5752:"); |
| asm("CMP r11,#3"); |
| asm("ADD r11,r0,r4,LSL #1"); |
| asm("STRNEH r3,[r11,#0]"); |
| asm("STRNEH r10,[r0,#0]"); |
| asm("BNE L1.5880"); |
| asm("STRH r3,[r11],#2"); |
| asm("ORR r3,r3,r3,LSL #16"); |
| asm("STR r3,[r11,#0]"); |
| asm("STRH r10,[r0,#0]"); |
| asm("ORR r3,r10,r10,LSL #16"); |
| asm("MOV r10,#2"); |
| asm("STR r3,[r10,r0]"); |
| asm("B L1.5880"); |
| asm("L1.5804:"); |
| asm("CMP r11,#2"); |
| asm("BNE L1.5832"); |
| asm("ORR r3,r3,r3,LSL #16"); |
| asm("STR r3,[r0,r4,LSL #1]"); |
| asm("ORR r3,r10,r10,LSL #16"); |
| asm("STR r3,[r0,#0]"); |
| asm("B L1.5880"); |
| asm("L1.5832:"); |
| asm("CMP r11,#3"); |
| asm("ADDNE r11,r0,r4,LSL #1"); |
| asm("STRNEH r3,[r11,#0]"); |
| asm("STRNEH r10,[r0,#0]"); |
| asm("BNE L1.5880"); |
| asm("ORR r11,r3,r3,LSL #16"); |
| asm("STR r11,[r0,r4,LSL #1]"); |
| asm("ADD r11,r0,r4,LSL #1"); |
| asm("STRH r3,[r11,#4]"); |
| asm("ORR r3,r10,r10,LSL #16"); |
| asm("STR r3,[r0,#0]"); |
| asm("STRH r10,[r0,#4]"); |
| asm("L1.5880:"); |
| asm("LDRB r3,[r9,r1]"); |
| asm("ADD r0,r0,r3,LSL #1"); |
| asm("ADD r3,r9,r1"); |
| asm("STR r3,[sp,#0x40]"); |
| asm("LDRB r3,[r3,#1]"); |
| asm("CMP r3,#0"); |
| asm("LDREQ r10,[sp,#4]"); |
| asm("ADDEQ r6,r6,r10"); |
| asm("BEQ L1.6484"); |
| asm("LDR r3,[sp,#8]"); |
| asm("TST r0,#3"); |
| asm("LDRB r10,[r6,r3]"); |
| asm("RSB r11,lr,r10,LSL #16"); |
| asm("STR r11,[sp,#0x14]"); |
| asm("LDR r11,[sp,#0x30]"); |
| asm("ADD r3,r11,r10,LSL #16"); |
| asm("LDR r11,[sp,#0x2c]"); |
| asm("ADD r11,r11,r10,LSL #16"); |
| asm("AND r10,r12,#0xff"); |
| asm("ADD r11,r11,r10,LSL #16"); |
| asm("MOV r10,#0xff0000"); |
| asm("AND r10,r10,r12,LSL #8"); |
| asm("STR r11,[sp,#0x18]"); |
| asm("LDR r11,[sp,#0x14]"); |
| asm("AND r12,r12,#0xff0000"); |
| asm("ADD r11,r10,r11"); |
| asm("LDR r10,[sp,#0x80]"); |
| asm("ADD r12,r12,r3"); |
| asm("ADD r3,r10,r1,LSL #2"); |
| asm("STR r3,[sp,#0x3c]"); |
| asm("STR r11,[sp,#0x14]"); |
| asm("LDR r3,[r3,#4]"); |
| asm("LDR r11,[sp,#0x18]"); |
| asm("AND r10,r3,#0xff"); |
| asm("ADD r10,r11,r10,LSL #16"); |
| asm("STR r10,[sp,#0x18]"); |
| asm("MOV r10,#0xff0000"); |
| asm("AND r10,r10,r3,LSL #8"); |
| asm("AND r3,r3,#0xff0000"); |
| asm("ADD r3,r3,r12"); |
| asm("LDR r11,[sp,#0x14]"); |
| asm("LDR r12,[sp,#0x18]"); |
| asm("ADD r10,r10,r11"); |
| asm("LDRB r11,[r5,r12,ASR #16]"); |
| asm("STR r11,[sp,#0x18]"); |
| asm("LDRB r10,[r5,r10,ASR #16]"); |
| asm("LDRB r12,[r5,r3,ASR #16]"); |
| asm("AND r3,r11,#0xf0"); |
| asm("AND r11,r10,#0xf0"); |
| asm("ORR r3,r11,r3,LSL #4"); |
| asm("LDR r11,[sp,#0x18]"); |
| asm("ORR r3,r3,r12,ASR #4"); |
| asm("AND r11,r11,#0xe"); |
| asm("MOV r11,r11,LSR #1"); |
| asm("STR r11,[sp,#0x18]"); |
| asm("AND r10,r10,#0xe"); |
| asm("MOV r11,r10,LSR #1"); |
| asm("AND r12,r12,#0xe"); |
| asm("MOV r10,r12,LSR #1"); |
| asm("LDR r12,[sp,#0x18]"); |
| asm("STR r10,[sp,#0x10]"); |
| asm("ORR r12,r12,r11,LSL #8"); |
| asm("ORR r12,r12,r10,LSL #16"); |
| asm("LDRB r10,[r6,#0]"); |
| asm("STR r10,[sp,#0x34]"); |
| asm("LDR r10,[sp,#4]"); |
| asm("ADD r6,r6,r10"); |
| asm("LDR r10,[sp,#0x34]"); |
| asm("RSB lr,lr,r10,LSL #16"); |
| asm("ADD lr,lr,r11,LSL #16"); |
| asm("STR lr,[sp,#0x14]"); |
| asm("LDR lr,[sp,#0x30]"); |
| asm("ADD lr,lr,r10,LSL #16"); |
| asm("LDR r10,[sp,#0x10]"); |
| asm("ADD r11,lr,r10,LSL #16"); |
| asm("LDR lr,[sp,#0x2c]"); |
| asm("LDR r10,[sp,#0x34]"); |
| asm("ADD lr,lr,r10,LSL #16"); |
| asm("LDR r10,[sp,#0x18]"); |
| asm("ADD lr,lr,r10,LSL #16"); |
| asm("AND r10,r2,#0xff"); |
| asm("ADD lr,lr,r10,LSL #16"); |
| asm("STR lr,[sp,#0x18]"); |
| asm("LDR lr,[sp,#0x14]"); |
| asm("MOV r10,#0xff0000"); |
| asm("AND r10,r10,r2,LSL #8"); |
| asm("ADD r10,r10,lr"); |
| asm("LDR lr,[sp,#0x18]"); |
| asm("AND r2,r2,#0xff0000"); |
| asm("LDRB lr,[r5,lr,ASR #16]"); |
| asm("ADD r2,r2,r11"); |
| asm("STR lr,[sp,#0x18]"); |
| asm("LDRB lr,[r5,r10,ASR #16]"); |
| asm("LDRB r10,[r5,r2,ASR #16]"); |
| asm("LDR r2,[sp,#0x18]"); |
| asm("AND r11,lr,#0xe"); |
| asm("MOV r2,r2,LSL #28"); |
| asm("MOV r2,r2,LSR #29"); |
| asm("ORR r2,r2,r11,LSL #7"); |
| asm("AND r11,r10,#0xe"); |
| asm("ORR r2,r2,r11,LSL #15"); |
| asm("LDR r11,[sp,#0x3c]"); |
| asm("AND lr,lr,#0xf0"); |
| asm("STR r2,[r11,#4]"); |
| asm("LDR r11,[sp,#0x18]"); |
| asm("AND r11,r11,#0xf0"); |
| asm("ORR lr,lr,r11,LSL #4"); |
| asm("ORR lr,lr,r10,ASR #4"); |
| asm("LDR r10,[sp,#0x40]"); |
| asm("LDRB r10,[r10,#1]"); |
| asm("BEQ L1.6408"); |
| asm("CMP r10,#2"); |
| asm("BNE L1.6356"); |
| asm("ADD r10,r0,r4,LSL #1"); |
| asm("STRH r3,[r10,#0]"); |
| asm("STRH r3,[r10,#2]"); |
| asm("STRH lr,[r0,#0]"); |
| asm("STRH lr,[r0,#2]"); |
| asm("B L1.6484"); |
| asm("L1.6356:"); |
| asm("CMP r10,#3"); |
| asm("ADD r10,r0,r4,LSL #1"); |
| asm("STRNEH r3,[r10,#0]"); |
| asm("STRNEH lr,[r0,#0]"); |
| asm("BNE L1.6484"); |
| asm("STRH r3,[r10],#2"); |
| asm("ORR r3,r3,r3,LSL #16"); |
| asm("STR r3,[r10,#0]"); |
| asm("STRH lr,[r0,#0]"); |
| asm("ORR r3,lr,lr,LSL #16"); |
| asm("MOV lr,#2"); |
| asm("STR r3,[lr,r0]"); |
| asm("B L1.6484"); |
| asm("L1.6408:"); |
| asm("CMP r10,#2"); |
| asm("BNE L1.6436"); |
| asm("ORR r3,r3,r3,LSL #16"); |
| asm("STR r3,[r0,r4,LSL #1]"); |
| asm("ORR r3,lr,lr,LSL #16"); |
| asm("STR r3,[r0,#0]"); |
| asm("B L1.6484"); |
| asm("L1.6436:"); |
| asm("CMP r10,#3"); |
| asm("ADDNE r10,r0,r4,LSL #1"); |
| asm("STRNEH r3,[r10,#0]"); |
| asm("STRNEH lr,[r0,#0]"); |
| asm("BNE L1.6484"); |
| asm("ORR r10,r3,r3,LSL #16"); |
| asm("STR r10,[r0,r4,LSL #1]"); |
| asm("ADD r10,r0,r4,LSL #1"); |
| asm("STRH r3,[r10,#4]"); |
| asm("ORR r3,lr,lr,LSL #16"); |
| asm("STR r3,[r0,#0]"); |
| asm("STRH lr,[r0,#4]"); |
| asm("L1.6484:"); |
| asm("LDR r3,[sp,#0x40]"); |
| asm("SUBS r1,r1,#2"); |
| asm("LDRB r3,[r3,#1]"); |
| asm("ADD r0,r0,r3,LSL #1"); |
| asm("BPL L1.5164"); |
| asm("L1.6504:"); |
| asm("LDR r1,[sp,#0x28]"); |
| asm("LDR r2,[sp,#0x1c]"); |
| asm("ADD r6,r6,r1"); |
| asm("LDR r1,[sp,#0x20]"); |
| asm("ADD r7,r7,r1"); |
| asm("ADD r8,r8,r1"); |
| asm("LDR r1,[sp,#0x24]"); |
| asm("SUB r10,r0,r1,LSL #1"); |
| asm("LDR r1,[sp,#0x88]"); |
| asm("LDRB r0,[r1,r2]"); |
| asm("LDR r1,[sp,#0x44]"); |
| asm("LDRB r1,[r1,#-1]"); |
| asm("MUL r11,r4,r0"); |
| asm("CMP r1,#0"); |
| asm("BEQ L1.6684"); |
| asm("CMP r0,#1"); |
| asm("BEQ L1.6588"); |
| asm("ADD r1,r10,r4,LSL #1"); |
| asm("ADD r0,r10,r11,LSL #1"); |
| asm("LDR r2,[sp,#0x48]"); |
| asm("BL memcpy"); |
| asm("L1.6588:"); |
| asm("LDR r1,[sp,#0x44]"); |
| asm("LDRB r0,[r1,#-1]"); |
| asm("CMP r0,#2"); |
| asm("BNE L1.6628"); |
| asm("ADD r0,r10,r11,LSL #1"); |
| asm("ADD r0,r0,r4,LSL #1"); |
| asm("ADD r1,r10,r4,LSL #1"); |
| asm("LDR r2,[sp,#0x48]"); |
| asm("BL memcpy"); |
| asm("B L1.6684"); |
| asm("L1.6628:"); |
| asm("CMP r0,#3"); |
| asm("BNE L1.6684"); |
| asm("ADD r0,r10,r11,LSL #1"); |
| asm("STR r0,[sp,#0x38]"); |
| asm("ADD r11,r10,r4,LSL #1"); |
| asm("MOV r1,r11"); |
| asm("ADD r0,r0,r4,LSL #1"); |
| asm("LDR r2,[sp,#0x48]"); |
| asm("BL memcpy"); |
| asm("LDR r0,[sp,#0x38]"); |
| asm("MOV r1,r11"); |
| asm("LDR r2,[sp,#0x48]"); |
| asm("ADD r0,r0,r4,LSL #2"); |
| asm("BL memcpy"); |
| asm("L1.6684:"); |
| asm("LDR r1,[sp,#0x88]"); |
| asm("LDR r2,[sp,#0x1c]"); |
| asm("LDRB r0,[r1,r2]"); |
| asm("CMP r0,#2"); |
| asm("BNE L1.6724"); |
| asm("ADD r0,r10,r4,LSL #1"); |
| asm("MOV r1,r10"); |
| asm("LDR r2,[sp,#0x48]"); |
| asm("BL memcpy"); |
| asm("B L1.6764"); |
| asm("L1.6724:"); |
| asm("CMP r0,#3"); |
| asm("BNE L1.6764"); |
| asm("ADD r0,r10,r4,LSL #1"); |
| asm("MOV r1,r10"); |
| asm("LDR r2,[sp,#0x48]"); |
| asm("BL memcpy"); |
| asm("ADD r0,r10,r4,LSL #2"); |
| asm("MOV r1,r10"); |
| asm("LDR r2,[sp,#0x48]"); |
| asm("BL memcpy"); |
| asm("L1.6764:"); |
| asm("LDR r1,[sp,#0x44]"); |
| asm("LDRB r0,[r1,#-1]"); |
| asm("LDR r1,[sp,#0x88]"); |
| asm("LDR r2,[sp,#0x1c]"); |
| asm("LDRB r1,[r1,r2]"); |
| asm("ADD r0,r0,r1"); |
| asm("MUL r0,r4,r0"); |
| asm("ADD r0,r10,r0,LSL #1"); |
| asm("L1.6796:"); |
| asm("LDR r2,[sp,#0x1c]"); |
| asm("SUB r2,r2,#2"); |
| asm("STR r2,[sp,#0x1c]"); |
| asm("CMP r2,#0"); |
| asm("BGT L1.5072"); |
| asm("L1.6816:"); |
| asm("ADD sp,sp,#0x5c"); |
| asm("LDMFD sp!,{r4-r11,lr}"); |
| asm("MOV r0,#1"); |
| // asm("BX lr"); |
| asm("L1.6820:"); |
| asm(".align 0"); |
| asm("L1.6824:"); |
| asm(".word 0x00015f03"); |
| asm("L1.6828:"); |
| asm(".word 0x0001bbd2"); |
| |
| } |
| return 1; |
| #else |
| return 0; |
| #endif // defined(CCROTATE) && defined(CCSCALING) |
| } |
| |
| #else // straight C version |
| |
| ///////////////////////////////////////////////////////////////////////////// |
| // Note:: This zoom algorithm needs an extra line of RGB buffer. So, users |
| // have to use GetRGBBufferSize API to get the size it needs. See GetRGBBufferSize(). |
| int32 cc12sc_rotate(uint8 **src, uint8 *dst, int *disp, |
| uint8 *clip, uint8 *pErr_horz, |
| uint8 *_mRowPix, uint8 *_mColPix, |
| bool _mIsRotateClkwise) |
| { |
| #if (CCROTATE && CCSCALING) |
| const static uint32 JCoeff[4] = |
| { |
| 45774, //65536*0.813/1.164; |
| 89859, //65536*1.596/1.164; |
| 22014, //65536*0.391/1.164; |
| 113618 //65536*2.018/1.164; |
| }; |
| |
| uint8 *pCb, *pCr, *pY; |
| uint16 *pDst; |
| int32 src_pitch, dst_pitch, src_width; |
| int32 Y, Cb, Cr, Cg; |
| uint32 left_err_t, left_err_b; /* error from the left pixels */ |
| uint32 top_err_l, top_err_r; /* error from the top pixels */ |
| int32 deltaY, dst_width, deltaCbCr; |
| int32 row, col; |
| int32 tmp0, tmp1, tmp2; |
| uint32 rgb; |
| int32 offset; |
| |
| |
| src_pitch = disp[0]; |
| dst_pitch = disp[1]; |
| src_width = disp[2]; |
| dst_width = disp[4]; |
| |
| if (_mIsRotateClkwise) |
| { |
| deltaY = src_pitch * disp[3] + 2; |
| deltaCbCr = ((src_pitch * disp[3]) >> 2) + 1; |
| } |
| else // rotate counterclockwise |
| { |
| deltaY = -(src_pitch * disp[3] + 2); |
| deltaCbCr = -(((src_pitch * disp[3]) >> 2) + 1); |
| } |
| |
| // map origin of the destination to the source |
| if (_mIsRotateClkwise) |
| { |
| pY = src[0] + src_pitch * (disp[3] - 1); |
| pCb = src[1] + ((src_pitch >> 1) * ((disp[3] >> 1) - 1)); |
| pCr = src[2] + ((src_pitch >> 1) * ((disp[3] >> 1) - 1)); |
| } |
| else // rotate counterclockwise |
| { |
| pY = src[0] + src_width - 1; |
| pCb = src[1] + (src_width >> 1) - 1; |
| pCr = src[2] + (src_width >> 1) - 1; |
| } |
| |
| pDst = (uint16 *)dst; |
| |
| int half_src_pitch, read_idx, tmp_src_pitch; |
| if (_mIsRotateClkwise) |
| { |
| half_src_pitch = -(src_pitch >> 1); |
| read_idx = 1; |
| tmp_src_pitch = -src_pitch; |
| } |
| else // rotate counterclockwise |
| { |
| half_src_pitch = (src_pitch >> 1); |
| read_idx = -1; |
| tmp_src_pitch = src_pitch; |
| } |
| |
| for (row = src_width - 1; row > 0; row -= 2) |
| { /* decrement index, _mColPix[.] is |
| symmetric to increment index */ |
| |
| if ((_mColPix[row-1] == 0) && (_mColPix[row] == 0)) |
| { |
| pCb += read_idx; |
| pCr += read_idx; |
| pY += (read_idx * 2); |
| continue; |
| } |
| |
| left_err_t = left_err_b = 0; /* reset left pixel errors */ |
| |
| for (col = disp[3] - 2; col >= 0; col -= 2) |
| {/* decrement index, _mRowPix[.] is |
| symmetric to increment index */ |
| |
| Cb = *pCb; |
| pCb += half_src_pitch; |
| Cr = *pCr; |
| pCr += half_src_pitch; |
| |
| //Cb = *pCb++; Cr = *pCr++; |
| |
| //load the bottom two pixels |
| //Y = *(((uint16 *)pY)+src_pitch); |
| //Y = *((uint16 *)(((uint16 *)pY) + src_pitch)); |
| |
| Cb -= 128; |
| Cr -= 128; |
| Cg = Cr * JCoeff[0]; |
| Cg += Cb * JCoeff[2]; |
| |
| Cr *= JCoeff[1]; |
| Cb *= JCoeff[3]; |
| |
| if (_mRowPix[col]) /* compute this pixel */ |
| { |
| //tmp0 = pY[src_pitch]; //bottom left |
| |
| tmp0 = pY[read_idx]; |
| |
| tmp1 = (tmp0 << 16) - Cg; |
| tmp2 = (tmp0 << 16) + Cb; |
| tmp0 = (tmp0 << 16) + Cr; |
| |
| //add the error from top and left |
| tmp0 += ((left_err_b & 0xFF) << 16);// err_vert[0]; |
| tmp1 += (((left_err_b >> 8) & 0xFF) << 16);//err_vert[1]; |
| tmp2 += (((left_err_b >> 16) & 0xFF) << 16);//err_vert[2]; |
| |
| top_err_l = *((uint*)(pErr_horz + (col << 2))); |
| tmp0 += ((top_err_l & 0xFF) << 16);//pErr_horz[col]; |
| tmp1 += (((top_err_l >> 8) & 0xFF) << 16);//mErr_horz[1][col]; |
| tmp2 += (((top_err_l >> 16) & 0xFF) << 16);//mErr_horz[2][col]; |
| |
| tmp0 = clip[tmp0>>16]; |
| tmp1 = clip[tmp1>>16]; |
| tmp2 = clip[tmp2>>16]; |
| #ifdef OUTPUT_RGB_565 |
| //RGB_565 |
| rgb = (tmp0 >> 3); |
| rgb = (tmp1 >> 2) | (rgb << 6); |
| rgb = (tmp2 >> 3) | (rgb << 5); |
| #else |
| //RGB_444 |
| rgb = (tmp0 & 0xF0) << 4; |
| rgb |= (tmp1 & 0xF0); |
| rgb |= (tmp2 >> 4); |
| #endif |
| tmp0 &= 0xE; |
| tmp1 &= 0xE; |
| tmp2 &= 0xE; |
| tmp0 >>= 1; |
| tmp1 >>= 1; |
| tmp2 >>= 1; |
| |
| //save error |
| left_err_b = tmp0 | (tmp1 << 8) | (tmp2 << 16); // = top_err_l also |
| |
| //Y = *pY++; //upper left |
| Y = *pY; |
| pY += tmp_src_pitch; |
| |
| // error from the top already available |
| tmp1 = (Y << 16) - Cg + (tmp1 << 16); |
| tmp2 = (Y << 16) + Cb + (tmp2 << 16); |
| tmp0 = (Y << 16) + Cr + (tmp0 << 16); |
| |
| //add the error from left |
| tmp0 += ((left_err_t & 0xFF) << 16);// err_vert[3]; |
| tmp1 += (((left_err_t >> 8) & 0xFF) << 16);//err_vert[4]; |
| tmp2 += (((left_err_t >> 16) & 0xFF) << 16);//err_vert[5]; |
| |
| tmp0 = clip[tmp0>>16]; |
| tmp1 = clip[tmp1>>16]; |
| tmp2 = clip[tmp2>>16]; |
| |
| //save error |
| left_err_t = ((tmp0 & 0xE) >> 1) | ((tmp1 & 0xE) << 7) | ((tmp2 & 0xE) << 15); //= top_err_l also |
| *((uint*)(pErr_horz + (col << 2))) = left_err_t; // =top_err_l; |
| |
| #ifdef OUTPUT_RGB_565 |
| //RGB_565 |
| tmp0 = (tmp0 >> 3); |
| tmp0 = (tmp1 >> 2) | (tmp0 << 6); |
| tmp0 = (tmp2 >> 3) | (tmp0 << 5); |
| #else |
| //RGB_444 |
| tmp0 = (tmp0 & 0xF0) << 4; |
| tmp0 |= (tmp1 & 0xF0); |
| tmp0 |= (tmp2 >> 4); |
| #endif |
| if (((uint)pDst) & 3) //half word aligned |
| { |
| if (_mRowPix[col] == 2) |
| { |
| *(pDst + dst_pitch) = rgb; |
| *(pDst + dst_pitch + 1) = rgb; |
| *(pDst) = tmp0; |
| *(pDst + 1) = tmp0; |
| } |
| else if (_mRowPix[col] == 3) |
| { |
| *(pDst + dst_pitch) = rgb; |
| *((uint*)(pDst + dst_pitch + 1)) = rgb | (rgb << 16); |
| |
| *(pDst) = tmp0; |
| *((uint*)(pDst + 1)) = tmp0 | (tmp0 << 16); |
| } |
| else |
| { |
| *(pDst + dst_pitch) = rgb; |
| *(pDst) = tmp0; |
| } |
| } |
| else //word aligned |
| { |
| if (_mRowPix[col] == 2) |
| { |
| *((uint*)(pDst + dst_pitch)) = rgb | (rgb << 16); |
| *((uint*)(pDst)) = tmp0 | (tmp0 << 16); |
| } |
| else if (_mRowPix[col] == 3) |
| { |
| *((uint*)(pDst + dst_pitch)) = rgb | (rgb << 16); |
| *(pDst + dst_pitch + 2) = rgb; |
| |
| *((uint*)(pDst)) = tmp0 | (tmp0 << 16); |
| *(pDst + 2) = tmp0; |
| } |
| else |
| { |
| *(pDst + dst_pitch) = rgb; |
| *(pDst) = tmp0; |
| } |
| } |
| } /* if(_mRowPix[col]) */ |
| else |
| { |
| |
| pY += tmp_src_pitch; |
| } |
| pDst += _mRowPix[col]; |
| |
| if (_mRowPix[col+1]) /* compute this pixel */ |
| { |
| //load the top two pixels |
| //Y = *((uint16 *)pY)++; |
| |
| tmp0 = pY[read_idx]; |
| //tmp0 = pY[src_pitch]; //bottom right |
| |
| tmp1 = (tmp0 << 16) - Cg; |
| tmp2 = (tmp0 << 16) + Cb; |
| tmp0 = (tmp0 << 16) + Cr; |
| |
| //add the error from top and left |
| tmp0 += ((left_err_b & 0xFF) << 16);// err_vert[0]; |
| tmp1 += (((left_err_b >> 8) & 0xFF) << 16);//err_vert[1]; |
| tmp2 += (((left_err_b >> 16) & 0xFF) << 16);//err_vert[2]; |
| |
| top_err_r = *((uint*)(pErr_horz + (col << 2) + 4)); |
| tmp0 += ((top_err_r & 0xFF) << 16);//pErr_horz[col+1]; |
| tmp1 += (((top_err_r >> 8) & 0xFF) << 16);//mErr_horz[1][col+1]; |
| tmp2 += (((top_err_r >> 16) & 0xFF) << 16);//mErr_horz[2][col+1]; |
| |
| tmp0 = clip[tmp0>>16]; |
| tmp1 = clip[tmp1>>16]; |
| tmp2 = clip[tmp2>>16]; |
| |
| #ifdef OUTPUT_RGB_565 |
| //RGB_565 |
| rgb = (tmp0 >> 3); |
| rgb = (tmp1 >> 2) | (rgb << 6); |
| rgb = (tmp2 >> 3) | (rgb << 5); |
| #else |
| //RGB_444 |
| rgb = (tmp0 & 0xF0) << 4; |
| rgb |= (tmp1 & 0xF0); |
| rgb |= (tmp2 >> 4); |
| #endif |
| |
| tmp0 &= 0xE; |
| tmp1 &= 0xE; |
| tmp2 &= 0xE; |
| tmp0 >>= 1; |
| tmp1 >>= 1; |
| tmp2 >>= 1; |
| |
| //save error |
| left_err_b = tmp0 | (tmp1 << 8) | (tmp2 << 16); // = top_err_r also |
| |
| Y = *pY; |
| pY += tmp_src_pitch; |
| // Y = *pY++; |
| |
| // error from the top already available |
| tmp1 = (Y << 16) - Cg + (tmp1 << 16); |
| tmp2 = (Y << 16) + Cb + (tmp2 << 16); |
| tmp0 = (Y << 16) + Cr + (tmp0 << 16); |
| |
| //add the error from left |
| tmp0 += ((left_err_t & 0xFF) << 16);// err_vert[3]; |
| tmp1 += (((left_err_t >> 8) & 0xFF) << 16);//err_vert[4]; |
| tmp2 += (((left_err_t >> 16) & 0xFF) << 16);//err_vert[5]; |
| |
| tmp0 = clip[tmp0>>16]; |
| tmp1 = clip[tmp1>>16]; |
| tmp2 = clip[tmp2>>16]; |
| |
| //save error |
| left_err_t = ((tmp0 & 0xE) >> 1) | ((tmp1 & 0xE) << 7) | ((tmp2 & 0xE) << 15);//= top_err_r also |
| *((uint*)(pErr_horz + (col << 2) + 4)) = left_err_t;// =top_err_r; |
| |
| #ifdef OUTPUT_RGB_565 |
| //RGB_565 |
| tmp0 = (tmp0 >> 3); |
| tmp0 = (tmp1 >> 2) | (tmp0 << 6); |
| tmp0 = (tmp2 >> 3) | (tmp0 << 5); |
| #else |
| //RGB_444 |
| tmp0 = (tmp0 & 0xF0) << 4; |
| tmp0 |= (tmp1 & 0xF0); |
| tmp0 |= (tmp2 >> 4); |
| #endif |
| |
| if (((uint)pDst) & 3) //half word aligned |
| { |
| if (_mRowPix[col+1] == 2) |
| { |
| *(pDst + dst_pitch) = rgb; |
| *(pDst + dst_pitch + 1) = rgb; |
| *(pDst) = tmp0; |
| *(pDst + 1) = tmp0; |
| } |
| else if (_mRowPix[col+1] == 3) |
| { |
| *(pDst + dst_pitch) = rgb; |
| *((uint*)(pDst + dst_pitch + 1)) = rgb | (rgb << 16); |
| |
| *(pDst) = tmp0; |
| *((uint*)(pDst + 1)) = tmp0 | (tmp0 << 16); |
| } |
| else |
| { |
| *(pDst + dst_pitch) = rgb; |
| *(pDst) = tmp0; |
| } |
| } |
| else //word aligned |
| { |
| if (_mRowPix[col+1] == 2) |
| { |
| *((uint*)(pDst + dst_pitch)) = rgb | (rgb << 16); |
| *((uint*)(pDst)) = tmp0 | (tmp0 << 16); |
| } |
| else if (_mRowPix[col+1] == 3) |
| { |
| *((uint*)(pDst + dst_pitch)) = rgb | (rgb << 16); |
| *(pDst + dst_pitch + 2) = rgb; |
| |
| *((uint*)(pDst)) = tmp0 | (tmp0 << 16); |
| *(pDst + 2) = tmp0; |
| } |
| else |
| { |
| *(pDst + dst_pitch) = rgb; |
| *(pDst) = tmp0; |
| } |
| } |
| } /* if(_mRowPix[col]) */ |
| else |
| { |
| pY += tmp_src_pitch; |
| } |
| pDst += _mRowPix[col+1]; |
| |
| }//end of COL |
| |
| pY += (deltaY); |
| pCb += deltaCbCr; |
| pCr += deltaCbCr; |
| |
| pDst -= (dst_width); //goes back to the beginning of the line; |
| |
| //copy down |
| offset = (_mColPix[row] * dst_pitch); |
| |
| if (_mColPix[row-1] && _mColPix[row] != 1) |
| { |
| oscl_memcpy(pDst + offset, pDst + dst_pitch, dst_width*2); |
| } |
| if (_mColPix[row-1] == 2) |
| { |
| oscl_memcpy(pDst + offset + dst_pitch, pDst + dst_pitch, dst_width*2); |
| } |
| else if (_mColPix[row-1] == 3) |
| { |
| oscl_memcpy(pDst + offset + dst_pitch, pDst + dst_pitch, dst_width*2); |
| oscl_memcpy(pDst + offset + dst_pitch*2, pDst + dst_pitch, dst_width*2); |
| } |
| |
| //copy up |
| if (_mColPix[row] == 2) |
| oscl_memcpy(pDst + dst_pitch, pDst, dst_width*2); |
| else if (_mColPix[row] == 3) |
| { |
| oscl_memcpy(pDst + dst_pitch, pDst, dst_width*2); |
| oscl_memcpy(pDst + dst_pitch*2, pDst, dst_width*2); |
| } |
| |
| pDst += dst_pitch * (_mColPix[row-1] + _mColPix[row]); |
| } |
| return 1; |
| #else |
| return 0; |
| #endif // defined(CCROTATE) && defined(CCSCALING) |
| } |
| #endif // USE_ARM_ASM_FOR_COLORCONVERT |
| |
| |
| |
| |
| |
| |