Merge git://codeaurora.org/platform/hardware/qcom/display.git ics into ics and resolve conflicts
Change-Id: I3acb5e963763821d2b547cf3c9390754dc42c12f
This commit is contained in:
commit
b67994677f
@ -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
|
Loading…
x
Reference in New Issue
Block a user