diff --git a/libcopybit/Android.mk b/libcopybit/Android.mk index 5740a65..c23ecd8 100644 --- a/libcopybit/Android.mk +++ b/libcopybit/Android.mk @@ -34,6 +34,12 @@ else ifneq ($(call is-chipset-in-board-platform,msm7630),true) ifeq ($(call is-board-platform-in-list,$(MSM7K_BOARD_PLATFORMS)),true) include $(CLEAR_VARS) + ifeq ($(ARCH_ARM_HAVE_NEON),true) + LOCAL_CFLAGS += -D__ARM_HAVE_NEON + endif + ifeq ($(call is-board-platform,msm7627a),true) + LOCAL_CFLAGS += -DTARGET_7x27A + endif ifeq ($(TARGET_GRALLOC_USES_ASHMEM),true) LOCAL_CFLAGS += -DUSE_ASHMEM ifeq ($(call is-chipset-prefix-in-board-platform,msm7627),true) @@ -44,8 +50,9 @@ else LOCAL_PRELINK_MODULE := false LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw LOCAL_SHARED_LIBRARIES := liblog - LOCAL_SRC_FILES := copybit.cpp - LOCAL_MODULE := copybit.msm7k + LOCAL_SRC_FILES := software_converter.cpp copybit.cpp + LOCAL_MODULE := copybit.$(TARGET_BOARD_PLATFORM) + LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp index 55b95b7..9807aef 100644 --- a/libcopybit/copybit.cpp +++ b/libcopybit/copybit.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 The Android Open Source Project + * Copyright (c) 2010 - 2011, Code Aurora Forum. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,6 +36,7 @@ #include #include "gralloc_priv.h" +#include "software_converter.h" #define DEBUG_MDP_ERRORS 1 @@ -136,19 +138,15 @@ static int get_format(int format) { static void set_image(struct mdp_img *img, const struct copybit_image_t *rhs) { private_handle_t* hnd = (private_handle_t*)rhs->handle; + if(hnd == NULL){ + LOGE("copybit: Invalid handle"); + return; + } img->width = rhs->w; img->height = rhs->h; img->format = get_format(rhs->format); img->offset = hnd->offset; - #if defined(COPYBIT_MSM7K) - #if defined(USE_ASHMEM) && (TARGET_7x27) - img->memory_id = hnd->fd; - #else //USE_ASHMEM not defined - img->memory_id = hnd->fd; - #endif //end USE_ASHMEM - #else - img->memory_id = hnd->fd; - #endif + img->memory_id = hnd->fd; } /** setup rectangles */ static void set_rects(struct copybit_context_t *dev, @@ -387,6 +385,18 @@ static int stretch_copybit( if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) return -EINVAL; + if(src->format == HAL_PIXEL_FORMAT_YV12) { + if(0 == convertYV12toYCrCb420SP(src)){ + //if inplace conversion,just convert and return + if(src->base == dst->base) + return status; + } + else{ + LOGE("Error copybit conversion from yv12 failed"); + return -EINVAL; + } + } + const uint32_t maxCount = sizeof(list.req)/sizeof(list.req[0]); const struct copybit_rect_t bounds = { 0, 0, dst->w, dst->h }; struct copybit_rect_t clip; @@ -397,6 +407,11 @@ static int stretch_copybit( mdp_blit_req* req = &list.req[list.count]; int flags = 0; + private_handle_t* src_hnd = (private_handle_t*)src->handle; + if(src_hnd != NULL && src_hnd->flags & private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH) { + flags |= MDP_BLIT_NON_CACHED; + } + set_infos(ctx, req, flags); set_image(&req->dst, dst); set_image(&req->src, src); diff --git a/libcopybit/copybit.h b/libcopybit/copybit.h index 7e9fbbe..920f858 100644 --- a/libcopybit/copybit.h +++ b/libcopybit/copybit.h @@ -113,7 +113,9 @@ struct copybit_image_t { /* handle to the image */ native_handle_t* handle; /* number of pixels added for the stride */ - uint32_t padding; + uint32_t horiz_padding; + /* number of pixels added for the vertical stride */ + uint32_t vert_padding; }; /* Rectangle */ diff --git a/libcopybit/software_converter.cpp b/libcopybit/software_converter.cpp new file mode 100644 index 0000000..73c2c88 --- /dev/null +++ b/libcopybit/software_converter.cpp @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2011, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Code Aurora Forum, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "copybit" +#include +#include +#include +#include "software_converter.h" +#include "gralloc_priv.h" + +/** Convert YV12 to YCrCb_420_SP */ +int convertYV12toYCrCb420SP(const copybit_image_t *src) +{ + private_handle_t* hnd = (private_handle_t*)src->handle; + + if(hnd == NULL){ + LOGE("Invalid handle"); + return -1; + } + + // Please refer to the description of YV12 in hardware.h + // for the formulae used to calculate buffer sizes and offsets + + // In a copybit_image_t, w is the stride and + // stride - horiz_padding is the actual width + // vertical stride is the same as height, so not considered + unsigned int stride = src->w; + unsigned int width = src->w - src->horiz_padding; + unsigned int height = src->h; + unsigned int padding = src->horiz_padding; + unsigned int y_size = stride * src->h; + unsigned int c_width = ALIGN(stride/2, 16); + unsigned int c_size = c_width * src->h/2; + unsigned char* chroma = (unsigned char *) (hnd->base + y_size); + unsigned int tempBufSize = c_size * 2; + unsigned char* tempBuf = (unsigned char*) malloc (tempBufSize); + + if(tempBuf == NULL) { + LOGE("Failed to allocate temporary buffer"); + return -errno; + } + +#ifdef __ARM_HAVE_NEON + /* copy into temp buffer */ + + unsigned char * t1 = chroma; + unsigned char * t2 = tempBuf; + +#ifdef TARGET_7x27A + // Since the Sparrow core on 7x27A has a performance issue + // with reading from uncached memory using Neon instructions, + // use regular ARM instructions to copy the buffer on this + // target. There is no issue with storing, hence using + // Neon instructions for interleaving + for(unsigned int i=0; i < (tempBufSize>>5); i++) { + __asm__ __volatile__ ( + "LDMIA %0!, {r3 - r10} \n" + "STMIA %1!, {r3 - r10} \n" + :"+r"(t1), "+r"(t2) + : + :"memory","r3","r4","r5", + "r6","r7","r8","r9","r10" + ); + + } +#else + for(unsigned int i=0; i < (tempBufSize>>5); i++) { + __asm__ __volatile__ ( + "vld1.u8 {d0-d3}, [%0]! \n" + "vst1.u8 {d0-d3}, [%1]! \n" + :"+r"(t1), "+r"(t2) + : + :"memory","d0","d1","d2","d3" + ); + + } +#endif //TARGET_7x27A + + /* interleave */ + if(!padding) { + t1 = chroma; + t2 = tempBuf; + unsigned char * t3 = t2 + tempBufSize/2; + for(unsigned int i=0; i < (tempBufSize/2)>>3; i++) { + __asm__ __volatile__ ( + "vld1.u8 d0, [%0]! \n" + "vld1.u8 d1, [%1]! \n" + "vst2.u8 {d0, d1}, [%2]! \n" + :"+r"(t2), "+r"(t3), "+r"(t1) + : + :"memory","d0","d1" + ); + + } + } +#else //__ARM_HAVE_NEON + memcpy(tempBuf, chroma, tempBufSize); + if(!padding) { + for(unsigned int i = 0; i< tempBufSize/2; i++) { + chroma[i*2] = tempBuf[i]; + chroma[i*2+1] = tempBuf[i+tempBufSize/2]; + } + + } +#endif + // If the image is not aligned to 16 pixels, + // convert using the C routine below + // r1 tracks the row of the source buffer + // r2 tracks the row of the destination buffer + // The width/2 checks are to avoid copying + // from the padding + + if(padding) { + unsigned int r1 = 0, r2 = 0, i = 0, j = 0; + while(r1 < height/2) { + if(j == width/2) { + j = 0; + r2++; + continue; + } + if (j+1 == width/2) { + chroma[r2*c_width + j] = tempBuf[r1*c_width+i]; + r2++; + chroma[r2*c_width] = tempBuf[r1*c_width+i+c_size]; + j = 1; + } else { + chroma[r2*c_width + j] = tempBuf[r1*c_width+i]; + chroma[r2*c_width + j + 1] = tempBuf[r1*c_width+i+c_size]; + j+=2; + } + i++; + if (i == width/2 ) { + i = 0; + r1++; + } + } + } + + if(tempBuf) + free(tempBuf); + return 0; +} diff --git a/libcopybit/software_converter.h b/libcopybit/software_converter.h new file mode 100644 index 0000000..345c7c0 --- /dev/null +++ b/libcopybit/software_converter.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Code Aurora Forum, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + + +#include + +inline unsigned int ALIGN(unsigned int x, unsigned int align) { + return (x + align-1) & ~(align-1); +} + +int convertYV12toYCrCb420SP(const copybit_image_t *src);