liboverlay: Add liboverlay and enable for MSM8660 target
liboverlay based on MSM8660-1066 release. Change-Id: Ic9453d38c5a60b40728e2a3651f7a065d802817e
This commit is contained in:
parent
53cb829a9c
commit
155d9fa5fb
37
liboverlay/Android.mk
Normal file
37
liboverlay/Android.mk
Normal file
@ -0,0 +1,37 @@
|
||||
# Copyright (C) 2008 The Android Open Source Project
|
||||
# Copyright (c) 2009, 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
|
||||
#
|
||||
|
||||
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 += hardware/msm7k/libgralloc-qsd8k
|
||||
LOCAL_SRC_FILES := overlayLib.cpp
|
||||
LOCAL_MODULE := liboverlay
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
# HAL module implemenation, not prelinked and stored in
|
||||
# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
||||
LOCAL_SHARED_LIBRARIES := liblog liboverlay libcutils
|
||||
LOCAL_C_INCLUDES += hardware/msm7k/libgralloc-qsd8k
|
||||
LOCAL_SRC_FILES := overlay.cpp
|
||||
LOCAL_MODULE := overlay.default
|
||||
include $(BUILD_SHARED_LIBRARY)
|
820
liboverlay/overlay.cpp
Normal file
820
liboverlay/overlay.cpp
Normal file
@ -0,0 +1,820 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* Copyright (c) 2009, 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "Overlay"
|
||||
|
||||
#include <hardware/hardware.h>
|
||||
#include "overlayLib.h"
|
||||
#include <cutils/properties.h>
|
||||
#include <cutils/ashmem.h>
|
||||
#include <utils/threads.h>
|
||||
#include <linux/ashmem.h>
|
||||
#include <gralloc_priv.h>
|
||||
|
||||
using android::Mutex;
|
||||
|
||||
#define USE_MSM_ROTATOR
|
||||
#define EVEN_OUT(x) if (x & 0x0001) {x--;}
|
||||
|
||||
#define SHARED_MEMORY_REGION_NAME "overlay_shared_memory"
|
||||
/*****************************************************************************/
|
||||
|
||||
using namespace overlay;
|
||||
|
||||
struct overlay_control_context_t {
|
||||
struct overlay_control_device_t device;
|
||||
void *sharedMemBase;
|
||||
};
|
||||
|
||||
struct ov_crop_rect_t {
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
int h;
|
||||
};
|
||||
|
||||
struct overlay_data_context_t {
|
||||
struct overlay_data_device_t device;
|
||||
OverlayDataChannel* pobjDataChannel[2];
|
||||
int setCrop;
|
||||
struct ov_crop_rect_t cropRect;
|
||||
void *sharedMemBase;
|
||||
};
|
||||
|
||||
static int overlay_device_open(const struct hw_module_t* module, const char* name,
|
||||
struct hw_device_t** device);
|
||||
|
||||
static struct hw_module_methods_t overlay_module_methods = {
|
||||
open: overlay_device_open
|
||||
};
|
||||
|
||||
struct private_overlay_module_t {
|
||||
overlay_module_t base;
|
||||
Mutex *pobjMutex;
|
||||
};
|
||||
|
||||
struct private_overlay_module_t HAL_MODULE_INFO_SYM = {
|
||||
base: {
|
||||
common: {
|
||||
tag: HARDWARE_MODULE_TAG,
|
||||
version_major: 1,
|
||||
version_minor: 0,
|
||||
id: OVERLAY_HARDWARE_MODULE_ID,
|
||||
name: "QCT MSM OVERLAY module",
|
||||
author: "QuIC, Inc.",
|
||||
methods: &overlay_module_methods,
|
||||
}
|
||||
},
|
||||
pobjMutex: NULL,
|
||||
};
|
||||
|
||||
struct handle_t : public native_handle {
|
||||
int sharedMemoryFd;
|
||||
int ovid[2];
|
||||
int rotid[2];
|
||||
int size;
|
||||
int w;
|
||||
int h;
|
||||
int format;
|
||||
OverlayControlChannel *pobjControlChannel[2];
|
||||
};
|
||||
|
||||
static int handle_get_ovId(const overlay_handle_t overlay, int index = 0) {
|
||||
return static_cast<const struct handle_t *>(overlay)->ovid[index];
|
||||
}
|
||||
|
||||
static int handle_get_rotId(const overlay_handle_t overlay, int index = 0) {
|
||||
return static_cast<const struct handle_t *>(overlay)->rotid[index];
|
||||
}
|
||||
|
||||
|
||||
static int handle_get_size(const overlay_handle_t overlay) {
|
||||
return static_cast<const struct handle_t *>(overlay)->size;
|
||||
}
|
||||
|
||||
static int handle_get_shared_fd(const overlay_handle_t overlay) {
|
||||
return static_cast<const struct handle_t *>(overlay)->sharedMemoryFd;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the overlay_t object, it is returned to the user and represents
|
||||
* an overlay.
|
||||
* This handles will be passed across processes and possibly given to other
|
||||
* HAL modules (for instance video decode modules).
|
||||
*/
|
||||
class overlay_object : public overlay_t {
|
||||
handle_t mHandle;
|
||||
|
||||
static overlay_handle_t getHandleRef(struct overlay_t* overlay) {
|
||||
/* returns a reference to the handle, caller doesn't take ownership */
|
||||
return &(static_cast<overlay_object *>(overlay)->mHandle);
|
||||
}
|
||||
|
||||
public:
|
||||
overlay_object(int w, int h, int format, int fd) {
|
||||
this->overlay_t::getHandleRef = getHandleRef;
|
||||
mHandle.version = sizeof(native_handle);
|
||||
mHandle.sharedMemoryFd = fd;
|
||||
mHandle.numFds = 1;
|
||||
mHandle.numInts = (sizeof(mHandle) - sizeof(native_handle)) / 4;
|
||||
mHandle.ovid[0] = -1;
|
||||
mHandle.ovid[1] = -1;
|
||||
mHandle.rotid[0] = -1;
|
||||
mHandle.rotid[1] = -1;
|
||||
mHandle.size = -1;
|
||||
mHandle.w = w;
|
||||
mHandle.h = h;
|
||||
mHandle.format = format;
|
||||
mHandle.pobjControlChannel[0] = 0;
|
||||
mHandle.pobjControlChannel[1] = 0;
|
||||
}
|
||||
|
||||
~overlay_object() {
|
||||
destroy_overlay();
|
||||
}
|
||||
|
||||
int getHwOvId(int index = 0) { return mHandle.ovid[index]; }
|
||||
int getRotSessionId(int index = 0) { return mHandle.rotid[index]; }
|
||||
int getSharedMemoryFD() {return mHandle.sharedMemoryFd;}
|
||||
|
||||
bool startControlChannel(int fbnum, bool norot = false) {
|
||||
if (!mHandle.pobjControlChannel[fbnum])
|
||||
mHandle.pobjControlChannel[fbnum] = new OverlayControlChannel();
|
||||
else {
|
||||
mHandle.pobjControlChannel[fbnum]->closeControlChannel();
|
||||
mHandle.pobjControlChannel[fbnum] = new OverlayControlChannel();
|
||||
}
|
||||
bool ret = mHandle.pobjControlChannel[fbnum]->startControlChannel(
|
||||
mHandle.w, mHandle.h, mHandle.format, fbnum, norot);
|
||||
if (ret) {
|
||||
if (!(mHandle.pobjControlChannel[fbnum]->
|
||||
getOvSessionID(mHandle.ovid[fbnum]) &&
|
||||
mHandle.pobjControlChannel[fbnum]->
|
||||
getRotSessionID(mHandle.rotid[fbnum]) &&
|
||||
mHandle.pobjControlChannel[fbnum]->
|
||||
getSize(mHandle.size)))
|
||||
ret = false;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
closeControlChannel(fbnum);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool setPosition(int x, int y, uint32_t w, uint32_t h, int fbnum) {
|
||||
if (!mHandle.pobjControlChannel[fbnum])
|
||||
return false;
|
||||
return mHandle.pobjControlChannel[fbnum]->setPosition(
|
||||
x, y, w, h);
|
||||
}
|
||||
|
||||
bool setParameter(int param, int value, int fbnum) {
|
||||
if (!mHandle.pobjControlChannel[fbnum])
|
||||
return false;
|
||||
return mHandle.pobjControlChannel[fbnum]->setParameter(
|
||||
param, value);
|
||||
}
|
||||
|
||||
bool closeControlChannel(int fbnum) {
|
||||
if (!mHandle.pobjControlChannel[fbnum])
|
||||
return true;
|
||||
bool ret = mHandle.pobjControlChannel[fbnum]->
|
||||
closeControlChannel();
|
||||
delete mHandle.pobjControlChannel[fbnum];
|
||||
mHandle.pobjControlChannel[fbnum] = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool getPosition(int *x, int *y, uint32_t *w, uint32_t *h, int fbnum) {
|
||||
if (!mHandle.pobjControlChannel[fbnum])
|
||||
return false;
|
||||
return mHandle.pobjControlChannel[fbnum]->getPosition(
|
||||
*x, *y, *w, *h);
|
||||
}
|
||||
|
||||
bool getOrientation(int *orientation, int fbnum) {
|
||||
if (!mHandle.pobjControlChannel[fbnum])
|
||||
return false;
|
||||
return mHandle.pobjControlChannel[fbnum]->getOrientation(
|
||||
*orientation);
|
||||
}
|
||||
|
||||
void destroy_overlay() {
|
||||
close(mHandle.sharedMemoryFd);
|
||||
closeControlChannel(0);
|
||||
closeControlChannel(1);
|
||||
}
|
||||
|
||||
int getFBWidth(int fbnum) {
|
||||
if (!mHandle.pobjControlChannel[fbnum])
|
||||
return false;
|
||||
return mHandle.pobjControlChannel[fbnum]->getFBWidth();
|
||||
}
|
||||
|
||||
int getFBHeight(int fbnum) {
|
||||
if (!mHandle.pobjControlChannel[fbnum])
|
||||
return false;
|
||||
return mHandle.pobjControlChannel[fbnum]->getFBHeight();
|
||||
}
|
||||
};
|
||||
|
||||
// ****************************************************************************
|
||||
// Control module
|
||||
// ****************************************************************************
|
||||
|
||||
static int overlay_get(struct overlay_control_device_t *dev, int name) {
|
||||
int result = -1;
|
||||
switch (name) {
|
||||
case OVERLAY_MINIFICATION_LIMIT:
|
||||
result = HW_OVERLAY_MINIFICATION_LIMIT;
|
||||
break;
|
||||
case OVERLAY_MAGNIFICATION_LIMIT:
|
||||
result = HW_OVERLAY_MAGNIFICATION_LIMIT;
|
||||
break;
|
||||
case OVERLAY_SCALING_FRAC_BITS:
|
||||
result = 32;
|
||||
break;
|
||||
case OVERLAY_ROTATION_STEP_DEG:
|
||||
result = 90; // 90 rotation steps (for instance)
|
||||
break;
|
||||
case OVERLAY_HORIZONTAL_ALIGNMENT:
|
||||
result = 1; // 1-pixel alignment
|
||||
break;
|
||||
case OVERLAY_VERTICAL_ALIGNMENT:
|
||||
result = 1; // 1-pixel alignment
|
||||
break;
|
||||
case OVERLAY_WIDTH_ALIGNMENT:
|
||||
result = 1; // 1-pixel alignment
|
||||
break;
|
||||
case OVERLAY_HEIGHT_ALIGNMENT:
|
||||
result = 1; // 1-pixel alignment
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static overlay_t* overlay_createOverlay(struct overlay_control_device_t *dev,
|
||||
uint32_t w, uint32_t h, int32_t format) {
|
||||
overlay_object *overlay = NULL;
|
||||
overlay_control_context_t *ctx = (overlay_control_context_t *)dev;
|
||||
private_overlay_module_t* m = reinterpret_cast<private_overlay_module_t*>(
|
||||
dev->common.module);
|
||||
Mutex::Autolock objLock(m->pobjMutex);
|
||||
|
||||
// Open shared memory to store shared data
|
||||
int size = sizeof(overlay_shared_data);
|
||||
void *base;
|
||||
int fd = ashmem_create_region(SHARED_MEMORY_REGION_NAME,
|
||||
size);
|
||||
|
||||
if(fd < 0) {
|
||||
LOGE("%s: create shared memory failed", __func__);
|
||||
return NULL;
|
||||
}
|
||||
if (ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE) < 0) {
|
||||
LOGE("ashmem_set_prot_region(fd=%d, failed (%s)",
|
||||
fd, strerror(-errno));
|
||||
close(fd);
|
||||
fd = -1;
|
||||
return NULL;
|
||||
} else {
|
||||
base = mmap(0, size, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED|MAP_POPULATE, fd, 0);
|
||||
if (base == MAP_FAILED) {
|
||||
LOGE("alloc mmap(fd=%d, size=%d) failed (%s)",
|
||||
fd, size, strerror(-errno));
|
||||
close(fd);
|
||||
fd = -1;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
ctx->sharedMemBase = base;
|
||||
memset(ctx->sharedMemBase, 0, size);
|
||||
|
||||
/* number of buffer is not being used as overlay buffers are coming from client */
|
||||
overlay = new overlay_object(w, h, format, fd);
|
||||
|
||||
if (overlay == NULL) {
|
||||
LOGE("%s: can't create overlay object!", __FUNCTION__);
|
||||
if(ctx && (ctx->sharedMemBase != MAP_FAILED)) {
|
||||
munmap(ctx->sharedMemBase, size);
|
||||
ctx->sharedMemBase = MAP_FAILED;
|
||||
}
|
||||
if(fd > 0)
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef USE_MSM_ROTATOR
|
||||
if (!overlay->startControlChannel(0)) {
|
||||
#else
|
||||
if (!overlay->startControlChannel(0, true)) {
|
||||
#endif
|
||||
LOGE("Failed to start control channel for framebuffer 0");
|
||||
overlay->closeControlChannel(0);
|
||||
if(ctx && (ctx->sharedMemBase != MAP_FAILED)) {
|
||||
munmap(ctx->sharedMemBase, size);
|
||||
ctx->sharedMemBase = MAP_FAILED;
|
||||
}
|
||||
if(fd > 0)
|
||||
close(fd);
|
||||
|
||||
delete overlay;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char value[PROPERTY_VALUE_MAX];
|
||||
property_get("hw.hdmiON", value, "0");
|
||||
if (!atoi(value)) {
|
||||
return overlay;
|
||||
}
|
||||
|
||||
if (!overlay->startControlChannel(1, true)) {
|
||||
LOGE("Failed to start control channel for framebuffer 1");
|
||||
overlay->closeControlChannel(1);
|
||||
if(ctx && (ctx->sharedMemBase != MAP_FAILED)) {
|
||||
munmap(ctx->sharedMemBase, size);
|
||||
ctx->sharedMemBase = MAP_FAILED;
|
||||
}
|
||||
if(fd > 0)
|
||||
close(fd);
|
||||
|
||||
delete overlay;
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
int width = w, height = h, x, y;
|
||||
int fbWidthHDMI = overlay->getFBWidth(1);
|
||||
int fbHeightHDMI = overlay->getFBHeight(1);
|
||||
// width and height for YUV TILE format
|
||||
int tempWidth = w, tempHeight = h;
|
||||
/* Caculate the width and height if it is YUV TILE format*/
|
||||
if(format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
|
||||
tempWidth = w - ( (((w-1)/64 +1)*64) - w);
|
||||
tempHeight = h - ((((h-1)/32 +1)*32) - h);
|
||||
}
|
||||
|
||||
if (width * fbHeightHDMI >
|
||||
fbWidthHDMI * height) {
|
||||
height = fbWidthHDMI * height / width;
|
||||
EVEN_OUT(height);
|
||||
width = fbWidthHDMI;
|
||||
} else if (width * fbHeightHDMI <
|
||||
fbWidthHDMI * height) {
|
||||
width = fbHeightHDMI * width / height;
|
||||
EVEN_OUT(width);
|
||||
height = fbHeightHDMI;
|
||||
} else {
|
||||
width = fbWidthHDMI;
|
||||
height = fbHeightHDMI;
|
||||
}
|
||||
/* Scaling of upto a max of 8 times supported */
|
||||
if(width >(tempWidth * HW_OVERLAY_MAGNIFICATION_LIMIT)){
|
||||
width = HW_OVERLAY_MAGNIFICATION_LIMIT * tempWidth;
|
||||
}
|
||||
if(height >(tempHeight*HW_OVERLAY_MAGNIFICATION_LIMIT)) {
|
||||
height = HW_OVERLAY_MAGNIFICATION_LIMIT * tempHeight;
|
||||
}
|
||||
if (width > fbWidthHDMI) width = fbWidthHDMI;
|
||||
if (height > fbHeightHDMI) height = fbHeightHDMI;
|
||||
x = (fbWidthHDMI - width) / 2;
|
||||
y = (fbHeightHDMI - height) / 2;
|
||||
|
||||
if (!overlay->setPosition(x, y, width, height, 1))
|
||||
LOGE("Failed to upscale for framebuffer 1");
|
||||
}
|
||||
|
||||
return overlay;
|
||||
|
||||
}
|
||||
|
||||
static void overlay_destroyOverlay(struct overlay_control_device_t *dev,
|
||||
overlay_t* overlay)
|
||||
{
|
||||
overlay_control_context_t *ctx = (overlay_control_context_t *)dev;
|
||||
overlay_object * obj = static_cast<overlay_object *>(overlay);
|
||||
private_overlay_module_t* m = reinterpret_cast<private_overlay_module_t*>(
|
||||
dev->common.module);
|
||||
Mutex::Autolock objLock(m->pobjMutex);
|
||||
if(ctx && (ctx->sharedMemBase != MAP_FAILED)) {
|
||||
munmap(ctx->sharedMemBase, sizeof(overlay_shared_data));
|
||||
ctx->sharedMemBase = MAP_FAILED;
|
||||
}
|
||||
obj->destroy_overlay();
|
||||
delete overlay;
|
||||
}
|
||||
|
||||
static int overlay_setPosition(struct overlay_control_device_t *dev,
|
||||
overlay_t* overlay,
|
||||
int x, int y, uint32_t w, uint32_t h) {
|
||||
/* set this overlay's position (talk to the h/w) */
|
||||
overlay_control_context_t *ctx = (overlay_control_context_t *)dev;
|
||||
overlay_object * obj = static_cast<overlay_object *>(overlay);
|
||||
private_overlay_module_t* m = reinterpret_cast<private_overlay_module_t*>(
|
||||
dev->common.module);
|
||||
Mutex::Autolock objLock(m->pobjMutex);
|
||||
|
||||
bool ret = obj->setPosition(x, y, w, h, 0);
|
||||
if (!ret)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int overlay_commit(struct overlay_control_device_t *dev,
|
||||
overlay_t* overlay)
|
||||
{
|
||||
overlay_control_context_t *ctx = (overlay_control_context_t *)dev;
|
||||
overlay_object *obj = static_cast<overlay_object *>(overlay);
|
||||
private_overlay_module_t* m = reinterpret_cast<private_overlay_module_t*>(
|
||||
dev->common.module);
|
||||
|
||||
Mutex::Autolock objLock(m->pobjMutex);
|
||||
if (obj && (obj->getSharedMemoryFD() > 0) &&
|
||||
(ctx->sharedMemBase != MAP_FAILED)) {
|
||||
overlay_shared_data data;
|
||||
data.readyToQueue = 1;
|
||||
memcpy(ctx->sharedMemBase, (void*)&data, sizeof(overlay_shared_data));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int overlay_getPosition(struct overlay_control_device_t *dev,
|
||||
overlay_t* overlay,
|
||||
int* x, int* y, uint32_t* w, uint32_t* h) {
|
||||
|
||||
/* get this overlay's position */
|
||||
private_overlay_module_t* m = reinterpret_cast<private_overlay_module_t*>(
|
||||
dev->common.module);
|
||||
Mutex::Autolock objLock(m->pobjMutex);
|
||||
overlay_object * obj = static_cast<overlay_object *>(overlay);
|
||||
bool ret = obj->getPosition(x, y, w, h, 0);
|
||||
if (!ret)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int overlay_setParameter(struct overlay_control_device_t *dev,
|
||||
overlay_t* overlay, int param, int value) {
|
||||
|
||||
overlay_control_context_t *ctx = (overlay_control_context_t *)dev;
|
||||
overlay_object *obj = static_cast<overlay_object *>(overlay);
|
||||
private_overlay_module_t* m = reinterpret_cast<private_overlay_module_t*>(
|
||||
dev->common.module);
|
||||
|
||||
Mutex::Autolock objLock(m->pobjMutex);
|
||||
|
||||
if (obj && (obj->getSharedMemoryFD() > 0) &&
|
||||
(ctx->sharedMemBase != MAP_FAILED)) {
|
||||
overlay_shared_data data;
|
||||
data.readyToQueue = 0;
|
||||
memcpy(ctx->sharedMemBase, (void*)&data, sizeof(data));
|
||||
}
|
||||
|
||||
bool ret = obj->setParameter(param, value, 0);
|
||||
if (!ret)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int overlay_control_close(struct hw_device_t *dev)
|
||||
{
|
||||
struct overlay_control_context_t* ctx = (struct overlay_control_context_t*)dev;
|
||||
if (ctx) {
|
||||
/* free all resources associated with this device here
|
||||
* in particular the overlay_handle_t, outstanding overlay_t, etc...
|
||||
*/
|
||||
free(ctx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
// Data module
|
||||
// ****************************************************************************
|
||||
|
||||
int overlay_initialize(struct overlay_data_device_t *dev,
|
||||
overlay_handle_t handle)
|
||||
{
|
||||
/*
|
||||
* overlay_handle_t should contain all the information to "inflate" this
|
||||
* overlay. Typically it'll have a file descriptor, informations about
|
||||
* how many buffers are there, etc...
|
||||
* It is also the place to mmap all buffers associated with this overlay
|
||||
* (see getBufferAddress).
|
||||
*
|
||||
* NOTE: this function doesn't take ownership of overlay_handle_t
|
||||
*
|
||||
*/
|
||||
|
||||
struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev;
|
||||
int ovid = handle_get_ovId(handle);
|
||||
int rotid = handle_get_rotId(handle);
|
||||
int size = handle_get_size(handle);
|
||||
int sharedFd = handle_get_shared_fd(handle);
|
||||
|
||||
private_overlay_module_t* m = reinterpret_cast<private_overlay_module_t*>(
|
||||
dev->common.module);
|
||||
Mutex::Autolock objLock(m->pobjMutex);
|
||||
|
||||
ctx->sharedMemBase = MAP_FAILED;
|
||||
|
||||
if(sharedFd > 0) {
|
||||
void *base = mmap(0, sizeof(overlay_shared_data), PROT_READ,
|
||||
MAP_SHARED|MAP_POPULATE, sharedFd, 0);
|
||||
if(base == MAP_FAILED) {
|
||||
LOGE("%s: map region failed %d", __func__, -errno);
|
||||
return -1;
|
||||
}
|
||||
ctx->sharedMemBase = base;
|
||||
} else {
|
||||
LOGE("Received invalid shared memory fd");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->pobjDataChannel[0] = new OverlayDataChannel();
|
||||
if (!ctx->pobjDataChannel[0]->startDataChannel(ovid, rotid,
|
||||
size, 0)) {
|
||||
LOGE("Couldnt start data channel for framebuffer 0");
|
||||
delete ctx->pobjDataChannel[0];
|
||||
ctx->pobjDataChannel[0] = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
char value[PROPERTY_VALUE_MAX];
|
||||
property_get("hw.hdmiON", value, "0");
|
||||
if (!atoi(value)) {
|
||||
ctx->pobjDataChannel[1] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ovid = handle_get_ovId(handle, 1);
|
||||
rotid = handle_get_rotId(handle, 1);
|
||||
ctx->pobjDataChannel[1] = new OverlayDataChannel();
|
||||
if (!ctx->pobjDataChannel[1]->startDataChannel(ovid, rotid,
|
||||
size, 1, true)) {
|
||||
LOGE("Couldnt start data channel for framebuffer 1");
|
||||
delete ctx->pobjDataChannel[1];
|
||||
ctx->pobjDataChannel[1] = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int overlay_dequeueBuffer(struct overlay_data_device_t *dev,
|
||||
overlay_buffer_t* buf)
|
||||
{
|
||||
/* blocks until a buffer is available and return an opaque structure
|
||||
* representing this buffer.
|
||||
*/
|
||||
|
||||
/* no interal overlay buffer to dequeue */
|
||||
LOGE("%s: no buffer to dequeue ...\n", __FUNCTION__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int overlay_queueBuffer(struct overlay_data_device_t *dev,
|
||||
overlay_buffer_t buffer)
|
||||
{
|
||||
/* Mark this buffer for posting and recycle or free overlay_buffer_t. */
|
||||
struct overlay_data_context_t *ctx = (struct overlay_data_context_t*)dev;
|
||||
private_overlay_module_t* m = reinterpret_cast<private_overlay_module_t*>(
|
||||
dev->common.module);
|
||||
Mutex::Autolock objLock(m->pobjMutex);
|
||||
|
||||
// Check if readyToQueue is enabled.
|
||||
overlay_shared_data data;
|
||||
if(ctx->sharedMemBase != MAP_FAILED)
|
||||
memcpy(&data, ctx->sharedMemBase, sizeof(data));
|
||||
else
|
||||
return false;
|
||||
|
||||
if(!data.readyToQueue) {
|
||||
LOGE("Overlay is not ready to queue buffers");
|
||||
return -1;
|
||||
}
|
||||
if(ctx->setCrop) {
|
||||
bool result = (ctx->pobjDataChannel[0] &&
|
||||
ctx->pobjDataChannel[0]->
|
||||
setCrop(ctx->cropRect.x,ctx->cropRect.y,ctx->cropRect.w,ctx->cropRect.h));
|
||||
ctx->setCrop = 0;
|
||||
if (!result) {
|
||||
LOGE("set crop failed for framebuffer 0");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool result = (ctx->pobjDataChannel[0] &&
|
||||
ctx->pobjDataChannel[0]->
|
||||
queueBuffer((uint32_t) buffer));
|
||||
if (!result)
|
||||
LOGE("Queuebuffer failed for framebuffer 0");
|
||||
else {
|
||||
char value[PROPERTY_VALUE_MAX];
|
||||
property_get("hw.hdmiON", value, "0");
|
||||
if (!atoi(value)) {
|
||||
return 0;
|
||||
}
|
||||
result = (ctx->pobjDataChannel[1] &&
|
||||
ctx->pobjDataChannel[1]->
|
||||
queueBuffer((uint32_t) buffer));
|
||||
if (!result) {
|
||||
LOGE("QueueBuffer failed for framebuffer 1");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int overlay_setFd(struct overlay_data_device_t *dev, int fd)
|
||||
{
|
||||
private_overlay_module_t* m = reinterpret_cast<private_overlay_module_t*>(
|
||||
dev->common.module);
|
||||
struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev;
|
||||
Mutex::Autolock objLock(m->pobjMutex);
|
||||
|
||||
bool ret = (ctx->pobjDataChannel[0] &&
|
||||
ctx->pobjDataChannel[0]->setFd(fd));
|
||||
if (!ret) {
|
||||
LOGE("set fd failed for framebuffer 0");
|
||||
return -1;
|
||||
}
|
||||
|
||||
char value[PROPERTY_VALUE_MAX];
|
||||
property_get("hw.hdmiON", value, "0");
|
||||
if (!atoi(value)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = (ctx->pobjDataChannel[1] &&
|
||||
ctx->pobjDataChannel[1]->setFd(fd));
|
||||
if (!ret) {
|
||||
LOGE("set fd failed for framebuffer 1");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int overlay_setCrop(struct overlay_data_device_t *dev, uint32_t x,
|
||||
uint32_t y, uint32_t w, uint32_t h)
|
||||
{
|
||||
private_overlay_module_t* m = reinterpret_cast<private_overlay_module_t*>(
|
||||
dev->common.module);
|
||||
struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev;
|
||||
Mutex::Autolock objLock(m->pobjMutex);
|
||||
|
||||
//For primary set Crop
|
||||
ctx->setCrop = 1;
|
||||
ctx->cropRect.x = x;
|
||||
ctx->cropRect.y = y;
|
||||
ctx->cropRect.w = w;
|
||||
ctx->cropRect.h = h;
|
||||
|
||||
char value[PROPERTY_VALUE_MAX];
|
||||
property_get("hw.hdmiON", value, "0");
|
||||
if (!atoi(value)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ret = (ctx->pobjDataChannel[1] &&
|
||||
ctx->pobjDataChannel[1]->
|
||||
setCrop(x, y, w, h));
|
||||
if (!ret) {
|
||||
LOGE("set crop failed for framebuffer 1");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *overlay_getBufferAddress(struct overlay_data_device_t *dev,
|
||||
overlay_buffer_t buffer)
|
||||
{
|
||||
/* overlay buffers are coming from client */
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
int overlay_getBufferCount(struct overlay_data_device_t *dev)
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
static int overlay_data_close(struct hw_device_t *dev)
|
||||
{
|
||||
struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev;
|
||||
if (ctx) {
|
||||
/* free all resources associated with this device here
|
||||
* in particular all pending overlay_buffer_t if needed.
|
||||
*
|
||||
* NOTE: overlay_handle_t passed in initialize() is NOT freed and
|
||||
* its file descriptors are not closed (this is the responsibility
|
||||
* of the caller).
|
||||
*/
|
||||
|
||||
if (ctx->pobjDataChannel[0]) {
|
||||
ctx->pobjDataChannel[0]->closeDataChannel();
|
||||
delete ctx->pobjDataChannel[0];
|
||||
ctx->pobjDataChannel[0] = 0;
|
||||
}
|
||||
|
||||
if (ctx->pobjDataChannel[1]) {
|
||||
ctx->pobjDataChannel[1]->closeDataChannel();
|
||||
delete ctx->pobjDataChannel[1];
|
||||
ctx->pobjDataChannel[1] = 0;
|
||||
}
|
||||
|
||||
if(ctx->sharedMemBase != MAP_FAILED) {
|
||||
munmap(ctx->sharedMemBase, sizeof(overlay_shared_data));
|
||||
ctx->sharedMemBase = MAP_FAILED;
|
||||
}
|
||||
|
||||
free(ctx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static int overlay_device_open(const struct hw_module_t* module, const char* name,
|
||||
struct hw_device_t** device)
|
||||
{
|
||||
int status = -EINVAL;
|
||||
|
||||
private_overlay_module_t* m = reinterpret_cast<private_overlay_module_t*>
|
||||
(const_cast<hw_module_t*>(module));
|
||||
if (!m->pobjMutex)
|
||||
m->pobjMutex = new Mutex();
|
||||
|
||||
if (!strcmp(name, OVERLAY_HARDWARE_CONTROL)) {
|
||||
struct overlay_control_context_t *dev;
|
||||
dev = (overlay_control_context_t*)malloc(sizeof(*dev));
|
||||
|
||||
if (!dev)
|
||||
return status;
|
||||
|
||||
/* initialize our state here */
|
||||
memset(dev, 0, sizeof(*dev));
|
||||
|
||||
/* initialize the procs */
|
||||
dev->device.common.tag = HARDWARE_DEVICE_TAG;
|
||||
dev->device.common.version = 0;
|
||||
dev->device.common.module = const_cast<hw_module_t*>(module);
|
||||
dev->device.common.close = overlay_control_close;
|
||||
|
||||
dev->device.get = overlay_get;
|
||||
dev->device.createOverlay = overlay_createOverlay;
|
||||
dev->device.destroyOverlay = overlay_destroyOverlay;
|
||||
dev->device.setPosition = overlay_setPosition;
|
||||
dev->device.getPosition = overlay_getPosition;
|
||||
dev->device.setParameter = overlay_setParameter;
|
||||
dev->device.commit = overlay_commit;
|
||||
|
||||
*device = &dev->device.common;
|
||||
status = 0;
|
||||
} else if (!strcmp(name, OVERLAY_HARDWARE_DATA)) {
|
||||
struct overlay_data_context_t *dev;
|
||||
dev = (overlay_data_context_t*)malloc(sizeof(*dev));
|
||||
|
||||
if (!dev)
|
||||
return status;
|
||||
|
||||
/* initialize our state here */
|
||||
memset(dev, 0, sizeof(*dev));
|
||||
|
||||
/* initialize the procs */
|
||||
dev->device.common.tag = HARDWARE_DEVICE_TAG;
|
||||
dev->device.common.version = 0;
|
||||
dev->device.common.module = const_cast<hw_module_t*>(module);
|
||||
dev->device.common.close = overlay_data_close;
|
||||
|
||||
dev->device.initialize = overlay_initialize;
|
||||
dev->device.setCrop = overlay_setCrop;
|
||||
dev->device.dequeueBuffer = overlay_dequeueBuffer;
|
||||
dev->device.queueBuffer = overlay_queueBuffer;
|
||||
dev->device.setFd = overlay_setFd;
|
||||
dev->device.getBufferAddress = overlay_getBufferAddress;
|
||||
dev->device.getBufferCount = overlay_getBufferCount;
|
||||
|
||||
*device = &dev->device.common;
|
||||
status = 0;
|
||||
}
|
||||
return status;
|
||||
}
|
849
liboverlay/overlayLib.cpp
Normal file
849
liboverlay/overlayLib.cpp
Normal file
@ -0,0 +1,849 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* Copyright (c) 2010, 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 "overlayLib.h"
|
||||
#include "gralloc_priv.h"
|
||||
|
||||
#define INTERLACE_MASK 0x80
|
||||
/* Helper functions */
|
||||
|
||||
static int get_mdp_format(int format) {
|
||||
switch (format) {
|
||||
case HAL_PIXEL_FORMAT_RGBA_8888 :
|
||||
return MDP_RGBA_8888;
|
||||
case HAL_PIXEL_FORMAT_BGRA_8888:
|
||||
return MDP_BGRA_8888;
|
||||
case HAL_PIXEL_FORMAT_RGB_565:
|
||||
return MDP_RGB_565;
|
||||
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
|
||||
return MDP_Y_CBCR_H2V1;
|
||||
case HAL_PIXEL_FORMAT_YCbCr_420_SP:
|
||||
return MDP_Y_CBCR_H2V2;
|
||||
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
|
||||
return MDP_Y_CRCB_H2V2;
|
||||
case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
|
||||
return MDP_Y_CRCB_H2V2_TILE;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int get_size(int format, int w, int h) {
|
||||
int size, aligned_height, pitch;
|
||||
|
||||
size = w * h;
|
||||
switch (format) {
|
||||
case MDP_RGBA_8888:
|
||||
case MDP_BGRA_8888:
|
||||
size *= 4;
|
||||
break;
|
||||
case MDP_RGB_565:
|
||||
case MDP_Y_CBCR_H2V1:
|
||||
size *= 2;
|
||||
break;
|
||||
case MDP_Y_CBCR_H2V2:
|
||||
case MDP_Y_CRCB_H2V2:
|
||||
size = (size * 3) / 2;
|
||||
break;
|
||||
case MDP_Y_CRCB_H2V2_TILE:
|
||||
aligned_height = (h + 31) & ~31;
|
||||
pitch = (w + 127) & ~127;
|
||||
size = pitch * aligned_height;
|
||||
size = (size + 8191) & ~8191;
|
||||
|
||||
aligned_height = ((h >> 1) + 31) & ~31;
|
||||
size += pitch * aligned_height;
|
||||
size = (size + 8191) & ~8191;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
#define LOG_TAG "OverlayLIB"
|
||||
static void reportError(const char* message) {
|
||||
LOGE( "%s", message);
|
||||
}
|
||||
|
||||
using namespace overlay;
|
||||
|
||||
Overlay::Overlay() : mChannelUP(false) {
|
||||
}
|
||||
|
||||
Overlay::~Overlay() {
|
||||
closeChannel();
|
||||
}
|
||||
|
||||
int Overlay::getFBWidth() const {
|
||||
return objOvCtrlChannel.getFBWidth();
|
||||
}
|
||||
|
||||
int Overlay::getFBHeight() const {
|
||||
return objOvCtrlChannel.getFBHeight();
|
||||
}
|
||||
|
||||
bool Overlay::startChannel(int w, int h, int format, int fbnum, bool norot, bool uichannel) {
|
||||
mChannelUP = objOvCtrlChannel.startControlChannel(w, h, format, fbnum, norot);
|
||||
if (!mChannelUP) {
|
||||
return mChannelUP;
|
||||
}
|
||||
return objOvDataChannel.startDataChannel(objOvCtrlChannel, fbnum, norot, uichannel);
|
||||
}
|
||||
|
||||
bool Overlay::closeChannel() {
|
||||
if (!mChannelUP)
|
||||
return true;
|
||||
objOvCtrlChannel.closeControlChannel();
|
||||
objOvDataChannel.closeDataChannel();
|
||||
mChannelUP = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Overlay::getPosition(int& x, int& y, uint32_t& w, uint32_t& h) {
|
||||
return objOvCtrlChannel.getPosition(x, y, w, h);
|
||||
}
|
||||
|
||||
bool Overlay::getOrientation(int& orientation) const {
|
||||
return objOvCtrlChannel.getOrientation(orientation);
|
||||
}
|
||||
|
||||
bool Overlay::setPosition(int x, int y, uint32_t w, uint32_t h) {
|
||||
return objOvCtrlChannel.setPosition(x, y, w, h);
|
||||
}
|
||||
|
||||
bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation) {
|
||||
if (!objOvCtrlChannel.setSource(w, h, format, orientation)) {
|
||||
objOvCtrlChannel.closeControlChannel();
|
||||
objOvDataChannel.closeDataChannel();
|
||||
mChannelUP = false;
|
||||
return startChannel(w, h, format, 0, !orientation);
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Overlay::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) {
|
||||
if (!mChannelUP)
|
||||
return false;
|
||||
return objOvDataChannel.setCrop(x, y, w, h);
|
||||
}
|
||||
|
||||
bool Overlay::setParameter(int param, int value) {
|
||||
return objOvCtrlChannel.setParameter(param, value);
|
||||
}
|
||||
|
||||
bool Overlay::setOrientation(int value) {
|
||||
return objOvCtrlChannel.setParameter(OVERLAY_TRANSFORM, value);
|
||||
}
|
||||
|
||||
bool Overlay::setFd(int fd) {
|
||||
return objOvDataChannel.setFd(fd);
|
||||
}
|
||||
|
||||
bool Overlay::queueBuffer(uint32_t offset) {
|
||||
return objOvDataChannel.queueBuffer(offset);
|
||||
}
|
||||
|
||||
bool Overlay::queueBuffer(buffer_handle_t buffer) {
|
||||
private_handle_t const* hnd = reinterpret_cast
|
||||
<private_handle_t const*>(buffer);
|
||||
const size_t offset = hnd->offset;
|
||||
const int fd = hnd->fd;
|
||||
if (setFd(fd)) {
|
||||
return queueBuffer(offset);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
OverlayControlChannel::OverlayControlChannel() : mNoRot(false), mFD(-1), mRotFD(-1) {
|
||||
memset(&mOVInfo, 0, sizeof(mOVInfo));
|
||||
memset(&mRotInfo, 0, sizeof(mRotInfo));
|
||||
}
|
||||
|
||||
|
||||
OverlayControlChannel::~OverlayControlChannel() {
|
||||
closeControlChannel();
|
||||
}
|
||||
|
||||
bool OverlayControlChannel::openDevices(int fbnum) {
|
||||
if (fbnum < 0)
|
||||
return false;
|
||||
|
||||
char const * const device_template =
|
||||
"/dev/graphics/fb%u";
|
||||
char dev_name[64];
|
||||
snprintf(dev_name, 64, device_template, fbnum);
|
||||
|
||||
mFD = open(dev_name, O_RDWR, 0);
|
||||
if (mFD < 0) {
|
||||
reportError("Cant open framebuffer ");
|
||||
return false;
|
||||
}
|
||||
|
||||
fb_fix_screeninfo finfo;
|
||||
if (ioctl(mFD, FBIOGET_FSCREENINFO, &finfo) == -1) {
|
||||
reportError("FBIOGET_FSCREENINFO on fb1 failed");
|
||||
close(mFD);
|
||||
mFD = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
fb_var_screeninfo vinfo;
|
||||
if (ioctl(mFD, FBIOGET_VSCREENINFO, &vinfo) == -1) {
|
||||
reportError("FBIOGET_VSCREENINFO on fb1 failed");
|
||||
close(mFD);
|
||||
mFD = -1;
|
||||
return false;
|
||||
}
|
||||
mFBWidth = vinfo.xres;
|
||||
mFBHeight = vinfo.yres;
|
||||
mFBbpp = vinfo.bits_per_pixel;
|
||||
mFBystride = finfo.line_length;
|
||||
|
||||
if (!mNoRot) {
|
||||
mRotFD = open("/dev/msm_rotator", O_RDWR, 0);
|
||||
if (mRotFD < 0) {
|
||||
reportError("Cant open rotator device");
|
||||
close(mFD);
|
||||
mFD = -1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OverlayControlChannel::setOverlayInformation(int w, int h,
|
||||
int format, int flags) {
|
||||
int origW, origH, xoff, yoff;
|
||||
|
||||
mOVInfo.id = MSMFB_NEW_REQUEST;
|
||||
mOVInfo.src.width = w;
|
||||
mOVInfo.src.height = h;
|
||||
mOVInfo.src_rect.x = 0;
|
||||
mOVInfo.src_rect.y = 0;
|
||||
mOVInfo.dst_rect.x = 0;
|
||||
mOVInfo.dst_rect.y = 0;
|
||||
mOVInfo.dst_rect.w = w;
|
||||
mOVInfo.dst_rect.h = h;
|
||||
if(format == MDP_Y_CRCB_H2V2_TILE) {
|
||||
if (mNoRot) {
|
||||
mOVInfo.src_rect.w = w - ( (((w-1)/64 +1)*64) - w);
|
||||
mOVInfo.src_rect.h = h - ((((h-1)/32 +1)*32) - h);
|
||||
mOVInfo.src.format = MDP_Y_CRCB_H2V2_TILE;
|
||||
} else {
|
||||
mOVInfo.src_rect.w = w;
|
||||
mOVInfo.src_rect.h = h;
|
||||
mOVInfo.src.width = (((w-1)/64 +1)*64);
|
||||
mOVInfo.src.height = (((h-1)/32 +1)*32);
|
||||
mOVInfo.src_rect.x = mOVInfo.src.width - w;
|
||||
mOVInfo.src_rect.y = mOVInfo.src.height - h;
|
||||
mOVInfo.src.format = MDP_Y_CRCB_H2V2;
|
||||
}
|
||||
} else {
|
||||
mOVInfo.src_rect.w = w;
|
||||
mOVInfo.src_rect.h = h;
|
||||
mOVInfo.src.format = format;
|
||||
}
|
||||
|
||||
if (w > mFBWidth)
|
||||
mOVInfo.dst_rect.w = mFBWidth;
|
||||
if (h > mFBHeight)
|
||||
mOVInfo.dst_rect.h = mFBHeight;
|
||||
mOVInfo.z_order = 0;
|
||||
mOVInfo.alpha = 0xff;
|
||||
mOVInfo.transp_mask = 0xffffffff;
|
||||
mOVInfo.flags = flags;
|
||||
mOVInfo.is_fg = 0;
|
||||
mSize = get_size(format, w, h);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OverlayControlChannel::startOVRotatorSessions(int w, int h,
|
||||
int format) {
|
||||
bool ret = true;
|
||||
if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) {
|
||||
reportError("startOVRotatorSessions, Overlay set failed");
|
||||
ret = false;
|
||||
}
|
||||
else if (mNoRot)
|
||||
return true;
|
||||
|
||||
if (ret) {
|
||||
mRotInfo.src.format = format;
|
||||
mRotInfo.src.width = w;
|
||||
mRotInfo.src.height = h;
|
||||
mRotInfo.src_rect.w = w;
|
||||
mRotInfo.src_rect.h = h;
|
||||
mRotInfo.dst.width = w;
|
||||
mRotInfo.dst.height = h;
|
||||
if(format == MDP_Y_CRCB_H2V2_TILE) {
|
||||
mRotInfo.src.width = (((w-1)/64 +1)*64);
|
||||
mRotInfo.src.height = (((h-1)/32 +1)*32);
|
||||
mRotInfo.src_rect.w = (((w-1)/64 +1)*64);
|
||||
mRotInfo.src_rect.h = (((h-1)/32 +1)*32);
|
||||
mRotInfo.dst.width = (((w-1)/64 +1)*64);
|
||||
mRotInfo.dst.height = (((h-1)/32 +1)*32);
|
||||
mRotInfo.dst.format = MDP_Y_CRCB_H2V2;
|
||||
} else {
|
||||
mRotInfo.dst.format = format;
|
||||
}
|
||||
mRotInfo.dst_x = 0;
|
||||
mRotInfo.dst_y = 0;
|
||||
mRotInfo.src_rect.x = 0;
|
||||
mRotInfo.src_rect.y = 0;
|
||||
mRotInfo.rotations = 0;
|
||||
mRotInfo.enable = 0;
|
||||
mRotInfo.session_id = 0;
|
||||
int result = ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo);
|
||||
if (result) {
|
||||
reportError("Rotator session failed");
|
||||
ret = false;
|
||||
}
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
|
||||
closeControlChannel();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool OverlayControlChannel::startControlChannel(int w, int h,
|
||||
int format, int fbnum, bool norot) {
|
||||
mNoRot = norot;
|
||||
fb_fix_screeninfo finfo;
|
||||
fb_var_screeninfo vinfo;
|
||||
int hw_format;
|
||||
int flags = 0;
|
||||
int colorFormat = format;
|
||||
if (format & INTERLACE_MASK) {
|
||||
flags |= MDP_DEINTERLACE;
|
||||
|
||||
// Get the actual format
|
||||
colorFormat = format ^ HAL_PIXEL_FORMAT_INTERLACE;
|
||||
}
|
||||
hw_format = get_mdp_format(colorFormat);
|
||||
if (hw_format < 0) {
|
||||
reportError("Unsupported format");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!openDevices(fbnum))
|
||||
return false;
|
||||
|
||||
if (!setOverlayInformation(w, h, hw_format, flags))
|
||||
return false;
|
||||
|
||||
return startOVRotatorSessions(w, h, hw_format);
|
||||
}
|
||||
|
||||
bool OverlayControlChannel::closeControlChannel() {
|
||||
if (!isChannelUP())
|
||||
return true;
|
||||
|
||||
if (!mNoRot && mRotFD > 0) {
|
||||
ioctl(mRotFD, MSM_ROTATOR_IOCTL_FINISH, &(mRotInfo.session_id));
|
||||
close(mRotFD);
|
||||
mRotFD = -1;
|
||||
}
|
||||
|
||||
int ovid = mOVInfo.id;
|
||||
int ret = ioctl(mFD, MSMFB_OVERLAY_UNSET, &ovid);
|
||||
close(mFD);
|
||||
memset(&mOVInfo, 0, sizeof(mOVInfo));
|
||||
memset(&mRotInfo, 0, sizeof(mRotInfo));
|
||||
mFD = -1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OverlayControlChannel::setSource(uint32_t w, uint32_t h, int format, int orientation) {
|
||||
format = get_mdp_format(format);
|
||||
if ((orientation == mOrientation) && ((orientation == MDP_ROT_90)
|
||||
|| (orientation == MDP_ROT_270))) {
|
||||
if (format == MDP_Y_CRCB_H2V2_TILE) {
|
||||
format = MDP_Y_CRCB_H2V2;
|
||||
w = (((w-1)/64 +1)*64);
|
||||
h = (((h-1)/32 +1)*32);
|
||||
}
|
||||
int tmp = w;
|
||||
w = h;
|
||||
h = tmp;
|
||||
}
|
||||
if (w == mOVInfo.src.width && h == mOVInfo.src.height
|
||||
&& format == mOVInfo.src.format && orientation == mOrientation)
|
||||
return true;
|
||||
mOrientation = orientation;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OverlayControlChannel::setPosition(int x, int y, uint32_t w, uint32_t h) {
|
||||
|
||||
int width = w, height = h;
|
||||
if (!isChannelUP() ||
|
||||
(x < 0) || (y < 0) || ((x + w) > mFBWidth) ||
|
||||
((y + h) > mFBHeight)) {
|
||||
reportError("setPosition failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
mdp_overlay ov;
|
||||
ov.id = mOVInfo.id;
|
||||
if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) {
|
||||
reportError("setPosition, overlay GET failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Scaling of upto a max of 8 times supported */
|
||||
if(w >(ov.src_rect.w * HW_OVERLAY_MAGNIFICATION_LIMIT)){
|
||||
w = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.w;
|
||||
}
|
||||
if(h >(ov.src_rect.h * HW_OVERLAY_MAGNIFICATION_LIMIT)) {
|
||||
h = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.h;
|
||||
}
|
||||
ov.dst_rect.x = x;
|
||||
ov.dst_rect.y = y;
|
||||
ov.dst_rect.w = w;
|
||||
ov.dst_rect.h = h;
|
||||
|
||||
if (ioctl(mFD, MSMFB_OVERLAY_SET, &ov)) {
|
||||
reportError("setPosition, Overlay SET failed");
|
||||
return false;
|
||||
}
|
||||
mOVInfo = ov;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OverlayControlChannel::swapOVRotWidthHeight() {
|
||||
int tmp = mOVInfo.src.width;
|
||||
mOVInfo.src.width = mOVInfo.src.height;
|
||||
mOVInfo.src.height = tmp;
|
||||
|
||||
tmp = mOVInfo.src_rect.h;
|
||||
mOVInfo.src_rect.h = mOVInfo.src_rect.w;
|
||||
mOVInfo.src_rect.w = tmp;
|
||||
|
||||
tmp = mRotInfo.dst.width;
|
||||
mRotInfo.dst.width = mRotInfo.dst.height;
|
||||
mRotInfo.dst.height = tmp;
|
||||
}
|
||||
|
||||
bool OverlayControlChannel::setParameter(int param, int value) {
|
||||
if (!isChannelUP())
|
||||
return false;
|
||||
|
||||
mdp_overlay ov;
|
||||
ov.id = mOVInfo.id;
|
||||
if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) {
|
||||
reportError("setParameter, overlay GET failed");
|
||||
return false;
|
||||
}
|
||||
mOVInfo = ov;
|
||||
|
||||
switch (param) {
|
||||
case OVERLAY_DITHER:
|
||||
break;
|
||||
case OVERLAY_TRANSFORM:
|
||||
{
|
||||
int val = mOVInfo.user_data[0];
|
||||
if (value && mNoRot)
|
||||
return true;
|
||||
|
||||
switch(value) {
|
||||
case 0:
|
||||
{
|
||||
if (val == MDP_ROT_90) {
|
||||
int tmp = mOVInfo.src_rect.y;
|
||||
mOVInfo.src_rect.y = mOVInfo.src.width -
|
||||
(mOVInfo.src_rect.x + mOVInfo.src_rect.w);
|
||||
mOVInfo.src_rect.x = tmp;
|
||||
swapOVRotWidthHeight();
|
||||
}
|
||||
else if (val == MDP_ROT_270) {
|
||||
int tmp = mOVInfo.src_rect.x;
|
||||
mOVInfo.src_rect.x = mOVInfo.src.height - (
|
||||
mOVInfo.src_rect.y + mOVInfo.src_rect.h);
|
||||
mOVInfo.src_rect.y = tmp;
|
||||
swapOVRotWidthHeight();
|
||||
}
|
||||
mOVInfo.user_data[0] = MDP_ROT_NOP;
|
||||
break;
|
||||
}
|
||||
case OVERLAY_TRANSFORM_ROT_90:
|
||||
{
|
||||
if (val == MDP_ROT_270) {
|
||||
mOVInfo.src_rect.x = mOVInfo.src.width - (
|
||||
mOVInfo.src_rect.x + mOVInfo.src_rect.w);
|
||||
mOVInfo.src_rect.y = mOVInfo.src.height - (
|
||||
mOVInfo.src_rect.y + mOVInfo.src_rect.h);
|
||||
}
|
||||
else if (val == MDP_ROT_NOP || val == MDP_ROT_180) {
|
||||
int tmp = mOVInfo.src_rect.x;
|
||||
mOVInfo.src_rect.x = mOVInfo.src.height -
|
||||
(mOVInfo.src_rect.y + mOVInfo.src_rect.h);
|
||||
mOVInfo.src_rect.y = tmp;
|
||||
swapOVRotWidthHeight();
|
||||
}
|
||||
mOVInfo.user_data[0] = MDP_ROT_90;
|
||||
break;
|
||||
}
|
||||
case OVERLAY_TRANSFORM_ROT_180:
|
||||
{
|
||||
if (val == MDP_ROT_270) {
|
||||
int tmp = mOVInfo.src_rect.y;
|
||||
mOVInfo.src_rect.y = mOVInfo.src.width -
|
||||
(mOVInfo.src_rect.x + mOVInfo.src_rect.w);
|
||||
mOVInfo.src_rect.x = tmp;
|
||||
swapOVRotWidthHeight();
|
||||
}
|
||||
else if (val == MDP_ROT_90) {
|
||||
int tmp = mOVInfo.src_rect.x;
|
||||
mOVInfo.src_rect.x = mOVInfo.src.height - (
|
||||
mOVInfo.src_rect.y + mOVInfo.src_rect.h);
|
||||
mOVInfo.src_rect.y = tmp;
|
||||
swapOVRotWidthHeight();
|
||||
}
|
||||
mOVInfo.user_data[0] = MDP_ROT_180;
|
||||
break;
|
||||
}
|
||||
case OVERLAY_TRANSFORM_ROT_270:
|
||||
{
|
||||
if (val == MDP_ROT_90) {
|
||||
mOVInfo.src_rect.y = mOVInfo.src.height -
|
||||
(mOVInfo.src_rect.y + mOVInfo.src_rect.h);
|
||||
mOVInfo.src_rect.x = mOVInfo.src.width -
|
||||
(mOVInfo.src_rect.x + mOVInfo.src_rect.w);
|
||||
}
|
||||
else if (val == MDP_ROT_NOP || val == MDP_ROT_180) {
|
||||
int tmp = mOVInfo.src_rect.y;
|
||||
mOVInfo.src_rect.y = mOVInfo.src.width - (
|
||||
mOVInfo.src_rect.x + mOVInfo.src_rect.w);
|
||||
mOVInfo.src_rect.x = tmp;
|
||||
swapOVRotWidthHeight();
|
||||
}
|
||||
|
||||
mOVInfo.user_data[0] = MDP_ROT_270;
|
||||
break;
|
||||
}
|
||||
default: return false;
|
||||
}
|
||||
mRotInfo.rotations = mOVInfo.user_data[0];
|
||||
if (mOVInfo.user_data[0])
|
||||
mRotInfo.enable = 1;
|
||||
else {
|
||||
if(mRotInfo.src.format == MDP_Y_CRCB_H2V2_TILE)
|
||||
mOVInfo.src.format = MDP_Y_CRCB_H2V2_TILE;
|
||||
mRotInfo.enable = 0;
|
||||
}
|
||||
if (ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo)) {
|
||||
reportError("setParameter, rotator start failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) {
|
||||
reportError("setParameter, overlay set failed");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
reportError("Unsupproted param");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OverlayControlChannel::getPosition(int& x, int& y,
|
||||
uint32_t& w, uint32_t& h) {
|
||||
if (!isChannelUP())
|
||||
return false;
|
||||
|
||||
mdp_overlay ov;
|
||||
ov.id = mOVInfo.id;
|
||||
if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) {
|
||||
reportError("getPosition, overlay GET failed");
|
||||
return false;
|
||||
}
|
||||
mOVInfo = ov;
|
||||
|
||||
x = mOVInfo.dst_rect.x;
|
||||
y = mOVInfo.dst_rect.y;
|
||||
w = mOVInfo.dst_rect.w;
|
||||
h = mOVInfo.dst_rect.h;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OverlayControlChannel::getOrientation(int& orientation) const {
|
||||
if (!isChannelUP())
|
||||
return false;
|
||||
|
||||
mdp_overlay ov;
|
||||
ov.id = mOVInfo.id;
|
||||
if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) {
|
||||
reportError("getOrientation, overlay GET failed");
|
||||
return false;
|
||||
}
|
||||
orientation = ov.user_data[0];
|
||||
return true;
|
||||
}
|
||||
bool OverlayControlChannel::getOvSessionID(int& sessionID) const {
|
||||
if (!isChannelUP())
|
||||
return false;
|
||||
sessionID = mOVInfo.id;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OverlayControlChannel::getRotSessionID(int& sessionID) const {
|
||||
if (!isChannelUP())
|
||||
return false;
|
||||
sessionID = mRotInfo.session_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OverlayControlChannel::getSize(int& size) const {
|
||||
if (!isChannelUP())
|
||||
return false;
|
||||
size = mSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
OverlayDataChannel::OverlayDataChannel() : mNoRot(false), mFD(-1), mRotFD(-1),
|
||||
mPmemFD(-1), mPmemAddr(0) {
|
||||
}
|
||||
|
||||
OverlayDataChannel::~OverlayDataChannel() {
|
||||
closeDataChannel();
|
||||
}
|
||||
|
||||
bool OverlayDataChannel::startDataChannel(
|
||||
const OverlayControlChannel& objOvCtrlChannel,
|
||||
int fbnum, bool norot, bool uichannel) {
|
||||
int ovid, rotid, size;
|
||||
mNoRot = norot;
|
||||
memset(&mOvData, 0, sizeof(mOvData));
|
||||
memset(&mOvDataRot, 0, sizeof(mOvDataRot));
|
||||
memset(&mRotData, 0, sizeof(mRotData));
|
||||
if (objOvCtrlChannel.getOvSessionID(ovid) &&
|
||||
objOvCtrlChannel.getRotSessionID(rotid) &&
|
||||
objOvCtrlChannel.getSize(size)) {
|
||||
return startDataChannel(ovid, rotid, size, fbnum, norot, uichannel);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OverlayDataChannel::openDevices(int fbnum, bool uichannel) {
|
||||
if (fbnum < 0)
|
||||
return false;
|
||||
char const * const device_template =
|
||||
"/dev/graphics/fb%u";
|
||||
char dev_name[64];
|
||||
snprintf(dev_name, 64, device_template, fbnum);
|
||||
|
||||
mFD = open(dev_name, O_RDWR, 0);
|
||||
if (mFD < 0) {
|
||||
reportError("Cant open framebuffer ");
|
||||
return false;
|
||||
}
|
||||
if (!mNoRot) {
|
||||
mRotFD = open("/dev/msm_rotator", O_RDWR, 0);
|
||||
if (mRotFD < 0) {
|
||||
reportError("Cant open rotator device");
|
||||
close(mFD);
|
||||
mFD = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
mPmemAddr = MAP_FAILED;
|
||||
|
||||
if(!uichannel) {
|
||||
mPmemFD = open("/dev/pmem_smipool", O_RDWR | O_SYNC);
|
||||
if(mPmemFD >= 0)
|
||||
mPmemAddr = (void *) mmap(NULL, mPmemOffset * 2, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, mPmemFD, 0);
|
||||
}
|
||||
|
||||
if (mPmemAddr == MAP_FAILED) {
|
||||
mPmemFD = open("/dev/pmem_adsp", O_RDWR | O_SYNC);
|
||||
if (mPmemFD < 0) {
|
||||
reportError("Cant open pmem_adsp ");
|
||||
close(mFD);
|
||||
mFD = -1;
|
||||
close(mRotFD);
|
||||
mRotFD = -1;
|
||||
return false;
|
||||
} else {
|
||||
mPmemAddr = (void *) mmap(NULL, mPmemOffset * 2, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, mPmemFD, 0);
|
||||
if (mPmemAddr == MAP_FAILED) {
|
||||
reportError("Cant map pmem_adsp ");
|
||||
close(mFD);
|
||||
mFD = -1;
|
||||
close(mPmemFD);
|
||||
mPmemFD = -1;
|
||||
close(mRotFD);
|
||||
mRotFD = -1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mOvDataRot.data.memory_id = mPmemFD;
|
||||
mRotData.dst.memory_id = mPmemFD;
|
||||
mRotData.dst.offset = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OverlayDataChannel::startDataChannel(int ovid, int rotid, int size,
|
||||
int fbnum, bool norot, bool uichannel) {
|
||||
memset(&mOvData, 0, sizeof(mOvData));
|
||||
memset(&mOvDataRot, 0, sizeof(mOvDataRot));
|
||||
memset(&mRotData, 0, sizeof(mRotData));
|
||||
mNoRot = norot;
|
||||
mOvData.data.memory_id = -1;
|
||||
mOvData.id = ovid;
|
||||
mOvDataRot = mOvData;
|
||||
mPmemOffset = size;
|
||||
mRotData.session_id = rotid;
|
||||
|
||||
return openDevices(fbnum, uichannel);
|
||||
}
|
||||
|
||||
bool OverlayDataChannel::closeDataChannel() {
|
||||
if (!isChannelUP())
|
||||
return true;
|
||||
|
||||
if (!mNoRot && mRotFD > 0) {
|
||||
munmap(mPmemAddr, mPmemOffset * 2);
|
||||
close(mPmemFD);
|
||||
mPmemFD = -1;
|
||||
close(mRotFD);
|
||||
mRotFD = -1;
|
||||
}
|
||||
close(mFD);
|
||||
mFD = -1;
|
||||
memset(&mOvData, 0, sizeof(mOvData));
|
||||
memset(&mOvDataRot, 0, sizeof(mOvDataRot));
|
||||
memset(&mRotData, 0, sizeof(mRotData));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OverlayDataChannel::setFd(int fd) {
|
||||
mOvData.data.memory_id = fd;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OverlayDataChannel::queueBuffer(uint32_t offset) {
|
||||
if ((!isChannelUP()) || mOvData.data.memory_id < 0) {
|
||||
reportError("QueueBuffer failed, either channel is not set or no file descriptor to read from");
|
||||
return false;
|
||||
}
|
||||
|
||||
msmfb_overlay_data *odPtr;
|
||||
mOvData.data.offset = offset;
|
||||
odPtr = &mOvData;
|
||||
|
||||
if (!mNoRot) {
|
||||
mRotData.src.memory_id = mOvData.data.memory_id;
|
||||
mRotData.src.offset = offset;
|
||||
mRotData.dst.offset = (mRotData.dst.offset) ? 0 : mPmemOffset;
|
||||
|
||||
int result = ioctl(mRotFD,
|
||||
MSM_ROTATOR_IOCTL_ROTATE, &mRotData);
|
||||
|
||||
if (!result) {
|
||||
mOvDataRot.data.offset = (uint32_t) mRotData.dst.offset;
|
||||
odPtr = &mOvDataRot;
|
||||
}
|
||||
}
|
||||
|
||||
if (ioctl(mFD, MSMFB_OVERLAY_PLAY, odPtr)) {
|
||||
reportError("overlay play failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OverlayDataChannel::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) {
|
||||
if (!isChannelUP()) {
|
||||
reportError("Channel not set");
|
||||
return false;
|
||||
}
|
||||
|
||||
mdp_overlay ov;
|
||||
ov.id = mOvData.id;
|
||||
if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) {
|
||||
reportError("setCrop, overlay GET failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ov.user_data[0] == MDP_ROT_90) {
|
||||
int tmp = x;
|
||||
x = ov.src.width - (y + h);
|
||||
y = tmp;
|
||||
|
||||
tmp = w;
|
||||
w = h;
|
||||
h = tmp;
|
||||
}
|
||||
else if (ov.user_data[0] == MDP_ROT_270) {
|
||||
int tmp = y;
|
||||
y = ov.src.height - (x + w);
|
||||
x = tmp;
|
||||
|
||||
tmp = w;
|
||||
w = h;
|
||||
h = tmp;
|
||||
}
|
||||
|
||||
if ((ov.src_rect.x == x) &&
|
||||
(ov.src_rect.y == y) &&
|
||||
(ov.src_rect.w == w) &&
|
||||
(ov.src_rect.h == h))
|
||||
return true;
|
||||
if ( (int) x < 0 || (int) y < 0 || (int) w < 0 || (int) h < 0){
|
||||
LOGE("%s: invalid value for crop: x=%d,y=%d,w=%d,h=%d",__func__,x,y,w,h);
|
||||
return false;
|
||||
}
|
||||
|
||||
ov.src_rect.x = x;
|
||||
ov.src_rect.y = y;
|
||||
ov.src_rect.w = w;
|
||||
ov.src_rect.h = h;
|
||||
|
||||
/* Scaling of upto a max of 8 times supported */
|
||||
if(ov.dst_rect.w >(ov.src_rect.w * HW_OVERLAY_MAGNIFICATION_LIMIT)){
|
||||
ov.dst_rect.w = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.w;
|
||||
}
|
||||
if(ov.dst_rect.h >(ov.src_rect.h * HW_OVERLAY_MAGNIFICATION_LIMIT)) {
|
||||
ov.dst_rect.h = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.h;
|
||||
}
|
||||
if (ioctl(mFD, MSMFB_OVERLAY_SET, &ov)) {
|
||||
reportError("setCrop, overlay set error");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
153
liboverlay/overlayLib.h
Normal file
153
liboverlay/overlayLib.h
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* Copyright (c) 2010, 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 INCLUDE_OVERLAY_LIB
|
||||
#define INCLUDE_OVERLAY_LIB
|
||||
|
||||
#include <cutils/log.h>
|
||||
#include <cutils/properties.h>
|
||||
#include <cutils/atomic.h>
|
||||
|
||||
#include <hardware/hardware.h>
|
||||
#include <hardware/gralloc.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <linux/fb.h>
|
||||
#include <linux/msm_mdp.h>
|
||||
#include <linux/msm_rotator.h>
|
||||
#include <linux/android_pmem.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <hardware/overlay.h>
|
||||
|
||||
#define HW_OVERLAY_MAGNIFICATION_LIMIT 8
|
||||
#define HW_OVERLAY_MINIFICATION_LIMIT HW_OVERLAY_MAGNIFICATION_LIMIT
|
||||
|
||||
namespace overlay {
|
||||
|
||||
class OverlayControlChannel {
|
||||
|
||||
bool mNoRot;
|
||||
|
||||
int mFBWidth;
|
||||
int mFBHeight;
|
||||
int mFBbpp;
|
||||
int mFBystride;
|
||||
|
||||
int mFD;
|
||||
int mRotFD;
|
||||
int mSize;
|
||||
int mOrientation;
|
||||
mdp_overlay mOVInfo;
|
||||
msm_rotator_img_info mRotInfo;
|
||||
bool openDevices(int fbnum = -1);
|
||||
bool setOverlayInformation(int w, int h, int format, int flags);
|
||||
bool startOVRotatorSessions(int w, int h, int format);
|
||||
void swapOVRotWidthHeight();
|
||||
|
||||
public:
|
||||
OverlayControlChannel();
|
||||
~OverlayControlChannel();
|
||||
bool startControlChannel(int w, int h, int format,
|
||||
int fbnum, bool norot = false);
|
||||
bool closeControlChannel();
|
||||
bool setPosition(int x, int y, uint32_t w, uint32_t h);
|
||||
bool setParameter(int param, int value);
|
||||
bool getPosition(int& x, int& y, uint32_t& w, uint32_t& h);
|
||||
bool getOvSessionID(int& sessionID) const;
|
||||
bool getRotSessionID(int& sessionID) const;
|
||||
bool getSize(int& size) const;
|
||||
bool isChannelUP() const { return (mFD > 0); }
|
||||
int getFBWidth() const { return mFBWidth; }
|
||||
int getFBHeight() const { return mFBHeight; }
|
||||
bool getOrientation(int& orientation) const;
|
||||
bool setSource(uint32_t w, uint32_t h, int format, int orientation);
|
||||
};
|
||||
|
||||
class OverlayDataChannel {
|
||||
|
||||
bool mNoRot;
|
||||
int mFD;
|
||||
int mRotFD;
|
||||
int mPmemFD;
|
||||
void* mPmemAddr;
|
||||
uint32_t mPmemOffset;
|
||||
msmfb_overlay_data mOvData;
|
||||
msmfb_overlay_data mOvDataRot;
|
||||
msm_rotator_data_info mRotData;
|
||||
|
||||
bool openDevices(int fbnum = -1, bool uichannel = false);
|
||||
|
||||
public:
|
||||
OverlayDataChannel();
|
||||
~OverlayDataChannel();
|
||||
bool startDataChannel(const OverlayControlChannel& objOvCtrlChannel,
|
||||
int fbnum, bool norot = false, bool uichannel = false);
|
||||
bool startDataChannel(int ovid, int rotid, int size,
|
||||
int fbnum, bool norot = false, bool uichannel = false);
|
||||
bool closeDataChannel();
|
||||
bool setFd(int fd);
|
||||
bool queueBuffer(uint32_t offset);
|
||||
bool setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h);
|
||||
bool isChannelUP() const { return (mFD > 0); }
|
||||
};
|
||||
|
||||
/*
|
||||
* Overlay class for single thread application
|
||||
* A multiple thread/process application need to use Overlay HAL
|
||||
*/
|
||||
class Overlay {
|
||||
|
||||
bool mChannelUP;
|
||||
|
||||
OverlayControlChannel objOvCtrlChannel;
|
||||
OverlayDataChannel objOvDataChannel;
|
||||
|
||||
public:
|
||||
Overlay();
|
||||
~Overlay();
|
||||
|
||||
bool startChannel(int w, int h, int format, int fbnum, bool norot = false, bool uichannel = false);
|
||||
bool closeChannel();
|
||||
bool setPosition(int x, int y, uint32_t w, uint32_t h);
|
||||
bool setParameter(int param, int value);
|
||||
bool setOrientation(int value);
|
||||
bool setFd(int fd);
|
||||
bool queueBuffer(uint32_t offset);
|
||||
bool getPosition(int& x, int& y, uint32_t& w, uint32_t& h);
|
||||
bool isChannelUP() const { return mChannelUP; }
|
||||
int getFBWidth() const;
|
||||
int getFBHeight() const;
|
||||
bool getOrientation(int& orientation) const;
|
||||
bool queueBuffer(buffer_handle_t buffer);
|
||||
bool setSource(uint32_t w, uint32_t h, int format, int orientation);
|
||||
bool setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h);
|
||||
};
|
||||
|
||||
struct overlay_shared_data {
|
||||
int readyToQueue;
|
||||
};
|
||||
|
||||
};
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user