Merge git://codeaurora.org/platform/hardware/qcom/display.git ics into ics and resolve conflicts
Change-Id: I3acb5e963763821d2b547cf3c9390754dc42c12f
This commit is contained in:
		| @@ -2,5 +2,6 @@ | ||||
|  | ||||
| ifeq ($(BOARD_USES_QCOM_HARDWARE),true) | ||||
| 	display-hals := libhwcomposer liboverlay libgralloc libcopybit | ||||
| 	display-hals += libqcomui | ||||
| 	include $(call all-named-subdir-makefiles,$(display-hals)) | ||||
| endif | ||||
|   | ||||
| @@ -21,8 +21,8 @@ ifeq ($(TARGET_USES_C2D_COMPOSITION),true) | ||||
|     include $(CLEAR_VARS) | ||||
|     LOCAL_PRELINK_MODULE := false | ||||
|     LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw | ||||
|     LOCAL_SHARED_LIBRARIES := liblog libdl | ||||
|     LOCAL_SRC_FILES := copybit_c2d.cpp | ||||
|     LOCAL_SHARED_LIBRARIES := liblog libdl libcutils | ||||
|     LOCAL_SRC_FILES := copybit_c2d.cpp software_converter.cpp | ||||
|     LOCAL_MODULE := copybit.$(TARGET_BOARD_PLATFORM) | ||||
|     LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc | ||||
|     LOCAL_CFLAGS += -DCOPYBIT_Z180=1 -DC2D_SUPPORT_DISPLAY=1 | ||||
|   | ||||
| @@ -387,9 +387,8 @@ static int stretch_copybit( | ||||
|  | ||||
|         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; | ||||
|                 (const_cast<copybit_image_t *>(src))->format = | ||||
|                         HAL_PIXEL_FORMAT_YCrCb_420_SP; | ||||
|             } | ||||
|             else{ | ||||
|                 LOGE("Error copybit conversion from yv12 failed"); | ||||
|   | ||||
| @@ -65,7 +65,11 @@ enum { | ||||
|     COPYBIT_BLUR            = 5, | ||||
|     /* Informs the copybit that the source and destination contains | ||||
|     premultiplied alpha */ | ||||
|     COPYBIT_PREMULTIPLIED_ALPHA  = 6 | ||||
|     COPYBIT_PREMULTIPLIED_ALPHA  = 6, | ||||
|     /* FB width */ | ||||
|     COPYBIT_FRAMEBUFFER_WIDTH = 7, | ||||
|     /* FB height */ | ||||
|     COPYBIT_FRAMEBUFFER_HEIGHT = 8, | ||||
| }; | ||||
|  | ||||
| /* values for copybit_set_parameter(COPYBIT_TRANSFORM) */ | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										57
									
								
								libcopybit/copybit_priv.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								libcopybit/copybit_priv.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| /* | ||||
|  * 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 <copybit.h> | ||||
| struct copybit_iterator : public copybit_region_t { | ||||
|     copybit_iterator(const copybit_rect_t& rect) { | ||||
|         mRect = rect; | ||||
|         mCount = 1; | ||||
|         this->next = iterate; | ||||
|     } | ||||
| private: | ||||
|     static int iterate(copybit_region_t const * self, copybit_rect_t* rect) { | ||||
|         if (!self || !rect) { | ||||
|             return 0; | ||||
|         } | ||||
|  | ||||
|         copybit_iterator const* me = static_cast<copybit_iterator const*>(self); | ||||
|         if (me->mCount) { | ||||
|             rect->l = me->mRect.l; | ||||
|             rect->t = me->mRect.t; | ||||
|             rect->r = me->mRect.r; | ||||
|             rect->b = me->mRect.b; | ||||
|             me->mCount--; | ||||
|             return 1; | ||||
|         } | ||||
|         return 0; | ||||
|     } | ||||
|     copybit_rect_t mRect; | ||||
|     mutable int mCount; | ||||
| }; | ||||
|  | ||||
| @@ -32,7 +32,6 @@ | ||||
| #include <stdlib.h> | ||||
| #include <errno.h> | ||||
| #include "software_converter.h" | ||||
| #include "gralloc_priv.h" | ||||
|  | ||||
| /** Convert YV12 to YCrCb_420_SP */ | ||||
| int convertYV12toYCrCb420SP(const copybit_image_t *src) | ||||
| @@ -166,3 +165,141 @@ int convertYV12toYCrCb420SP(const copybit_image_t *src) | ||||
|         free(tempBuf); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| struct copyInfo{ | ||||
|     int width; | ||||
|     int height; | ||||
|     int src_stride; | ||||
|     int dst_stride; | ||||
|     int src_plane1_offset; | ||||
|     int src_plane2_offset; | ||||
|     int dst_plane1_offset; | ||||
|     int dst_plane2_offset; | ||||
| }; | ||||
|  | ||||
| /* Internal function to do the actual copy of source to destination */ | ||||
| static int copy_source_to_destination(const int src_base, const int dst_base, | ||||
|                                       copyInfo& info) | ||||
| { | ||||
|     if (!src_base || !dst_base) { | ||||
|         LOGE("%s: invalid memory src_base = 0x%x dst_base=0x%x", | ||||
|              __FUNCTION__, src_base, dst_base); | ||||
|          return COPYBIT_FAILURE; | ||||
|     } | ||||
|  | ||||
|     int width = info.width; | ||||
|     int height = info.height; | ||||
|     unsigned char *src = (unsigned char*)src_base; | ||||
|     unsigned char *dst = (unsigned char*)dst_base; | ||||
|  | ||||
|     // Copy the luma | ||||
|     for (int i = 0; i < height; i++) { | ||||
|         memcpy(dst, src, width); | ||||
|         src += info.src_stride; | ||||
|         dst += info.dst_stride; | ||||
|     } | ||||
|  | ||||
|     // Copy plane 1 | ||||
|     src = (unsigned char*)(src_base + info.src_plane1_offset); | ||||
|     dst = (unsigned char*)(dst_base + info.dst_plane1_offset); | ||||
|     width = width/2; | ||||
|     height = height/2; | ||||
|     for (int i = 0; i < height; i++) { | ||||
|         memcpy(dst, src, info.src_stride); | ||||
|         src += info.src_stride; | ||||
|         dst += info.dst_stride; | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Function to convert the c2d format into an equivalent Android format | ||||
|  * | ||||
|  * @param: source buffer handle | ||||
|  * @param: destination image | ||||
|  * | ||||
|  * @return: return status | ||||
|  */ | ||||
| int convert_yuv_c2d_to_yuv_android(private_handle_t *hnd, | ||||
|                                    struct copybit_image_t const *rhs) | ||||
| { | ||||
|     LOGD("Enter %s", __FUNCTION__); | ||||
|     if (!hnd || !rhs) { | ||||
|         LOGE("%s: invalid inputs hnd=%p rhs=%p", __FUNCTION__, hnd, rhs); | ||||
|         return COPYBIT_FAILURE; | ||||
|     } | ||||
|  | ||||
|     int ret = COPYBIT_SUCCESS; | ||||
|     private_handle_t *dst_hnd = (private_handle_t *)rhs->handle; | ||||
|  | ||||
|     copyInfo info; | ||||
|     info.width = rhs->w; | ||||
|     info.height = rhs->h; | ||||
|     info.src_stride = ALIGN(info.width, 32); | ||||
|     info.dst_stride = ALIGN(info.width, 16); | ||||
|     switch(rhs->format) { | ||||
|         case HAL_PIXEL_FORMAT_YCbCr_420_SP: | ||||
|         case HAL_PIXEL_FORMAT_YCrCb_420_SP: { | ||||
|             info.src_plane1_offset = info.src_stride*info.height; | ||||
|             info.dst_plane1_offset = info.dst_stride*info.height; | ||||
|         } break; | ||||
|         case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: { | ||||
|             // Chroma is 2K aligned for the NV12 encodeable format. | ||||
|             info.src_plane1_offset = ALIGN(info.src_stride*info.height, 2048); | ||||
|             info.dst_plane1_offset = ALIGN(info.dst_stride*info.height, 2048); | ||||
|         } break; | ||||
|         default: | ||||
|             LOGE("%s: unsupported format (format=0x%x)", __FUNCTION__, | ||||
|                  rhs->format); | ||||
|             return COPYBIT_FAILURE; | ||||
|     } | ||||
|  | ||||
|     ret = copy_source_to_destination(hnd->base, dst_hnd->base, info); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Function to convert the Android format into an equivalent C2D format | ||||
|  * | ||||
|  * @param: source buffer handle | ||||
|  * @param: destination image | ||||
|  * | ||||
|  * @return: return status | ||||
|  */ | ||||
| int convert_yuv_android_to_yuv_c2d(private_handle_t *hnd, | ||||
|                                    struct copybit_image_t const *rhs) | ||||
| { | ||||
|     if (!hnd || !rhs) { | ||||
|         LOGE("%s: invalid inputs hnd=%p rhs=%p", __FUNCTION__, hnd, rhs); | ||||
|         return COPYBIT_FAILURE; | ||||
|     } | ||||
|  | ||||
|     int ret = COPYBIT_SUCCESS; | ||||
|     private_handle_t *dst_hnd = (private_handle_t *)rhs->handle; | ||||
|  | ||||
|     copyInfo info; | ||||
|     info.width = rhs->w; | ||||
|     info.height = rhs->h; | ||||
|     info.src_stride = ALIGN(info.width, 16); | ||||
|     info.dst_stride = ALIGN(info.width, 32); | ||||
|     switch(rhs->format) { | ||||
|         case HAL_PIXEL_FORMAT_YCbCr_420_SP: | ||||
|         case HAL_PIXEL_FORMAT_YCrCb_420_SP: { | ||||
|             info.src_plane1_offset = info.src_stride*info.height; | ||||
|             info.dst_plane1_offset = info.dst_stride*info.height; | ||||
|         } break; | ||||
|         case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: { | ||||
|             // Chroma is 2K aligned for the NV12 encodeable format. | ||||
|             info.src_plane1_offset = ALIGN(info.src_stride*info.height, 2048); | ||||
|             info.dst_plane1_offset = ALIGN(info.dst_stride*info.height, 2048); | ||||
|         } break; | ||||
|         default: | ||||
|             LOGE("%s: unsupported format (format=0x%x)", __FUNCTION__, | ||||
|                  rhs->format); | ||||
|             return -1; | ||||
|     } | ||||
|  | ||||
|     ret = copy_source_to_destination(hnd->base, dst_hnd->base, info); | ||||
|     return ret; | ||||
| } | ||||
| @@ -30,9 +30,36 @@ | ||||
|  | ||||
|  | ||||
| #include <copybit.h> | ||||
| #include "gralloc_priv.h" | ||||
|  | ||||
| #define COPYBIT_SUCCESS 0 | ||||
| #define COPYBIT_FAILURE -1 | ||||
|  | ||||
| inline unsigned int ALIGN(unsigned int x, unsigned int align) { | ||||
|         return (x + align-1) & ~(align-1); | ||||
| } | ||||
|  | ||||
| int convertYV12toYCrCb420SP(const copybit_image_t *src); | ||||
|  | ||||
| /* | ||||
|  * Function to convert the c2d format into an equivalent Android format | ||||
|  * | ||||
|  * @param: source buffer handle | ||||
|  * @param: destination image | ||||
|  * | ||||
|  * @return: return status | ||||
|  */ | ||||
| int convert_yuv_c2d_to_yuv_android(private_handle_t *hnd, | ||||
|                                    struct copybit_image_t const *rhs); | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Function to convert the Android format into an equivalent C2D format | ||||
|  * | ||||
|  * @param: source buffer handle | ||||
|  * @param: destination image | ||||
|  * | ||||
|  * @return: return status | ||||
|  */ | ||||
| int convert_yuv_android_to_yuv_c2d(private_handle_t *hnd, | ||||
|                                    struct copybit_image_t const *rhs); | ||||
|   | ||||
							
								
								
									
										15
									
								
								libgenlock/Android.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								libgenlock/Android.mk
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| LOCAL_PATH := $(call my-dir) | ||||
|  | ||||
| include $(CLEAR_VARS) | ||||
| LOCAL_PRELINK_MODULE := false | ||||
| LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES) | ||||
| LOCAL_SHARED_LIBRARIES := liblog libcutils | ||||
| LOCAL_C_INCLUDES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include | ||||
| LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc | ||||
| LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr | ||||
| LOCAL_SRC_FILES := genlock.cpp | ||||
| LOCAL_CFLAGS:= -DLOG_TAG=\"libgenlock\" | ||||
| LOCAL_MODULE_TAGS := optional | ||||
| LOCAL_MODULE := libgenlock | ||||
| include $(BUILD_SHARED_LIBRARY) | ||||
|  | ||||
							
								
								
									
										323
									
								
								libgenlock/genlock.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										323
									
								
								libgenlock/genlock.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,323 @@ | ||||
| /* | ||||
|  * 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 <cutils/log.h> | ||||
| #include <cutils/native_handle.h> | ||||
| #include <gralloc_priv.h> | ||||
| #include <linux/genlock.h> | ||||
| #include <fcntl.h> | ||||
| #include <sys/ioctl.h> | ||||
|  | ||||
| #include "genlock.h" | ||||
|  | ||||
| #define GENLOCK_DEVICE "/dev/genlock" | ||||
|  | ||||
| #ifndef USE_GENLOCK | ||||
| #define USE_GENLOCK | ||||
| #endif | ||||
|  | ||||
| namespace { | ||||
|     /* Internal function to map the userspace locks to the kernel lock types */ | ||||
|     int get_kernel_lock_type(genlock_lock_type lockType) | ||||
|     { | ||||
|         int kLockType = 0; | ||||
|         // If the user sets both a read and write lock, higher preference is | ||||
|         // given to the write lock. | ||||
|         if (lockType & GENLOCK_WRITE_LOCK) { | ||||
|             kLockType = GENLOCK_WRLOCK; | ||||
|         } else if (lockType & GENLOCK_READ_LOCK) { | ||||
|             kLockType = GENLOCK_RDLOCK; | ||||
|         } else { | ||||
|             LOGE("%s: invalid lockType (lockType = %d)", __FUNCTION__, lockType); | ||||
|             return -1; | ||||
|         } | ||||
|         return kLockType; | ||||
|     } | ||||
|  | ||||
|     /* Internal function to perform the actual lock/unlock operations */ | ||||
|     genlock_status_t perform_lock_unlock_operation(native_handle_t *buffer_handle, | ||||
|             int lockType, int timeout) | ||||
|     { | ||||
|         if (private_handle_t::validate(buffer_handle)) { | ||||
|             LOGE("%s: handle is invalid", __FUNCTION__); | ||||
|             return GENLOCK_FAILURE; | ||||
|         } | ||||
|  | ||||
|         private_handle_t *hnd = reinterpret_cast<private_handle_t*>(buffer_handle); | ||||
|         if (hnd->genlockPrivFd < 0) { | ||||
|             LOGE("%s: the lock has not been created, or has not been attached", | ||||
|                     __FUNCTION__); | ||||
|             return GENLOCK_FAILURE; | ||||
|         } | ||||
|  | ||||
|         genlock_lock lock; | ||||
|         lock.op = lockType; | ||||
|         lock.flags = 0; | ||||
|         lock.timeout = timeout; | ||||
|         lock.fd = hnd->genlockHandle; | ||||
|  | ||||
|         if (ioctl(hnd->genlockPrivFd, GENLOCK_IOC_LOCK, &lock)) { | ||||
|             LOGE("%s: GENLOCK_IOC_LOCK failed (lockType0x%x, err=%s fd=%d)", __FUNCTION__, | ||||
|                     lockType, strerror(errno), hnd->fd); | ||||
|             if (ETIMEDOUT == errno) | ||||
|                 return GENLOCK_TIMEDOUT; | ||||
|  | ||||
|             return GENLOCK_FAILURE; | ||||
|         } | ||||
|         return GENLOCK_NO_ERROR; | ||||
|     } | ||||
|  | ||||
|     /* Internal function to close the fd and release the handle */ | ||||
|     void close_genlock_fd_and_handle(int& fd, int& handle) | ||||
|     { | ||||
|         if (fd >=0 ) { | ||||
|             close(fd); | ||||
|             fd = -1; | ||||
|         } | ||||
|  | ||||
|         if (handle >= 0) { | ||||
|             close(handle); | ||||
|             handle = -1; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
| /* | ||||
|  * Create a genlock lock. The genlock lock file descriptor and the lock | ||||
|  * handle are stored in the buffer_handle. | ||||
|  * | ||||
|  * @param: handle of the buffer | ||||
|  * @return error status. | ||||
|  */ | ||||
| genlock_status_t genlock_create_lock(native_handle_t *buffer_handle) | ||||
| { | ||||
|     genlock_status_t ret = GENLOCK_NO_ERROR; | ||||
|     if (private_handle_t::validate(buffer_handle)) { | ||||
|         LOGE("%s: handle is invalid", __FUNCTION__); | ||||
|         return GENLOCK_FAILURE; | ||||
|     } | ||||
|  | ||||
|     private_handle_t *hnd = reinterpret_cast<private_handle_t*>(buffer_handle); | ||||
| #ifdef USE_GENLOCK | ||||
|     // Open the genlock device | ||||
|     int fd = open(GENLOCK_DEVICE, O_RDWR); | ||||
|     if (fd < 0) { | ||||
|         LOGE("%s: open genlock device failed (err=%s)", __FUNCTION__, | ||||
|                 strerror(errno)); | ||||
|         return GENLOCK_FAILURE; | ||||
|     } | ||||
|  | ||||
|     // Create a new lock | ||||
|     genlock_lock lock; | ||||
|     if (ioctl(fd, GENLOCK_IOC_NEW, NULL)) { | ||||
|         LOGE("%s: GENLOCK_IOC_NEW failed (error=%s)", __FUNCTION__, | ||||
|                 strerror(errno)); | ||||
|         close_genlock_fd_and_handle(fd, lock.fd); | ||||
|         ret = GENLOCK_FAILURE; | ||||
|     } | ||||
|  | ||||
|     // Export the lock for other processes to be able to use it. | ||||
|     if (GENLOCK_FAILURE != ret) { | ||||
|         if (ioctl(fd, GENLOCK_IOC_EXPORT, &lock)) { | ||||
|             LOGE("%s: GENLOCK_IOC_EXPORT failed (error=%s)", __FUNCTION__, | ||||
|                     strerror(errno)); | ||||
|             close_genlock_fd_and_handle(fd, lock.fd); | ||||
|             ret = GENLOCK_FAILURE; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Store the lock params in the handle. | ||||
|     hnd->genlockPrivFd = fd; | ||||
|     hnd->genlockHandle = lock.fd; | ||||
| #else | ||||
|     hnd->genlockHandle = 0; | ||||
| #endif | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Release a genlock lock associated with the handle. | ||||
|  * | ||||
|  * @param: handle of the buffer | ||||
|  * @return error status. | ||||
|  */ | ||||
| genlock_status_t genlock_release_lock(native_handle_t *buffer_handle) | ||||
| { | ||||
|     genlock_status_t ret = GENLOCK_NO_ERROR; | ||||
| #ifdef USE_GENLOCK | ||||
|     if (private_handle_t::validate(buffer_handle)) { | ||||
|         LOGE("%s: handle is invalid", __FUNCTION__); | ||||
|         return GENLOCK_FAILURE; | ||||
|     } | ||||
|  | ||||
|     private_handle_t *hnd = reinterpret_cast<private_handle_t*>(buffer_handle); | ||||
|     if (hnd->genlockPrivFd < 0) { | ||||
|         LOGE("%s: the lock is invalid", __FUNCTION__); | ||||
|         return GENLOCK_FAILURE; | ||||
|     } | ||||
|  | ||||
|     if (ioctl(hnd->genlockPrivFd, GENLOCK_IOC_RELEASE, NULL)) { | ||||
|         LOGE("%s: GENLOCK_IOC_RELEASE failed (err=%s)", __FUNCTION__, | ||||
|                 strerror(errno)); | ||||
|         ret = GENLOCK_FAILURE; | ||||
|     } | ||||
|  | ||||
|     // Close the fd and reset the parameters. | ||||
|     close_genlock_fd_and_handle(hnd->genlockPrivFd, hnd->genlockHandle); | ||||
| #endif | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Attach a lock to the buffer handle passed via an IPC. | ||||
|  * | ||||
|  * @param: handle of the buffer | ||||
|  * @return error status. | ||||
|  */ | ||||
| genlock_status_t genlock_attach_lock(native_handle_t *buffer_handle) | ||||
| { | ||||
|     genlock_status_t ret = GENLOCK_NO_ERROR; | ||||
| #ifdef USE_GENLOCK | ||||
|     if (private_handle_t::validate(buffer_handle)) { | ||||
|         LOGE("%s: handle is invalid", __FUNCTION__); | ||||
|         return GENLOCK_FAILURE; | ||||
|     } | ||||
|  | ||||
|     // Open the genlock device | ||||
|     int fd = open(GENLOCK_DEVICE, O_RDWR); | ||||
|     if (fd < 0) { | ||||
|         LOGE("%s: open genlock device failed (err=%s)", __FUNCTION__, | ||||
|                 strerror(errno)); | ||||
|         return GENLOCK_FAILURE; | ||||
|     } | ||||
|  | ||||
|     // Attach the local handle to an existing lock | ||||
|     private_handle_t *hnd = reinterpret_cast<private_handle_t*>(buffer_handle); | ||||
|     genlock_lock lock; | ||||
|     lock.fd = hnd->genlockHandle; | ||||
|     if (ioctl(fd, GENLOCK_IOC_ATTACH, &lock)) { | ||||
|         LOGE("%s: GENLOCK_IOC_ATTACH failed (err=%s)", __FUNCTION__, | ||||
|                 strerror(errno)); | ||||
|         close_genlock_fd_and_handle(fd, lock.fd); | ||||
|         ret = GENLOCK_FAILURE; | ||||
|     } | ||||
|  | ||||
|     // Store the relavant information in the handle | ||||
|     hnd->genlockPrivFd = fd; | ||||
| #endif | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Lock the buffer specified by the buffer handle. The lock held by the buffer | ||||
|  * is specified by the lockType. This function will block if a write lock is | ||||
|  * requested on the buffer which has previously been locked for a read or write | ||||
|  * operation. A buffer can be locked by multiple clients for read. An optional | ||||
|  * timeout value can be specified. By default, there is no timeout. | ||||
|  * | ||||
|  * @param: handle of the buffer | ||||
|  * @param: type of lock to be acquired by the buffer. | ||||
|  * @param: timeout value in ms. GENLOCK_MAX_TIMEOUT is the maximum timeout value. | ||||
|  * @return error status. | ||||
|  */ | ||||
| genlock_status_t genlock_lock_buffer(native_handle_t *buffer_handle, | ||||
|         genlock_lock_type_t lockType, | ||||
|         int timeout) | ||||
| { | ||||
|     genlock_status_t ret = GENLOCK_NO_ERROR; | ||||
| #ifdef USE_GENLOCK | ||||
|     // Translate the locktype | ||||
|     int kLockType = get_kernel_lock_type(lockType); | ||||
|     if (-1 == kLockType) { | ||||
|         LOGE("%s: invalid lockType", __FUNCTION__); | ||||
|         return GENLOCK_FAILURE; | ||||
|     } | ||||
|  | ||||
|     if (0 == timeout) { | ||||
|         LOGW("%s: trying to lock a buffer with timeout = 0", __FUNCTION__); | ||||
|     } | ||||
|     // Call the private function to perform the lock operation specified. | ||||
|     ret = perform_lock_unlock_operation(buffer_handle, kLockType, timeout); | ||||
| #endif | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Unlocks a buffer that has previously been locked by the client. | ||||
|  * | ||||
|  * @param: handle of the buffer to be unlocked. | ||||
|  * @return: error status. | ||||
| */ | ||||
| genlock_status_t genlock_unlock_buffer(native_handle_t *buffer_handle) | ||||
| { | ||||
|     genlock_status_t ret = GENLOCK_NO_ERROR; | ||||
| #ifdef USE_GENLOCK | ||||
|     // Do the unlock operation by setting the unlock flag. Timeout is always | ||||
|     // 0 in this case. | ||||
|     ret = perform_lock_unlock_operation(buffer_handle, GENLOCK_UNLOCK, 0); | ||||
| #endif | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Blocks the calling process until the lock held on the handle is unlocked. | ||||
|  * | ||||
|  * @param: handle of the buffer | ||||
|  * @param: timeout value for the wait. | ||||
|  * return: error status. | ||||
|  */ | ||||
| genlock_status_t genlock_wait(native_handle_t *buffer_handle, int timeout) { | ||||
| #ifdef USE_GENLOCK | ||||
|     if (private_handle_t::validate(buffer_handle)) { | ||||
|         LOGE("%s: handle is invalid", __FUNCTION__); | ||||
|         return GENLOCK_FAILURE; | ||||
|     } | ||||
|  | ||||
|     private_handle_t *hnd = reinterpret_cast<private_handle_t*>(buffer_handle); | ||||
|     if (hnd->genlockPrivFd < 0) { | ||||
|         LOGE("%s: the lock is invalid", __FUNCTION__); | ||||
|         return GENLOCK_FAILURE; | ||||
|     } | ||||
|  | ||||
|     if (0 == timeout) | ||||
|         LOGW("%s: timeout = 0", __FUNCTION__); | ||||
|  | ||||
|     genlock_lock lock; | ||||
|     lock.fd = hnd->genlockHandle; | ||||
|     lock.timeout = timeout; | ||||
|     if (ioctl(hnd->genlockPrivFd, GENLOCK_IOC_WAIT, &lock)) { | ||||
|         LOGE("%s: GENLOCK_IOC_WAIT failed (err=%s)",  __FUNCTION__, strerror(errno)); | ||||
|         return GENLOCK_FAILURE; | ||||
|     } | ||||
| #endif | ||||
|     return GENLOCK_NO_ERROR; | ||||
| } | ||||
							
								
								
									
										118
									
								
								libgenlock/genlock.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								libgenlock/genlock.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,118 @@ | ||||
| /* | ||||
|  * 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. | ||||
|  */ | ||||
|  | ||||
| #ifndef INCLUDE_LIBGENLOCK | ||||
| #define INCLUDE_LIBGENLOCK | ||||
|  | ||||
| #include <cutils/native_handle.h> | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| /* Genlock lock types */ | ||||
| typedef enum genlock_lock_type{ | ||||
|     GENLOCK_READ_LOCK  = 1<<0,  // Read lock | ||||
|     GENLOCK_WRITE_LOCK = 1<<1,  // Write lock | ||||
| }genlock_lock_type_t; | ||||
|  | ||||
| /* Genlock return values */ | ||||
| typedef enum genlock_status{ | ||||
|     GENLOCK_NO_ERROR = 0, | ||||
|     GENLOCK_TIMEDOUT, | ||||
|     GENLOCK_FAILURE, | ||||
| } genlock_status_t; | ||||
|  | ||||
| /* Genlock defines */ | ||||
| #define GENLOCK_MAX_TIMEOUT 1000 // Max 1s timeout | ||||
|  | ||||
| /* | ||||
|  * Create a genlock lock. The genlock lock file descriptor and the lock | ||||
|  * handle are stored in the buffer_handle. | ||||
|  * | ||||
|  * @param: handle of the buffer | ||||
|  * @return error status. | ||||
|  */ | ||||
| genlock_status_t genlock_create_lock(native_handle_t *buffer_handle); | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Release a genlock lock associated with the handle. | ||||
|  * | ||||
|  * @param: handle of the buffer | ||||
|  * @return error status. | ||||
|  */ | ||||
| genlock_status_t genlock_release_lock(native_handle_t *buffer_handle); | ||||
|  | ||||
| /* | ||||
|  * Attach a lock to the buffer handle passed via an IPC. | ||||
|  * | ||||
|  * @param: handle of the buffer | ||||
|  * @return error status. | ||||
|  */ | ||||
| genlock_status_t genlock_attach_lock(native_handle_t *buffer_handle); | ||||
|  | ||||
| /* | ||||
|  * Lock the buffer specified by the buffer handle. The lock held by the buffer | ||||
|  * is specified by the lockType. This function will block if a write lock is | ||||
|  * requested on the buffer which has previously been locked for a read or write | ||||
|  * operation. A buffer can be locked by multiple clients for read. An optional | ||||
|  * timeout value can be specified. By default, there is no timeout. | ||||
|  * | ||||
|  * @param: handle of the buffer | ||||
|  * @param: type of lock to be acquired by the buffer. | ||||
|  * @param: timeout value in ms. GENLOCK_MAX_TIMEOUT is the maximum timeout value. | ||||
|  * @return error status. | ||||
|  */ | ||||
| genlock_status_t genlock_lock_buffer(native_handle_t *buffer_handle, | ||||
|                                      genlock_lock_type_t lockType, | ||||
|                                      int timeout); | ||||
|  | ||||
| /* | ||||
|  * Unlocks a buffer that has previously been locked by the client. | ||||
|  * | ||||
|  * @param: handle of the buffer to be unlocked. | ||||
|  * @return: error status. | ||||
| */ | ||||
| genlock_status_t genlock_unlock_buffer(native_handle_t *buffer_handle); | ||||
|  | ||||
| /* | ||||
|  * Blocks the calling process until the lock held on the handle is unlocked. | ||||
|  * | ||||
|  * @param: handle of the buffer | ||||
|  * @param: timeout value for the wait. | ||||
|  * return: error status. | ||||
|  */ | ||||
| genlock_status_t genlock_wait(native_handle_t *buffer_handle, int timeout); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										7
									
								
								libgralloc/Android.mk
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										7
									
								
								libgralloc/Android.mk
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| @@ -21,7 +21,8 @@ include $(CLEAR_VARS) | ||||
| LOCAL_PRELINK_MODULE := false | ||||
| LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw | ||||
| LOCAL_SHARED_LIBRARIES := liblog libcutils libGLESv1_CM libutils libmemalloc | ||||
|  | ||||
| LOCAL_SHARED_LIBRARIES += libgenlock | ||||
| LOCAL_C_INCLUDES += hardware/qcom/display/libgenlock | ||||
| LOCAL_SRC_FILES :=  framebuffer.cpp \ | ||||
|                     gpu.cpp         \ | ||||
|                     gralloc.cpp     \ | ||||
| @@ -41,8 +42,8 @@ ifeq ($(TARGET_HAVE_HDMI_OUT),true) | ||||
|     LOCAL_SHARED_LIBRARIES += liboverlay | ||||
| endif | ||||
|  | ||||
| ifeq ($(TARGET_USES_SF_BYPASS),true) | ||||
|     LOCAL_CFLAGS += -DSF_BYPASS | ||||
| ifeq ($(TARGET_HAVE_BYPASS),true) | ||||
|     LOCAL_CFLAGS += -DCOMPOSITION_BYPASS | ||||
| endif | ||||
|  | ||||
| ifeq ($(TARGET_GRALLOC_USES_ASHMEM),true) | ||||
|   | ||||
| @@ -89,6 +89,7 @@ int IonController::allocate(alloc_data& data, int usage, | ||||
| { | ||||
|     int ionFlags = 0; | ||||
|     int ret; | ||||
|     bool noncontig = false; | ||||
|  | ||||
|     //System heap cannot be uncached | ||||
|     if (usage & GRALLOC_USAGE_PRIVATE_UNCACHED && | ||||
| @@ -106,8 +107,10 @@ int IonController::allocate(alloc_data& data, int usage, | ||||
|     if(usage & GRALLOC_USAGE_PRIVATE_EBI_HEAP) | ||||
|         ionFlags |= 1 << ION_HEAP_EBI_ID; | ||||
|  | ||||
|     if(usage & GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP) | ||||
|     if(usage & GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP) { | ||||
|         ionFlags |= 1 << ION_HEAP_SYSTEM_ID; | ||||
|         noncontig = true; | ||||
|     } | ||||
|  | ||||
|     // if no flags are set, default to | ||||
|     // EBI heap, so that bypass can work | ||||
| @@ -125,11 +128,15 @@ int IonController::allocate(alloc_data& data, int usage, | ||||
|     { | ||||
|         LOGW("Falling back to system heap"); | ||||
|         data.flags = 1 << ION_HEAP_SYSTEM_ID; | ||||
|         noncontig = true; | ||||
|         ret = mIonAlloc->alloc_buffer(data); | ||||
|     } | ||||
|  | ||||
|     if(ret >= 0 ) | ||||
|     if(ret >= 0 ) { | ||||
|         data.allocType = private_handle_t::PRIV_FLAGS_USES_ION; | ||||
|         if(noncontig) | ||||
|             data.allocType |= private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     return ret; | ||||
| @@ -166,6 +173,8 @@ int PmemKernelController::allocate(alloc_data& data, int usage, | ||||
| { | ||||
|     int ret = 0; | ||||
|     bool adspFallback = false; | ||||
|     if (!(usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP)) | ||||
|         adspFallback = true; | ||||
|  | ||||
|     // Try SMI first | ||||
|     if ((usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP) || | ||||
| @@ -181,8 +190,8 @@ int PmemKernelController::allocate(alloc_data& data, int usage, | ||||
|             if(ret >= 0) | ||||
|                 return ret; | ||||
|             else { | ||||
|                 adspFallback = true; | ||||
|                 LOGW("Allocation from SMI failed, trying ADSP"); | ||||
|                 if(adspFallback) | ||||
|                     LOGW("Allocation from SMI failed, trying ADSP"); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -252,8 +261,10 @@ int PmemAshmemController::allocate(alloc_data& data, int usage, | ||||
|  | ||||
|     if(usage & GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP) { | ||||
|         ret = mAshmemAlloc->alloc_buffer(data); | ||||
|         if(ret >= 0) | ||||
|         if(ret >= 0) { | ||||
|             data.allocType = private_handle_t::PRIV_FLAGS_USES_ASHMEM; | ||||
|             data.allocType |= private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM; | ||||
|         } | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
| @@ -269,8 +280,10 @@ int PmemAshmemController::allocate(alloc_data& data, int usage, | ||||
|     } else if(ret < 0 && canFallback(compositionType, usage, false)) { | ||||
|         LOGW("Falling back to ashmem"); | ||||
|         ret = mAshmemAlloc->alloc_buffer(data); | ||||
|         if(ret >= 0) | ||||
|         if(ret >= 0) { | ||||
|             data.allocType = private_handle_t::PRIV_FLAGS_USES_ASHMEM; | ||||
|             data.allocType |= private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return ret; | ||||
|   | ||||
| @@ -103,7 +103,7 @@ int AshmemAlloc::map_buffer(void **pBase, size_t size, int offset, int fd) | ||||
|         return err; | ||||
|  | ||||
|     base = mmap(0, size, PROT_READ| PROT_WRITE, | ||||
|             MAP_SHARED, fd, 0); | ||||
|             MAP_SHARED|MAP_POPULATE, fd, 0); | ||||
|     *pBase = base; | ||||
|     if(base == MAP_FAILED) { | ||||
|         LOGD("%s: Failed to map memory in the client: %s", | ||||
|   | ||||
| @@ -319,7 +319,7 @@ static void *disp_loop(void *ptr) | ||||
|         pthread_mutex_lock(&(m->qlock)); | ||||
|  | ||||
|         // wait (sleep) while display queue is empty; | ||||
|         if (m->disp.isEmpty()) { | ||||
|         while (m->disp.isEmpty()) { | ||||
|             pthread_cond_wait(&(m->qpost),&(m->qlock)); | ||||
|         } | ||||
|  | ||||
| @@ -347,6 +347,14 @@ static void *disp_loop(void *ptr) | ||||
|             LOGE("ERROR FBIOPUT_VSCREENINFO failed; frame not displayed"); | ||||
|         } | ||||
|  | ||||
| #if defined COMPOSITION_BYPASS | ||||
|         //Signal so that we can close channels if we need to | ||||
|         pthread_mutex_lock(&m->bufferPostLock); | ||||
|         m->bufferPostDone = true; | ||||
|         pthread_cond_signal(&m->bufferPostCond); | ||||
|         pthread_mutex_unlock(&m->bufferPostLock); | ||||
| #endif | ||||
|  | ||||
| #ifdef DEBUG_CALC_FPS | ||||
|         if (debug_fps_level > 0) calc_fps(ns2us(systemTime())); | ||||
| #endif | ||||
| @@ -599,6 +607,34 @@ static int fb_orientationChanged(struct framebuffer_device_t* dev, int orientati | ||||
| } | ||||
| #endif | ||||
|  | ||||
| //Wait until framebuffer content is displayed. | ||||
| //This is called in the context of threadLoop. | ||||
| //Display loop wakes this up after display. | ||||
| static int fb_waitForBufferPost(struct framebuffer_device_t* dev) | ||||
| { | ||||
| #if defined COMPOSITION_BYPASS | ||||
|     private_module_t* m = reinterpret_cast<private_module_t*>( | ||||
|             dev->common.module); | ||||
|     pthread_mutex_lock(&m->bufferPostLock); | ||||
|     while(m->bufferPostDone == false) { | ||||
|         pthread_cond_wait(&(m->bufferPostCond), &(m->bufferPostLock)); | ||||
|     } | ||||
|     pthread_mutex_unlock(&m->bufferPostLock); | ||||
| #endif | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int fb_resetBufferPostStatus(struct framebuffer_device_t* dev) | ||||
| { | ||||
| #if defined COMPOSITION_BYPASS | ||||
|     private_module_t* m = reinterpret_cast<private_module_t*>( | ||||
|             dev->common.module); | ||||
|     pthread_mutex_lock(&m->bufferPostLock); | ||||
|     m->bufferPostDone = false; | ||||
|     pthread_mutex_unlock(&m->bufferPostLock); | ||||
| #endif | ||||
|     return 0; | ||||
| } | ||||
| static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) | ||||
| { | ||||
|     if (private_handle_t::validate(buffer) < 0) | ||||
| @@ -990,6 +1026,11 @@ int mapFrameBufferLocked(struct private_module_t* module) | ||||
|     pthread_t hdmiUIThread; | ||||
|     pthread_create(&hdmiUIThread, NULL, &hdmi_ui_loop, (void *) module); | ||||
| #endif | ||||
| #if defined COMPOSITION_BYPASS | ||||
|     pthread_mutex_init(&(module->bufferPostLock), NULL); | ||||
|     pthread_cond_init(&(module->bufferPostCond), NULL); | ||||
|     module->bufferPostDone = false; | ||||
| #endif | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
| @@ -1053,6 +1094,11 @@ int fb_device_open(hw_module_t const* module, const char* name, | ||||
|         dev->device.setActionSafeHeightRatio = fb_setActionSafeHeightRatio; | ||||
| #endif | ||||
|  | ||||
| #if defined COMPOSITION_BYPASS | ||||
|         dev->device.waitForBufferPost = fb_waitForBufferPost; | ||||
|         dev->device.resetBufferPostStatus = fb_resetBufferPostStatus; | ||||
| #endif | ||||
|  | ||||
|         private_module_t* m = (private_module_t*)module; | ||||
|         status = mapFrameBuffer(m); | ||||
|         if (status >= 0) { | ||||
|   | ||||
							
								
								
									
										31
									
								
								libgralloc/gpu.cpp
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										31
									
								
								libgralloc/gpu.cpp
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| @@ -21,16 +21,13 @@ | ||||
| #include <cutils/properties.h> | ||||
| #include <sys/mman.h> | ||||
|  | ||||
| #include <genlock.h> | ||||
|  | ||||
| #include "gr.h" | ||||
| #include "gpu.h" | ||||
| #include "memalloc.h" | ||||
| #include "alloc_controller.h" | ||||
|  | ||||
| static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00; | ||||
| static const int QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka = 0x7FA30C03; | ||||
| static const int QOMX_INTERLACE_FLAG = 0x49283654; | ||||
| static const int QOMX_3D_VIDEO_FLAG = 0x23784238; | ||||
|  | ||||
| using namespace gralloc; | ||||
| using android::sp; | ||||
|  | ||||
| @@ -170,7 +167,6 @@ int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, | ||||
|  | ||||
|         hnd->offset = data.offset; | ||||
|         hnd->base = int(data.base) + data.offset; | ||||
|         hnd->lockState = private_handle_t::LOCK_STATE_MAPPED; | ||||
|         *pHandle = hnd; | ||||
|     } | ||||
|  | ||||
| @@ -247,6 +243,7 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage, | ||||
|             size  = ALIGN( alignedw * alignedh, 8192); | ||||
|             size += ALIGN( alignedw * ALIGN(h/2, 32), 8192); | ||||
|             break; | ||||
|         case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: | ||||
|         case HAL_PIXEL_FORMAT_YCbCr_420_SP: | ||||
|         case HAL_PIXEL_FORMAT_YCrCb_420_SP: | ||||
|         case HAL_PIXEL_FORMAT_YV12: | ||||
| @@ -256,8 +253,14 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage, | ||||
|             } | ||||
|             alignedw = ALIGN(w, 16); | ||||
|             alignedh = h; | ||||
|             size = alignedw*alignedh + | ||||
|             if (HAL_PIXEL_FORMAT_NV12_ENCODEABLE == colorFormat) { | ||||
|                 // The encoder requires a 2K aligned chroma offset. | ||||
|                 size = ALIGN(alignedw*alignedh, 2048) + | ||||
|                        (ALIGN(alignedw/2, 16) * (alignedh/2))*2; | ||||
|             } else { | ||||
|                 size = alignedw*alignedh + | ||||
|                     (ALIGN(alignedw/2, 16) * (alignedh/2))*2; | ||||
|             } | ||||
|             size = ALIGN(size, 4096); | ||||
|             break; | ||||
|  | ||||
| @@ -289,6 +292,13 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage, | ||||
|         return err; | ||||
|     } | ||||
|  | ||||
|     // Create a genlock lock for this buffer handle. | ||||
|     err = genlock_create_lock((native_handle_t*)(*pHandle)); | ||||
|     if (err) { | ||||
|         LOGE("%s: genlock_create_lock failed", __FUNCTION__); | ||||
|         free_impl(reinterpret_cast<private_handle_t*>(pHandle)); | ||||
|         return err; | ||||
|     } | ||||
|     *pStride = alignedw; | ||||
|     return 0; | ||||
| } | ||||
| @@ -308,6 +318,13 @@ int gpu_context_t::free_impl(private_handle_t const* hnd) { | ||||
|             return err; | ||||
|         terminateBuffer(&m->base, const_cast<private_handle_t*>(hnd)); | ||||
|     } | ||||
|  | ||||
|     // Release the genlock | ||||
|     int err = genlock_release_lock((native_handle_t*)hnd); | ||||
|     if (err) { | ||||
|         LOGE("%s: genlock_release_lock failed", __FUNCTION__); | ||||
|     } | ||||
|  | ||||
|     delete hnd; | ||||
|     return 0; | ||||
| } | ||||
|   | ||||
| @@ -52,6 +52,13 @@ enum { | ||||
|     GRALLOC_USAGE_PRIVATE_ION = 0x00020000, | ||||
| }; | ||||
|  | ||||
| enum { | ||||
|     /* Gralloc perform enums | ||||
|     */ | ||||
|     GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER = 0x080000001, | ||||
| }; | ||||
|  | ||||
|  | ||||
| enum { | ||||
|     GPU_COMPOSITION, | ||||
|     C2D_COMPOSITION, | ||||
| @@ -155,14 +162,7 @@ private: | ||||
|  | ||||
| enum { | ||||
|     /* OEM specific HAL formats */ | ||||
|     //HAL_PIXEL_FORMAT_YCbCr_422_SP = 0x100, // defined in hardware.h | ||||
|     //HAL_PIXEL_FORMAT_YCrCb_420_SP = 0x101, // defined in hardware.h | ||||
|     HAL_PIXEL_FORMAT_YCbCr_422_P  = 0x102, | ||||
|     HAL_PIXEL_FORMAT_YCbCr_420_P  = 0x103, | ||||
|     //HAL_PIXEL_FORMAT_YCbCr_422_I  = 0x104, // defined in hardware.h | ||||
|     HAL_PIXEL_FORMAT_YCbCr_420_I  = 0x105, | ||||
|     HAL_PIXEL_FORMAT_CbYCrY_422_I = 0x106, | ||||
|     HAL_PIXEL_FORMAT_CbYCrY_420_I = 0x107, | ||||
|     HAL_PIXEL_FORMAT_NV12_ENCODEABLE  = 0x102, | ||||
|     HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED     = 0x108, | ||||
|     HAL_PIXEL_FORMAT_YCbCr_420_SP           = 0x109, | ||||
|     HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO    = 0x10A, | ||||
| @@ -260,6 +260,11 @@ struct private_module_t { | ||||
|     pthread_mutex_t overlayLock; | ||||
|     pthread_cond_t overlayPost; | ||||
| #endif | ||||
| #ifdef COMPOSITION_BYPASS | ||||
|     pthread_mutex_t bufferPostLock; | ||||
|     pthread_cond_t bufferPostCond; | ||||
|     bool bufferPostDone; | ||||
| #endif | ||||
| }; | ||||
|  | ||||
| /*****************************************************************************/ | ||||
| @@ -278,16 +283,14 @@ struct private_handle_t { | ||||
|         PRIV_FLAGS_USES_ASHMEM    = 0x00000010, | ||||
|         PRIV_FLAGS_NEEDS_FLUSH    = 0x00000020, | ||||
|         PRIV_FLAGS_DO_NOT_FLUSH   = 0x00000040, | ||||
|     }; | ||||
|  | ||||
|     enum { | ||||
|         LOCK_STATE_WRITE     =   1<<31, | ||||
|         LOCK_STATE_MAPPED    =   1<<30, | ||||
|         LOCK_STATE_READ_MASK =   0x3FFFFFFF | ||||
|         PRIV_FLAGS_SW_LOCK        = 0x00000080, | ||||
|         PRIV_FLAGS_NONCONTIGUOUS_MEM = 0x00000100, | ||||
|         PRIV_FLAGS_HWC_LOCK       = 0x00000200, // Set by HWC when storing the handle | ||||
|     }; | ||||
|  | ||||
|     // file-descriptors | ||||
|     int     fd; | ||||
|     int     genlockHandle; // genlock handle to be dup'd by the binder | ||||
|     // ints | ||||
|     int     magic; | ||||
|     int     flags; | ||||
| @@ -297,23 +300,22 @@ struct private_handle_t { | ||||
|  | ||||
|     // FIXME: the attributes below should be out-of-line | ||||
|     int     base; | ||||
|     int     lockState; | ||||
|     int     writeOwner; | ||||
|     int     gpuaddr; // The gpu address mapped into the mmu. If using ashmem, set to 0 They don't care | ||||
|     int     pid; | ||||
|     int     format; | ||||
|     int     width; | ||||
|     int     height; | ||||
|     int     genlockPrivFd; // local fd of the genlock device. | ||||
|  | ||||
| #ifdef __cplusplus | ||||
|     static const int sNumInts = 13; | ||||
|     static const int sNumFds = 1; | ||||
|     static const int sNumInts = 12; | ||||
|     static const int sNumFds = 2; | ||||
|     static const int sMagic = 'gmsm'; | ||||
|  | ||||
|     private_handle_t(int fd, int size, int flags, int bufferType, int format, int width, int height) : | ||||
|         fd(fd), magic(sMagic), flags(flags), size(size), offset(0), bufferType(bufferType), | ||||
|         base(0), lockState(0), writeOwner(0), gpuaddr(0), pid(getpid()), format(format), width(width), | ||||
|         height(height) | ||||
|         fd(fd), genlockHandle(-1), magic(sMagic), flags(flags), size(size), offset(0), | ||||
|         bufferType(bufferType), base(0), gpuaddr(0), pid(getpid()), format(format), | ||||
|         width(width), height(height), genlockPrivFd(-1) | ||||
|     { | ||||
|         version = sizeof(native_handle); | ||||
|         numInts = sNumInts; | ||||
|   | ||||
| @@ -139,10 +139,9 @@ int IonAlloc::alloc_buffer(alloc_data& data) | ||||
|         close(ionSyncFd); | ||||
|     ionSyncFd = FD_INIT; | ||||
|  | ||||
|     // Not doing memset for ION, uncomment if needed | ||||
|     // memset(base, 0, ionAllocData.len); | ||||
|     memset(base, 0, ionAllocData.len); | ||||
|     // Clean cache after memset | ||||
|     // clean_buffer(base, data.size, data.offset, fd_data.fd); | ||||
|     clean_buffer(base, data.size, data.offset, fd_data.fd); | ||||
|     data.base = base; | ||||
|     data.fd = fd_data.fd; | ||||
|     ioctl(mIonFd, ION_IOC_FREE, &handle_data); | ||||
|   | ||||
							
								
								
									
										186
									
								
								libgralloc/mapper.cpp
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										186
									
								
								libgralloc/mapper.cpp
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| @@ -34,6 +34,7 @@ | ||||
|  | ||||
| #include <hardware/hardware.h> | ||||
| #include <hardware/gralloc.h> | ||||
| #include <genlock.h> | ||||
|  | ||||
| #include <linux/android_pmem.h> | ||||
|  | ||||
| @@ -132,8 +133,31 @@ int gralloc_register_buffer(gralloc_module_t const* module, | ||||
|     private_handle_t* hnd = (private_handle_t*)handle; | ||||
|     if (hnd->pid != getpid()) { | ||||
|         hnd->base = 0; | ||||
|         hnd->lockState  = 0; | ||||
|         hnd->writeOwner = 0; | ||||
|         void *vaddr; | ||||
|         int err = gralloc_map(module, handle, &vaddr); | ||||
|         if (err) { | ||||
|             LOGE("%s: gralloc_map failed", __FUNCTION__); | ||||
|             return err; | ||||
|         } | ||||
|  | ||||
|         // Reset the genlock private fd flag in the handle | ||||
|         hnd->genlockPrivFd = -1; | ||||
|  | ||||
|         // Check if there is a valid lock attached to the handle. | ||||
|         if (-1 == hnd->genlockHandle) { | ||||
|             LOGE("%s: the lock is invalid.", __FUNCTION__); | ||||
|             gralloc_unmap(module, handle); | ||||
|             hnd->base = 0; | ||||
|             return -EINVAL; | ||||
|         } | ||||
|  | ||||
|         // Attach the genlock handle | ||||
|         if (GENLOCK_FAILURE == genlock_attach_lock((native_handle_t *)handle)) { | ||||
|             LOGE("%s: genlock_attach_lock failed", __FUNCTION__); | ||||
|             gralloc_unmap(module, handle); | ||||
|             hnd->base = 0; | ||||
|             return -EINVAL; | ||||
|         } | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
| @@ -152,18 +176,19 @@ int gralloc_unregister_buffer(gralloc_module_t const* module, | ||||
|  | ||||
|     private_handle_t* hnd = (private_handle_t*)handle; | ||||
|  | ||||
|     LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK, | ||||
|             "[unregister] handle %p still locked (state=%08x)", | ||||
|             hnd, hnd->lockState); | ||||
|  | ||||
|     // never unmap buffers that were created in this process | ||||
|     if (hnd->pid != getpid()) { | ||||
|         if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) { | ||||
|         if (hnd->base != 0) { | ||||
|             gralloc_unmap(module, handle); | ||||
|         } | ||||
|         hnd->base = 0; | ||||
|         hnd->lockState  = 0; | ||||
|         hnd->writeOwner = 0; | ||||
|         // Release the genlock | ||||
|         if (-1 != hnd->genlockHandle) { | ||||
|             return genlock_release_lock((native_handle_t *)handle); | ||||
|         } else { | ||||
|             LOGE("%s: there was no genlock attached to this buffer", __FUNCTION__); | ||||
|             return -EINVAL; | ||||
|         } | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
| @@ -176,11 +201,7 @@ int terminateBuffer(gralloc_module_t const* module, | ||||
|      * to un-map it. It's an error to be here with a locked buffer. | ||||
|      */ | ||||
|  | ||||
|     LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK, | ||||
|             "[terminate] handle %p still locked (state=%08x)", | ||||
|             hnd, hnd->lockState); | ||||
|  | ||||
|     if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) { | ||||
|     if (hnd->base != 0) { | ||||
|         // this buffer was mapped, unmap it now | ||||
|         if (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM | | ||||
|                           private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP | | ||||
| @@ -211,70 +232,43 @@ int gralloc_lock(gralloc_module_t const* module, | ||||
|  | ||||
|     int err = 0; | ||||
|     private_handle_t* hnd = (private_handle_t*)handle; | ||||
|     int32_t current_value, new_value; | ||||
|     int retry; | ||||
|  | ||||
|     do { | ||||
|         current_value = hnd->lockState; | ||||
|         new_value = current_value; | ||||
|  | ||||
|         if (current_value & private_handle_t::LOCK_STATE_WRITE) { | ||||
|             // already locked for write | ||||
|             LOGE("handle %p already locked for write", handle); | ||||
|             return -EBUSY; | ||||
|         } else if (current_value & private_handle_t::LOCK_STATE_READ_MASK) { | ||||
|             // already locked for read | ||||
|             if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) { | ||||
|                 LOGE("handle %p already locked for read", handle); | ||||
|                 return -EBUSY; | ||||
|             } else { | ||||
|                 // this is not an error | ||||
|                 //LOGD("%p already locked for read... count = %d", | ||||
|                 //        handle, (current_value & ~(1<<31))); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // not currently locked | ||||
|         if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) { | ||||
|             // locking for write | ||||
|             new_value |= private_handle_t::LOCK_STATE_WRITE; | ||||
|         } | ||||
|         new_value++; | ||||
|  | ||||
|         retry = android_atomic_cmpxchg(current_value, new_value, | ||||
|                 (volatile int32_t*)&hnd->lockState); | ||||
|     } while (retry); | ||||
|  | ||||
|     if (new_value & private_handle_t::LOCK_STATE_WRITE) { | ||||
|         // locking for write, store the tid | ||||
|         hnd->writeOwner = gettid(); | ||||
|     } | ||||
|  | ||||
|     // if requesting sw write for non-framebuffer handles, flag for | ||||
|     // flushing at unlock | ||||
|  | ||||
|     if ((usage & GRALLOC_USAGE_SW_WRITE_MASK) && | ||||
|             !(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { | ||||
|         hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH; | ||||
|     } | ||||
|  | ||||
|     if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) { | ||||
|         if (!(current_value & private_handle_t::LOCK_STATE_MAPPED)) { | ||||
|         if (hnd->base == 0) { | ||||
|             // we need to map for real | ||||
|             pthread_mutex_t* const lock = &sMapLock; | ||||
|             pthread_mutex_lock(lock); | ||||
|             if (!(hnd->lockState & private_handle_t::LOCK_STATE_MAPPED)) { | ||||
|                 err = gralloc_map(module, handle, vaddr); | ||||
|                 if (err == 0) { | ||||
|                     android_atomic_or(private_handle_t::LOCK_STATE_MAPPED, | ||||
|                             (volatile int32_t*)&(hnd->lockState)); | ||||
|                 } | ||||
|             } | ||||
|             err = gralloc_map(module, handle, vaddr); | ||||
|             pthread_mutex_unlock(lock); | ||||
|         } | ||||
|         *vaddr = (void*)hnd->base; | ||||
|     } | ||||
|  | ||||
|         // Lock the buffer for read/write operation as specified. Write lock | ||||
|         // has a higher priority over read lock. | ||||
|         int lockType = 0; | ||||
|         if (usage & GRALLOC_USAGE_SW_WRITE_MASK) { | ||||
|             lockType = GENLOCK_WRITE_LOCK; | ||||
|         } else if (usage & GRALLOC_USAGE_SW_READ_MASK) { | ||||
|             lockType = GENLOCK_READ_LOCK; | ||||
|         } | ||||
|  | ||||
|         int timeout = GENLOCK_MAX_TIMEOUT; | ||||
|         if (GENLOCK_FAILURE == genlock_lock_buffer((native_handle_t *)handle, | ||||
|                                                    (genlock_lock_type)lockType, | ||||
|                                                    timeout)) { | ||||
|             LOGE("%s: genlock_lock_buffer (lockType=0x%x) failed", __FUNCTION__, | ||||
|                 lockType); | ||||
|             return -EINVAL; | ||||
|         } else { | ||||
|             // Mark this buffer as locked for SW read/write operation. | ||||
|             hnd->flags |= private_handle_t::PRIV_FLAGS_SW_LOCK; | ||||
|         } | ||||
|  | ||||
|         if ((usage & GRALLOC_USAGE_SW_WRITE_MASK) && | ||||
|             !(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { | ||||
|             // Mark the buffer to be flushed after cpu read/write | ||||
|             hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH; | ||||
|         } | ||||
|     } | ||||
|     return err; | ||||
| } | ||||
|  | ||||
| @@ -285,7 +279,6 @@ int gralloc_unlock(gralloc_module_t const* module, | ||||
|         return -EINVAL; | ||||
|  | ||||
|     private_handle_t* hnd = (private_handle_t*)handle; | ||||
|     int32_t current_value, new_value; | ||||
|  | ||||
|     if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) { | ||||
|         int err; | ||||
| @@ -297,28 +290,14 @@ int gralloc_unlock(gralloc_module_t const* module, | ||||
|         hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH; | ||||
|     } | ||||
|  | ||||
|     do { | ||||
|         current_value = hnd->lockState; | ||||
|         new_value = current_value; | ||||
|  | ||||
|         if (current_value & private_handle_t::LOCK_STATE_WRITE) { | ||||
|             // locked for write | ||||
|             if (hnd->writeOwner == gettid()) { | ||||
|                 hnd->writeOwner = 0; | ||||
|                 new_value &= ~private_handle_t::LOCK_STATE_WRITE; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if ((new_value & private_handle_t::LOCK_STATE_READ_MASK) == 0) { | ||||
|             LOGE("handle %p not locked", handle); | ||||
|     if ((hnd->flags & private_handle_t::PRIV_FLAGS_SW_LOCK)) { | ||||
|         // Unlock the buffer. | ||||
|         if (GENLOCK_FAILURE == genlock_unlock_buffer((native_handle_t *)handle)) { | ||||
|             LOGE("%s: genlock_unlock_buffer failed", __FUNCTION__); | ||||
|             return -EINVAL; | ||||
|         } | ||||
|  | ||||
|         new_value--; | ||||
|  | ||||
|     } while (android_atomic_cmpxchg(current_value, new_value, | ||||
|                 (volatile int32_t*)&hnd->lockState)); | ||||
|  | ||||
|         } else | ||||
|             hnd->flags &= ~private_handle_t::PRIV_FLAGS_SW_LOCK; | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| @@ -330,7 +309,6 @@ int gralloc_perform(struct gralloc_module_t const* module, | ||||
|     int res = -EINVAL; | ||||
|     va_list args; | ||||
|     va_start(args, operation); | ||||
| #if 0 | ||||
|     switch (operation) { | ||||
|         case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER: | ||||
|             { | ||||
| @@ -338,6 +316,9 @@ int gralloc_perform(struct gralloc_module_t const* module, | ||||
|                 size_t size = va_arg(args, size_t); | ||||
|                 size_t offset = va_arg(args, size_t); | ||||
|                 void* base = va_arg(args, void*); | ||||
|                 int width = va_arg(args, int); | ||||
|                 int height = va_arg(args, int); | ||||
|                 int format = va_arg(args, int); | ||||
|  | ||||
|                 native_handle_t** handle = va_arg(args, native_handle_t**); | ||||
|                 int memoryFlags = va_arg(args, int); | ||||
| @@ -367,31 +348,18 @@ int gralloc_perform(struct gralloc_module_t const* module, | ||||
|                 hnd->size = size; | ||||
|                 hnd->offset = offset; | ||||
|                 hnd->base = intptr_t(base) + offset; | ||||
|                 hnd->lockState = private_handle_t::LOCK_STATE_MAPPED; | ||||
|                 hnd->gpuaddr = 0; | ||||
|                 hnd->width = width; | ||||
|                 hnd->height = height; | ||||
|                 hnd->format = format; | ||||
|                 *handle = (native_handle_t *)hnd; | ||||
|                 res = 0; | ||||
|                 break; | ||||
|  | ||||
|             } | ||||
|         case GRALLOC_MODULE_PERFORM_UPDATE_BUFFER_HANDLE: | ||||
|             { | ||||
|                 native_handle_t* handle = va_arg(args, native_handle_t*); | ||||
|                 int w = va_arg(args, int); | ||||
|                 int h = va_arg(args, int); | ||||
|                 int f = va_arg(args, int); | ||||
|                 private_handle_t* hnd = (private_handle_t*)handle; | ||||
|                 hnd->width = w; | ||||
|                 hnd->height = h; | ||||
|                 if (hnd->format != f) { | ||||
|                     hnd->format = f; | ||||
|                 } | ||||
|                 break; | ||||
|             } | ||||
|         default: | ||||
|             break; | ||||
|     } | ||||
| #endif | ||||
|     va_end(args); | ||||
|     return res; | ||||
| } | ||||
|   | ||||
							
								
								
									
										8
									
								
								libhwcomposer/Android.mk
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										8
									
								
								libhwcomposer/Android.mk
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| @@ -6,18 +6,26 @@ include $(CLEAR_VARS) | ||||
| LOCAL_PRELINK_MODULE := false | ||||
| LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw | ||||
| LOCAL_SHARED_LIBRARIES := liblog libcutils libEGL libhardware libutils liboverlay | ||||
| LOCAL_SHARED_LIBRARIES += libgenlock | ||||
|  | ||||
| LOCAL_SRC_FILES := 	\ | ||||
| 	hwcomposer.cpp | ||||
| 	 | ||||
| LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM) | ||||
| LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).hwcomposer\" | ||||
|  | ||||
| LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc | ||||
| LOCAL_C_INCLUDES += hardware/qcom/display/liboverlay | ||||
| LOCAL_C_INCLUDES += hardware/qcom/display/libcopybit | ||||
| LOCAL_C_INCLUDES += hardware/qcom/display/libgenlock | ||||
| LOCAL_C_INCLUDES += hardware/qcom/display/libqcomui | ||||
|  | ||||
| ifeq ($(TARGET_HAVE_HDMI_OUT),true) | ||||
| LOCAL_CFLAGS += -DHDMI_DUAL_DISPLAY | ||||
| endif | ||||
| ifeq ($(TARGET_USES_OVERLAY),true) | ||||
| LOCAL_CFLAGS += -DUSE_OVERLAY | ||||
| endif | ||||
| ifeq ($(TARGET_HAVE_BYPASS),true) | ||||
| LOCAL_CFLAGS += -DCOMPOSITION_BYPASS | ||||
| endif | ||||
|   | ||||
							
								
								
									
										277
									
								
								libhwcomposer/hwcomposer.cpp
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										277
									
								
								libhwcomposer/hwcomposer.cpp
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| @@ -37,6 +37,8 @@ | ||||
| #include <EGL/eglext.h> | ||||
| #include <ui/android_native_buffer.h> | ||||
| #include <gralloc_priv.h> | ||||
| #include <genlock.h> | ||||
| #include <qcom_ui.h> | ||||
|  | ||||
| /*****************************************************************************/ | ||||
| #define ALIGN(x, align) (((x) + ((align)-1)) & ~((align)-1)) | ||||
| @@ -58,12 +60,6 @@ enum HWCCompositionType { | ||||
|     HWC_USE_COPYBIT                // This layer is to be handled by copybit | ||||
| }; | ||||
|  | ||||
| enum HWCPrivateFlags { | ||||
|     HWC_USE_ORIGINAL_RESOLUTION = HWC_FLAGS_PRIVATE_0, // This layer is to be drawn using overlays | ||||
|     HWC_DO_NOT_USE_OVERLAY      = HWC_FLAGS_PRIVATE_1, // Do not use overlays to draw this layer | ||||
|     HWC_COMP_BYPASS             = HWC_FLAGS_PRIVATE_3, // Layer "might" use or have used bypass | ||||
| }; | ||||
|  | ||||
| enum HWCLayerType{ | ||||
|     HWC_SINGLE_VIDEO           = 0x1, | ||||
|     HWC_ORIG_RESOLUTION        = 0x2, | ||||
| @@ -82,6 +78,11 @@ enum { | ||||
|     MAX_BYPASS_LAYERS = 2, | ||||
|     ANIM_FRAME_COUNT = 30, | ||||
| }; | ||||
|  | ||||
| enum BypassBufferLockState { | ||||
|     BYPASS_BUFFER_UNLOCKED, | ||||
|     BYPASS_BUFFER_LOCKED, | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| enum eHWCOverlayStatus { | ||||
| @@ -94,8 +95,11 @@ struct hwc_context_t { | ||||
|     hwc_composer_device_t device; | ||||
|     /* our private state goes below here */ | ||||
|     overlay::Overlay* mOverlayLibObject; | ||||
|     native_handle_t *previousOverlayHandle; | ||||
| #ifdef COMPOSITION_BYPASS | ||||
|     overlay::OverlayUI* mOvUI[MAX_BYPASS_LAYERS]; | ||||
|     native_handle_t* previousBypassHandle[MAX_BYPASS_LAYERS]; | ||||
|     BypassBufferLockState bypassBufferLockState[MAX_BYPASS_LAYERS]; | ||||
|     int animCount; | ||||
|     BypassState bypassState; | ||||
| #endif | ||||
| @@ -227,14 +231,39 @@ static int hwc_closeOverlayChannels(hwc_context_t* ctx) { | ||||
|  | ||||
| #ifdef COMPOSITION_BYPASS | ||||
| // To-do: Merge this with other blocks & move them to a separate file. | ||||
| void unlockPreviousBypassBuffers(hwc_context_t* ctx) { | ||||
|     // Unlock the previous bypass buffers. We can blindly unlock the buffers here, | ||||
|     // because buffers will be in this list only if the lock was successfully acquired. | ||||
|     for(int i = 0; i < MAX_BYPASS_LAYERS; i++) { | ||||
|         if (ctx->previousBypassHandle[i]) { | ||||
|             private_handle_t *hnd = (private_handle_t*) ctx->previousBypassHandle[i]; | ||||
|             // Validate the handle to make sure it hasn't been deallocated. | ||||
|             if (private_handle_t::validate(ctx->previousBypassHandle[i])) { | ||||
|                 continue; | ||||
|             } | ||||
|             // Check if the handle was locked previously | ||||
|             if (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags) { | ||||
|                 if (GENLOCK_FAILURE == genlock_unlock_buffer(ctx->previousBypassHandle[i])) { | ||||
|                     LOGE("%s: genlock_unlock_buffer failed", __FUNCTION__); | ||||
|                 } else { | ||||
|                     ctx->previousBypassHandle[i] = NULL; | ||||
|                     // Reset the lock flag | ||||
|                     hnd->flags &= ~private_handle_t::PRIV_FLAGS_HWC_LOCK; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| void closeBypass(hwc_context_t* ctx) { | ||||
|     for (int index = 0 ; index < MAX_BYPASS_LAYERS; index++) { | ||||
|         ctx->mOvUI[index]->closeChannel(); | ||||
|         unlockPreviousBypassBuffers(ctx); | ||||
|         for (int index = 0 ; index < MAX_BYPASS_LAYERS; index++) { | ||||
|             ctx->mOvUI[index]->closeChannel(); | ||||
|         } | ||||
|         #ifdef DEBUG | ||||
|             LOGE("%s", __FUNCTION__); | ||||
|         #endif | ||||
|     } | ||||
| } | ||||
| #endif | ||||
|  | ||||
| /* | ||||
| @@ -307,6 +336,25 @@ static int prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer, const bool wai | ||||
|      return 0; | ||||
| } | ||||
|  | ||||
| void unlockPreviousOverlayBuffer(hwc_context_t* ctx) | ||||
| { | ||||
|     if (ctx->previousOverlayHandle) { | ||||
|         // Validate the handle before attempting to use it. | ||||
|         if (!private_handle_t::validate(ctx->previousOverlayHandle)) { | ||||
|             private_handle_t *hnd = (private_handle_t*)ctx->previousOverlayHandle; | ||||
|             // Unlock any previously locked buffers | ||||
|             if (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags) { | ||||
|                 if (GENLOCK_NO_ERROR == genlock_unlock_buffer(ctx->previousOverlayHandle)) { | ||||
|                     ctx->previousOverlayHandle = NULL; | ||||
|                     hnd->flags &= ~private_handle_t::PRIV_FLAGS_HWC_LOCK; | ||||
|                 } else { | ||||
|                     LOGE("%s: genlock_unlock_buffer failed", __FUNCTION__); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| bool canSkipComposition(hwc_context_t* ctx, int yuvBufferCount, int currentLayerCount, | ||||
|                         int numLayersNotUpdating) | ||||
| { | ||||
| @@ -459,9 +507,21 @@ static int drawLayerUsingBypass(hwc_context_t *ctx, hwc_layer_t *layer, | ||||
|         overlay::OverlayUI *ovUI = ctx->mOvUI[index]; | ||||
|         int ret = 0; | ||||
|         private_handle_t *hnd = (private_handle_t *)layer->handle; | ||||
|         ctx->bypassBufferLockState[index] = BYPASS_BUFFER_UNLOCKED; | ||||
|         if (GENLOCK_FAILURE == genlock_lock_buffer(hnd, GENLOCK_READ_LOCK, | ||||
|                                                    GENLOCK_MAX_TIMEOUT)) { | ||||
|             LOGE("%s: genlock_lock_buffer(READ) failed", __FUNCTION__); | ||||
|             return -1; | ||||
|         } | ||||
|         ctx->bypassBufferLockState[index] = BYPASS_BUFFER_LOCKED; | ||||
|         ret = ovUI->queueBuffer(hnd); | ||||
|         if (ret) { | ||||
|             LOGE("drawLayerUsingBypass queueBuffer failed"); | ||||
|             // Unlock the locked buffer | ||||
|             if (GENLOCK_FAILURE == genlock_unlock_buffer(hnd)) { | ||||
|                 LOGE("%s: genlock_unlock_buffer failed", __FUNCTION__); | ||||
|             } | ||||
|             ctx->bypassBufferLockState[index] = BYPASS_BUFFER_UNLOCKED; | ||||
|             return -1; | ||||
|         } | ||||
|     } | ||||
| @@ -498,9 +558,26 @@ static bool isDisjoint(const hwc_layer_list_t* list) { | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| static bool usesContiguousMemory(const hwc_layer_list_t* list) { | ||||
|     for(int i = 0; i < list->numHwLayers; i++) { | ||||
|         const private_handle_t *hnd = | ||||
|             reinterpret_cast<const private_handle_t *>(list->hwLayers[i].handle); | ||||
|         if(hnd != NULL && (hnd->flags & | ||||
|                            private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM | ||||
|                           )) { | ||||
|             // Bypass cannot work for non contiguous buffers | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Checks if doing comp. bypass is possible. If video is not on and there | ||||
|  * are 2 layers then its doable. | ||||
|  * Checks if doing comp. bypass is possible. | ||||
|  * It is possible if | ||||
|  * 1. If video is not on | ||||
|  * 2. There are 2 layers | ||||
|  * 3. The memory type is contiguous | ||||
|  */ | ||||
| inline static bool isBypassDoable(hwc_composer_device_t *dev, const int yuvCount, | ||||
|         const hwc_layer_list_t* list) { | ||||
| @@ -511,6 +588,9 @@ inline static bool isBypassDoable(hwc_composer_device_t *dev, const int yuvCount | ||||
|     if(hwcModule->isBypassEnabled == false) { | ||||
|         return false; | ||||
|     } | ||||
|     // Check if memory type is contiguous | ||||
|     if(!usesContiguousMemory(list)) | ||||
|        return false; | ||||
|     //Disable bypass during animation | ||||
|     if(UNLIKELY(ctx->animCount)) { | ||||
|         --(ctx->animCount); | ||||
| @@ -570,6 +650,25 @@ void unsetBypassLayerFlags(hwc_layer_list_t* list) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| void unsetBypassBufferLockState(hwc_context_t* ctx) { | ||||
|     for (int i=0; i< MAX_BYPASS_LAYERS; i++) { | ||||
|         ctx->bypassBufferLockState[i] = BYPASS_BUFFER_UNLOCKED; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void storeLockedBypassHandle(hwc_layer_list_t* list, hwc_context_t* ctx) { | ||||
|     for (int index = 0 ; index < list->numHwLayers; index++) { | ||||
|         // Store the current bypass handle. | ||||
|         if (list->hwLayers[index].flags == HWC_COMP_BYPASS) { | ||||
|             private_handle_t *hnd = (private_handle_t*)list->hwLayers[index].handle; | ||||
|             if (ctx->bypassBufferLockState[index] == BYPASS_BUFFER_LOCKED) { | ||||
|                 ctx->previousBypassHandle[index] = (native_handle_t*)list->hwLayers[index].handle; | ||||
|                 hnd->flags |= private_handle_t::PRIV_FLAGS_HWC_LOCK; | ||||
|             } else | ||||
|                 ctx->previousBypassHandle[index] = NULL; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| #endif  //COMPOSITION_BYPASS | ||||
|  | ||||
|  | ||||
| @@ -708,15 +807,20 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { | ||||
|  | ||||
|     hwc_context_t* ctx = (hwc_context_t*)(dev); | ||||
|  | ||||
|     if(!ctx || !list) { | ||||
|          LOGE("hwc_prepare invalid context or list"); | ||||
|          return -1; | ||||
|     if(!ctx) { | ||||
|         LOGE("hwc_prepare invalid context"); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>( | ||||
|                                                            dev->common.module); | ||||
|     if(!hwcModule) { | ||||
|         LOGE("hwc_prepare null module "); | ||||
|     if (!list || !hwcModule) { | ||||
|         LOGE("hwc_prepare invalid list or module"); | ||||
| #ifdef COMPOSITION_BYPASS | ||||
|         unlockPreviousBypassBuffers(ctx); | ||||
|         unsetBypassBufferLockState(ctx); | ||||
| #endif | ||||
|         unlockPreviousOverlayBuffer(ctx); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
| @@ -739,6 +843,8 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { | ||||
|             s3dVideoFormat = getS3DVideoFormat(list); | ||||
|             if (s3dVideoFormat) | ||||
|                 isS3DCompositionNeeded = isS3DCompositionRequired(); | ||||
|         } else { | ||||
|             unlockPreviousOverlayBuffer(ctx); | ||||
|         } | ||||
|  | ||||
|         if (list->flags & HWC_GEOMETRY_CHANGED) { | ||||
| @@ -757,29 +863,55 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { | ||||
|                 // need to still mark the layer for S3D composition | ||||
|                 if (isS3DCompositionNeeded) | ||||
|                     markUILayerForS3DComposition(list->hwLayers[i], s3dVideoFormat); | ||||
|  | ||||
|                 if (hwcModule->compositionType | ||||
|                         & (COMPOSITION_TYPE_C2D | COMPOSITION_TYPE_MDP)) { | ||||
|                     // Ensure that HWC_OVERLAY layers below skip layers do not | ||||
|                     // overwrite GPU composed skip layers. | ||||
|                     ssize_t layer_countdown = ((ssize_t)i) - 1; | ||||
|                     while (layer_countdown >= 0) | ||||
|                     { | ||||
|                         // Mark every non-mdp overlay layer below the | ||||
|                         // skip-layer for GPU composition. | ||||
|                         switch(list->hwLayers[layer_countdown].compositionType) { | ||||
|                         case HWC_FRAMEBUFFER: | ||||
|                         case HWC_USE_OVERLAY: | ||||
|                             break; | ||||
|                         case HWC_USE_COPYBIT: | ||||
|                         default: | ||||
|                             list->hwLayers[layer_countdown].compositionType = HWC_FRAMEBUFFER; | ||||
|                             break; | ||||
|                         } | ||||
|                         layer_countdown--; | ||||
|                     } | ||||
|                 } | ||||
|                 continue; | ||||
|             } | ||||
|             if (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) && (yuvBufferCount == 1)) { | ||||
|                 bool waitForVsync = skipComposition ? true:false; | ||||
|                 bool waitForVsync = true; | ||||
|                 if (!isValidDestination(hwcModule->fbDevice, list->hwLayers[i].displayFrame)) { | ||||
|                     list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; | ||||
|                     skipComposition = false; | ||||
| #ifdef USE_OVERLAY | ||||
|                 } else if(prepareOverlay(ctx, &(list->hwLayers[i]), waitForVsync) == 0) { | ||||
|                     list->hwLayers[i].compositionType = HWC_USE_OVERLAY; | ||||
|                     list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB; | ||||
|                     // We've opened the channel. Set the state to open. | ||||
|                     ctx->hwcOverlayStatus = HWC_OVERLAY_OPEN; | ||||
| #endif | ||||
|                 } | ||||
|                 else if (hwcModule->compositionType & (COMPOSITION_TYPE_C2D)) { | ||||
|                 else if (hwcModule->compositionType & (COMPOSITION_TYPE_C2D| | ||||
|                             COMPOSITION_TYPE_MDP)) { | ||||
|                     //Fail safe path: If drawing with overlay fails, | ||||
|  | ||||
|                     //Use C2D if available. | ||||
|                     list->hwLayers[i].compositionType = HWC_USE_COPYBIT; | ||||
|                     skipComposition = false; | ||||
|                 } | ||||
|                 else { | ||||
|                     //If C2D is not enabled fall back to GPU. | ||||
|                     list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; | ||||
|                 } | ||||
|                 if (HWC_USE_OVERLAY != list->hwLayers[i].compositionType) { | ||||
|                     unlockPreviousOverlayBuffer(ctx); | ||||
|                     skipComposition = false; | ||||
|                 } | ||||
|             } else if (isS3DCompositionNeeded) { | ||||
| @@ -819,7 +951,9 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { | ||||
|                 ctx->bypassState = BYPASS_ON; | ||||
|             } | ||||
|         } else { | ||||
|             unlockPreviousBypassBuffers(ctx); | ||||
|             unsetBypassLayerFlags(list); | ||||
|             unsetBypassBufferLockState(ctx); | ||||
|             if(ctx->bypassState == BYPASS_ON) { | ||||
|                 ctx->bypassState = BYPASS_OFF_PENDING; | ||||
|             } | ||||
| @@ -887,6 +1021,14 @@ static int drawLayerUsingCopybit(hwc_composer_device_t *dev, hwc_layer_t *layer, | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     // Lock this buffer for read. | ||||
|     genlock_lock_type lockType = GENLOCK_READ_LOCK; | ||||
|     int err = genlock_lock_buffer(hnd, lockType, GENLOCK_MAX_TIMEOUT); | ||||
|     if (GENLOCK_FAILURE == err) { | ||||
|         LOGE("%s: genlock_lock_buffer(READ) failed", __FUNCTION__); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     // Set the copybit source: | ||||
|     copybit_image_t src; | ||||
|     src.w = ALIGN(hnd->width, 32); | ||||
| @@ -894,6 +1036,11 @@ static int drawLayerUsingCopybit(hwc_composer_device_t *dev, hwc_layer_t *layer, | ||||
|     src.format = hnd->format; | ||||
|     src.base = (void *)hnd->base; | ||||
|     src.handle = (native_handle_t *)layer->handle; | ||||
|     src.horiz_padding = src.w - hnd->width; | ||||
|     // Initialize vertical padding to zero for now, | ||||
|     // this needs to change to accomodate vertical stride | ||||
|     // if needed in the future | ||||
|     src.vert_padding = 0; | ||||
|  | ||||
|     // Copybit source rect | ||||
|     hwc_rect_t sourceCrop = layer->sourceCrop; | ||||
| @@ -912,11 +1059,13 @@ static int drawLayerUsingCopybit(hwc_composer_device_t *dev, hwc_layer_t *layer, | ||||
|     android_native_buffer_t *renderBuffer = (android_native_buffer_t *)eglGetRenderBufferANDROID(dpy, surface); | ||||
|     if (!renderBuffer) { | ||||
|         LOGE("eglGetRenderBufferANDROID returned NULL buffer"); | ||||
|         genlock_unlock_buffer(hnd); | ||||
|         return -1; | ||||
|     } | ||||
|     private_handle_t *fbHandle = (private_handle_t *)renderBuffer->handle; | ||||
|     if(!fbHandle) { | ||||
|         LOGE("Framebuffer handle is NULL"); | ||||
|         genlock_unlock_buffer(hnd); | ||||
|         return -1; | ||||
|     } | ||||
|     dst.w = ALIGN(fbHandle->width,32); | ||||
| @@ -930,16 +1079,24 @@ static int drawLayerUsingCopybit(hwc_composer_device_t *dev, hwc_layer_t *layer, | ||||
|     region_iterator copybitRegion(region); | ||||
|  | ||||
|     copybit_device_t *copybit = hwcModule->copybitEngine; | ||||
|     copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_WIDTH, renderBuffer->width); | ||||
|     copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_HEIGHT, renderBuffer->height); | ||||
|     copybit->set_parameter(copybit, COPYBIT_TRANSFORM, layer->transform); | ||||
|     copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, | ||||
|                            (layer->blending == HWC_BLENDING_NONE) ? 0xFF : layer->alpha); | ||||
|     copybit->set_parameter(copybit, COPYBIT_PREMULTIPLIED_ALPHA, | ||||
|                            (layer->blending == HWC_BLENDING_PREMULT)? COPYBIT_ENABLE : COPYBIT_DISABLE); | ||||
|     int err = copybit->stretch(copybit, &dst, &src, &dstRect, &srcRect, ©bitRegion); | ||||
|     err = copybit->stretch(copybit, &dst, &src, &dstRect, &srcRect, ©bitRegion); | ||||
|  | ||||
|     if(err < 0) | ||||
|         LOGE("copybit stretch failed"); | ||||
|  | ||||
|     // Unlock this buffer since copybit is done with it. | ||||
|     err = genlock_unlock_buffer(hnd); | ||||
|     if (GENLOCK_FAILURE == err) { | ||||
|         LOGE("%s: genlock_unlock_buffer failed", __FUNCTION__); | ||||
|     } | ||||
|  | ||||
|     return err; | ||||
| } | ||||
|  | ||||
| @@ -955,13 +1112,33 @@ static int drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer) | ||||
|         overlay::Overlay *ovLibObject = ctx->mOverlayLibObject; | ||||
|         int ret = 0; | ||||
|  | ||||
|         ret = ovLibObject->queueBuffer(hnd); | ||||
|         if (!ret) { | ||||
|             LOGE("drawLayerUsingOverlay queueBuffer failed"); | ||||
|         // Lock this buffer for read. | ||||
|         if (GENLOCK_NO_ERROR != genlock_lock_buffer(hnd, GENLOCK_READ_LOCK, | ||||
|                                                     GENLOCK_MAX_TIMEOUT)) { | ||||
|             LOGE("%s: genlock_lock_buffer(READ) failed", __FUNCTION__); | ||||
|             return -1; | ||||
|         } | ||||
|  | ||||
|         ret = ovLibObject->queueBuffer(hnd); | ||||
|  | ||||
|         // Unlock the previously locked buffer, since the overlay has completed reading the buffer | ||||
|         unlockPreviousOverlayBuffer(ctx); | ||||
|  | ||||
|         if (!ret) { | ||||
|             LOGE("drawLayerUsingOverlay queueBuffer failed"); | ||||
|             // Unlock the buffer handle | ||||
|             genlock_unlock_buffer(hnd); | ||||
|             ctx->previousOverlayHandle = NULL; | ||||
|         } else { | ||||
|             // Store the current buffer handle as the one that is to be unlocked after | ||||
|             // the next overlay play call. | ||||
|             ctx->previousOverlayHandle = hnd; | ||||
|             hnd->flags |= private_handle_t::PRIV_FLAGS_HWC_LOCK; | ||||
|         } | ||||
|  | ||||
|         return ret; | ||||
|     } | ||||
|     return 0; | ||||
|     return -1; | ||||
| } | ||||
|  | ||||
| static int hwc_set(hwc_composer_device_t *dev, | ||||
| @@ -970,15 +1147,23 @@ static int hwc_set(hwc_composer_device_t *dev, | ||||
|         hwc_layer_list_t* list) | ||||
| { | ||||
|     hwc_context_t* ctx = (hwc_context_t*)(dev); | ||||
|     if(!ctx || !list) { | ||||
|          LOGE("hwc_set invalid context or list"); | ||||
|          return -1; | ||||
|     if(!ctx) { | ||||
|         LOGE("hwc_set invalid context"); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>( | ||||
|                                                            dev->common.module); | ||||
|     if(!hwcModule) { | ||||
|         LOGE("hwc_set null module "); | ||||
|  | ||||
|     framebuffer_device_t *fbDev = hwcModule->fbDevice; | ||||
|  | ||||
|     if (!list || !hwcModule) { | ||||
|         LOGE("hwc_set invalid list or module"); | ||||
| #ifdef COMPOSITION_BYPASS | ||||
|         unlockPreviousBypassBuffers(ctx); | ||||
|         unsetBypassBufferLockState(ctx); | ||||
| #endif | ||||
|         unlockPreviousOverlayBuffer(ctx); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
| @@ -1000,15 +1185,34 @@ static int hwc_set(hwc_composer_device_t *dev, | ||||
|         } | ||||
|     } | ||||
|  | ||||
| #ifdef COMPOSITION_BYPASS | ||||
|     unlockPreviousBypassBuffers(ctx); | ||||
|     storeLockedBypassHandle(list, ctx); | ||||
|     // We have stored the handles, unset the current lock states in the context. | ||||
|     unsetBypassBufferLockState(ctx); | ||||
|  | ||||
|     //Setup for waiting until 1 FB post is done before closing bypass mode. | ||||
|     if (ctx->bypassState == BYPASS_OFF_PENDING) { | ||||
|         fbDev->resetBufferPostStatus(fbDev); | ||||
|     } | ||||
| #endif | ||||
|  | ||||
|     // Do not call eglSwapBuffers if we the skip composition flag is set on the list. | ||||
|     if (!(list->flags & HWC_SKIP_COMPOSITION)) { | ||||
|         EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur); | ||||
|         if (!sucess) { | ||||
|             ret = HWC_EGL_ERROR; | ||||
|             LOGE("eglSwapBuffers() failed in %s", __FUNCTION__); | ||||
|         } | ||||
|     } | ||||
| #ifdef COMPOSITION_BYPASS | ||||
|     if(ctx->bypassState == BYPASS_OFF_PENDING) { | ||||
|         //Close channels only after fb content is displayed. | ||||
|         //We have already reset status before eglSwapBuffers. | ||||
|         if (!(list->flags & HWC_SKIP_COMPOSITION)) { | ||||
|             fbDev->waitForBufferPost(fbDev); | ||||
|         } | ||||
|  | ||||
|         closeBypass(ctx); | ||||
|         ctx->bypassState = BYPASS_OFF; | ||||
|     } | ||||
| @@ -1047,13 +1251,17 @@ static int hwc_device_close(struct hw_device_t *dev) | ||||
|         hwcModule->fbDevice = NULL; | ||||
|     } | ||||
|  | ||||
|     unlockPreviousOverlayBuffer(ctx); | ||||
|  | ||||
|     if (ctx) { | ||||
|          delete ctx->mOverlayLibObject; | ||||
|          ctx->mOverlayLibObject = NULL; | ||||
| #ifdef COMPOSITION_BYPASS | ||||
|          for(int i = 0; i < MAX_BYPASS_LAYERS; i++) { | ||||
|             delete ctx->mOvUI[i]; | ||||
|          } | ||||
|             for(int i = 0; i < MAX_BYPASS_LAYERS; i++) { | ||||
|                 delete ctx->mOvUI[i]; | ||||
|             } | ||||
|             unlockPreviousBypassBuffers(ctx); | ||||
|             unsetBypassBufferLockState(ctx); | ||||
| #endif | ||||
|         free(ctx); | ||||
|     } | ||||
| @@ -1130,7 +1338,9 @@ static int hwc_device_open(const struct hw_module_t* module, const char* name, | ||||
| #ifdef COMPOSITION_BYPASS | ||||
|         for(int i = 0; i < MAX_BYPASS_LAYERS; i++) { | ||||
|             dev->mOvUI[i] = new overlay::OverlayUI(); | ||||
|             dev->previousBypassHandle[i] = NULL; | ||||
|         } | ||||
|         unsetBypassBufferLockState(dev); | ||||
|         dev->animCount = 0; | ||||
|         dev->bypassState = BYPASS_OFF; | ||||
| #endif | ||||
| @@ -1139,6 +1349,7 @@ static int hwc_device_open(const struct hw_module_t* module, const char* name, | ||||
|         dev->mHDMIEnabled = false; | ||||
|         dev->pendingHDMI = false; | ||||
| #endif | ||||
|         dev->previousOverlayHandle = NULL; | ||||
|         dev->hwcOverlayStatus = HWC_OVERLAY_CLOSED; | ||||
|         /* initialize the procs */ | ||||
|         dev->device.common.tag = HARDWARE_DEVICE_TAG; | ||||
|   | ||||
| @@ -256,8 +256,21 @@ bool overlay::enableBarrier (unsigned int orientation) { | ||||
|  | ||||
| int overlay::getColorFormat(int format) | ||||
| { | ||||
|     return (format == HAL_PIXEL_FORMAT_YV12) ? | ||||
|             format : COLOR_FORMAT(format); | ||||
|     if (format == HAL_PIXEL_FORMAT_YV12) | ||||
|         return format; | ||||
|     else if (format & INTERLACE_MASK) | ||||
|         return format ^ HAL_PIXEL_FORMAT_INTERLACE; | ||||
|     else | ||||
|         return COLOR_FORMAT(format); | ||||
| } | ||||
|  | ||||
| bool overlay::isInterlacedContent(int format) | ||||
| { | ||||
|     if ((format != HAL_PIXEL_FORMAT_YV12) && | ||||
|         (format & INTERLACE_MASK)) | ||||
|         return true; | ||||
|  | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| unsigned int overlay::getOverlayConfig (unsigned int format3D, bool poll, | ||||
| @@ -466,8 +479,8 @@ bool Overlay::updateOverlaySource(const overlay_buffer_info& info, int orientati | ||||
|     int orientHdmi = 0; | ||||
|     int orientPrimary = sHDMIAsPrimary ? 0 : orientation; | ||||
|     int orient[2] = {orientPrimary, orientHdmi}; | ||||
|     // enable waitForVsync on HDMI | ||||
|     bool waitForHDMI = true; | ||||
|     // disable waitForVsync on HDMI, since we call the wait ioctl | ||||
|     bool waitForHDMI = false; | ||||
|     bool waitForPrimary = sHDMIAsPrimary ? true : waitForVsync; | ||||
|     bool waitCond[2] = {waitForPrimary, waitForHDMI}; | ||||
|  | ||||
| @@ -582,7 +595,7 @@ bool Overlay::setSource(const overlay_buffer_info& info, int orientation, | ||||
|                     if (FRAMEBUFFER_1 == i) { | ||||
|                         // Disable rotation for HDMI | ||||
|                         noRot = true; | ||||
|                         waitForVsync = true; | ||||
|                         waitForVsync = false; | ||||
|                     } | ||||
|                     if(!startChannel(info, i, noRot, false, mS3DFormat, | ||||
|                                 i, waitForVsync, num_buffers)) { | ||||
| @@ -715,6 +728,10 @@ bool Overlay::queueBuffer(uint32_t offset, int channel) { | ||||
|     return objOvDataChannel[channel].queueBuffer(offset); | ||||
| } | ||||
|  | ||||
| bool Overlay::waitForHdmiVsync(int channel) { | ||||
|     return objOvDataChannel[channel].waitForHdmiVsync(); | ||||
| } | ||||
|  | ||||
| bool Overlay::queueBuffer(buffer_handle_t buffer) { | ||||
|     private_handle_t const* hnd = reinterpret_cast | ||||
|                                    <private_handle_t const*>(buffer); | ||||
| @@ -737,12 +754,17 @@ bool Overlay::queueBuffer(buffer_handle_t buffer) { | ||||
|         case OV_3D_VIDEO_3D_PANEL: | ||||
|         case OV_3D_VIDEO_2D_TV: | ||||
|         case OV_3D_VIDEO_3D_TV: | ||||
|             for (int i=0; i<NUM_CHANNELS; i++) { | ||||
|             for (int i=NUM_CHANNELS-1; i>=0; i--) { | ||||
|                 if(!queueBuffer(fd, offset, i)) { | ||||
|                     LOGE("%s:failed for channel %d", __FUNCTION__, i); | ||||
|                     return false; | ||||
|                 } | ||||
|             } | ||||
|             //Wait for HDMI done.. | ||||
|             if(!waitForHdmiVsync(VG1_PIPE)) { | ||||
|                 LOGE("%s: waitforHdmiVsync failed", __FUNCTION__); | ||||
|                 return false; | ||||
|             } | ||||
|             break; | ||||
|         default: | ||||
|             LOGE("%s:Unknown state %d", __FUNCTION__, mState); | ||||
| @@ -961,8 +983,8 @@ bool OverlayControlChannel::setOverlayInformation(const overlay_buffer_info& inf | ||||
|         mOVInfo.z_order = zorder; | ||||
|         mOVInfo.alpha = 0xff; | ||||
|         mOVInfo.transp_mask = 0xffffffff; | ||||
|         mOVInfo.flags = flags; | ||||
|     } | ||||
|     mOVInfo.flags = flags; | ||||
|     if (!ignoreFB) | ||||
|         mOVInfo.flags |= MDP_OV_PLAY_NOWAIT; | ||||
|     else | ||||
| @@ -1042,7 +1064,9 @@ bool OverlayControlChannel::updateOverlaySource(const overlay_buffer_info& info, | ||||
|     ovBufInfo.height = info.height; | ||||
|     ovBufInfo.format = hw_format; | ||||
|  | ||||
|     if (!setOverlayInformation(ovBufInfo, 0, orientation, 0, waitForVsync, UPDATE_REQUEST)) | ||||
|     int flags = isInterlacedContent(info.format) ? MDP_DEINTERLACE : 0; | ||||
|     if (!setOverlayInformation(ovBufInfo, flags, orientation, 0, waitForVsync, | ||||
|                                UPDATE_REQUEST)) | ||||
|         return false; | ||||
|  | ||||
|     return startOVRotatorSessions(ovBufInfo, orientation, UPDATE_REQUEST); | ||||
| @@ -1063,7 +1087,7 @@ bool OverlayControlChannel::startControlChannel(int w, int h, | ||||
|     int colorFormat = format; | ||||
|     // The interlace mask is part of the HAL_PIXEL_FORMAT_YV12 value. Add | ||||
|     // an explicit check for the format | ||||
|     if ((format != HAL_PIXEL_FORMAT_YV12) && (format & INTERLACE_MASK)) { | ||||
|     if (isInterlacedContent(format)) { | ||||
|         flags |= MDP_DEINTERLACE; | ||||
|  | ||||
|         // Get the actual format | ||||
| @@ -1608,6 +1632,19 @@ bool OverlayDataChannel::queue(uint32_t offset) { | ||||
|         reportError("overlay play failed."); | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| bool OverlayDataChannel::waitForHdmiVsync() { | ||||
|     if (!isChannelUP()) { | ||||
|         reportError("waitForHdmiVsync: channel not up"); | ||||
|         return false; | ||||
|     } | ||||
|     if (ioctl(mFD, MSMFB_OVERLAY_PLAY_WAIT, &mOvData)) { | ||||
|         reportError("waitForHdmiVsync: MSMFB_OVERLAY_PLAY_WAIT failed"); | ||||
|         return false; | ||||
|     } | ||||
|     return true; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -144,6 +144,7 @@ bool enableBarrier(unsigned int orientation); | ||||
| unsigned int  getOverlayConfig (unsigned int format3D, bool poll = true, | ||||
|                                 bool isHDMI = false); | ||||
| int getColorFormat(int format); | ||||
| bool isInterlacedContent(int format); | ||||
| int get_mdp_format(int format); | ||||
| int get_size(int format, int w, int h); | ||||
| int get_rot_output_format(int format); | ||||
| @@ -250,6 +251,7 @@ public: | ||||
|     bool closeDataChannel(); | ||||
|     bool setFd(int fd); | ||||
|     bool queueBuffer(uint32_t offset); | ||||
|     bool waitForHdmiVsync(); | ||||
|     bool setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h); | ||||
|     bool getCropS3D(overlay_rect *inRect, int channel, int format, overlay_rect *rect); | ||||
|     bool isChannelUP() const { return (mFD > 0); } | ||||
| @@ -297,6 +299,7 @@ public: | ||||
|     bool setSource(const overlay_buffer_info& info, int orientation, bool hdmiConnected, | ||||
|                     bool ignoreFB = false, int numBuffers = 2); | ||||
|     bool setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h); | ||||
|     bool waitForHdmiVsync(int channel); | ||||
|     int  getChannelStatus() const { return (mChannelUP ? OVERLAY_CHANNEL_UP: OVERLAY_CHANNEL_DOWN); } | ||||
|     void setHDMIStatus (bool isHDMIConnected) { mHDMIConnected = isHDMIConnected; mState = -1; } | ||||
|     int getHDMIStatus() const {return (mHDMIConnected ? HDMI_ON : HDMI_OFF); } | ||||
|   | ||||
							
								
								
									
										17
									
								
								libqcomui/Android.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								libqcomui/Android.mk
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| LOCAL_PATH := $(call my-dir) | ||||
| include $(CLEAR_VARS) | ||||
|  | ||||
| LOCAL_SRC_FILES := \ | ||||
|         qcom_ui.cpp | ||||
|  | ||||
| LOCAL_SHARED_LIBRARIES := \ | ||||
|         libutils \ | ||||
|         libcutils \ | ||||
|         libmemalloc \ | ||||
|         libui | ||||
|  | ||||
| LOCAL_C_INCLUDES := $(TOP)/hardware/qcom/display/libgralloc \ | ||||
| LOCAL_CFLAGS := -DLOG_TAG=\"libQcomUI\" | ||||
| LOCAL_MODULE := libQcomUI | ||||
| LOCAL_MODULE_TAGS := optional | ||||
| include $(BUILD_SHARED_LIBRARY) | ||||
							
								
								
									
										293
									
								
								libqcomui/qcom_ui.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										293
									
								
								libqcomui/qcom_ui.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,293 @@ | ||||
| /* | ||||
|  * 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 <cutils/log.h> | ||||
| #include <qcom_ui.h> | ||||
| #include <gralloc_priv.h> | ||||
| #include <alloc_controller.h> | ||||
| #include <memalloc.h> | ||||
| #include <errno.h> | ||||
|  | ||||
| using gralloc::IMemAlloc; | ||||
| using gralloc::IonController; | ||||
| using gralloc::alloc_data; | ||||
| using android::sp; | ||||
|  | ||||
| namespace { | ||||
|  | ||||
|     static android::sp<gralloc::IAllocController> sAlloc = 0; | ||||
|  | ||||
|     int reallocate_memory(native_handle_t *buffer_handle, int mReqSize, int usage) | ||||
|     { | ||||
|         int ret = 0; | ||||
|         if (sAlloc == 0) { | ||||
|             sAlloc = gralloc::IAllocController::getInstance(true); | ||||
|         } | ||||
|         if (sAlloc == 0) { | ||||
|             LOGE("sAlloc is still NULL"); | ||||
|             return -EINVAL; | ||||
|         } | ||||
|  | ||||
|         // Dealloc the old memory | ||||
|         private_handle_t *hnd = (private_handle_t *)buffer_handle; | ||||
|         sp<IMemAlloc> memalloc = sAlloc->getAllocator(hnd->flags); | ||||
|         ret = memalloc->free_buffer((void*)hnd->base, hnd->size, hnd->offset, hnd->fd); | ||||
|  | ||||
|         if (ret) { | ||||
|             LOGE("%s: free_buffer failed", __FUNCTION__); | ||||
|             return -1; | ||||
|         } | ||||
|  | ||||
|         // Realloc new memory | ||||
|         alloc_data data; | ||||
|         data.base = 0; | ||||
|         data.fd = -1; | ||||
|         data.offset = 0; | ||||
|         data.size = mReqSize; | ||||
|         data.align = getpagesize(); | ||||
|         data.uncached = true; | ||||
|         int allocFlags = usage; | ||||
|  | ||||
|         switch (hnd->format) { | ||||
|             case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: | ||||
|             case (HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED^HAL_PIXEL_FORMAT_INTERLACE): { | ||||
|                 data.align = 8192; | ||||
|             } break; | ||||
|             default: break; | ||||
|         } | ||||
|         ret = sAlloc->allocate(data, allocFlags, 0); | ||||
|         if (ret == 0) { | ||||
|             hnd->fd = data.fd; | ||||
|             hnd->base = (int)data.base; | ||||
|             hnd->offset = data.offset; | ||||
|             hnd->size = data.size; | ||||
|         } else { | ||||
|             LOGE("%s: allocate failed", __FUNCTION__); | ||||
|             return -EINVAL; | ||||
|         } | ||||
|         return ret; | ||||
|     } | ||||
| }; // ANONYNMOUS NAMESPACE | ||||
|  | ||||
| /* | ||||
|  * Gets the number of arguments required for this operation. | ||||
|  * | ||||
|  * @param: operation whose argument count is required. | ||||
|  * | ||||
|  * @return -EINVAL if the operation is invalid. | ||||
|  */ | ||||
| int getNumberOfArgsForOperation(int operation) { | ||||
|     int num_args = -EINVAL; | ||||
|     switch(operation) { | ||||
|         case NATIVE_WINDOW_SET_BUFFERS_SIZE: | ||||
|             num_args = 1; | ||||
|             break; | ||||
|         case  NATIVE_WINDOW_UPDATE_BUFFERS_GEOMETRY: | ||||
|             num_args = 3; | ||||
|             break; | ||||
|         default: LOGE("%s: invalid operation(0x%x)", __FUNCTION__, operation); | ||||
|             break; | ||||
|     }; | ||||
|     return num_args; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Checks if the format is supported by the GPU. | ||||
|  * | ||||
|  * @param: format to check | ||||
|  * | ||||
|  * @return true if the format is supported by the GPU. | ||||
|  */ | ||||
| bool isGPUSupportedFormat(int format) { | ||||
|     bool isSupportedFormat = true; | ||||
|     switch(format) { | ||||
|         case (HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED^HAL_PIXEL_FORMAT_INTERLACE): | ||||
|         case (HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED|HAL_3D_OUT_SIDE_BY_SIDE | ||||
|               |HAL_3D_IN_SIDE_BY_SIDE_R_L): | ||||
|         case (HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED|HAL_3D_OUT_SIDE_BY_SIDE | ||||
|               |HAL_3D_IN_SIDE_BY_SIDE_L_R): | ||||
|             isSupportedFormat = false; | ||||
|             break; | ||||
|         default: break; | ||||
|     } | ||||
|     return isSupportedFormat; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Function to check if the allocated buffer is of the correct size. | ||||
|  * Reallocate the buffer with the correct size, if the size doesn't | ||||
|  * match | ||||
|  * | ||||
|  * @param: handle of the allocated buffer | ||||
|  * @param: requested size for the buffer | ||||
|  * @param: usage flags | ||||
|  * | ||||
|  * return 0 on success | ||||
|  */ | ||||
| int checkBuffer(native_handle_t *buffer_handle, int size, int usage) | ||||
| { | ||||
|     // If the client hasn't set a size, return | ||||
|     if (0 == size) { | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     // Validate the handle | ||||
|     if (private_handle_t::validate(buffer_handle)) { | ||||
|         LOGE("%s: handle is invalid", __FUNCTION__); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     // Obtain the private_handle from the native handle | ||||
|     private_handle_t *hnd = reinterpret_cast<private_handle_t*>(buffer_handle); | ||||
|     if (hnd->size < size) { | ||||
|         return reallocate_memory(hnd, size, usage); | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Checks if memory needs to be reallocated for this buffer. | ||||
|  * | ||||
|  * @param: Geometry of the current buffer. | ||||
|  * @param: Required Geometry. | ||||
|  * @param: Geometry of the updated buffer. | ||||
|  * | ||||
|  * @return True if a memory reallocation is required. | ||||
|  */ | ||||
| bool needNewBuffer(const qBufGeometry currentGeometry, | ||||
|                    const qBufGeometry requiredGeometry, | ||||
|                    const qBufGeometry updatedGeometry) | ||||
| { | ||||
|     // If the current buffer info matches the updated info, | ||||
|     // we do not require any memory allocation. | ||||
|     if (updatedGeometry.width && updatedGeometry.height && | ||||
|         updatedGeometry.format) { | ||||
|         return false; | ||||
|     } | ||||
|     if (currentGeometry.width != requiredGeometry.width || | ||||
|         currentGeometry.height != requiredGeometry.height || | ||||
|         currentGeometry.format != requiredGeometry.format) { | ||||
|         // Current and required geometry do not match. Allocation | ||||
|         // required. | ||||
|         return true; | ||||
|     } | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Update the geometry of this buffer without reallocation. | ||||
|  * | ||||
|  * @param: buffer whose geometry needs to be updated. | ||||
|  * @param: Updated width | ||||
|  * @param: Updated height | ||||
|  * @param: Updated format | ||||
|  */ | ||||
| int updateBufferGeometry(sp<GraphicBuffer> buffer, const qBufGeometry updatedGeometry) | ||||
| { | ||||
|     if (buffer == 0) { | ||||
|         LOGE("%s: graphic buffer is NULL", __FUNCTION__); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     if (!updatedGeometry.width || !updatedGeometry.height || | ||||
|         !updatedGeometry.format) { | ||||
|         // No update required. Return. | ||||
|         return 0; | ||||
|     } | ||||
|     if (buffer->width == updatedGeometry.width && | ||||
|         buffer->height == updatedGeometry.height && | ||||
|         buffer->format == updatedGeometry.format) { | ||||
|         // The buffer has already been updated. Return. | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     // Validate the handle | ||||
|     if (private_handle_t::validate(buffer->handle)) { | ||||
|         LOGE("%s: handle is invalid", __FUNCTION__); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|     buffer->width  = updatedGeometry.width; | ||||
|     buffer->height = updatedGeometry.height; | ||||
|     buffer->format = updatedGeometry.format; | ||||
|     private_handle_t *hnd = (private_handle_t*)(buffer->handle); | ||||
|     if (hnd) { | ||||
|         hnd->width  = updatedGeometry.width; | ||||
|         hnd->height = updatedGeometry.height; | ||||
|         hnd->format = updatedGeometry.format; | ||||
|     } else { | ||||
|         LOGE("%s: hnd is NULL", __FUNCTION__); | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Updates the flags for the layer | ||||
|  * | ||||
|  * @param: Attribute | ||||
|  * @param: Identifies if the attribute was enabled or disabled. | ||||
|  * | ||||
|  * @return: -EINVAL if the attribute is invalid | ||||
|  */ | ||||
| int updateLayerQcomFlags(eLayerAttrib attribute, bool enable, int& currentFlags) | ||||
| { | ||||
|     int ret = 0; | ||||
|     switch (attribute) { | ||||
|         case LAYER_UPDATE_STATUS: { | ||||
|             if (enable) | ||||
|                 currentFlags |= LAYER_UPDATING; | ||||
|             else | ||||
|                 currentFlags &= ~LAYER_UPDATING; | ||||
|         } break; | ||||
|         default: LOGE("%s: invalid attribute(0x%x)", __FUNCTION__, attribute); | ||||
|                  break; | ||||
|     } | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Gets the per frame HWC flags for this layer. | ||||
|  * | ||||
|  * @param: current hwcl flags | ||||
|  * @param: current layerFlags | ||||
|  * | ||||
|  * @return: the per frame flags. | ||||
|  */ | ||||
| int getPerFrameFlags(int hwclFlags, int layerFlags) { | ||||
|     int flags = hwclFlags; | ||||
|     if (layerFlags & LAYER_UPDATING) | ||||
|         flags &= ~HWC_LAYER_NOT_UPDATING; | ||||
|     else | ||||
|         flags |= HWC_LAYER_NOT_UPDATING; | ||||
|  | ||||
|     return flags; | ||||
| } | ||||
|  | ||||
							
								
								
									
										158
									
								
								libqcomui/qcom_ui.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								libqcomui/qcom_ui.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,158 @@ | ||||
| /* | ||||
|  * 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. | ||||
|  */ | ||||
|  | ||||
| #ifndef INCLUDE_LIBQCOM_UI | ||||
| #define INCLUDE_LIBQCOM_UI | ||||
|  | ||||
| #include <cutils/native_handle.h> | ||||
| #include <ui/GraphicBuffer.h> | ||||
|  | ||||
| using android::sp; | ||||
| using android::GraphicBuffer; | ||||
|  | ||||
| /* | ||||
|  * Qcom specific Native Window perform operations | ||||
|  */ | ||||
| enum { | ||||
|     NATIVE_WINDOW_SET_BUFFERS_SIZE        = 0x10000000, | ||||
|     NATIVE_WINDOW_UPDATE_BUFFERS_GEOMETRY = 0x20000000, | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * Layer Attributes | ||||
|  */ | ||||
| enum eLayerAttrib { | ||||
|     LAYER_UPDATE_STATUS, | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * Layer Flags | ||||
|  */ | ||||
| enum { | ||||
|     LAYER_UPDATING = 1<<0, | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * Flags set by the layer and sent to HWC | ||||
|  */ | ||||
| enum { | ||||
|     HWC_LAYER_NOT_UPDATING      = 0x00000002, | ||||
|     HWC_USE_ORIGINAL_RESOLUTION = 0x10000000, | ||||
|     HWC_DO_NOT_USE_OVERLAY      = 0x20000000, | ||||
|     HWC_COMP_BYPASS             = 0x40000000, | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * Structure to hold the buffer geometry | ||||
|  */ | ||||
| struct qBufGeometry { | ||||
|     int width; | ||||
|     int height; | ||||
|     int format; | ||||
|     void set(int w, int h, int f) { | ||||
|        width = w; | ||||
|        height = h; | ||||
|        format = f; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /* | ||||
|  * Function to check if the allocated buffer is of the correct size. | ||||
|  * Reallocate the buffer with the correct size, if the size doesn't | ||||
|  * match | ||||
|  * | ||||
|  * @param: handle of the allocated buffer | ||||
|  * @param: requested size for the buffer | ||||
|  * @param: usage flags | ||||
|  * | ||||
|  * return 0 on success | ||||
|  */ | ||||
| int checkBuffer(native_handle_t *buffer_handle, int size, int usage); | ||||
|  | ||||
| /* | ||||
|  * Checks if the format is supported by the GPU. | ||||
|  * | ||||
|  * @param: format to check | ||||
|  * | ||||
|  * @return true if the format is supported by the GPU. | ||||
|  */ | ||||
| bool isGPUSupportedFormat(int format); | ||||
|  | ||||
| /* | ||||
|  * Gets the number of arguments required for this operation. | ||||
|  * | ||||
|  * @param: operation whose argument count is required. | ||||
|  * | ||||
|  * @return -EINVAL if the operation is invalid. | ||||
|  */ | ||||
| int getNumberOfArgsForOperation(int operation); | ||||
|  | ||||
| /* | ||||
|  * Checks if memory needs to be reallocated for this buffer. | ||||
|  * | ||||
|  * @param: Geometry of the current buffer. | ||||
|  * @param: Required Geometry. | ||||
|  * @param: Geometry of the updated buffer. | ||||
|  * | ||||
|  * @return True if a memory reallocation is required. | ||||
|  */ | ||||
| bool needNewBuffer(const qBufGeometry currentGeometry, | ||||
|                             const qBufGeometry requiredGeometry, | ||||
|                             const qBufGeometry updatedGeometry); | ||||
|  | ||||
| /* | ||||
|  * Update the geometry of this buffer without reallocation. | ||||
|  * | ||||
|  * @param: buffer whose geometry needs to be updated. | ||||
|  * @param: Updated buffer geometry | ||||
|  */ | ||||
| int updateBufferGeometry(sp<GraphicBuffer> buffer, const qBufGeometry bufGeometry); | ||||
|  | ||||
| /* | ||||
|  * Updates the flags for the layer | ||||
|  * | ||||
|  * @param: Attribute | ||||
|  * @param: Identifies if the attribute was enabled or disabled. | ||||
|  * @param: current Layer flags. | ||||
|  * | ||||
|  * @return: Flags for the layer | ||||
|  */ | ||||
| int updateLayerQcomFlags(eLayerAttrib attribute, bool enable, int& currentFlags); | ||||
|  | ||||
| /* | ||||
|  * Gets the per frame HWC flags for this layer. | ||||
|  * | ||||
|  * @param: current hwcl flags | ||||
|  * @param: current layerFlags | ||||
|  * | ||||
|  * @return: the per frame flags. | ||||
|  */ | ||||
| int getPerFrameFlags(int hwclFlags, int layerFlags); | ||||
|  | ||||
| #endif // INCLUDE_LIBQCOM_UI | ||||
							
								
								
									
										26
									
								
								libtilerenderer/Android.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								libtilerenderer/Android.mk
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| LOCAL_PATH := $(call my-dir) | ||||
| include $(CLEAR_VARS) | ||||
|  | ||||
| ifeq ($(USE_OPENGL_RENDERER),true) | ||||
| LOCAL_PRELINK_MODULE := false | ||||
| LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES) | ||||
| LOCAL_SHARED_LIBRARIES := libutils libcutils libGLESv2 libhwui | ||||
|  | ||||
| LOCAL_C_INCLUDES += \ | ||||
| 	frameworks/base/include/utils \ | ||||
| 	frameworks/base/libs/hwui \ | ||||
| 	external/skia/include/core \ | ||||
| 	external/skia/include/effects \ | ||||
| 	external/skia/include/images \ | ||||
| 	external/skia/src/ports \ | ||||
| 	external/skia/include/utils \ | ||||
| 	hardware/libhardware/include/hardware \ | ||||
| 	frameworks/base/opengl/include/GLES2 | ||||
|  | ||||
| LOCAL_SRC_FILES := 	\ | ||||
| 	tilerenderer.cpp | ||||
|  | ||||
| LOCAL_MODULE := libtilerenderer | ||||
| LOCAL_MODULE_TAGS := optional | ||||
| include $(BUILD_SHARED_LIBRARY) | ||||
| endif | ||||
							
								
								
									
										103
									
								
								libtilerenderer/tilerenderer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								libtilerenderer/tilerenderer.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,103 @@ | ||||
| /* | ||||
|  * Copyright (C) 2010 The Android Open Source Project | ||||
|  * Copyright (c) 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. | ||||
|  * 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 <GLES2/gl2.h> | ||||
| #include <EGL/egl.h> | ||||
| #include <gl2ext.h> | ||||
| #include <OpenGLRenderer.h> | ||||
| #include "tilerenderer.h" | ||||
|  | ||||
| namespace android { | ||||
| ANDROID_SINGLETON_STATIC_INSTANCE(uirenderer::TileRenderer) ; | ||||
| namespace uirenderer { | ||||
|  | ||||
| TileRenderer::TileRenderer() { | ||||
|     mIsTiled = false; | ||||
| } | ||||
|  | ||||
| TileRenderer::~TileRenderer() { | ||||
| } | ||||
|  | ||||
| void TileRenderer::startTileRendering(OpenGLRenderer* renderer, | ||||
|                                       int left, int top, | ||||
|                                       int right, int bottom) { | ||||
|     int width = 0; | ||||
|     int height = 0; | ||||
|     GLenum status = GL_NO_ERROR; | ||||
|  | ||||
|     if (renderer != NULL) { | ||||
|         renderer->getViewport(width, height); | ||||
|     } | ||||
|  | ||||
|     if (!left && !right && !top && !bottom) { | ||||
|         left = 0; | ||||
|         top = 0; | ||||
|         right = width; | ||||
|         bottom = height; | ||||
|     } | ||||
|  | ||||
|     if (!left && !right && !top && !bottom) { | ||||
|         //can't do tile rendering | ||||
|         LOGE("can't tile render; drity region, width, height not available"); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     int l = left, t = (height - bottom), w = (right - left), h = (bottom - top), preserve = 0; | ||||
|  | ||||
|     if (l < 0 || t < 0) { | ||||
|         l = (l < 0) ? 0 : l; | ||||
|         t = (t < 0) ? 0 : t; | ||||
|         preserve = 1; | ||||
|     } | ||||
|  | ||||
|     if (w > width || h > height) { | ||||
|         w = (w > width) ? width : w; | ||||
|         h = (h > height) ? height : h; | ||||
|         preserve = 1; | ||||
|     } | ||||
|  | ||||
|     //clear off all errors before tiling, if any | ||||
|     while ((status = glGetError()) != GL_NO_ERROR) { | ||||
|         LOGE("glStartTilingQCOM: 0x%x", status); | ||||
|     } | ||||
|  | ||||
|     if (preserve) | ||||
|         glStartTilingQCOM(l, t, w, h, GL_COLOR_BUFFER_BIT0_QCOM); | ||||
|     else | ||||
|         glStartTilingQCOM(l, t, w, h, GL_NONE); | ||||
|  | ||||
|     status = glGetError(); | ||||
|     if (status == GL_NO_ERROR) | ||||
|         mIsTiled = true; | ||||
|     else | ||||
|         LOGE("glStartTilingQCOM: 0x%x", status); | ||||
| } | ||||
|  | ||||
| void TileRenderer::endTileRendering(OpenGLRenderer*) { | ||||
|     if (!mIsTiled) { | ||||
|         return; | ||||
|     } | ||||
|     glEndTilingQCOM(GL_COLOR_BUFFER_BIT0_QCOM); | ||||
|     mIsTiled = false; | ||||
|     GLenum status = GL_NO_ERROR; | ||||
|     while ((status = glGetError()) != GL_NO_ERROR) { | ||||
|         LOGE("glEndTilingQCOM: 0x%x", status); | ||||
|     } | ||||
| } | ||||
|  | ||||
| }; // namespace uirenderer | ||||
| }; // namespace android | ||||
							
								
								
									
										42
									
								
								libtilerenderer/tilerenderer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								libtilerenderer/tilerenderer.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| /* | ||||
|  * Copyright (C) 2010 The Android Open Source Project | ||||
|  * Copyright (c) 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. | ||||
|  * 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. | ||||
|  */ | ||||
| #ifndef ANDROID_TILE_RENDERER_H | ||||
| #define ANDROID_TILE_RENDERER_H | ||||
|  | ||||
| #include <utils/Singleton.h> | ||||
|  | ||||
| namespace android { | ||||
| namespace uirenderer { | ||||
|  | ||||
| class OpenGLRenderer; | ||||
|  | ||||
| class TileRenderer: public Singleton<TileRenderer> { | ||||
| public: | ||||
|     TileRenderer(); | ||||
|     ~TileRenderer(); | ||||
|  | ||||
|     void startTileRendering(OpenGLRenderer* renderer, int left, int top, int right, int bottom); | ||||
|     void endTileRendering(OpenGLRenderer*); | ||||
|  | ||||
| private: | ||||
|     bool mIsTiled; | ||||
| }; | ||||
|  | ||||
| }; // namespace uirenderer | ||||
| }; // namespace android | ||||
|  | ||||
| #endif | ||||
		Reference in New Issue
	
	Block a user