| /* |
| ** |
| ** Copyright 2009 Samsung Electronics Co, Ltd. |
| ** |
| ** 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. |
| ** |
| ** |
| */ |
| |
| /////////////////////////////////////////////////// |
| // include |
| /////////////////////////////////////////////////// |
| #define LOG_NDEBUG 0 |
| #define LOG_TAG "FimgC210" |
| #include <utils/Log.h> |
| |
| #include "FimgC210.h" |
| |
| namespace android |
| { |
| |
| //---------------------------------------------------------------------------// |
| // FimgC210 |
| //---------------------------------------------------------------------------// |
| |
| Mutex FimgC210::m_instanceLock; |
| int FimgC210::m_curFimgC210Index = 0; |
| int FimgC210::m_numOfInstance = 0; |
| FimgApi * FimgC210::m_ptrFimgApiList[NUMBER_FIMG_LIST] = {NULL, }; |
| |
| //---------------------------------------------------------------------------// |
| |
| FimgC210::FimgC210() |
| : m_g2dFd(0), |
| m_g2dVirtAddr(NULL), |
| m_g2dSize(0), |
| m_g2dSrcVirtAddr(NULL), |
| m_g2dSrcSize(0), |
| m_g2dDstVirtAddr(NULL), |
| m_g2dDstSize(0) |
| { |
| m_lock = new Mutex(Mutex::SHARED, "FimgC210"); |
| } |
| |
| FimgC210::~FimgC210() |
| { |
| delete m_lock; |
| } |
| |
| FimgApi * FimgC210::CreateInstance() |
| { |
| Mutex::Autolock autolock(m_instanceLock); |
| |
| FimgApi * ptrFimg = NULL; |
| |
| // Using List like RingBuffer... |
| for(int i = m_curFimgC210Index; i < NUMBER_FIMG_LIST; i++) { |
| if(m_ptrFimgApiList[i] == NULL) |
| m_ptrFimgApiList[i] = new FimgC210; |
| |
| if(m_ptrFimgApiList[i]->FlagCreate() == false) { |
| if(m_ptrFimgApiList[i]->Create() == false) { |
| PRINT("%s::Create(%d) fail\n", __func__, i); |
| goto CreateInstance_End; |
| } |
| else |
| m_numOfInstance++; |
| } |
| |
| if(i < NUMBER_FIMG_LIST - 1) |
| m_curFimgC210Index = i + 1; |
| else |
| m_curFimgC210Index = 0; |
| |
| ptrFimg = m_ptrFimgApiList[i]; |
| goto CreateInstance_End; |
| } |
| |
| CreateInstance_End : |
| |
| return ptrFimg; |
| } |
| |
| void FimgC210::DestroyInstance(FimgApi * ptrFimgApi) |
| { |
| Mutex::Autolock autolock(m_instanceLock); |
| |
| for(int i = 0; i < NUMBER_FIMG_LIST; i++) { |
| if(m_ptrFimgApiList[i] != NULL |
| && m_ptrFimgApiList[i] == ptrFimgApi) { |
| if(m_ptrFimgApiList[i]->FlagCreate() == true |
| && m_ptrFimgApiList[i]->Destroy() == false) { |
| PRINT("%s::Destroy() fail\n", __func__); |
| } else { |
| FimgC210 * tempFimgC210 = (FimgC210 *)m_ptrFimgApiList[i]; |
| delete tempFimgC210; |
| m_ptrFimgApiList[i] = NULL; |
| |
| m_numOfInstance--; |
| } |
| |
| break; |
| } |
| } |
| } |
| |
| void FimgC210::DestroyAllInstance(void) |
| { |
| Mutex::Autolock autolock(m_instanceLock); |
| |
| for(int i = 0; i < NUMBER_FIMG_LIST; i++) { |
| if(m_ptrFimgApiList[i] != NULL) { |
| if(m_ptrFimgApiList[i]->FlagCreate() == true |
| && m_ptrFimgApiList[i]->Destroy() == false) { |
| PRINT("%s::Destroy() fail\n", __func__); |
| } else { |
| FimgC210 * tempFimgC210 = (FimgC210 *)m_ptrFimgApiList[i]; |
| delete tempFimgC210; |
| m_ptrFimgApiList[i] = NULL; |
| } |
| } |
| } |
| } |
| |
| |
| bool FimgC210::t_Create(void) |
| { |
| bool ret = true; |
| |
| if(m_CreateG2D() == false) { |
| PRINT("%s::m_CreateG2D() fail \n", __func__); |
| |
| if(m_DestroyG2D() == false) |
| PRINT("%s::m_DestroyG2D() fail \n", __func__); |
| |
| ret = false; |
| } |
| |
| return ret; |
| } |
| |
| bool FimgC210::t_Destroy(void) |
| { |
| bool ret = true; |
| |
| if(m_DestroyG2D() == false) { |
| PRINT("%s::m_DestroyG2D() fail \n", __func__); |
| ret = false; |
| } |
| |
| return ret; |
| } |
| |
| bool FimgC210::t_Stretch(FimgRect * src, FimgRect * dst, FimgClip * clip, FimgFlag * flag) |
| { |
| #ifdef CHECK_FIMGC210_PERFORMANCE |
| #define NUM_OF_STEP (10) |
| StopWatch stopWatch("CHECK_FIMGC210_PERFORMANCE"); |
| const char * stopWatchName[NUM_OF_STEP]; |
| nsecs_t stopWatchTime[NUM_OF_STEP]; |
| int stopWatchIndex = 0; |
| #endif // CHECK_FIMGC210_PERFORMANCE |
| |
| if(m_DoG2D(src, dst, clip, flag) == false) { |
| goto STRETCH_FAIL; |
| } |
| |
| #ifdef G2D_NONE_BLOCKING_MODE |
| if(m_PollG2D(&m_g2dPoll) == false) |
| { |
| PRINT("%s::m_PollG2D() fail\n", __func__); |
| goto STRETCH_FAIL; |
| } |
| #endif |
| |
| #ifdef CHECK_FIMGC210_PERFORMANCE |
| m_PrintFimgC210Performance(src, dst, stopWatchIndex, stopWatchName, stopWatchTime); |
| #endif // CHECK_FIMGC210_PERFORMANCE |
| |
| return true; |
| |
| STRETCH_FAIL: |
| return false; |
| |
| } |
| |
| bool FimgC210::t_Sync(void) |
| { |
| #if 0 |
| if(ioctl(m_g2dFd, G2D_SYNC) < 0) { |
| PRINT("%s::G2D_Sync fail\n", __func__); |
| goto SYNC_FAIL; |
| } |
| #else |
| if(m_PollG2D(&m_g2dPoll) == false) |
| { |
| PRINT("%s::m_PollG2D() fail\n", __func__); |
| goto SYNC_FAIL; |
| } |
| #endif |
| return true; |
| |
| SYNC_FAIL: |
| return false; |
| |
| } |
| |
| bool FimgC210::t_Lock(void) |
| { |
| m_lock->lock(); |
| return true; |
| } |
| |
| bool FimgC210::t_UnLock(void) |
| { |
| m_lock->unlock(); |
| return true; |
| } |
| |
| bool FimgC210::m_CreateG2D(void) |
| { |
| void * mmap_base; |
| |
| if(m_g2dFd != 0) { |
| PRINT("%s::m_g2dFd(%d) is not 0 fail\n", __func__, m_g2dFd); |
| return false; |
| } |
| |
| #ifdef G2D_NONE_BLOCKING_MODE |
| m_g2dFd = open(SEC_G2D_DEV_NAME, O_RDWR | O_NONBLOCK); |
| #else |
| m_g2dFd = open(SEC_G2D_DEV_NAME, O_RDWR); |
| #endif |
| if(m_g2dFd < 0) { |
| PRINT("%s::open(%s) fail(%s)\n", __func__, SEC_G2D_DEV_NAME, strerror(errno)); |
| m_g2dFd = 0; |
| return false; |
| } |
| |
| memset(&m_g2dPoll, 0, sizeof(m_g2dPoll)); |
| m_g2dPoll.fd = m_g2dFd; |
| m_g2dPoll.events = POLLOUT | POLLERR; |
| |
| return true; |
| } |
| |
| bool FimgC210::m_DestroyG2D(void) |
| { |
| if(m_g2dVirtAddr != NULL) { |
| munmap(m_g2dVirtAddr, m_g2dSize); |
| m_g2dVirtAddr = NULL; |
| m_g2dSize = 0; |
| } |
| |
| if(0 < m_g2dFd) { |
| close(m_g2dFd); |
| } |
| m_g2dFd = 0; |
| |
| return true; |
| } |
| |
| //bool FimgC210::m_DoG2D(FimgRect * src, FimgRect * dst, int rotateValue, int alphaValue, int colorKey) |
| bool FimgC210::m_DoG2D(FimgRect * src, FimgRect * dst, FimgClip * clip, FimgFlag * flag) |
| { |
| g2d_params params; |
| |
| memcpy(¶ms.src_rect, src, sizeof(FimgRect)); |
| memcpy(¶ms.dst_rect, dst, sizeof(FimgRect)); |
| memcpy(¶ms.clip, clip, sizeof(FimgClip)); |
| memcpy(¶ms.flag, flag, sizeof(FimgFlag)); |
| |
| if(ioctl(m_g2dFd, G2D_BLIT, ¶ms) < 0) { |
| #if 0 |
| { |
| PRINT("---------------------------------------\n"); |
| PRINT("src.color_format : %d \n", src->color_format); |
| PRINT("src.full_w : %d \n", src->full_w); |
| PRINT("src.full_h : %d \n", src->full_h); |
| PRINT("src.x : %d \n", src->x); |
| PRINT("src.y : %d \n", src->y); |
| PRINT("src.w : %d \n", src->w); |
| PRINT("src.h : %d \n", src->h); |
| |
| PRINT("dst.color_format : %d \n", dst->color_format); |
| PRINT("dst.full_w : %d \n", dst->full_w); |
| PRINT("dst.full_h : %d \n", dst->full_h); |
| PRINT("dst.x : %d \n", dst->x); |
| PRINT("dst.y : %d \n", dst->y); |
| PRINT("dst.w : %d \n", dst->w); |
| PRINT("dst.h : %d \n", dst->h); |
| |
| PRINT("flag.rotate_val : %d \n", flag->rotate_val); |
| PRINT("flag.alpha_val : %d(%d) \n", flag->alpha_val); |
| PRINT("flag.color_key_mode : %d(%d) \n", flag->color_key_mode, flag->color_key_val); |
| PRINT("---------------------------------------\n"); |
| } |
| #endif |
| |
| return false; |
| } |
| |
| return true; |
| } |
| |
| inline bool FimgC210::m_PollG2D(struct pollfd * events) |
| { |
| #define G2D_POLL_TIME (1000) |
| |
| int ret; |
| |
| ret = poll(events, 1, G2D_POLL_TIME); |
| |
| if (ret < 0) { |
| if(ioctl(m_g2dFd, G2D_RESET) < 0) { |
| PRINT("%s::G2D_RESET fail\n", __func__); |
| } |
| PRINT("%s::poll fail \n", __func__); |
| return false; |
| } |
| else if (ret == 0) { |
| if(ioctl(m_g2dFd, G2D_RESET) < 0) { |
| PRINT("%s::G2D_RESET fail\n", __func__); |
| } |
| PRINT("%s::No data in %d milli secs..\n", __func__, G2D_POLL_TIME); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| inline bool FimgC210::m_CleanG2D(unsigned int virtAddr, unsigned int size) |
| { |
| g2d_dma_info dma_info = { virtAddr, size }; |
| |
| if(ioctl(m_g2dFd, G2D_DMA_CACHE_CLEAN, &dma_info) < 0) { |
| PRINT("%s::G2D_DMA_CACHE_CLEAN(%d, %d) fail\n", __func__, virtAddr, size); |
| return false; |
| } |
| return true; |
| } |
| |
| inline bool FimgC210::m_FlushG2D (unsigned int virtAddr, unsigned int size) |
| { |
| g2d_dma_info dma_info = { virtAddr, size }; |
| |
| if(ioctl(m_g2dFd, G2D_DMA_CACHE_FLUSH, &dma_info) < 0) { |
| PRINT("%s::G2D_DMA_CACHE_FLUSH(%d, %d) fail\n", __func__, virtAddr, size); |
| return false; |
| } |
| return true; |
| } |
| |
| inline int FimgC210::m_RotateValueFimgApi2FimgHw(int rotateValue) |
| { |
| switch (rotateValue) { |
| case ROTATE_0: return G2D_ROT_0; |
| case ROTATE_90: return G2D_ROT_90; |
| case ROTATE_180: return G2D_ROT_180; |
| case ROTATE_270: return G2D_ROT_270; |
| case ROTATE_X_FLIP: return G2D_ROT_X_FLIP; |
| case ROTATE_Y_FLIP: return G2D_ROT_Y_FLIP; |
| } |
| |
| return -1; |
| } |
| |
| |
| #ifdef CHECK_FIMGC210_PERFORMANCE |
| void FimgC210::m_PrintFimgC210Performance(FimgRect * src, |
| FimgRect * dst, |
| int stopWatchIndex, |
| const char * stopWatchName[], |
| nsecs_t stopWatchTime[]) |
| { |
| char * srcColorFormat = "UNKNOW_COLOR_FORMAT"; |
| char * dstColorFormat = "UNKNOW_COLOR_FORMAT"; |
| |
| switch(src->color_format) |
| { |
| case COLOR_FORMAT_RGB_565 : |
| srcColorFormat = "RGB_565"; |
| break; |
| case COLOR_FORMAT_RGBA_8888 : |
| srcColorFormat = "RGBA_8888"; |
| break; |
| case COLOR_FORMAT_RGBX_8888 : |
| srcColorFormat = "RGBX_8888"; |
| break; |
| default : |
| srcColorFormat = "UNKNOW_COLOR_FORMAT"; |
| break; |
| } |
| |
| switch(dst->color_format) |
| { |
| case COLOR_FORMAT_RGB_565 : |
| dstColorFormat = "RGB_565"; |
| break; |
| case COLOR_FORMAT_RGBA_8888 : |
| dstColorFormat = "RGBA_8888"; |
| break; |
| case COLOR_FORMAT_RGBX_8888 : |
| dstColorFormat = "RGBX_8888"; |
| break; |
| default : |
| dstColorFormat = "UNKNOW_COLOR_FORMAT"; |
| break; |
| } |
| |
| |
| #ifdef CHECK_FIMGC210_CRITICAL_PERFORMANCE |
| #else |
| PRINT("===============================================\n"); |
| PRINT("src[%3d, %3d | %10s] -> dst[%3d, %3d | %10s]\n", |
| src->w, src->h, srcColorFormat, |
| dst->w, dst->h, dstColorFormat); |
| #endif |
| |
| nsecs_t totalTime = stopWatchTime[stopWatchIndex - 1]; |
| |
| for(int i = 0 ; i < stopWatchIndex; i++) { |
| nsecs_t sectionTime; |
| |
| if(i != 0) |
| sectionTime = stopWatchTime[i] - stopWatchTime[i-1]; |
| else |
| sectionTime = stopWatchTime[i]; |
| |
| #ifdef CHECK_FIMGC210_CRITICAL_PERFORMANCE |
| if(1500 < (sectionTime / 1000)) // check 1.5 mille second.. |
| #endif |
| { |
| PRINT("===============================================\n"); |
| PRINT("src[%3d, %3d | %10s] -> dst[%3d, %3d | %10s]\n", |
| src->w, src->h, srcColorFormat, |
| dst->w, dst->h, dstColorFormat); |
| |
| PRINT("%20s : %5lld msec(%5.2f %%)\n", |
| stopWatchName[i], |
| sectionTime / 1000, |
| ((float)sectionTime / (float)totalTime) * 100.0f); |
| } |
| } |
| |
| } |
| #endif // CHECK_FIMGC210_PERFORMANCE |
| |
| //---------------------------------------------------------------------------// |
| // extern function |
| //---------------------------------------------------------------------------// |
| extern "C" struct FimgApi * createFimgApi() |
| { |
| if (fimgApiAutoFreeThread == 0) |
| fimgApiAutoFreeThread = new FimgApiAutoFreeThread(); |
| else |
| fimgApiAutoFreeThread->SetOneMoreSleep(); |
| |
| return FimgC210::CreateInstance(); |
| } |
| |
| extern "C" void destroyFimgApi(FimgApi * ptrFimgApi) |
| { |
| // Dont' call DestrotInstance.. |
| // return FimgC210::DestroyInstance(ptrFimgApi); |
| } |
| |
| }; // namespace android |