am 0028b620: overlay: Call MSMFB_SECURE on alloc/free of secure rotator buffer
* commit '0028b620909a0ddc8edac301967bfa43fb33a421':
overlay: Call MSMFB_SECURE on alloc/free of secure rotator buffer
diff --git a/msm8084/Android.mk b/msm8084/Android.mk
index 0959e7a..59a9751 100644
--- a/msm8084/Android.mk
+++ b/msm8084/Android.mk
@@ -1,6 +1,6 @@
display-hals := libgralloc libcopybit liblight libvirtual
display-hals += libhwcomposer liboverlay libqdutils libexternal libqservice
-display-hals += libmemtrack hdmi_cec
+display-hals += libmemtrack
ifeq ($(call is-vendor-board-platform,QCOM),true)
include $(call all-named-subdir-makefiles,$(display-hals))
else
diff --git a/msm8084/hdmi_cec/Android.mk b/msm8084/hdmi_cec/Android.mk
deleted file mode 100644
index a605b6b..0000000
--- a/msm8084/hdmi_cec/Android.mk
+++ /dev/null
@@ -1,15 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(LOCAL_PATH)/../common.mk
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := hdmi_cec.$(TARGET_BOARD_PLATFORM)
-LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
-LOCAL_MODULE_TAGS := optional
-LOCAL_C_INCLUDES := $(common_includes)
-LOCAL_SHARED_LIBRARIES := $(common_libs) libqservice libbinder libqdutils
-
-LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdhdmi_cec\"
-LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
-LOCAL_SRC_FILES := qhdmi_cec.cpp \
- QHDMIClient.cpp
-include $(BUILD_SHARED_LIBRARY)
diff --git a/msm8084/hdmi_cec/QHDMIClient.cpp b/msm8084/hdmi_cec/QHDMIClient.cpp
deleted file mode 100644
index 176779a..0000000
--- a/msm8084/hdmi_cec/QHDMIClient.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-* Copyright (c) 2014 The Linux Foundation. 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 The Linux Foundation. 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 <QServiceUtils.h>
-#include "QHDMIClient.h"
-
-using namespace android;
-using namespace qhdmicec;
-using namespace qService;
-
-namespace qClient {
-
-void QHDMIClient::binderDied(const wp<IBinder>& who __unused)
-{
- ALOGW("%s: Display QService died", __FUNCTION__);
-}
-
-void QHDMIClient::onHdmiHotplug(int connected)
-{
- ALOGD("%s: HDMI connected event connected: %d", __FUNCTION__, connected);
- cec_hdmi_hotplug(mCtx, connected);
-}
-
-void QHDMIClient::onCECMessageRecieved(char *msg, ssize_t len)
-{
- ALOGD("%s: CEC message received len: %zd", __FUNCTION__, len);
- cec_receive_message(mCtx, msg, len);
-}
-
-void QHDMIClient::registerClient(sp<QHDMIClient>& client)
-{
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder = sm->getService(String16("display.qservice"));
- binder->linkToDeath(client);
- mQService = interface_cast<IQService>(binder);
- mQService->connect(interface_cast<IQHDMIClient>(client));
-}
-
-};
diff --git a/msm8084/hdmi_cec/QHDMIClient.h b/msm8084/hdmi_cec/QHDMIClient.h
deleted file mode 100644
index 9e54f2f..0000000
--- a/msm8084/hdmi_cec/QHDMIClient.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-* Copyright (c) 2014 The Linux Foundation. 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 The Linux Foundation. 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 "IQHDMIClient.h"
-#include "qhdmi_cec.h"
-#include <IQService.h>
-
-namespace qClient {
-
-class QHDMIClient: public android::IBinder::DeathRecipient,
- public BnQHDMIClient
-{
-public:
- QHDMIClient() {}
-
- virtual void binderDied(const android::wp<android::IBinder>& who);
-
- virtual void onHdmiHotplug(int connected);
-
- virtual void onCECMessageRecieved(char *msg, ssize_t len);
-
- void setCECContext(qhdmicec::cec_context_t* ctx) { mCtx = ctx; }
-
- void registerClient(android::sp<QHDMIClient>& client);
-
-private:
- qhdmicec::cec_context_t* mCtx;
- android::sp<qService::IQService> mQService;
-
-};
-};
diff --git a/msm8084/hdmi_cec/qhdmi_cec.cpp b/msm8084/hdmi_cec/qhdmi_cec.cpp
deleted file mode 100644
index d23fce6..0000000
--- a/msm8084/hdmi_cec/qhdmi_cec.cpp
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
-* Copyright (c) 2014 The Linux Foundation. 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 The Linux Foundation. nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#define DEBUG 1
-#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
-#include <cstdlib>
-#include <cutils/log.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <hardware/hdmi_cec.h>
-#include <utils/Trace.h>
-#include "qhdmi_cec.h"
-#include "QHDMIClient.h"
-
-namespace qhdmicec {
-
-const int NUM_HDMI_PORTS = 1;
-const int MAX_SYSFS_DATA = 128;
-const int MAX_CEC_FRAME_SIZE = 20;
-const int MAX_SEND_MESSAGE_RETRIES = 1;
-
-enum {
- LOGICAL_ADDRESS_SET = 1,
- LOGICAL_ADDRESS_UNSET = -1,
-};
-
-// Offsets of members of struct hdmi_cec_msg
-// drivers/video/msm/mdss/mdss_hdmi_cec.c
-// XXX: Get this from a driver header
-enum {
- CEC_OFFSET_SENDER_ID,
- CEC_OFFSET_RECEIVER_ID,
- CEC_OFFSET_OPCODE,
- CEC_OFFSET_OPERAND,
- CEC_OFFSET_FRAME_LENGTH = 18,
- CEC_OFFSET_RETRANSMIT,
-};
-
-//Forward declarations
-static void cec_close_context(cec_context_t* ctx __unused);
-static int cec_enable(cec_context_t *ctx, int enable);
-
-static ssize_t read_node(const char *path, char *data)
-{
- ssize_t err = 0;
- FILE *fp = NULL;
- err = access(path, R_OK);
- if (!err) {
- fp = fopen(path, "r");
- err = fread(data, sizeof(char), MAX_SYSFS_DATA ,fp);
- fclose(fp);
- }
- return err;
-}
-
-static ssize_t write_node(const char *path, const char *data, size_t len)
-{
- ssize_t err = 0;
- int fd = -1;
- err = access(path, W_OK);
- if (!err) {
- fd = open(path, O_WRONLY);
- errno = 0;
- err = write(fd, data, len);
- if (err < 0) {
- err = -errno;
- }
- close(fd);
- } else {
- ALOGE("%s: Failed to access path: %s error: %s",
- __FUNCTION__, path, strerror(errno));
- err = -errno;
- }
- return err;
-}
-
-// Helper function to write integer values to the full sysfs path
-static ssize_t write_int_to_node(cec_context_t *ctx,
- const char *path_postfix,
- const int value)
-{
- char sysfs_full_path[MAX_PATH_LENGTH];
- char sysfs_data[MAX_SYSFS_DATA];
- snprintf(sysfs_data, sizeof(sysfs_data), "%d",value);
- snprintf(sysfs_full_path,sizeof(sysfs_full_path), "%s/%s",
- ctx->fb_sysfs_path, path_postfix);
- ssize_t err = write_node(sysfs_full_path, sysfs_data, strlen(sysfs_data));
- return err;
-}
-
-static void hex_to_string(const char *msg, ssize_t len, char *str)
-{
- //Functions assumes sufficient memory in str
- char *ptr = str;
- for(int i=0; i < len ; i++) {
- ptr += snprintf(ptr, 3, "%02X", msg[i]);
- // Overwrite null termination of snprintf in all except the last byte
- if (i < len - 1)
- *ptr = ':';
- ptr++;
- }
-}
-
-static ssize_t cec_get_fb_node_number(cec_context_t *ctx)
-{
- //XXX: Do this from a common utility library across the display HALs
- const int MAX_FB_DEVICES = 2;
- ssize_t len = 0;
- char fb_type_path[MAX_PATH_LENGTH];
- char fb_type[MAX_SYSFS_DATA];
- const char *dtv_panel_str = "dtv panel";
-
- for(int num = 0; num < MAX_FB_DEVICES; num++) {
- snprintf(fb_type_path, sizeof(fb_type_path),"%s%d/msm_fb_type",
- SYSFS_BASE,num);
- ALOGD_IF(DEBUG, "%s: num: %d fb_type_path: %s", __FUNCTION__, num, fb_type_path);
- len = read_node(fb_type_path, fb_type);
- ALOGD_IF(DEBUG, "%s: fb_type:%s", __FUNCTION__, fb_type);
- if(len > 0 && (strncmp(fb_type, dtv_panel_str, strlen(dtv_panel_str)) == 0)){
- ALOGD_IF(DEBUG, "%s: Found DTV panel at fb%d", __FUNCTION__, num);
- ctx->fb_num = num;
- snprintf(ctx->fb_sysfs_path, sizeof(ctx->fb_sysfs_path),
- "%s%d", SYSFS_BASE, num);
- break;
- }
- }
- if (len < 0)
- return len;
- else
- return 0;
-}
-
-static int cec_add_logical_address(const struct hdmi_cec_device* dev,
- cec_logical_address_t addr)
-{
- if (addr < CEC_ADDR_TV || addr > CEC_ADDR_BROADCAST) {
- ALOGE("%s: Received invalid address: %d ", __FUNCTION__, addr);
- return -EINVAL;
- }
- cec_context_t* ctx = (cec_context_t*)(dev);
- ctx->logical_address[addr] = LOGICAL_ADDRESS_SET;
-
- //XXX: We can get multiple logical addresses here but we can only send one
- //to the driver. Store locally for now
- ssize_t err = write_int_to_node(ctx, "cec/logical_addr", addr);
- ALOGD_IF(DEBUG, "%s: Allocated logical address: %d ", __FUNCTION__, addr);
- return (int) err;
-}
-
-static void cec_clear_logical_address(const struct hdmi_cec_device* dev)
-{
- cec_context_t* ctx = (cec_context_t*)(dev);
- memset(ctx->logical_address, LOGICAL_ADDRESS_UNSET,
- sizeof(ctx->logical_address));
- //XXX: Find logical_addr that needs to be reset
- write_int_to_node(ctx, "cec/logical_addr", -1);
- ALOGD_IF(DEBUG, "%s: Cleared logical addresses", __FUNCTION__);
-}
-
-static int cec_get_physical_address(const struct hdmi_cec_device* dev,
- uint16_t* addr)
-{
- cec_context_t* ctx = (cec_context_t*)(dev);
- //XXX: Not sure if this physical address is the same as the one in port info
- *addr = ctx->port_info[0].physical_address;
- ALOGD_IF(DEBUG, "%s: Physical Address: 0x%x", __FUNCTION__, *addr);
- return 0;
-}
-
-static int cec_send_message(const struct hdmi_cec_device* dev,
- const cec_message_t* msg)
-{
- ATRACE_CALL();
- cec_context_t* ctx = (cec_context_t*)(dev);
- ALOGD_IF(DEBUG, "%s: initiator: %d destination: %d length: %u",
- __FUNCTION__, msg->initiator, msg->destination,
- (uint32_t) msg->length);
-
- // Dump message received from framework
- char dump[128];
- if(msg->length > 0) {
- hex_to_string((char*)msg->body, msg->length, dump);
- ALOGD_IF(DEBUG, "%s: message from framework: %s", __FUNCTION__, dump);
- }
-
- char write_msg_path[MAX_PATH_LENGTH];
- char write_msg[MAX_CEC_FRAME_SIZE];
- memset(write_msg, 0, sizeof(write_msg));
- // See definition of struct hdmi_cec_msg in driver code
- // drivers/video/msm/mdss/mdss_hdmi_cec.c
- // Write header block
- // XXX: Include this from header in kernel
- write_msg[CEC_OFFSET_SENDER_ID] = msg->initiator;
- write_msg[CEC_OFFSET_RECEIVER_ID] = msg->destination;
- //Kernel splits opcode/operand, but Android sends it in one byte array
- write_msg[CEC_OFFSET_OPCODE] = msg->body[0];
- if(msg->length > 1) {
- memcpy(&write_msg[CEC_OFFSET_OPERAND], &msg->body[1],
- sizeof(char)*(msg->length - 1));
- }
- //msg length + initiator + destination
- write_msg[CEC_OFFSET_FRAME_LENGTH] = (unsigned char) (msg->length + 1);
- hex_to_string(write_msg, sizeof(write_msg), dump);
- ALOGD_IF(DEBUG, "%s: message to driver: %s", __FUNCTION__, dump);
- snprintf(write_msg_path, sizeof(write_msg_path), "%s/cec/wr_msg",
- ctx->fb_sysfs_path);
- int retry_count = 0;
- ssize_t err = 0;
- //HAL spec requires us to retry at least once.
- while (true) {
- err = write_node(write_msg_path, write_msg, sizeof(write_msg));
- retry_count++;
- if (err == -EAGAIN && retry_count <= MAX_SEND_MESSAGE_RETRIES) {
- ALOGE("%s: CEC line busy, retrying", __FUNCTION__);
- } else {
- break;
- }
- }
-
- if (err < 0) {
- if (err == -ENXIO) {
- ALOGE("%s: No device exists with the destination address",
- __FUNCTION__);
- return HDMI_RESULT_NACK;
- } else if (err == -EAGAIN) {
- ALOGE("%s: CEC line is busy, max retry count exceeded",
- __FUNCTION__);
- return HDMI_RESULT_BUSY;
- } else {
- return HDMI_RESULT_FAIL;
- ALOGE("%s: Failed to send CEC message err: %zd - %s",
- __FUNCTION__, err, strerror(-err));
- }
- } else {
- ALOGD_IF(DEBUG, "%s: Sent CEC message - %zd bytes written",
- __FUNCTION__, err);
- return HDMI_RESULT_SUCCESS;
- }
-}
-
-void cec_receive_message(cec_context_t *ctx, char *msg, ssize_t len)
-{
- char dump[128];
- if(len > 0) {
- hex_to_string(msg, len, dump);
- ALOGD_IF(DEBUG, "%s: Message from driver: %s", __FUNCTION__, dump);
- }
-
- hdmi_event_t event;
- event.type = HDMI_EVENT_CEC_MESSAGE;
- event.dev = (hdmi_cec_device *) ctx;
- // Remove initiator/destination from this calculation
- event.cec.length = msg[CEC_OFFSET_FRAME_LENGTH] - 1;
- event.cec.initiator = (cec_logical_address_t) msg[CEC_OFFSET_SENDER_ID];
- event.cec.destination = (cec_logical_address_t) msg[CEC_OFFSET_RECEIVER_ID];
- //Copy opcode and operand
- memcpy(event.cec.body, &msg[CEC_OFFSET_OPCODE], event.cec.length);
- hex_to_string((char *) event.cec.body, event.cec.length, dump);
- ALOGD_IF(DEBUG, "%s: Message to framework: %s", __FUNCTION__, dump);
- ctx->callback.callback_func(&event, ctx->callback.callback_arg);
-}
-
-void cec_hdmi_hotplug(cec_context_t *ctx, int connected)
-{
- hdmi_event_t event;
- event.type = HDMI_EVENT_HOT_PLUG;
- event.dev = (hdmi_cec_device *) ctx;
- event.hotplug.connected = connected ? HDMI_CONNECTED : HDMI_NOT_CONNECTED;
- ctx->callback.callback_func(&event, ctx->callback.callback_arg);
-}
-
-static void cec_register_event_callback(const struct hdmi_cec_device* dev,
- event_callback_t callback, void* arg)
-{
- ALOGD_IF(DEBUG, "%s: Registering callback", __FUNCTION__);
- cec_context_t* ctx = (cec_context_t*)(dev);
- ctx->callback.callback_func = callback;
- ctx->callback.callback_arg = arg;
-}
-
-static void cec_get_version(const struct hdmi_cec_device* dev, int* version)
-{
- cec_context_t* ctx = (cec_context_t*)(dev);
- *version = ctx->version;
- ALOGD_IF(DEBUG, "%s: version: %d", __FUNCTION__, *version);
-}
-
-static void cec_get_vendor_id(const struct hdmi_cec_device* dev,
- uint32_t* vendor_id)
-{
- cec_context_t* ctx = (cec_context_t*)(dev);
- *vendor_id = ctx->vendor_id;
- ALOGD_IF(DEBUG, "%s: vendor id: %u", __FUNCTION__, *vendor_id);
-}
-
-static void cec_get_port_info(const struct hdmi_cec_device* dev,
- struct hdmi_port_info* list[], int* total)
-{
- ALOGD_IF(DEBUG, "%s: Get port info", __FUNCTION__);
- cec_context_t* ctx = (cec_context_t*)(dev);
- *total = NUM_HDMI_PORTS;
- *list = ctx->port_info;
-}
-
-static void cec_set_option(const struct hdmi_cec_device* dev, int flag,
- int value)
-{
- cec_context_t* ctx = (cec_context_t*)(dev);
- ALOGD_IF(DEBUG, "%s: flag:%d value:%d", __FUNCTION__, flag, value);
- switch (flag) {
- case HDMI_OPTION_WAKEUP:
- //XXX
- break;
- case HDMI_OPTION_ENABLE_CEC:
- cec_enable(ctx, value? 1 : 0);
- break;
- case HDMI_OPTION_SYSTEM_CEC_CONTROL:
- //XXX
- break;
- }
-}
-
-static void cec_set_audio_return_channel(const struct hdmi_cec_device* dev,
- int flag)
-{
- cec_context_t* ctx = (cec_context_t*)(dev);
- ctx->arc_enabled = flag ? true : false;
- ALOGD_IF(DEBUG, "%s: ARC flag: %d", __FUNCTION__, flag);
-}
-
-static int cec_is_connected(const struct hdmi_cec_device* dev, int port_id)
-{
- // Ignore port_id since we have only one port
- int connected = 0;
- cec_context_t* ctx = (cec_context_t*)(dev);
- char connected_path[MAX_PATH_LENGTH];
- char connected_data[MAX_SYSFS_DATA];
- snprintf (connected_path, sizeof(connected_path),"%s/connected",
- ctx->fb_sysfs_path);
- ssize_t err = read_node(connected_path, connected_data);
- connected = atoi(connected_data);
-
- ALOGD_IF(DEBUG, "%s: HDMI at port %d is - %s", __FUNCTION__, port_id,
- connected ? "connected":"disconnected");
- if (err)
- return (int) err;
- else
- return connected;
-}
-
-static int cec_device_close(struct hw_device_t *dev)
-{
- ALOGD_IF(DEBUG, "%s: Close CEC HAL ", __FUNCTION__);
- if (!dev) {
- ALOGE("%s: NULL device pointer", __FUNCTION__);
- return -EINVAL;
- }
- cec_context_t* ctx = (cec_context_t*)(dev);
- cec_close_context(ctx);
- free(dev);
- return 0;
-}
-
-static int cec_enable(cec_context_t *ctx, int enable)
-{
- ssize_t err;
- err = write_int_to_node(ctx, "cec/enable", !!enable);
- if(err < 0) {
- ALOGE("%s: Failed to toggle CEC: enable: %d",
- __FUNCTION__, enable);
- return (int) err;
- }
- ctx->enabled = enable;
- return 0;
-}
-
-static void cec_init_context(cec_context_t *ctx)
-{
- ALOGD_IF(DEBUG, "%s: Initializing context", __FUNCTION__);
- cec_get_fb_node_number(ctx);
-
- //Initialize ports - We support only one output port
- ctx->port_info = new hdmi_port_info[NUM_HDMI_PORTS];
- ctx->port_info[0].type = HDMI_OUTPUT;
- //XXX: Updated l-dev has port_id field
- ctx->port_info[0].port_id = 1;
- ctx->port_info[0].cec_supported = 1;
- //XXX: Enable ARC if supported
- ctx->port_info[0].arc_supported = 0;
- //XXX: Get physical address from driver
- ctx->port_info[0].physical_address = 0x1000;
-
- ctx->version = 0x4;
- //XXX: Get vendor ID from driver - this is currently a placeholder value
- ctx->vendor_id = 0x4571;
- cec_clear_logical_address((hdmi_cec_device_t*)ctx);
-
- //Set up listener for HDMI events
- ctx->disp_client = new qClient::QHDMIClient();
- ctx->disp_client->setCECContext(ctx);
- ctx->disp_client->registerClient(ctx->disp_client);
-
- //Enable CEC - framework expects it to be enabled by default
- cec_enable(ctx, true);
-
- ALOGD("%s: CEC enabled", __FUNCTION__);
-}
-
-static void cec_close_context(cec_context_t* ctx __unused)
-{
- ALOGD("%s: Closing context", __FUNCTION__);
-}
-
-static int cec_device_open(const struct hw_module_t* module,
- const char* name,
- struct hw_device_t** device)
-{
- ALOGD_IF(DEBUG, "%s: name: %s", __FUNCTION__, name);
- int status = -EINVAL;
- if (!strcmp(name, HDMI_CEC_HARDWARE_INTERFACE )) {
- struct cec_context_t *dev;
- dev = (cec_context_t *) calloc (1, sizeof(*dev));
- cec_init_context(dev);
-
- //Setup CEC methods
- dev->device.common.tag = HARDWARE_DEVICE_TAG;
- dev->device.common.version = HDMI_CEC_DEVICE_API_VERSION_1_0;
- dev->device.common.module = const_cast<hw_module_t* >(module);
- dev->device.common.close = cec_device_close;
- dev->device.add_logical_address = cec_add_logical_address;
- dev->device.clear_logical_address = cec_clear_logical_address;
- dev->device.get_physical_address = cec_get_physical_address;
- dev->device.send_message = cec_send_message;
- dev->device.register_event_callback = cec_register_event_callback;
- dev->device.get_version = cec_get_version;
- dev->device.get_vendor_id = cec_get_vendor_id;
- dev->device.get_port_info = cec_get_port_info;
- dev->device.set_option = cec_set_option;
- dev->device.set_audio_return_channel = cec_set_audio_return_channel;
- dev->device.is_connected = cec_is_connected;
-
- *device = &dev->device.common;
- status = 0;
- }
- return status;
-}
-}; //namespace qhdmicec
-
-// Standard HAL module, should be outside qhdmicec namespace
-static struct hw_module_methods_t cec_module_methods = {
- .open = qhdmicec::cec_device_open
-};
-
-hdmi_module_t HAL_MODULE_INFO_SYM = {
- .common = {
- .tag = HARDWARE_MODULE_TAG,
- .version_major = 1,
- .version_minor = 0,
- .id = HDMI_CEC_HARDWARE_MODULE_ID,
- .name = "QTI HDMI CEC module",
- .author = "The Linux Foundation",
- .methods = &cec_module_methods,
- }
-};
-
-
diff --git a/msm8084/hdmi_cec/qhdmi_cec.h b/msm8084/hdmi_cec/qhdmi_cec.h
deleted file mode 100644
index 4afd07f..0000000
--- a/msm8084/hdmi_cec/qhdmi_cec.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-* Copyright (c) 2014 The Linux Foundation. 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 The Linux Foundation. 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 QHDMI_CEC_H
-#define QHDMI_CEC_H
-
-#include <hardware/hdmi_cec.h>
-#include <utils/RefBase.h>
-
-namespace qClient {
- class QHDMIClient;
-};
-
-namespace qhdmicec {
-
-#define SYSFS_BASE "/sys/class/graphics/fb"
-#define MAX_PATH_LENGTH 128
-
-struct cec_callback_t {
- // Function in HDMI service to call back on CEC messages
- event_callback_t callback_func;
- // This stores the object to pass back to the framework
- void* callback_arg;
-
-};
-
-struct cec_context_t {
- hdmi_cec_device_t device; // Device for HW module
- cec_callback_t callback; // Struct storing callback object
- bool enabled;
- bool arc_enabled;
- int fb_num; // Framebuffer node for HDMI
- char fb_sysfs_path[MAX_PATH_LENGTH];
- hdmi_port_info *port_info; // HDMI port info
-
- // Logical address is stored in an array, the index of the array is the
- // logical address and the value in the index shows whether it is set or not
- int logical_address[CEC_ADDR_BROADCAST];
- int version;
- uint32_t vendor_id;
- android::sp<qClient::QHDMIClient> disp_client;
-};
-
-void cec_receive_message(cec_context_t *ctx, char *msg, ssize_t len);
-void cec_hdmi_hotplug(cec_context_t *ctx, int connected);
-
-}; //namespace
-#endif /* end of include guard: QHDMI_CEC_H */
diff --git a/msm8084/libgralloc/alloc_controller.cpp b/msm8084/libgralloc/alloc_controller.cpp
index 775ef44..4dae3e6 100644
--- a/msm8084/libgralloc/alloc_controller.cpp
+++ b/msm8084/libgralloc/alloc_controller.cpp
@@ -596,7 +596,7 @@
//Planar
case HAL_PIXEL_FORMAT_YV12:
ystride = hnd->width;
- cstride = hnd->width/2;
+ cstride = ALIGN(hnd->width/2, 16);
ycbcr->y = (void*)hnd->base;
ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
ycbcr->cb = (void*)(hnd->base + ystride * hnd->height +
diff --git a/msm8084/libgralloc/gpu.cpp b/msm8084/libgralloc/gpu.cpp
index 226e259..0782c96 100644
--- a/msm8084/libgralloc/gpu.cpp
+++ b/msm8084/libgralloc/gpu.cpp
@@ -30,6 +30,7 @@
using namespace gralloc;
#define SZ_1M 0x100000
+#define SZ_2M 0x200000
gpu_context_t::gpu_context_t(const private_module_t* module,
IAllocController* alloc_ctrl ) :
@@ -71,7 +72,7 @@
#ifdef MDSS_TARGET
if ((usage & GRALLOC_USAGE_PROTECTED) &&
(usage & GRALLOC_USAGE_PRIVATE_MM_HEAP)) {
- data.align = ALIGN((int) data.align, SZ_1M);
+ data.align = ALIGN((int) data.align, SZ_2M);
size = ALIGN(size, data.align);
}
#endif
diff --git a/msm8084/libhwcomposer/hwc_mdpcomp.cpp b/msm8084/libhwcomposer/hwc_mdpcomp.cpp
index 08aa4f2..603b8ef 100644
--- a/msm8084/libhwcomposer/hwc_mdpcomp.cpp
+++ b/msm8084/libhwcomposer/hwc_mdpcomp.cpp
@@ -347,7 +347,8 @@
* There also is a HW limilation in MDP, minimum block size is 2x2
* Fallback to GPU if height is less than 2.
*/
- if((crop_w < 5)||(crop_h < 5))
+ if(qdutils::MDPVersion::getInstance().hasMinCropWidthLimitation() and
+ (crop_w < 5 or crop_h < 5))
return false;
if((w_scale > 1.0f) || (h_scale > 1.0f)) {
@@ -2049,7 +2050,8 @@
qdutils::MDPVersion::getInstance().isSrcSplitAlways();
int lSplit = getLeftSplit(ctx, mDpy);
int dstWidth = dst.right - dst.left;
- int cropWidth = crop.right - crop.left;
+ int cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
+ crop.right - crop.left;
if(dstWidth > qdutils::MAX_DISPLAY_DIM or
cropWidth > qdutils::MAX_DISPLAY_DIM or
diff --git a/msm8084/libhwcomposer/hwc_virtual.cpp b/msm8084/libhwcomposer/hwc_virtual.cpp
index 97b19ea..5d3f593 100644
--- a/msm8084/libhwcomposer/hwc_virtual.cpp
+++ b/msm8084/libhwcomposer/hwc_virtual.cpp
@@ -112,9 +112,9 @@
ctx->dpyAttr[dpy].vsync_period
= ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period;
init(ctx);
- // XXX: for architectures with limited resources we would normally
- // allow one padding round to free up resources but this breaks
- // certain use cases.
+ // Do a padding round so that primary can free up a pipe for virtual
+ // The virtual composition falls back to GPU for this frame
+ ctx->isPaddingRound = true;
}
if(!ctx->dpyAttr[dpy].isPause) {
ctx->dpyAttr[dpy].isConfiguring = false;
diff --git a/msm8084/liboverlay/overlayMem.h b/msm8084/liboverlay/overlayMem.h
index e8338fb..b2e7dd1 100644
--- a/msm8084/liboverlay/overlayMem.h
+++ b/msm8084/liboverlay/overlayMem.h
@@ -41,6 +41,7 @@
#include "mdpWrapper.h"
#define SIZE_1M 0x00100000
+#define SIZE_2M 0x00200000
namespace overlay {
@@ -138,8 +139,8 @@
if(isSecure) {
allocFlags = GRALLOC_USAGE_PRIVATE_MM_HEAP;
allocFlags |= GRALLOC_USAGE_PROTECTED;
- mBufSzAligned = utils::align(bufSz, SIZE_1M);
- data.align = SIZE_1M;
+ mBufSzAligned = utils::align(bufSz, SIZE_2M);
+ data.align = SIZE_2M;
} else {
mBufSzAligned = bufSz;
data.align = getpagesize();
diff --git a/msm8084/libqdutils/mdp_version.cpp b/msm8084/libqdutils/mdp_version.cpp
index a2ecf8a..dcf8af7 100644
--- a/msm8084/libqdutils/mdp_version.cpp
+++ b/msm8084/libqdutils/mdp_version.cpp
@@ -364,6 +364,10 @@
}
+bool MDPVersion::hasMinCropWidthLimitation() const {
+ return mMdpRev <= MDSS_MDP_HW_REV_102;
+}
+
bool MDPVersion::supportsDecimation() {
return mFeatures & MDP_DECIMATION_EN;
}
diff --git a/msm8084/libqdutils/mdp_version.h b/msm8084/libqdutils/mdp_version.h
index 7246ad6..94d21f3 100644
--- a/msm8084/libqdutils/mdp_version.h
+++ b/msm8084/libqdutils/mdp_version.h
@@ -139,6 +139,7 @@
bool needsROIMerge() { return mPanelInfo.mNeedsROIMerge; }
unsigned long getLowBw() { return mLowBw; }
unsigned long getHighBw() { return mHighBw; }
+ bool hasMinCropWidthLimitation() const;
bool isSrcSplit() const;
bool isSrcSplitAlways() const;
bool isRGBScalarSupported() const;
diff --git a/msm8226/Android.mk b/msm8226/Android.mk
index 6f4b865..59a9751 100644
--- a/msm8226/Android.mk
+++ b/msm8226/Android.mk
@@ -4,8 +4,7 @@
ifeq ($(call is-vendor-board-platform,QCOM),true)
include $(call all-named-subdir-makefiles,$(display-hals))
else
-ifneq ($(filter msm8226 msm8x26,$(TARGET_BOARD_PLATFORM)),)
- #This is for mako since it doesn't have the QCOM make functions
+ifneq ($(filter msm% apq%,$(TARGET_BOARD_PLATFORM)),)
include $(call all-named-subdir-makefiles,$(display-hals))
endif
endif
diff --git a/msm8226/common.mk b/msm8226/common.mk
index 83407fb..0bcb288 100644
--- a/msm8226/common.mk
+++ b/msm8226/common.mk
@@ -1,12 +1,12 @@
#Common headers
-common_includes := hardware/qcom/display/msm8226/libgralloc
-common_includes += hardware/qcom/display/msm8226/liboverlay
-common_includes += hardware/qcom/display/msm8226/libcopybit
-common_includes += hardware/qcom/display/msm8226/libqdutils
-common_includes += hardware/qcom/display/msm8226/libhwcomposer
-common_includes += hardware/qcom/display/msm8226/libexternal
-common_includes += hardware/qcom/display/msm8226/libqservice
-common_includes += hardware/qcom/display/msm8226/libvirtual
+common_includes := $(LOCAL_PATH)/../libgralloc
+common_includes += $(LOCAL_PATH)/../liboverlay
+common_includes += $(LOCAL_PATH)/../libcopybit
+common_includes += $(LOCAL_PATH)/../libqdutils
+common_includes += $(LOCAL_PATH)/../libhwcomposer
+common_includes += $(LOCAL_PATH)/../libexternal
+common_includes += $(LOCAL_PATH)/../libqservice
+common_includes += $(LOCAL_PATH)/../libvirtual
ifeq ($(TARGET_USES_POST_PROCESSING),true)
common_flags += -DUSES_POST_PROCESSING
@@ -27,8 +27,8 @@
common_flags += -D__ARM_HAVE_NEON
endif
-ifeq ($(call is-board-platform-in-list, msm8226 msm8610 apq8084 \
- mpq8092 msm_bronze msm8916), true)
+ifeq ($(call is-board-platform-in-list, msm8974 msm8226 msm8610 apq8084 \
+ mpq8092 msm_bronze msm8916 msm8994), true)
common_flags += -DVENUS_COLOR_FORMAT
common_flags += -DMDSS_TARGET
endif
diff --git a/msm8226/libcopybit/Android.mk b/msm8226/libcopybit/Android.mk
index 2ac7d15..c239c3a 100644
--- a/msm8226/libcopybit/Android.mk
+++ b/msm8226/libcopybit/Android.mk
@@ -22,7 +22,7 @@
include $(BUILD_COPY_HEADERS)
LOCAL_MODULE := copybit.$(TARGET_BOARD_PLATFORM)
-LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
LOCAL_SHARED_LIBRARIES := $(common_libs) libdl libmemalloc
diff --git a/msm8226/libcopybit/copybit.cpp b/msm8226/libcopybit/copybit.cpp
index c0246e3..84d7620 100644
--- a/msm8226/libcopybit/copybit.cpp
+++ b/msm8226/libcopybit/copybit.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2010 - 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010 - 2014, The Linux Foundation. All rights reserved.
*
* Not a Contribution, Apache license notifications and license are retained
* for attribution purposes only.
@@ -154,7 +154,7 @@
img->width = rhs->w;
img->height = rhs->h;
img->format = get_format(rhs->format);
- img->offset = hnd->offset;
+ img->offset = (uint32_t)hnd->offset;
img->memory_id = hnd->fd;
}
/** setup rectangles */
@@ -162,9 +162,7 @@
struct mdp_blit_req *e,
const struct copybit_rect_t *dst,
const struct copybit_rect_t *src,
- const struct copybit_rect_t *scissor,
- uint32_t horiz_padding,
- uint32_t vert_padding) {
+ const struct copybit_rect_t *scissor) {
struct copybit_rect_t clip;
intersect(&clip, scissor, dst);
@@ -312,7 +310,7 @@
case COPYBIT_PLANE_ALPHA:
if (value < 0) value = MDP_ALPHA_NOP;
if (value >= 256) value = 255;
- ctx->mAlpha = value;
+ ctx->mAlpha = (uint8_t)value;
break;
case COPYBIT_DITHER:
if (value == COPYBIT_ENABLE) {
@@ -491,7 +489,8 @@
return -EINVAL;
}
}
- const uint32_t maxCount = sizeof(list->req)/sizeof(list->req[0]);
+ const uint32_t maxCount =
+ (uint32_t)(sizeof(list->req)/sizeof(list->req[0]));
const struct copybit_rect_t bounds = { 0, 0, (int)dst->w, (int)dst->h };
struct copybit_rect_t clip;
status = 0;
@@ -508,7 +507,7 @@
set_infos(ctx, req, flags);
set_image(&req->dst, dst);
set_image(&req->src, src);
- set_rects(ctx, req, dst_rect, src_rect, &clip, src->horiz_padding, src->vert_padding);
+ set_rects(ctx, req, dst_rect, src_rect, &clip);
if (req->src_rect.w<=0 || req->src_rect.h<=0)
continue;
@@ -553,6 +552,9 @@
static int finish_copybit(struct copybit_device_t *dev)
{
// NOP for MDP copybit
+ if(!dev)
+ return -EINVAL;
+
return 0;
}
static int clear_copybit(struct copybit_device_t *dev,
@@ -702,6 +704,10 @@
struct hw_device_t** device)
{
int status = -EINVAL;
+
+ if (strcmp(name, COPYBIT_HARDWARE_COPYBIT0)) {
+ return COPYBIT_FAILURE;
+ }
copybit_context_t *ctx;
ctx = (copybit_context_t *)malloc(sizeof(copybit_context_t));
memset(ctx, 0, sizeof(*ctx));
diff --git a/msm8226/libcopybit/copybit_c2d.cpp b/msm8226/libcopybit/copybit_c2d.cpp
index 7aad58c..d2b00dd 100644
--- a/msm8226/libcopybit/copybit_c2d.cpp
+++ b/msm8226/libcopybit/copybit_c2d.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
*
* Not a Contribution, Apache license notifications and license are retained
* for attribution purposes only.
@@ -78,8 +78,8 @@
C2D_STATUS (*LINK_c2dDestroySurface)( uint32 surface_id );
-C2D_STATUS (*LINK_c2dMapAddr) ( int mem_fd, void * hostptr, uint32 len,
- uint32 offset, uint32 flags, void ** gpuaddr);
+C2D_STATUS (*LINK_c2dMapAddr) ( int mem_fd, void * hostptr, size_t len,
+ size_t offset, uint32 flags, void ** gpuaddr);
C2D_STATUS (*LINK_c2dUnMapAddr) ( void * gpuaddr);
@@ -145,7 +145,7 @@
alloc_data temp_src_buffer;
alloc_data temp_dst_buffer;
unsigned int dst[NUM_SURFACE_TYPES]; // dst surfaces
- unsigned int mapped_gpu_addr[MAX_SURFACES]; // GPU addresses mapped inside copybit
+ uintptr_t mapped_gpu_addr[MAX_SURFACES]; // GPU addresses mapped inside copybit
int blit_rgb_count; // Total RGB surfaces being blit
int blit_yuv_2_plane_count; // Total 2 plane YUV surfaces being
int blit_yuv_3_plane_count; // Total 3 plane YUV surfaces being blit
@@ -180,8 +180,8 @@
int yStride; //luma stride
int plane1_stride;
int plane2_stride;
- int plane1_offset;
- int plane2_offset;
+ size_t plane1_offset;
+ size_t plane2_offset;
};
/**
@@ -257,6 +257,8 @@
static int get_format(int format) {
switch (format) {
case HAL_PIXEL_FORMAT_RGB_565: return C2D_COLOR_FORMAT_565_RGB;
+ case HAL_PIXEL_FORMAT_RGB_888: return C2D_COLOR_FORMAT_888_RGB |
+ C2D_FORMAT_SWAP_RB;
case HAL_PIXEL_FORMAT_RGBX_8888: return C2D_COLOR_FORMAT_8888_ARGB |
C2D_FORMAT_SWAP_RB |
C2D_FORMAT_DISABLE_ALPHA;
@@ -315,6 +317,9 @@
case C2D_COLOR_FORMAT_8888_ARGB:
c2dBpp = 32;
break;
+ case C2D_COLOR_FORMAT_888_RGB:
+ c2dBpp = 24;
+ break;
case C2D_COLOR_FORMAT_8_L:
case C2D_COLOR_FORMAT_8_A:
c2dBpp = 8;
@@ -332,10 +337,11 @@
return c2dBpp;
}
-static uint32 c2d_get_gpuaddr(copybit_context_t* ctx,
+static size_t c2d_get_gpuaddr(copybit_context_t* ctx,
struct private_handle_t *handle, int &mapped_idx)
{
- uint32 memtype, *gpuaddr = 0;
+ uint32 memtype;
+ size_t *gpuaddr = 0;
C2D_STATUS rc;
int freeindex = 0;
bool mapaddr = false;
@@ -372,11 +378,11 @@
if (rc == C2D_STATUS_OK) {
// We have mapped the GPU address inside copybit. We need to unmap
// this address after the blit. Store this address
- ctx->mapped_gpu_addr[freeindex] = (uint32) gpuaddr;
+ ctx->mapped_gpu_addr[freeindex] = (size_t)gpuaddr;
mapped_idx = freeindex;
}
}
- return (uint32) gpuaddr;
+ return (size_t)gpuaddr;
}
static void unmap_gpuaddr(copybit_context_t* ctx, int mapped_idx)
@@ -395,6 +401,7 @@
switch(format) {
case HAL_PIXEL_FORMAT_RGBA_8888:
case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_RGB_888:
case HAL_PIXEL_FORMAT_RGB_565:
case HAL_PIXEL_FORMAT_BGRA_8888: {
return COPYBIT_SUCCESS;
@@ -496,7 +503,7 @@
struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
C2D_SURFACE_TYPE surfaceType;
int status = COPYBIT_SUCCESS;
- uint32 gpuaddr = 0;
+ uintptr_t gpuaddr = 0;
int c2d_format;
mapped_idx = -1;
@@ -540,7 +547,7 @@
((flags & FLAGS_PREMULTIPLIED_ALPHA) ? C2D_FORMAT_PREMULTIPLIED : 0);
surfaceDef.width = rhs->w;
surfaceDef.height = rhs->h;
- int aligned_width = ALIGN(surfaceDef.width,32);
+ int aligned_width = ALIGN((int)surfaceDef.width,32);
surfaceDef.stride = (aligned_width * c2diGetBpp(surfaceDef.format))>>3;
if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType,
@@ -728,7 +735,8 @@
(ctx->trg_transform & C2D_TARGET_ROTATE_180)) {
/* target rotation is 270 */
c2dObject->target_rect.x = (dst->t)<<16;
- c2dObject->target_rect.y = ctx->fb_width?(ALIGN(ctx->fb_width,32)- dst->r):dst->r;
+ c2dObject->target_rect.y = ctx->fb_width?
+ (ALIGN(ctx->fb_width,32)- dst->r):dst->r;
c2dObject->target_rect.y = c2dObject->target_rect.y<<16;
c2dObject->target_rect.height = ((dst->r) - (dst->l))<<16;
c2dObject->target_rect.width = ((dst->b) - (dst->t))<<16;
@@ -741,7 +749,8 @@
} else if(ctx->trg_transform & C2D_TARGET_ROTATE_180) {
c2dObject->target_rect.y = ctx->fb_height?(ctx->fb_height - dst->b):dst->b;
c2dObject->target_rect.y = c2dObject->target_rect.y<<16;
- c2dObject->target_rect.x = ctx->fb_width?(ALIGN(ctx->fb_width,32) - dst->r):dst->r;
+ c2dObject->target_rect.x = ctx->fb_width?
+ (ALIGN(ctx->fb_width,32) - dst->r):dst->r;
c2dObject->target_rect.x = c2dObject->target_rect.x<<16;
c2dObject->target_rect.height = ((dst->b) - (dst->t))<<16;
c2dObject->target_rect.width = ((dst->r) - (dst->l))<<16;
@@ -953,9 +962,9 @@
/* Function to get the required size for a particular format, inorder for C2D to perform
* the blit operation.
*/
-static size_t get_size(const bufferInfo& info)
+static int get_size(const bufferInfo& info)
{
- size_t size = 0;
+ int size = 0;
int w = info.width;
int h = info.height;
int aligned_w = ALIGN(w, 32);
@@ -1065,8 +1074,7 @@
}
}
-static bool need_to_execute_draw(struct copybit_context_t* ctx,
- eC2DFlags flags)
+static bool need_to_execute_draw(eC2DFlags flags)
{
if (flags & FLAGS_TEMP_SRC_DST) {
return true;
@@ -1183,7 +1191,7 @@
dst_hnd->fd = ctx->temp_dst_buffer.fd;
dst_hnd->size = ctx->temp_dst_buffer.size;
dst_hnd->flags = ctx->temp_dst_buffer.allocType;
- dst_hnd->base = (int)(ctx->temp_dst_buffer.base);
+ dst_hnd->base = (uintptr_t)(ctx->temp_dst_buffer.base);
dst_hnd->offset = ctx->temp_dst_buffer.offset;
dst_hnd->gpuaddr = 0;
dst_image.handle = dst_hnd;
@@ -1268,7 +1276,7 @@
src_hnd->fd = ctx->temp_src_buffer.fd;
src_hnd->size = ctx->temp_src_buffer.size;
src_hnd->flags = ctx->temp_src_buffer.allocType;
- src_hnd->base = (int)(ctx->temp_src_buffer.base);
+ src_hnd->base = (uintptr_t)(ctx->temp_src_buffer.base);
src_hnd->offset = ctx->temp_src_buffer.offset;
src_hnd->gpuaddr = 0;
src_image.handle = src_hnd;
@@ -1352,7 +1360,7 @@
// Check if we need to perform an early draw-finish.
flags |= (need_temp_dst || need_temp_src) ? FLAGS_TEMP_SRC_DST : 0;
- if (need_to_execute_draw(ctx, (eC2DFlags)flags))
+ if (need_to_execute_draw((eC2DFlags)flags))
{
finish_copybit(dev);
}
@@ -1386,8 +1394,11 @@
}
static int set_sync_copybit(struct copybit_device_t *dev,
- int acquireFenceFd)
+ int /*acquireFenceFd*/)
{
+ if(!dev)
+ return -EINVAL;
+
return 0;
}
@@ -1430,9 +1441,12 @@
static int fill_color(struct copybit_device_t *dev,
struct copybit_image_t const *dst,
struct copybit_rect_t const *rect,
- uint32_t color)
+ uint32_t /*color*/)
{
// TODO: Implement once c2d driver supports color fill
+ if(!dev || !dst || !rect)
+ return -EINVAL;
+
return -EINVAL;
}
@@ -1500,10 +1514,13 @@
struct hw_device_t** device)
{
int status = COPYBIT_SUCCESS;
+ if (strcmp(name, COPYBIT_HARDWARE_COPYBIT0)) {
+ return COPYBIT_FAILURE;
+ }
+
C2D_RGB_SURFACE_DEF surfDefinition = {0};
C2D_YUV_SURFACE_DEF yuvSurfaceDef = {0} ;
struct copybit_context_t *ctx;
- char fbName[64];
ctx = (struct copybit_context_t *)malloc(sizeof(struct copybit_context_t));
if(!ctx) {
diff --git a/msm8226/libcopybit/software_converter.cpp b/msm8226/libcopybit/software_converter.cpp
index e26b795..5adacea 100644
--- a/msm8226/libcopybit/software_converter.cpp
+++ b/msm8226/libcopybit/software_converter.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011,2014, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -52,7 +52,7 @@
unsigned int width = src->w - src->horiz_padding;
unsigned int height = src->h;
unsigned int y_size = stride * src->h;
- unsigned int c_width = ALIGN(stride/2, 16);
+ unsigned int c_width = ALIGN(stride/2, (unsigned int)16);
unsigned int c_size = c_width * src->h/2;
unsigned int chromaPadding = c_width - width/2;
unsigned int chromaSize = c_size * 2;
@@ -128,19 +128,20 @@
int height;
int src_stride;
int dst_stride;
- int src_plane1_offset;
- int src_plane2_offset;
- int dst_plane1_offset;
- int dst_plane2_offset;
+ size_t src_plane1_offset;
+ size_t src_plane2_offset;
+ size_t dst_plane1_offset;
+ size_t 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,
+static int copy_source_to_destination(const uintptr_t src_base,
+ const uintptr_t dst_base,
copyInfo& info)
{
if (!src_base || !dst_base) {
- ALOGE("%s: invalid memory src_base = 0x%x dst_base=0x%x",
- __FUNCTION__, src_base, dst_base);
+ ALOGE("%s: invalid memory src_base = 0x%p dst_base=0x%p",
+ __FUNCTION__, (void*)src_base, (void*)dst_base);
return COPYBIT_FAILURE;
}
diff --git a/msm8226/libexternal/Android.mk b/msm8226/libexternal/Android.mk
index 3df6984..05e42d4 100644
--- a/msm8226/libexternal/Android.mk
+++ b/msm8226/libexternal/Android.mk
@@ -3,7 +3,6 @@
include $(CLEAR_VARS)
LOCAL_MODULE := libexternal
-LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
LOCAL_SHARED_LIBRARIES := $(common_libs) liboverlay libqdutils
diff --git a/msm8226/libexternal/external.cpp b/msm8226/libexternal/external.cpp
index b08c0c1..982146e 100644
--- a/msm8226/libexternal/external.cpp
+++ b/msm8226/libexternal/external.cpp
@@ -34,7 +34,6 @@
#include "external.h"
#include "overlayUtils.h"
#include "overlay.h"
-#include "mdp_version.h"
#include "qd_utils.h"
using namespace android;
@@ -192,7 +191,7 @@
return;
} else {
len = read(hdmiScanInfoFile, scanInfo, sizeof(scanInfo)-1);
- ALOGD("%s: Scan Info string: %s length = %zu",
+ ALOGD("%s: Scan Info string: %s length = %zd",
__FUNCTION__, scanInfo, len);
if (len <= 0) {
close(hdmiScanInfoFile);
@@ -314,7 +313,7 @@
return false;
} else {
len = read(hdmiEDIDFile, edidStr, sizeof(edidStr)-1);
- ALOGD_IF(DEBUG, "%s: EDID string: %s length = %zu",
+ ALOGD_IF(DEBUG, "%s: EDID string: %s length = %zd",
__FUNCTION__, edidStr, len);
if ( len <= 0) {
ALOGE("%s: edid_modes file empty '%s'",
@@ -586,7 +585,7 @@
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres = width;
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres = height;
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].mDownScaleMode = false;
- if(!qdutils::MDPVersion::getInstance().is8x26()
+ if(mHwcContext->mOverlay->isUIScalingOnExternalSupported()
&& mHwcContext->mMDPDownscaleEnabled) {
int priW = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
int priH = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
@@ -621,6 +620,13 @@
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].mDownScaleMode =true;
}
}
+ //Initialize the display viewFrame info
+ mHwcContext->mViewFrame[HWC_DISPLAY_EXTERNAL].left = 0;
+ mHwcContext->mViewFrame[HWC_DISPLAY_EXTERNAL].top = 0;
+ mHwcContext->mViewFrame[HWC_DISPLAY_EXTERNAL].right =
+ (int)mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres;
+ mHwcContext->mViewFrame[HWC_DISPLAY_EXTERNAL].bottom =
+ (int)mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres;
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].vsync_period =
(int) 1000000000l / fps;
}
diff --git a/msm8226/libgralloc/Android.mk b/msm8226/libgralloc/Android.mk
index ef10f54..412f1be 100644
--- a/msm8226/libgralloc/Android.mk
+++ b/msm8226/libgralloc/Android.mk
@@ -18,10 +18,10 @@
include $(CLEAR_VARS)
LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM)
-LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
-LOCAL_SHARED_LIBRARIES := $(common_libs) libmemalloc
+LOCAL_SHARED_LIBRARIES := $(common_libs) libmemalloc libqdMetaData
LOCAL_SHARED_LIBRARIES += libqdutils libGLESv1_CM
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdgralloc\"
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
diff --git a/msm8226/libgralloc/alloc_controller.cpp b/msm8226/libgralloc/alloc_controller.cpp
index 878f17c..b26f4ea 100644
--- a/msm8226/libgralloc/alloc_controller.cpp
+++ b/msm8226/libgralloc/alloc_controller.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2012,2014, The Linux Foundation. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -181,6 +181,7 @@
} else {
switch (format)
{
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
case HAL_PIXEL_FORMAT_RAW_SENSOR:
aligned_w = ALIGN(width, 32);
@@ -189,7 +190,6 @@
aligned_w = ALIGN(width, 128);
break;
case HAL_PIXEL_FORMAT_YCbCr_420_SP:
- case HAL_PIXEL_FORMAT_YCrCb_420_SP:
case HAL_PIXEL_FORMAT_YV12:
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
case HAL_PIXEL_FORMAT_YCrCb_422_SP:
@@ -271,7 +271,12 @@
//-------------- IonController-----------------------//
IonController::IonController()
{
- mIonAlloc = new IonAlloc();
+ allocateIonMem();
+}
+
+void IonController::allocateIonMem()
+{
+ mIonAlloc = new IonAlloc();
}
int IonController::allocate(alloc_data& data, int usage)
@@ -389,9 +394,9 @@
}
// helper function
-size_t getSize(int format, int width, int height, const int alignedw,
+unsigned int getSize(int format, int width, int height, const int alignedw,
const int alignedh) {
- size_t size = 0;
+ unsigned int size = 0;
switch (format) {
case HAL_PIXEL_FORMAT_RGBA_8888:
@@ -428,7 +433,7 @@
}
size = alignedw*alignedh +
(ALIGN(alignedw/2, 16) * (alignedh/2))*2;
- size = ALIGN(size, 4096);
+ size = ALIGN(size, (unsigned int)4096);
break;
case HAL_PIXEL_FORMAT_YCbCr_420_SP:
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
@@ -496,10 +501,10 @@
return size;
}
-size_t getBufferSizeAndDimensions(int width, int height, int format,
+unsigned int getBufferSizeAndDimensions(int width, int height, int format,
int& alignedw, int &alignedh)
{
- size_t size;
+ unsigned int size;
AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
height,
@@ -514,10 +519,10 @@
}
-size_t getBufferSizeAndDimensions(int width, int height, int format, int usage,
- int& alignedw, int &alignedh)
+unsigned int getBufferSizeAndDimensions(int width, int height, int format,
+ int usage, int& alignedw, int &alignedh)
{
- size_t size;
+ unsigned int size;
int tileEnabled = isMacroTileEnabled(format, usage);
AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
@@ -534,7 +539,7 @@
void getBufferAttributes(int width, int height, int format, int usage,
- int& alignedw, int &alignedh, int& tileEnabled, size_t& size)
+ int& alignedw, int &alignedh, int& tileEnabled, unsigned int& size)
{
tileEnabled = isMacroTileEnabled(format, usage);
@@ -547,6 +552,69 @@
size = getSize(format, width, height, alignedw, alignedh);
}
+int getYUVPlaneInfo(private_handle_t* hnd, struct android_ycbcr* ycbcr)
+{
+ int err = 0;
+ unsigned int ystride, cstride;
+ memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
+
+ // Get the chroma offsets from the handle width/height. We take advantage
+ // of the fact the width _is_ the stride
+ switch (hnd->format) {
+ //Semiplanar
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: //Same as YCbCr_420_SP_VENUS
+ ystride = cstride = hnd->width;
+ ycbcr->y = (void*)hnd->base;
+ ycbcr->cb = (void*)(hnd->base + ystride * hnd->height);
+ ycbcr->cr = (void*)(hnd->base + ystride * hnd->height + 1);
+ ycbcr->ystride = ystride;
+ ycbcr->cstride = cstride;
+ ycbcr->chroma_step = 2;
+ break;
+
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+ case HAL_PIXEL_FORMAT_NV21_ZSL:
+ case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ ystride = cstride = hnd->width;
+ ycbcr->y = (void*)hnd->base;
+ ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
+ ycbcr->cb = (void*)(hnd->base + ystride * hnd->height + 1);
+ ycbcr->ystride = ystride;
+ ycbcr->cstride = cstride;
+ ycbcr->chroma_step = 2;
+ break;
+
+ //Planar
+ case HAL_PIXEL_FORMAT_YV12:
+ ystride = hnd->width;
+ cstride = ALIGN(hnd->width/2, 16);
+ ycbcr->y = (void*)hnd->base;
+ ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
+ ycbcr->cb = (void*)(hnd->base + ystride * hnd->height +
+ cstride * hnd->height/2);
+ ycbcr->ystride = ystride;
+ ycbcr->cstride = cstride;
+ ycbcr->chroma_step = 1;
+
+ break;
+ //Unsupported formats
+ case HAL_PIXEL_FORMAT_YCbCr_422_I:
+ case HAL_PIXEL_FORMAT_YCrCb_422_I:
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+ default:
+ ALOGD("%s: Invalid format passed: 0x%x", __FUNCTION__,
+ hnd->format);
+ err = -EINVAL;
+ }
+ return err;
+
+}
+
// Allocate buffer from width, height and format into a
@@ -577,7 +645,7 @@
private_handle_t* hnd = new private_handle_t(data.fd, data.size,
data.allocType, 0, format,
alignedw, alignedh);
- hnd->base = (int) data.base;
+ hnd->base = (uint64_t) data.base;
hnd->offset = data.offset;
hnd->gpuaddr = 0;
*pHnd = hnd;
diff --git a/msm8226/libgralloc/alloc_controller.h b/msm8226/libgralloc/alloc_controller.h
index 5fe81fa..f0b8ed9 100644
--- a/msm8226/libgralloc/alloc_controller.h
+++ b/msm8226/libgralloc/alloc_controller.h
@@ -65,6 +65,7 @@
private:
IonAlloc* mIonAlloc;
+ void allocateIonMem();
};
} //end namespace gralloc
diff --git a/msm8226/libgralloc/fb_priv.h b/msm8226/libgralloc/fb_priv.h
index 01af2e1..7ff1f3a 100644
--- a/msm8226/libgralloc/fb_priv.h
+++ b/msm8226/libgralloc/fb_priv.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010,2014, The Linux Foundation. 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.
@@ -51,7 +51,6 @@
float ydpi;
float fps;
uint32_t swapInterval;
- uint32_t currentOffset;
};
diff --git a/msm8226/libgralloc/framebuffer.cpp b/msm8226/libgralloc/framebuffer.cpp
index a7a58dc..2ce5dc6 100644
--- a/msm8226/libgralloc/framebuffer.cpp
+++ b/msm8226/libgralloc/framebuffer.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2010-2012 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2012,2014 The Linux Foundation. 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.
@@ -72,7 +72,6 @@
if (property_interval >= 0)
interval = property_interval;
- fb_context_t* ctx = (fb_context_t*)dev;
private_module_t* m = reinterpret_cast<private_module_t*>(
dev->common.module);
if (interval < dev->minSwapInterval || interval > dev->maxSwapInterval)
@@ -88,9 +87,10 @@
reinterpret_cast<private_module_t*>(dev->common.module);
private_handle_t *hnd = static_cast<private_handle_t*>
(const_cast<native_handle_t*>(buffer));
- const size_t offset = hnd->base - m->framebuffer->base;
+ const unsigned int offset = (unsigned int) (hnd->base -
+ m->framebuffer->base);
m->info.activate = FB_ACTIVATE_VBL;
- m->info.yoffset = offset / m->finfo.line_length;
+ m->info.yoffset = (int)(offset / m->finfo.line_length);
if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) {
ALOGE("%s: FBIOPUT_VSCREENINFO for primary failed, str: %s",
__FUNCTION__, strerror(errno));
@@ -102,6 +102,9 @@
static int fb_compositionComplete(struct framebuffer_device_t* dev)
{
// TODO: Properly implement composition complete callback
+ if(!dev) {
+ return -1;
+ }
glFinish();
return 0;
@@ -202,8 +205,8 @@
}
//adreno needs 4k aligned offsets. Max hole size is 4096-1
- int size = roundUpToPageSize(info.yres * info.xres *
- (info.bits_per_pixel/8));
+ unsigned int size = roundUpToPageSize(info.yres * info.xres *
+ (info.bits_per_pixel/8));
/*
* Request NUM_BUFFERS screens (at least 2 for page flipping)
@@ -224,13 +227,13 @@
//consider the included hole by 4k alignment
uint32_t line_length = (info.xres * info.bits_per_pixel / 8);
- info.yres_virtual = (size * numberOfBuffers) / line_length;
+ info.yres_virtual = (uint32_t) ((size * numberOfBuffers) / line_length);
uint32_t flags = PAGE_FLIP;
if (info.yres_virtual < ((size * 2) / line_length) ) {
// we need at least 2 for page-flipping
- info.yres_virtual = size / line_length;
+ info.yres_virtual = (int)(size / line_length);
flags &= ~PAGE_FLIP;
ALOGW("page flipping not supported (yres_virtual=%d, requested=%d)",
info.yres_virtual, info.yres*2);
@@ -244,12 +247,13 @@
if (int(info.width) <= 0 || int(info.height) <= 0) {
// the driver doesn't return that information
// default to 160 dpi
- info.width = ((info.xres * 25.4f)/160.0f + 0.5f);
- info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
+ info.width = (uint32_t)(((float)(info.xres) * 25.4f)/160.0f + 0.5f);
+ info.height = (uint32_t)(((float)(info.yres) * 25.4f)/160.0f + 0.5f);
}
- float xdpi = (info.xres * 25.4f) / info.width;
- float ydpi = (info.yres * 25.4f) / info.height;
+ float xdpi = ((float)(info.xres) * 25.4f) / (float)info.width;
+ float ydpi = ((float)(info.yres) * 25.4f) / (float)info.height;
+
#ifdef MSMFB_METADATA_GET
struct msmfb_metadata metadata;
memset(&metadata, 0 , sizeof(metadata));
@@ -259,7 +263,7 @@
close(fd);
return -errno;
}
- float fps = metadata.data.panel_frame_rate;
+ float fps = (float)metadata.data.panel_frame_rate;
#else
//XXX: Remove reserved field usage on all baselines
//The reserved[3] field is used to store FPS by the driver.
@@ -320,11 +324,10 @@
* map the framebuffer
*/
- int err;
module->numBuffers = info.yres_virtual / info.yres;
module->bufferMask = 0;
//adreno needs page aligned offsets. Align the fbsize to pagesize.
- size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres)*
+ unsigned int fbSize = roundUpToPageSize(finfo.line_length * info.yres)*
module->numBuffers;
module->framebuffer = new private_handle_t(fd, fbSize,
private_handle_t::PRIV_FLAGS_USES_ION,
@@ -336,9 +339,8 @@
close(fd);
return -errno;
}
- module->framebuffer->base = intptr_t(vaddr);
+ module->framebuffer->base = uint64_t(vaddr);
memset(vaddr, 0, fbSize);
- module->currentOffset = 0;
//Enable vsync
int enable = 1;
ioctl(module->framebuffer->fd, MSMFB_OVERLAY_VSYNC_CTRL,
diff --git a/msm8226/libgralloc/gpu.cpp b/msm8226/libgralloc/gpu.cpp
index b6253cd..8739f34 100644
--- a/msm8226/libgralloc/gpu.cpp
+++ b/msm8226/libgralloc/gpu.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 The Android Open Source Project
- * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2014 The Linux Foundation. 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.
@@ -51,7 +51,7 @@
}
-int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage,
+int gpu_context_t::gralloc_alloc_buffer(unsigned int size, int usage,
buffer_handle_t* pHandle, int bufferType,
int format, int width, int height)
{
@@ -69,14 +69,15 @@
/* force 1MB alignment selectively for secure buffers, MDP5 onwards */
#ifdef MDSS_TARGET
- if (usage & GRALLOC_USAGE_PROTECTED) {
- data.align = ALIGN(data.align, SZ_1M);
+ if ((usage & GRALLOC_USAGE_PROTECTED) &&
+ (usage & GRALLOC_USAGE_PRIVATE_MM_HEAP)) {
+ data.align = ALIGN((int) data.align, SZ_1M);
size = ALIGN(size, data.align);
}
#endif
data.size = size;
- data.pHandle = (unsigned int) pHandle;
+ data.pHandle = (uintptr_t) pHandle;
err = mAllocCtrl->allocate(data, usage);
if (!err) {
@@ -97,9 +98,12 @@
flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY;
}
+ ColorSpace_t colorSpace = ITU_R_601;
+ flags |= private_handle_t::PRIV_FLAGS_ITU_R_601;
if (bufferType == BUFFER_TYPE_VIDEO) {
if (usage & GRALLOC_USAGE_HW_CAMERA_WRITE) {
#ifndef MDSS_TARGET
+ colorSpace = ITU_R_601_FR;
flags |= private_handle_t::PRIV_FLAGS_ITU_R_601_FR;
#else
// Per the camera spec ITU 709 format should be set only for
@@ -108,14 +112,15 @@
// camera buffer
//
if (usage & GRALLOC_USAGE_HW_CAMERA_MASK) {
- if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER)
+ if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) {
flags |= private_handle_t::PRIV_FLAGS_ITU_R_709;
- else
+ colorSpace = ITU_R_709;
+ } else {
flags |= private_handle_t::PRIV_FLAGS_ITU_R_601_FR;
+ colorSpace = ITU_R_601_FR;
+ }
}
#endif
- } else {
- flags |= private_handle_t::PRIV_FLAGS_ITU_R_601;
}
}
@@ -147,15 +152,20 @@
flags |= private_handle_t::PRIV_FLAGS_TILE_RENDERED;
}
+ if(usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
+ flags |= private_handle_t::PRIV_FLAGS_CPU_RENDERED;
+ }
+
flags |= data.allocType;
- int eBaseAddr = int(eData.base) + eData.offset;
+ uint64_t eBaseAddr = (uint64_t)(eData.base) + eData.offset;
private_handle_t *hnd = new private_handle_t(data.fd, size, flags,
bufferType, format, width, height, eData.fd, eData.offset,
eBaseAddr);
hnd->offset = data.offset;
- hnd->base = int(data.base) + data.offset;
+ hnd->base = (uint64_t)(data.base) + data.offset;
hnd->gpuaddr = 0;
+ setMetaData(hnd, UPDATE_COLOR_SPACE, (void*) &colorSpace);
*pHandle = hnd;
}
@@ -170,9 +180,6 @@
{
*bufferType = BUFFER_TYPE_VIDEO;
- if (inputFormat == HAL_PIXEL_FORMAT_RGB_888)
- return;
-
if (inputFormat <= HAL_PIXEL_FORMAT_sRGB_X_8888) {
// RGB formats
*bufferType = BUFFER_TYPE_UI;
@@ -182,7 +189,7 @@
}
}
-int gpu_context_t::gralloc_alloc_framebuffer_locked(size_t size, int usage,
+int gpu_context_t::gralloc_alloc_framebuffer_locked(int usage,
buffer_handle_t* pHandle)
{
private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
@@ -197,9 +204,9 @@
return -EINVAL;
}
- const uint32_t bufferMask = m->bufferMask;
+ const unsigned int bufferMask = m->bufferMask;
const uint32_t numBuffers = m->numBuffers;
- size_t bufferSize = m->finfo.line_length * m->info.yres;
+ unsigned int bufferSize = m->finfo.line_length * m->info.yres;
//adreno needs FB size to be page aligned
bufferSize = roundUpToPageSize(bufferSize);
@@ -219,7 +226,7 @@
}
// create a "fake" handle for it
- intptr_t vaddr = intptr_t(m->framebuffer->base);
+ uint64_t vaddr = uint64_t(m->framebuffer->base);
private_handle_t* hnd = new private_handle_t(
dup(m->framebuffer->fd), bufferSize,
private_handle_t::PRIV_FLAGS_USES_PMEM |
@@ -230,42 +237,43 @@
// find a free slot
for (uint32_t i=0 ; i<numBuffers ; i++) {
if ((bufferMask & (1LU<<i)) == 0) {
- m->bufferMask |= (1LU<<i);
+ m->bufferMask |= (uint32_t)(1LU<<i);
break;
}
vaddr += bufferSize;
}
hnd->base = vaddr;
- hnd->offset = vaddr - intptr_t(m->framebuffer->base);
+ hnd->offset = (unsigned int)(vaddr - m->framebuffer->base);
*pHandle = hnd;
return 0;
}
-int gpu_context_t::gralloc_alloc_framebuffer(size_t size, int usage,
+int gpu_context_t::gralloc_alloc_framebuffer(int usage,
buffer_handle_t* pHandle)
{
private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
pthread_mutex_lock(&m->lock);
- int err = gralloc_alloc_framebuffer_locked(size, usage, pHandle);
+ int err = gralloc_alloc_framebuffer_locked(usage, pHandle);
pthread_mutex_unlock(&m->lock);
return err;
}
int gpu_context_t::alloc_impl(int w, int h, int format, int usage,
buffer_handle_t* pHandle, int* pStride,
- size_t bufferSize) {
+ unsigned int bufferSize) {
if (!pHandle || !pStride)
return -EINVAL;
- size_t size;
+ unsigned int size;
int alignedw, alignedh;
int grallocFormat = format;
int bufferType;
//If input format is HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED then based on
//the usage bits, gralloc assigns a format.
- if(format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
+ if(format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED ||
+ format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
if(usage & GRALLOC_USAGE_HW_VIDEO_ENCODER)
grallocFormat = HAL_PIXEL_FORMAT_NV12_ENCODEABLE; //NV12
else if((usage & GRALLOC_USAGE_HW_CAMERA_MASK)
@@ -284,7 +292,7 @@
size = getBufferSizeAndDimensions(w, h, grallocFormat, usage, alignedw,
alignedh);
- if ((ssize_t)size <= 0)
+ if ((unsigned int)size <= 0)
return -EINVAL;
size = (bufferSize >= size)? bufferSize : size;
@@ -299,7 +307,7 @@
int err = 0;
if(useFbMem) {
- err = gralloc_alloc_framebuffer(size, usage, pHandle);
+ err = gralloc_alloc_framebuffer(usage, pHandle);
} else {
err = gralloc_alloc_buffer(size, usage, pHandle, bufferType,
grallocFormat, alignedw, alignedh);
@@ -316,21 +324,22 @@
int gpu_context_t::free_impl(private_handle_t const* hnd) {
private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
- const size_t bufferSize = m->finfo.line_length * m->info.yres;
- int index = (hnd->base - m->framebuffer->base) / bufferSize;
- m->bufferMask &= ~(1<<index);
+ const unsigned int bufferSize = m->finfo.line_length * m->info.yres;
+ unsigned int index = (unsigned int) ((hnd->base - m->framebuffer->base)
+ / bufferSize);
+ m->bufferMask &= (uint32_t)~(1LU<<index);
} else {
terminateBuffer(&m->base, const_cast<private_handle_t*>(hnd));
IMemAlloc* memalloc = mAllocCtrl->getAllocator(hnd->flags);
- int err = memalloc->free_buffer((void*)hnd->base, (size_t) hnd->size,
+ int err = memalloc->free_buffer((void*)hnd->base, hnd->size,
hnd->offset, hnd->fd);
if(err)
return err;
// free the metadata space
- unsigned long size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+ unsigned int size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
err = memalloc->free_buffer((void*)hnd->base_metadata,
- (size_t) size, hnd->offset_metadata,
+ size, hnd->offset_metadata,
hnd->fd_metadata);
if (err)
return err;
diff --git a/msm8226/libgralloc/gpu.h b/msm8226/libgralloc/gpu.h
index 5515759..262aed5 100644
--- a/msm8226/libgralloc/gpu.h
+++ b/msm8226/libgralloc/gpu.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2012,2014, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@
gpu_context_t(const private_module_t* module,
IAllocController* alloc_ctrl);
- int gralloc_alloc_buffer(size_t size, int usage,
+ int gralloc_alloc_buffer(unsigned int size, int usage,
buffer_handle_t* pHandle,
int bufferType, int format,
int width, int height);
@@ -44,16 +44,16 @@
int alloc_impl(int w, int h, int format, int usage,
buffer_handle_t* pHandle, int* pStride,
- size_t bufferSize = 0);
+ unsigned int bufferSize = 0);
static int gralloc_alloc(alloc_device_t* dev, int w, int h,
int format, int usage,
buffer_handle_t* pHandle,
int* pStride);
- int gralloc_alloc_framebuffer_locked(size_t size, int usage,
+ int gralloc_alloc_framebuffer_locked(int usage,
buffer_handle_t* pHandle);
- int gralloc_alloc_framebuffer(size_t size, int usage,
+ int gralloc_alloc_framebuffer(int usage,
buffer_handle_t* pHandle);
static int gralloc_free(alloc_device_t* dev, buffer_handle_t handle);
diff --git a/msm8226/libgralloc/gr.h b/msm8226/libgralloc/gr.h
index 73b176b..797d57e 100644
--- a/msm8226/libgralloc/gr.h
+++ b/msm8226/libgralloc/gr.h
@@ -33,11 +33,12 @@
struct private_module_t;
struct private_handle_t;
-inline size_t roundUpToPageSize(size_t x) {
+inline unsigned int roundUpToPageSize(unsigned int x) {
return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
}
-inline size_t ALIGN(size_t x, size_t align) {
+template <class Type>
+inline Type ALIGN(Type x, Type align) {
return (x + align-1) & ~(align-1);
}
@@ -46,16 +47,16 @@
int mapFrameBufferLocked(struct private_module_t* module);
int terminateBuffer(gralloc_module_t const* module, private_handle_t* hnd);
-size_t getBufferSizeAndDimensions(int width, int height, int format, int usage,
- int& alignedw, int &alignedh);
-size_t getBufferSizeAndDimensions(int width, int height, int format,
- int& alignedw, int &alignedh);
+unsigned int getBufferSizeAndDimensions(int width, int height, int format,
+ int usage, int& alignedw, int &alignedh);
+unsigned int getBufferSizeAndDimensions(int width, int height, int format,
+ int& alignedw, int &alignedh);
// Attributes include aligned width, aligned height, tileEnabled and size of the buffer
void getBufferAttributes(int width, int height, int format, int usage,
int& alignedw, int &alignedh,
- int& tileEnabled, size_t &size);
+ int& tileEnabled, unsigned int &size);
bool isMacroTileEnabled(int format, int usage);
@@ -68,11 +69,13 @@
// It is the responsibility of the caller to free the buffer
int alloc_buffer(private_handle_t **pHnd, int w, int h, int format, int usage);
void free_buffer(private_handle_t *hnd);
+int getYUVPlaneInfo(private_handle_t* pHnd, struct android_ycbcr* ycbcr);
/*****************************************************************************/
class Locker {
pthread_mutex_t mutex;
+ pthread_cond_t cond;
public:
class Autolock {
Locker& locker;
@@ -80,10 +83,18 @@
inline Autolock(Locker& locker) : locker(locker) { locker.lock(); }
inline ~Autolock() { locker.unlock(); }
};
- inline Locker() { pthread_mutex_init(&mutex, 0); }
- inline ~Locker() { pthread_mutex_destroy(&mutex); }
+ inline Locker() {
+ pthread_mutex_init(&mutex, 0);
+ pthread_cond_init(&cond, 0);
+ }
+ inline ~Locker() {
+ pthread_mutex_destroy(&mutex);
+ pthread_cond_destroy(&cond);
+ }
inline void lock() { pthread_mutex_lock(&mutex); }
+ inline void wait() { pthread_cond_wait(&cond, &mutex); }
inline void unlock() { pthread_mutex_unlock(&mutex); }
+ inline void signal() { pthread_cond_signal(&cond); }
};
diff --git a/msm8226/libgralloc/gralloc.cpp b/msm8226/libgralloc/gralloc.cpp
index b21ce75..c1c61aa 100644
--- a/msm8226/libgralloc/gralloc.cpp
+++ b/msm8226/libgralloc/gralloc.cpp
@@ -42,6 +42,11 @@
int l, int t, int w, int h,
void** vaddr);
+extern int gralloc_lock_ycbcr(gralloc_module_t const* module,
+ buffer_handle_t handle, int usage,
+ int l, int t, int w, int h,
+ struct android_ycbcr *ycbcr);
+
extern int gralloc_unlock(gralloc_module_t const* module,
buffer_handle_t handle);
@@ -56,36 +61,37 @@
// HAL module methods
static struct hw_module_methods_t gralloc_module_methods = {
-open: gralloc_device_open
+ open: gralloc_device_open
};
// HAL module initialize
struct private_module_t HAL_MODULE_INFO_SYM = {
-base: {
- common: {
- tag: HARDWARE_MODULE_TAG,
- version_major: 1,
- version_minor: 0,
- id: GRALLOC_HARDWARE_MODULE_ID,
- name: "Graphics Memory Allocator Module",
- author: "The Android Open Source Project",
- methods: &gralloc_module_methods,
- dso: 0,
- reserved: {0},
- },
- registerBuffer: gralloc_register_buffer,
- unregisterBuffer: gralloc_unregister_buffer,
- lock: gralloc_lock,
- unlock: gralloc_unlock,
- perform: gralloc_perform,
- },
-framebuffer: 0,
-fbFormat: 0,
-flags: 0,
-numBuffers: 0,
-bufferMask: 0,
-lock: PTHREAD_MUTEX_INITIALIZER,
-currentBuffer: 0,
+ base: {
+ common: {
+ tag: HARDWARE_MODULE_TAG,
+ version_major: 1,
+ version_minor: 0,
+ id: GRALLOC_HARDWARE_MODULE_ID,
+ name: "Graphics Memory Allocator Module",
+ author: "The Android Open Source Project",
+ methods: &gralloc_module_methods,
+ dso: 0,
+ reserved: {0},
+ },
+ registerBuffer: gralloc_register_buffer,
+ unregisterBuffer: gralloc_unregister_buffer,
+ lock: gralloc_lock,
+ unlock: gralloc_unlock,
+ perform: gralloc_perform,
+ lock_ycbcr: gralloc_lock_ycbcr,
+ },
+ framebuffer: 0,
+ fbFormat: 0,
+ flags: 0,
+ numBuffers: 0,
+ bufferMask: 0,
+ lock: PTHREAD_MUTEX_INITIALIZER,
+ currentBuffer: 0,
};
// Open Gralloc device
@@ -99,6 +105,9 @@
gpu_context_t *dev;
IAllocController* alloc_ctrl = IAllocController::getInstance();
dev = new gpu_context_t(m, alloc_ctrl);
+ if(!dev)
+ return status;
+
*device = &dev->common;
status = 0;
} else {
diff --git a/msm8226/libgralloc/gralloc_priv.h b/msm8226/libgralloc/gralloc_priv.h
index 89f1a88..f029b80 100644
--- a/msm8226/libgralloc/gralloc_priv.h
+++ b/msm8226/libgralloc/gralloc_priv.h
@@ -79,8 +79,10 @@
// libraries
GRALLOC_MODULE_PERFORM_GET_STRIDE,
GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE,
+ GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE,
GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES,
GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE,
+ GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO,
};
#define GRALLOC_HEAP_MASK (GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP |\
@@ -200,7 +202,9 @@
PRIV_FLAGS_ITU_R_709 = 0x00800000,
PRIV_FLAGS_SECURE_DISPLAY = 0x01000000,
// Buffer is rendered in Tile Format
- PRIV_FLAGS_TILE_RENDERED = 0x02000000
+ PRIV_FLAGS_TILE_RENDERED = 0x02000000,
+ // Buffer rendered using CPU/SW renderer
+ PRIV_FLAGS_CPU_RENDERED = 0x04000000
};
// file-descriptors
@@ -209,34 +213,37 @@
// ints
int magic;
int flags;
- int size;
- int offset;
+ unsigned int size;
+ unsigned int offset;
int bufferType;
- int base;
- int offset_metadata;
+ uint64_t base __attribute__((aligned(8)));
+ unsigned int offset_metadata;
// The gpu address mapped into the mmu.
- int gpuaddr;
+ uint64_t gpuaddr __attribute__((aligned(8)));
int format;
int width;
int height;
- int base_metadata;
+ uint64_t base_metadata __attribute__((aligned(8)));
#ifdef __cplusplus
- static const int sNumInts = 12;
static const int sNumFds = 2;
+ static inline int sNumInts() {
+ return ((sizeof(private_handle_t) - sizeof(native_handle_t)) /
+ sizeof(int)) - sNumFds;
+ }
static const int sMagic = 'gmsm';
- private_handle_t(int fd, int size, int flags, int bufferType,
- int format,int width, int height, int eFd = -1,
- int eOffset = 0, int eBase = 0) :
+ private_handle_t(int fd, unsigned int size, int flags, int bufferType,
+ int format, int width, int height, int eFd = -1,
+ unsigned int eOffset = 0, uint64_t eBase = 0) :
fd(fd), fd_metadata(eFd), magic(sMagic),
flags(flags), size(size), offset(0), bufferType(bufferType),
base(0), offset_metadata(eOffset), gpuaddr(0),
format(format), width(width), height(height),
base_metadata(eBase)
{
- version = sizeof(native_handle);
- numInts = sNumInts;
+ version = (int) sizeof(native_handle);
+ numInts = sNumInts();
numFds = sNumFds;
}
~private_handle_t() {
@@ -250,14 +257,15 @@
static int validate(const native_handle* h) {
const private_handle_t* hnd = (const private_handle_t*)h;
if (!h || h->version != sizeof(native_handle) ||
- h->numInts != sNumInts || h->numFds != sNumFds ||
+ h->numInts != sNumInts() || h->numFds != sNumFds ||
hnd->magic != sMagic)
{
ALOGD("Invalid gralloc handle (at %p): "
- "ver(%d/%d) ints(%d/%d) fds(%d/%d) magic(%c%c%c%c/%c%c%c%c)",
+ "ver(%d/%zu) ints(%d/%d) fds(%d/%d)"
+ "magic(%c%c%c%c/%c%c%c%c)",
h,
h ? h->version : -1, sizeof(native_handle),
- h ? h->numInts : -1, sNumInts,
+ h ? h->numInts : -1, sNumInts(),
h ? h->numFds : -1, sNumFds,
hnd ? (((hnd->magic >> 24) & 0xFF)?
((hnd->magic >> 24) & 0xFF) : '-') : '?',
diff --git a/msm8226/libgralloc/ionalloc.cpp b/msm8226/libgralloc/ionalloc.cpp
index bb6c2c8..10a662d 100644
--- a/msm8226/libgralloc/ionalloc.cpp
+++ b/msm8226/libgralloc/ionalloc.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2012,2014, The Linux Foundation. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -73,7 +73,7 @@
ionAllocData.len = data.size;
ionAllocData.align = data.align;
- ionAllocData.heap_mask = data.flags & ~ION_SECURE;
+ ionAllocData.heap_id_mask = data.flags & ~ION_SECURE;
ionAllocData.flags = data.uncached ? 0 : ION_FLAG_CACHED;
// ToDo: replace usage of alloc data structure with
// ionallocdata structure.
@@ -114,16 +114,17 @@
data.base = base;
data.fd = fd_data.fd;
ioctl(mIonFd, ION_IOC_FREE, &handle_data);
- ALOGD_IF(DEBUG, "ion: Allocated buffer base:%p size:%d fd:%d",
+ ALOGD_IF(DEBUG, "ion: Allocated buffer base:%p size:%zu fd:%d",
data.base, ionAllocData.len, data.fd);
return 0;
}
-int IonAlloc::free_buffer(void* base, size_t size, int offset, int fd)
+int IonAlloc::free_buffer(void* base, unsigned int size, unsigned int offset,
+ int fd)
{
Locker::Autolock _l(mLock);
- ALOGD_IF(DEBUG, "ion: Freeing buffer base:%p size:%d fd:%d",
+ ALOGD_IF(DEBUG, "ion: Freeing buffer base:%p size:%u fd:%d",
base, size, fd);
int err = 0;
err = open_device();
@@ -136,7 +137,8 @@
return err;
}
-int IonAlloc::map_buffer(void **pBase, size_t size, int offset, int fd)
+int IonAlloc::map_buffer(void **pBase, unsigned int size, unsigned int offset,
+ int fd)
{
int err = 0;
void *base = 0;
@@ -154,15 +156,16 @@
ALOGE("ion: Failed to map memory in the client: %s",
strerror(errno));
} else {
- ALOGD_IF(DEBUG, "ion: Mapped buffer base:%p size:%d offset:%d fd:%d",
+ ALOGD_IF(DEBUG, "ion: Mapped buffer base:%p size:%u offset:%u fd:%d",
base, size, offset, fd);
}
return err;
}
-int IonAlloc::unmap_buffer(void *base, size_t size, int offset)
+int IonAlloc::unmap_buffer(void *base, unsigned int size,
+ unsigned int /*offset*/)
{
- ALOGD_IF(DEBUG, "ion: Unmapping buffer base:%p size:%d", base, size);
+ ALOGD_IF(DEBUG, "ion: Unmapping buffer base:%p size:%u", base, size);
int err = 0;
if(munmap(base, size)) {
err = -errno;
@@ -172,12 +175,12 @@
return err;
}
-int IonAlloc::clean_buffer(void *base, size_t size, int offset, int fd, int op)
+int IonAlloc::clean_buffer(void *base, unsigned int size, unsigned int offset,
+ int fd, int op)
{
struct ion_flush_data flush_data;
struct ion_fd_data fd_data;
struct ion_handle_data handle_data;
- ion_user_handle_t handle;
int err = 0;
err = open_device();
@@ -195,6 +198,7 @@
handle_data.handle = fd_data.handle;
flush_data.handle = fd_data.handle;
flush_data.vaddr = base;
+ // offset and length are unsigned int
flush_data.offset = offset;
flush_data.length = size;
diff --git a/msm8226/libgralloc/ionalloc.h b/msm8226/libgralloc/ionalloc.h
index 174f44b..635bda5 100644
--- a/msm8226/libgralloc/ionalloc.h
+++ b/msm8226/libgralloc/ionalloc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -41,17 +41,17 @@
public:
virtual int alloc_buffer(alloc_data& data);
- virtual int free_buffer(void *base, size_t size,
- int offset, int fd);
+ virtual int free_buffer(void *base, unsigned int size,
+ unsigned int offset, int fd);
- virtual int map_buffer(void **pBase, size_t size,
- int offset, int fd);
+ virtual int map_buffer(void **pBase, unsigned int size,
+ unsigned int offset, int fd);
- virtual int unmap_buffer(void *base, size_t size,
- int offset);
+ virtual int unmap_buffer(void *base, unsigned int size,
+ unsigned int offset);
- virtual int clean_buffer(void*base, size_t size,
- int offset, int fd, int op);
+ virtual int clean_buffer(void*base, unsigned int size,
+ unsigned int offset, int fd, int op);
IonAlloc() { mIonFd = FD_INIT; }
diff --git a/msm8226/libgralloc/mapper.cpp b/msm8226/libgralloc/mapper.cpp
index 59e7d60..0ee69c8 100644
--- a/msm8226/libgralloc/mapper.cpp
+++ b/msm8226/libgralloc/mapper.cpp
@@ -53,14 +53,16 @@
}
static int gralloc_map(gralloc_module_t const* module,
- buffer_handle_t handle,
- void** vaddr)
+ buffer_handle_t handle)
{
+ if(!module)
+ return -EINVAL;
+
private_handle_t* hnd = (private_handle_t*)handle;
void *mappedAddress;
if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) &&
!(hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER)) {
- size_t size = hnd->size;
+ unsigned int size = hnd->size;
IMemAlloc* memalloc = getAllocator(hnd->flags) ;
int err = memalloc->map_buffer(&mappedAddress, size,
hnd->offset, hnd->fd);
@@ -71,9 +73,7 @@
return -errno;
}
- hnd->base = intptr_t(mappedAddress) + hnd->offset;
- //LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p",
- // hnd->fd, hnd->offset, hnd->size, mappedAddress);
+ hnd->base = uint64_t(mappedAddress) + hnd->offset;
mappedAddress = MAP_FAILED;
size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
err = memalloc->map_buffer(&mappedAddress, size,
@@ -84,20 +84,22 @@
hnd->base_metadata = 0;
return -errno;
}
- hnd->base_metadata = intptr_t(mappedAddress) + hnd->offset_metadata;
+ hnd->base_metadata = uint64_t(mappedAddress) + hnd->offset_metadata;
}
- *vaddr = (void*)hnd->base;
return 0;
}
static int gralloc_unmap(gralloc_module_t const* module,
buffer_handle_t handle)
{
+ if(!module)
+ return -EINVAL;
+
private_handle_t* hnd = (private_handle_t*)handle;
if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
int err = -EINVAL;
void* base = (void*)hnd->base;
- size_t size = hnd->size;
+ unsigned int size = hnd->size;
IMemAlloc* memalloc = getAllocator(hnd->flags) ;
if(memalloc != NULL) {
err = memalloc->unmap_buffer(base, size, hnd->offset);
@@ -128,7 +130,7 @@
int gralloc_register_buffer(gralloc_module_t const* module,
buffer_handle_t handle)
{
- if (private_handle_t::validate(handle) < 0)
+ if (!module || private_handle_t::validate(handle) < 0)
return -EINVAL;
// In this implementation, we don't need to do anything here
@@ -143,8 +145,7 @@
private_handle_t* hnd = (private_handle_t*)handle;
hnd->base = 0;
hnd->base_metadata = 0;
- void *vaddr;
- int err = gralloc_map(module, handle, &vaddr);
+ int err = gralloc_map(module, handle);
if (err) {
ALOGE("%s: gralloc_map failed", __FUNCTION__);
return err;
@@ -156,7 +157,7 @@
int gralloc_unregister_buffer(gralloc_module_t const* module,
buffer_handle_t handle)
{
- if (private_handle_t::validate(handle) < 0)
+ if (!module || private_handle_t::validate(handle) < 0)
return -EINVAL;
/*
@@ -178,6 +179,9 @@
int terminateBuffer(gralloc_module_t const* module,
private_handle_t* hnd)
{
+ if(!module)
+ return -EINVAL;
+
/*
* If the buffer has been mapped during a lock operation, it's time
* to un-map it. It's an error to be here with a locked buffer.
@@ -200,12 +204,10 @@
return 0;
}
-int gralloc_lock(gralloc_module_t const* module,
- buffer_handle_t handle, int usage,
- int l, int t, int w, int h,
- void** vaddr)
+static int gralloc_map_and_invalidate (gralloc_module_t const* module,
+ buffer_handle_t handle, int usage)
{
- if (private_handle_t::validate(handle) < 0)
+ if (!module || private_handle_t::validate(handle) < 0)
return -EINVAL;
int err = 0;
@@ -215,10 +217,9 @@
// we need to map for real
pthread_mutex_t* const lock = &sMapLock;
pthread_mutex_lock(lock);
- err = gralloc_map(module, handle, vaddr);
+ err = gralloc_map(module, handle);
pthread_mutex_unlock(lock);
}
- *vaddr = (void*)hnd->base;
if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) {
//Invalidate if reading in software. No need to do this for the
//metadata buffer as it is only read/written in software.
@@ -237,11 +238,36 @@
return err;
}
+int gralloc_lock(gralloc_module_t const* module,
+ buffer_handle_t handle, int usage,
+ int /*l*/, int /*t*/, int /*w*/, int /*h*/,
+ void** vaddr)
+{
+ private_handle_t* hnd = (private_handle_t*)handle;
+ int err = gralloc_map_and_invalidate(module, handle, usage);
+ if(!err)
+ *vaddr = (void*)hnd->base;
+ return err;
+}
+
+int gralloc_lock_ycbcr(gralloc_module_t const* module,
+ buffer_handle_t handle, int usage,
+ int /*l*/, int /*t*/, int /*w*/, int /*h*/,
+ struct android_ycbcr *ycbcr)
+{
+ private_handle_t* hnd = (private_handle_t*)handle;
+ int err = gralloc_map_and_invalidate(module, handle, usage);
+ if(!err)
+ err = getYUVPlaneInfo(hnd, ycbcr);
+ return err;
+}
+
int gralloc_unlock(gralloc_module_t const* module,
buffer_handle_t handle)
{
- if (private_handle_t::validate(handle) < 0)
+ if (!module || private_handle_t::validate(handle) < 0)
return -EINVAL;
+
int err = 0;
private_handle_t* hnd = (private_handle_t*)handle;
@@ -273,28 +299,30 @@
{
int res = -EINVAL;
va_list args;
+ if(!module)
+ return res;
+
va_start(args, operation);
switch (operation) {
case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER:
{
int fd = va_arg(args, int);
- size_t size = va_arg(args, size_t);
- size_t offset = va_arg(args, size_t);
+ unsigned int size = va_arg(args, unsigned int);
+ unsigned int offset = va_arg(args, unsigned int);
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);
private_handle_t* hnd = (private_handle_t*)native_handle_create(
- private_handle_t::sNumFds, private_handle_t::sNumInts);
+ private_handle_t::sNumFds, private_handle_t::sNumInts());
hnd->magic = private_handle_t::sMagic;
hnd->fd = fd;
hnd->flags = private_handle_t::PRIV_FLAGS_USES_ION;
hnd->size = size;
hnd->offset = offset;
- hnd->base = intptr_t(base) + offset;
+ hnd->base = uint64_t(base) + offset;
hnd->gpuaddr = 0;
hnd->width = width;
hnd->height = height;
@@ -349,6 +377,25 @@
res = 0;
} break;
+ case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE:
+ {
+ private_handle_t* hnd = va_arg(args, private_handle_t*);
+ int *stride = va_arg(args, int *);
+ int *height = va_arg(args, int *);
+ if (private_handle_t::validate(hnd)) {
+ return res;
+ }
+ MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+ if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+ *stride = metadata->bufferDim.sliceWidth;
+ *height = metadata->bufferDim.sliceHeight;
+ } else {
+ *stride = hnd->width;
+ *height = hnd->height;
+ }
+ res = 0;
+ } break;
+
case GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES:
{
int width = va_arg(args, int);
@@ -378,6 +425,15 @@
res = 0;
}
} break;
+ case GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO:
+ {
+ private_handle_t* hnd = va_arg(args, private_handle_t*);
+ android_ycbcr* ycbcr = va_arg(args, struct android_ycbcr *);
+ if (!private_handle_t::validate(hnd)) {
+ res = getYUVPlaneInfo(hnd, ycbcr);
+ }
+ } break;
+
default:
break;
}
diff --git a/msm8226/libgralloc/memalloc.h b/msm8226/libgralloc/memalloc.h
index 664bfa2..2bc1ddf 100644
--- a/msm8226/libgralloc/memalloc.h
+++ b/msm8226/libgralloc/memalloc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -43,10 +43,10 @@
struct alloc_data {
void *base;
int fd;
- int offset;
- size_t size;
- size_t align;
- unsigned int pHandle;
+ unsigned int offset;
+ unsigned int size;
+ unsigned int align;
+ uintptr_t pHandle;
bool uncached;
unsigned int flags;
int allocType;
@@ -61,20 +61,20 @@
virtual int alloc_buffer(alloc_data& data) = 0;
// Free buffer
- virtual int free_buffer(void *base, size_t size,
- int offset, int fd) = 0;
+ virtual int free_buffer(void *base, unsigned int size,
+ unsigned int offset, int fd) = 0;
// Map buffer
- virtual int map_buffer(void **pBase, size_t size,
- int offset, int fd) = 0;
+ virtual int map_buffer(void **pBase, unsigned int size,
+ unsigned int offset, int fd) = 0;
// Unmap buffer
- virtual int unmap_buffer(void *base, size_t size,
- int offset) = 0;
+ virtual int unmap_buffer(void *base, unsigned int size,
+ unsigned int offset) = 0;
// Clean and invalidate
- virtual int clean_buffer(void *base, size_t size,
- int offset, int fd, int op) = 0;
+ virtual int clean_buffer(void *base, unsigned int size,
+ unsigned int offset, int fd, int op) = 0;
// Destructor
virtual ~IMemAlloc() {};
diff --git a/msm8226/libhwcomposer/Android.mk b/msm8226/libhwcomposer/Android.mk
index 561ba2c..ef7778b 100644
--- a/msm8226/libhwcomposer/Android.mk
+++ b/msm8226/libhwcomposer/Android.mk
@@ -3,7 +3,7 @@
include $(CLEAR_VARS)
LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM)
-LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes) \
$(TOP)/external/skia/include/core \
@@ -12,6 +12,11 @@
libexternal libqdutils libhardware_legacy \
libdl libmemalloc libqservice libsync \
libbinder libmedia libvirtual
+
+ifeq ($(TARGET_USES_QCOM_BSP),true)
+LOCAL_SHARED_LIBRARIES += libskia
+endif #TARGET_USES_QCOM_BSP
+
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdhwcomposer\"
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
LOCAL_SRC_FILES := hwc.cpp \
diff --git a/msm8226/libhwcomposer/hwc.cpp b/msm8226/libhwcomposer/hwc.cpp
index fe418ad..8a64d67 100644
--- a/msm8226/libhwcomposer/hwc.cpp
+++ b/msm8226/libhwcomposer/hwc.cpp
@@ -44,7 +44,7 @@
using namespace overlay;
#define VSYNC_DEBUG 0
-#define BLANK_DEBUG 1
+#define POWER_MODE_DEBUG 1
static int hwc_device_open(const struct hw_module_t* module,
const char* name,
@@ -101,12 +101,104 @@
init_vsync_thread(ctx);
}
-//Helper
+static void setPaddingRound(hwc_context_t *ctx, int numDisplays,
+ hwc_display_contents_1_t** displays) {
+ ctx->isPaddingRound = false;
+ for(int i = 0; i < numDisplays; i++) {
+ hwc_display_contents_1_t *list = displays[i];
+ if (LIKELY(list && list->numHwLayers > 0)) {
+ if((ctx->mPrevHwLayerCount[i] == 1 or
+ ctx->mPrevHwLayerCount[i] == 0) and
+ (list->numHwLayers > 1)) {
+ /* If the previous cycle for dpy 'i' has 0 AppLayers and the
+ * current cycle has atleast 1 AppLayer, padding round needs
+ * to be invoked in current cycle on all the active displays
+ * to free up the resources.
+ */
+ ctx->isPaddingRound = true;
+ }
+ ctx->mPrevHwLayerCount[i] = (int)list->numHwLayers;
+ } else {
+ ctx->mPrevHwLayerCount[i] = 0;
+ }
+ }
+}
+
+/* Based on certain conditions, isPaddingRound will be set
+ * to make this function self-contained */
+static void setDMAState(hwc_context_t *ctx, int numDisplays,
+ hwc_display_contents_1_t** displays) {
+
+ if(ctx->mRotMgr->getNumActiveSessions() == 0)
+ Overlay::setDMAMode(Overlay::DMA_LINE_MODE);
+
+ for(int dpy = 0; dpy < numDisplays; dpy++) {
+ hwc_display_contents_1_t *list = displays[dpy];
+ if (LIKELY(list && list->numHwLayers > 0)) {
+ for(size_t layerIndex = 0; layerIndex < list->numHwLayers;
+ layerIndex++) {
+ if(list->hwLayers[layerIndex].compositionType !=
+ HWC_FRAMEBUFFER_TARGET)
+ {
+ hwc_layer_1_t const* layer = &list->hwLayers[layerIndex];
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+
+ /* If a layer requires rotation, set the DMA state
+ * to BLOCK_MODE */
+
+ if (canUseRotator(ctx, dpy) &&
+ has90Transform(layer) && isRotationDoable(ctx, hnd)) {
+ if(not ctx->mOverlay->isDMAMultiplexingSupported()) {
+ if(ctx->mOverlay->isPipeTypeAttached(
+ overlay::utils::OV_MDP_PIPE_DMA))
+ ctx->isPaddingRound = true;
+ }
+ Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE);
+ }
+ }
+ }
+ if(dpy) {
+ /* Uncomment the below code for testing purpose.
+ Assuming the orientation value is in terms of HAL_TRANSFORM,
+ this needs mapping to HAL, if its in different convention */
+
+ /* char value[PROPERTY_VALUE_MAX];
+ property_get("sys.ext_orientation", value, "0");
+ ctx->mExtOrientation = atoi(value);*/
+
+ if(ctx->mExtOrientation || ctx->mBufferMirrorMode) {
+ if(ctx->mOverlay->isPipeTypeAttached(
+ overlay::utils::OV_MDP_PIPE_DMA)) {
+ ctx->isPaddingRound = true;
+ }
+ Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE);
+ }
+ }
+ }
+ }
+}
+
+static void setNumActiveDisplays(hwc_context_t *ctx, int numDisplays,
+ hwc_display_contents_1_t** displays) {
+
+ ctx->numActiveDisplays = 0;
+ for(int i = 0; i < numDisplays; i++) {
+ hwc_display_contents_1_t *list = displays[i];
+ if (LIKELY(list && list->numHwLayers > 0)) {
+ /* For display devices like SSD and screenrecord, we cannot
+ * rely on isActive and connected attributes of dpyAttr to
+ * determine if the displaydevice is active. Hence in case if
+ * the layer-list is non-null and numHwLayers > 0, we assume
+ * the display device to be active.
+ */
+ ctx->numActiveDisplays += 1;
+ }
+ }
+}
+
static void reset(hwc_context_t *ctx, int numDisplays,
hwc_display_contents_1_t** displays) {
- ctx->numActiveDisplays = 0;
- ctx->isPaddingRound = false;
for(int i = 0; i < numDisplays; i++) {
hwc_display_contents_1_t *list = displays[i];
@@ -115,31 +207,15 @@
// cache we need to reset it.
// We can probably rethink that later on
if (LIKELY(list && list->numHwLayers > 0)) {
- for(uint32_t j = 0; j < list->numHwLayers; j++) {
+ for(size_t j = 0; j < list->numHwLayers; j++) {
if(list->hwLayers[j].compositionType != HWC_FRAMEBUFFER_TARGET)
list->hwLayers[j].compositionType = HWC_FRAMEBUFFER;
}
- /* For display devices like SSD and screenrecord, we cannot
- * rely on isActive and connected attributes of dpyAttr to
- * determine if the displaydevice is active. Hence in case if
- * the layer-list is non-null and numHwLayers > 0, we assume
- * the display device to be active.
- */
- ctx->numActiveDisplays += 1;
-
- if((ctx->mPrevHwLayerCount[i] == 1) and (list->numHwLayers > 1)) {
- /* If the previous cycle for dpy 'i' has 0 AppLayers and the
- * current cycle has atleast 1 AppLayer, padding round needs
- * to be invoked on current cycle to free up the resources.
- */
- ctx->isPaddingRound = true;
- }
- ctx->mPrevHwLayerCount[i] = list->numHwLayers;
- } else {
- ctx->mPrevHwLayerCount[i] = 0;
}
+ if(ctx->mMDPComp[i])
+ ctx->mMDPComp[i]->reset();
if(ctx->mFBUpdate[i])
ctx->mFBUpdate[i]->reset();
if(ctx->mCopyBit[i])
@@ -149,40 +225,30 @@
}
ctx->mAD->reset();
- MDPComp::reset();
if(ctx->mHWCVirtual)
ctx->mHWCVirtual->destroy(ctx, numDisplays, displays);
}
-bool isEqual(float f1, float f2) {
- return ((int)(f1*100) == (int)(f2*100)) ? true : false;
-}
-
static void scaleDisplayFrame(hwc_context_t *ctx, int dpy,
hwc_display_contents_1_t *list) {
- float origXres = ctx->dpyAttr[dpy].xres_orig;
- float origYres = ctx->dpyAttr[dpy].yres_orig;
- float fakeXres = ctx->dpyAttr[dpy].xres;
- float fakeYres = ctx->dpyAttr[dpy].yres;
- float xresRatio = origXres / fakeXres;
- float yresRatio = origYres / fakeYres;
+ uint32_t origXres = ctx->dpyAttr[dpy].xres;
+ uint32_t origYres = ctx->dpyAttr[dpy].yres;
+ uint32_t newXres = ctx->dpyAttr[dpy].xres_new;
+ uint32_t newYres = ctx->dpyAttr[dpy].yres_new;
+ float xresRatio = (float)origXres / (float)newXres;
+ float yresRatio = (float)origYres / (float)newYres;
for (size_t i = 0; i < list->numHwLayers; i++) {
hwc_layer_1_t *layer = &list->hwLayers[i];
hwc_rect_t& displayFrame = layer->displayFrame;
hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
- float layerWidth = displayFrame.right - displayFrame.left;
- float layerHeight = displayFrame.bottom - displayFrame.top;
- float sourceWidth = sourceCrop.right - sourceCrop.left;
- float sourceHeight = sourceCrop.bottom - sourceCrop.top;
-
- if (isEqual(layerWidth / sourceWidth, xresRatio) &&
- isEqual(layerHeight / sourceHeight, yresRatio))
- break;
-
- displayFrame.left = xresRatio * displayFrame.left;
- displayFrame.top = yresRatio * displayFrame.top;
- displayFrame.right = displayFrame.left + layerWidth * xresRatio;
- displayFrame.bottom = displayFrame.top + layerHeight * yresRatio;
+ uint32_t layerWidth = displayFrame.right - displayFrame.left;
+ uint32_t layerHeight = displayFrame.bottom - displayFrame.top;
+ displayFrame.left = (int)(xresRatio * (float)displayFrame.left);
+ displayFrame.top = (int)(yresRatio * (float)displayFrame.top);
+ displayFrame.right = (int)((float)displayFrame.left +
+ (float)layerWidth * xresRatio);
+ displayFrame.bottom = (int)((float)displayFrame.top +
+ (float)layerHeight * yresRatio);
}
}
@@ -195,17 +261,21 @@
if (LIKELY(list && list->numHwLayers > 1) &&
ctx->dpyAttr[dpy].isActive) {
- if (ctx->dpyAttr[dpy].customFBSize)
+ if (ctx->dpyAttr[dpy].customFBSize &&
+ list->flags & HWC_GEOMETRY_CHANGED)
scaleDisplayFrame(ctx, dpy, list);
- reset_layer_prop(ctx, dpy, list->numHwLayers - 1);
+ reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
setListStats(ctx, list, dpy);
fbComp = (ctx->mMDPComp[dpy]->prepare(ctx, list) < 0);
if (fbComp) {
const int fbZ = 0;
- ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
+ if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ)) {
+ ctx->mOverlay->clear(dpy);
+ ctx->mLayerRotMap[dpy]->clear();
+ }
}
if (ctx->mMDP.version < qdutils::MDP_V4_0) {
@@ -226,13 +296,17 @@
if (LIKELY(list && list->numHwLayers > 1) &&
ctx->dpyAttr[dpy].isActive &&
ctx->dpyAttr[dpy].connected) {
- reset_layer_prop(ctx, dpy, list->numHwLayers - 1);
+ reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
if(!ctx->dpyAttr[dpy].isPause) {
ctx->dpyAttr[dpy].isConfiguring = false;
setListStats(ctx, list, dpy);
if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
const int fbZ = 0;
- ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
+ if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
+ {
+ ctx->mOverlay->clear(dpy);
+ ctx->mLayerRotMap[dpy]->clear();
+ }
}
} else {
/* External Display is in Pause state.
@@ -261,13 +335,16 @@
//Will be unlocked at the end of set
ctx->mDrawLock.lock();
- reset(ctx, numDisplays, displays);
+ setPaddingRound(ctx, (int)numDisplays, displays);
+ setDMAState(ctx, (int)numDisplays, displays);
+ setNumActiveDisplays(ctx, (int)numDisplays, displays);
+ reset(ctx, (int)numDisplays, displays);
ctx->mOverlay->configBegin();
ctx->mRotMgr->configBegin();
overlay::Writeback::configBegin();
- for (int32_t i = (numDisplays-1); i >= 0; i--) {
+ for (int32_t i = ((int32_t)numDisplays-1); i >=0 ; i--) {
hwc_display_contents_1_t *list = displays[i];
int dpy = getDpyforExternalDisplay(ctx, i);
switch(dpy) {
@@ -324,106 +401,86 @@
return ret;
}
-static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank)
+static int hwc_setPowerMode(struct hwc_composer_device_1* dev, int dpy,
+ int mode)
{
ATRACE_CALL();
hwc_context_t* ctx = (hwc_context_t*)(dev);
-
- Locker::Autolock _l(ctx->mDrawLock);
int ret = 0, value = 0;
- /* In case of non-hybrid WFD session, we are fooling SF by
- * piggybacking on HDMI display ID for virtual.
- * TODO: Not needed once we have WFD client working on top
- * of Google API's.
- */
- dpy = getDpyforExternalDisplay(ctx,dpy);
+ Locker::Autolock _l(ctx->mDrawLock);
+ ALOGD_IF(POWER_MODE_DEBUG, "%s: Setting mode %d on display: %d",
+ __FUNCTION__, mode, dpy);
- ALOGD_IF(BLANK_DEBUG, "%s: %s display: %d", __FUNCTION__,
- blank==1 ? "Blanking":"Unblanking", dpy);
- if(blank) {
- // free up all the overlay pipes in use
- // when we get a blank for either display
- // makes sure that all pipes are freed
- ctx->mOverlay->configBegin();
- ctx->mOverlay->configDone();
- ctx->mRotMgr->clear();
- // If VDS is connected, do not clear WB object as it
- // will end up detaching IOMMU. This is required
- // to send black frame to WFD sink on power suspend.
- // Note: With this change, we keep the WriteBack object
- // alive on power suspend for AD use case.
+ switch(mode) {
+ case HWC_POWER_MODE_OFF:
+ // free up all the overlay pipes in use
+ // when we get a blank for either display
+ // makes sure that all pipes are freed
+ ctx->mOverlay->configBegin();
+ ctx->mOverlay->configDone();
+ ctx->mRotMgr->clear();
+ // If VDS is connected, do not clear WB object as it
+ // will end up detaching IOMMU. This is required
+ // to send black frame to WFD sink on power suspend.
+ // Note: With this change, we keep the WriteBack object
+ // alive on power suspend for AD use case.
+ value = FB_BLANK_POWERDOWN;
+ break;
+ case HWC_POWER_MODE_DOZE:
+ case HWC_POWER_MODE_DOZE_SUSPEND:
+ value = FB_BLANK_VSYNC_SUSPEND;
+ break;
+ case HWC_POWER_MODE_NORMAL:
+ value = FB_BLANK_UNBLANK;
+ break;
}
+
switch(dpy) {
case HWC_DISPLAY_PRIMARY:
- value = blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK;
if(ioctl(ctx->dpyAttr[dpy].fd, FBIOBLANK, value) < 0 ) {
- ALOGE("%s: Failed to handle blank event(%d) for Primary!!",
- __FUNCTION__, blank );
- return -1;
+ ALOGE("%s: ioctl FBIOBLANK failed for Primary with error %s"
+ " value %d", __FUNCTION__, strerror(errno), value);
+ return -errno;
}
- if(!blank) {
- // Enable HPD here, as during bootup unblank is called
+ if(mode == HWC_POWER_MODE_NORMAL) {
+ // Enable HPD here, as during bootup POWER_MODE_NORMAL is set
// when SF is completely initialized
ctx->mExtDisplay->setHPD(1);
}
- ctx->dpyAttr[dpy].isActive = !blank;
-
- if(ctx->mVirtualonExtActive) {
- /* if mVirtualonExtActive is true, display hal will
- * receive unblank calls for non-hybrid WFD solution
- * since we piggyback on HDMI.
- * TODO: Not needed once we have WFD client working on top
- of Google API's */
- break;
- }
+ ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
+ //Deliberate fall through since there is no explicit power mode for
+ //virtual displays.
case HWC_DISPLAY_VIRTUAL:
- /* There are two ways to reach this block of code.
-
- * Display hal has received unblank call on HWC_DISPLAY_EXTERNAL
- and ctx->mVirtualonExtActive is true. In this case, non-hybrid
- WFD is active. If so, getDpyforExternalDisplay will return dpy
- as HWC_DISPLAY_VIRTUAL.
-
- * Display hal has received unblank call on HWC_DISPLAY_PRIMARY
- and since SF is not aware of VIRTUAL DISPLAY being handle by HWC,
- it wont send blank / unblank events for it. We piggyback on
- PRIMARY DISPLAY events to release mdp pipes and
- activate/deactivate VIRTUAL DISPLAY.
-
- * TODO: This separate case statement is not needed once we have
- WFD client working on top of Google API's.
-
- */
-
if(ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected) {
- if(blank and (!ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isPause)) {
- int dpy = HWC_DISPLAY_VIRTUAL;
+ const int dpy = HWC_DISPLAY_VIRTUAL;
+ if(mode == HWC_POWER_MODE_OFF and
+ (not ctx->dpyAttr[dpy].isPause)) {
if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
- ALOGE("%s: display commit fail for virtual!", __FUNCTION__);
+ ALOGE("%s: displayCommit failed for virtual", __FUNCTION__);
ret = -1;
}
}
- ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = !blank;
+ ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
}
break;
case HWC_DISPLAY_EXTERNAL:
- if(blank) {
+ if(mode == HWC_POWER_MODE_OFF) {
if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
- ALOGE("%s: display commit fail for external!", __FUNCTION__);
+ ALOGE("%s: displayCommit failed for external", __FUNCTION__);
ret = -1;
}
}
- ctx->dpyAttr[dpy].isActive = !blank;
+ ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
break;
default:
return -EINVAL;
}
- ALOGD_IF(BLANK_DEBUG, "%s: Done %s display: %d", __FUNCTION__,
- blank ? "blanking":"unblanking", dpy);
+ ALOGD_IF(POWER_MODE_DEBUG, "%s: Done setting mode %d on display %d",
+ __FUNCTION__, mode, dpy);
return ret;
}
@@ -438,18 +495,18 @@
return;
}
- ALOGD("%s: calling BLANK DISPLAY", __FUNCTION__);
- ret = hwc_blank(dev, HWC_DISPLAY_PRIMARY, 1);
+ ALOGD("%s: setting power mode off", __FUNCTION__);
+ ret = hwc_setPowerMode(dev, HWC_DISPLAY_PRIMARY, HWC_POWER_MODE_OFF);
if (ret < 0) {
ALOGE("%s: FBIOBLANK failed to BLANK: %s", __FUNCTION__,
- strerror(errno));
+ strerror(errno));
}
- ALOGD("%s: calling UNBLANK DISPLAY and enabling vsync", __FUNCTION__);
- ret = hwc_blank(dev, HWC_DISPLAY_PRIMARY, 0);
+ ALOGD("%s: setting power mode normal and enabling vsync", __FUNCTION__);
+ ret = hwc_setPowerMode(dev, HWC_DISPLAY_PRIMARY, HWC_POWER_MODE_NORMAL);
if (ret < 0) {
ALOGE("%s: FBIOBLANK failed to UNBLANK : %s", __FUNCTION__,
- strerror(errno));
+ strerror(errno));
}
hwc_vsync_control(ctx, HWC_DISPLAY_PRIMARY, 1);
@@ -472,7 +529,8 @@
if(ctx->mMDP.hasOverlay) {
supported |= HWC_DISPLAY_VIRTUAL_BIT;
if(!(qdutils::MDPVersion::getInstance().is8x26() ||
- qdutils::MDPVersion::getInstance().is8x16()))
+ qdutils::MDPVersion::getInstance().is8x16() ||
+ qdutils::MDPVersion::getInstance().is8x39()))
supported |= HWC_DISPLAY_EXTERNAL_BIT;
}
value[0] = supported;
@@ -496,12 +554,18 @@
int ret = 0;
const int dpy = HWC_DISPLAY_PRIMARY;
if (LIKELY(list) && ctx->dpyAttr[dpy].isActive) {
- uint32_t last = list->numHwLayers - 1;
+ size_t last = list->numHwLayers - 1;
hwc_layer_1_t *fbLayer = &list->hwLayers[last];
int fd = -1; //FenceFD from the Copybit(valid in async mode)
bool copybitDone = false;
- if(ctx->mCopyBit[dpy])
- copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
+
+ if (ctx->mCopyBit[dpy]) {
+ if (ctx->mMDP.version < qdutils::MDP_V4_0)
+ copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
+ else
+ fd = ctx->mMDPComp[dpy]->drawOverlap(ctx, list);
+ }
+
if(list->numHwLayers > 1)
hwc_sync(ctx, list, dpy, fd);
@@ -521,6 +585,12 @@
hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
}
+ if(isAbcInUse(ctx) == true) {
+ int index = ctx->listStats[dpy].renderBufIndexforABC;
+ hwc_layer_1_t *tempLayer = &list->hwLayers[index];
+ hnd = (private_handle_t *)tempLayer->handle;
+ }
+
if(hnd) {
if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
ALOGE("%s: FBUpdate draw failed", __FUNCTION__);
@@ -528,8 +598,20 @@
}
}
- if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd,
- ctx->listStats[dpy].roi)) {
+ int lSplit = getLeftSplit(ctx, dpy);
+ qhwc::ovutils::Dim lRoi = qhwc::ovutils::Dim(
+ ctx->listStats[dpy].lRoi.left,
+ ctx->listStats[dpy].lRoi.top,
+ ctx->listStats[dpy].lRoi.right - ctx->listStats[dpy].lRoi.left,
+ ctx->listStats[dpy].lRoi.bottom - ctx->listStats[dpy].lRoi.top);
+
+ qhwc::ovutils::Dim rRoi = qhwc::ovutils::Dim(
+ ctx->listStats[dpy].rRoi.left - lSplit,
+ ctx->listStats[dpy].rRoi.top,
+ ctx->listStats[dpy].rRoi.right - ctx->listStats[dpy].rRoi.left,
+ ctx->listStats[dpy].rRoi.bottom - ctx->listStats[dpy].rRoi.top);
+
+ if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd, lRoi, rRoi)) {
ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
ret = -1;
}
@@ -552,7 +634,7 @@
if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
ctx->dpyAttr[dpy].connected &&
!ctx->dpyAttr[dpy].isPause) {
- uint32_t last = list->numHwLayers - 1;
+ size_t last = list->numHwLayers - 1;
hwc_layer_1_t *fbLayer = &list->hwLayers[last];
int fd = -1; //FenceFD from the Copybit(valid in async mode)
bool copybitDone = false;
@@ -605,7 +687,7 @@
{
int ret = 0;
hwc_context_t* ctx = (hwc_context_t*)(dev);
- for (uint32_t i = 0; i < numDisplays; i++) {
+ for (int i = 0; i < (int)numDisplays; i++) {
hwc_display_contents_1_t* list = displays[i];
int dpy = getDpyforExternalDisplay(ctx, i);
switch(dpy) {
@@ -628,8 +710,6 @@
CALC_FPS();
MDPComp::resetIdleFallBack();
ctx->mVideoTransFlag = false;
- if(ctx->mRotMgr->getNumActiveSessions() == 0)
- Overlay::setDMAMode(Overlay::DMA_LINE_MODE);
//Was locked at the beginning of prepare
ctx->mDrawLock.unlock();
return ret;
@@ -640,8 +720,8 @@
int ret = 0;
hwc_context_t* ctx = (hwc_context_t*)(dev);
disp = getDpyforExternalDisplay(ctx, disp);
- //in 1.1 there is no way to choose a config, report as config id # 0
- //This config is passed to getDisplayAttributes. Ignore for now.
+ //Currently we allow only 1 config, reported as config id # 0
+ //This config is passed in to getDisplayAttributes. Ignored for now.
switch(disp) {
case HWC_DISPLAY_PRIMARY:
if(*numConfigs > 0) {
@@ -685,7 +765,7 @@
HWC_DISPLAY_NO_ATTRIBUTE,
};
- const int NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) /
+ const size_t NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) /
sizeof(DISPLAY_ATTRIBUTES)[0]);
for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
@@ -694,14 +774,21 @@
values[i] = ctx->dpyAttr[disp].vsync_period;
break;
case HWC_DISPLAY_WIDTH:
- values[i] = ctx->dpyAttr[disp].xres;
+ if (ctx->dpyAttr[disp].customFBSize)
+ values[i] = ctx->dpyAttr[disp].xres_new;
+ else
+ values[i] = ctx->dpyAttr[disp].xres;
+
ALOGD("%s disp = %d, width = %d",__FUNCTION__, disp,
- ctx->dpyAttr[disp].xres);
+ values[i]);
break;
case HWC_DISPLAY_HEIGHT:
- values[i] = ctx->dpyAttr[disp].yres;
+ if (ctx->dpyAttr[disp].customFBSize)
+ values[i] = ctx->dpyAttr[disp].yres_new;
+ else
+ values[i] = ctx->dpyAttr[disp].yres;
ALOGD("%s disp = %d, height = %d",__FUNCTION__, disp,
- ctx->dpyAttr[disp].yres);
+ values[i]);
break;
case HWC_DISPLAY_DPI_X:
values[i] = (int32_t) (ctx->dpyAttr[disp].xdpi*1000.0);
@@ -730,7 +817,7 @@
dumpsys_log(aBuf, " Vsync is being faked!!\n");
for(int dpy = 0; dpy < HWC_NUM_DISPLAY_TYPES; dpy++) {
if(ctx->mMDPComp[dpy])
- ctx->mMDPComp[dpy]->dump(aBuf);
+ ctx->mMDPComp[dpy]->dump(aBuf, ctx);
}
char ovDump[2048] = {'\0'};
ctx->mOverlay->getDump(ovDump, 2048);
@@ -746,6 +833,17 @@
strlcpy(buff, aBuf.string(), buff_len);
}
+int hwc_getActiveConfig(struct hwc_composer_device_1* /*dev*/, int /*disp*/) {
+ //Supports only the default config (0th index) for now
+ return 0;
+}
+
+int hwc_setActiveConfig(struct hwc_composer_device_1* /*dev*/, int /*disp*/,
+ int index) {
+ //Supports only the default config (0th index) for now
+ return (index == 0) ? index : -EINVAL;
+}
+
static int hwc_device_close(struct hw_device_t *dev)
{
if(!dev) {
@@ -775,18 +873,20 @@
//Setup HWC methods
dev->device.common.tag = HARDWARE_DEVICE_TAG;
- dev->device.common.version = HWC_DEVICE_API_VERSION_1_3;
+ dev->device.common.version = HWC_DEVICE_API_VERSION_1_4;
dev->device.common.module = const_cast<hw_module_t*>(module);
dev->device.common.close = hwc_device_close;
dev->device.prepare = hwc_prepare;
dev->device.set = hwc_set;
dev->device.eventControl = hwc_eventControl;
- dev->device.blank = hwc_blank;
+ dev->device.setPowerMode = hwc_setPowerMode;
dev->device.query = hwc_query;
dev->device.registerProcs = hwc_registerProcs;
dev->device.dump = hwc_dump;
dev->device.getDisplayConfigs = hwc_getDisplayConfigs;
dev->device.getDisplayAttributes = hwc_getDisplayAttributes;
+ dev->device.getActiveConfig = hwc_getActiveConfig;
+ dev->device.setActiveConfig = hwc_setActiveConfig;
*device = &dev->device.common;
status = 0;
}
diff --git a/msm8226/libhwcomposer/hwc_ad.cpp b/msm8226/libhwcomposer/hwc_ad.cpp
index 236093b..49e7e2a 100644
--- a/msm8226/libhwcomposer/hwc_ad.cpp
+++ b/msm8226/libhwcomposer/hwc_ad.cpp
@@ -41,37 +41,6 @@
using namespace overlay::utils;
namespace qhwc {
-//Opens writeback framebuffer and returns fd.
-static int openWbFb() {
- int wbFd = -1;
- //Check opening which FB would connect LM to WB
- const int wbFbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
- if(wbFbNum >= 0) {
- char wbFbPath[256];
- snprintf (wbFbPath, sizeof(wbFbPath),
- "/sys/class/graphics/fb%d", wbFbNum);
- //Opening writeback fb first time would create ad node if the device
- //supports adaptive display
- wbFd = open(wbFbPath, O_RDONLY);
- if(wbFd < 0) {
- ALOGE("%s: Failed to open /sys/class/graphics/fb%d with error %s",
- __func__, wbFbNum, strerror(errno));
- }
- } else {
- ALOGD_IF(DEBUG, "%s: No writeback available", __func__);
- }
- return wbFd;
-}
-
-static inline void closeWbFb(int& fd) {
- if(fd >= 0) {
- close(fd);
- fd = -1;
- } else {
- ALOGE("%s: Invalid fd %d", __func__, fd);
- }
-}
-
//Helper to write data to ad node
static void adWrite(const int& value) {
const int wbFbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
@@ -82,7 +51,7 @@
if(adFd >= 0) {
char opStr[4] = "";
snprintf(opStr, sizeof(opStr), "%d", value);
- int ret = write(adFd, opStr, strlen(opStr));
+ ssize_t ret = write(adFd, opStr, strlen(opStr));
if(ret < 0) {
ALOGE("%s: Failed to write %d with error %s",
__func__, value, strerror(errno));
@@ -124,32 +93,31 @@
return ret;
}
-AssertiveDisplay::AssertiveDisplay(hwc_context_t *ctx) : mWbFd(-1),
- mDoable(false), mFeatureEnabled(false),
- mDest(overlay::utils::OV_INVALID) {
- int fd = openWbFb();
- if(fd >= 0) {
- //Values in ad node:
- //-1 means feature is disabled on device
- // 0 means feature exists but turned off, will be turned on by hwc
- // 1 means feature is turned on by hwc
- // Plus, we do this feature only on split primary displays.
- // Plus, we do this feature only if ro.qcom.ad=2
+AssertiveDisplay::AssertiveDisplay(hwc_context_t *ctx) :
+ mTurnedOff(true), mFeatureEnabled(false),
+ mDest(overlay::utils::OV_INVALID)
+{
+ //Values in ad node:
+ //-1 means feature is disabled on device
+ // 0 means feature exists but turned off, will be turned on by hwc
+ // 1 means feature is turned on by hwc
+ // Plus, we do this feature only on split primary displays.
+ // Plus, we do this feature only if ro.qcom.ad=2
- char property[PROPERTY_VALUE_MAX];
- const int ENABLED = 2;
- int val = 0;
+ char property[PROPERTY_VALUE_MAX];
+ const int ENABLED = 2;
+ int val = 0;
- if(property_get("ro.qcom.ad", property, "0") > 0) {
- val = atoi(property);
- }
+ if(property_get("ro.qcom.ad", property, "0") > 0) {
+ val = atoi(property);
+ }
- if(adRead() >= 0 && isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY) &&
- val == ENABLED) {
- ALOGD_IF(DEBUG, "Assertive display feature supported");
- mFeatureEnabled = true;
- }
- closeWbFb(fd);
+ if(adRead() >= 0 && isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY) &&
+ val == ENABLED) {
+ ALOGD_IF(DEBUG, "Assertive display feature supported");
+ mFeatureEnabled = true;
+ // If feature exists but is turned off, set mTurnedOff to true
+ mTurnedOff = adRead() > 0 ? false : true;
}
}
@@ -168,22 +136,33 @@
}
}
+void AssertiveDisplay::turnOffAD() {
+ if(mFeatureEnabled) {
+ if(!mTurnedOff) {
+ const int off = 0;
+ adWrite(off);
+ mTurnedOff = true;
+ }
+ }
+ mDoable = false;
+}
+
bool AssertiveDisplay::prepare(hwc_context_t *ctx,
const hwc_rect_t& crop,
const Whf& whf,
const private_handle_t *hnd) {
if(!isDoable()) {
- if(isModeOn()) {
- //Cleanup one time during this switch
- const int off = 0;
- adWrite(off);
- closeWbFb(mWbFd);
- }
+ //Cleanup one time during this switch
+ turnOffAD();
return false;
}
- ovutils::eDest dest = ctx->mOverlay->nextPipe(ovutils::OV_MDP_PIPE_VG,
- overlay::Overlay::DPY_WRITEBACK, Overlay::MIXER_DEFAULT);
+ Overlay::PipeSpecs pipeSpecs;
+ pipeSpecs.formatClass = Overlay::FORMAT_YUV;
+ pipeSpecs.dpy = overlay::Overlay::DPY_WRITEBACK;
+ pipeSpecs.fb = false;
+
+ ovutils::eDest dest = ctx->mOverlay->getPipe(pipeSpecs);
if(dest == OV_INVALID) {
ALOGE("%s failed: No VG pipe available", __func__);
mDoable = false;
@@ -206,7 +185,8 @@
return false;
}
- int tmpW, tmpH, size;
+ int tmpW, tmpH;
+ size_t size;
int format = ovutils::getHALFormat(wb->getOutputFormat());
if(format < 0) {
ALOGE("%s invalid format %d", __func__, format);
@@ -217,7 +197,7 @@
size = getBufferSizeAndDimensions(hnd->width, hnd->height,
format, tmpW, tmpH);
- if(!wb->configureMemory(size)) {
+ if(!wb->configureMemory((uint32_t)size)) {
ALOGE("%s: config memory failed", __func__);
mDoable = false;
return false;
@@ -241,27 +221,30 @@
}
mDest = dest;
- if(!isModeOn()) {
- mWbFd = openWbFb();
- if(mWbFd >= 0) {
- //write to sysfs, one time during this switch
- const int on = 1;
- adWrite(on);
- }
- }
-
- if(!ctx->mOverlay->validateAndSet(overlay::Overlay::DPY_WRITEBACK,
- mWbFd)) {
+ int wbFd = wb->getFbFd();
+ if(mFeatureEnabled && wbFd >= 0 &&
+ !ctx->mOverlay->validateAndSet(overlay::Overlay::DPY_WRITEBACK, wbFd))
+ {
ALOGE("%s: Failed to validate and set overlay for dpy %d"
,__FUNCTION__, overlay::Overlay::DPY_WRITEBACK);
+ turnOffAD();
return false;
}
+ // Only turn on AD if there are no errors during configuration stage
+ // and if it was previously in OFF state.
+ if(mFeatureEnabled && mTurnedOff) {
+ //write to sysfs, one time during this switch
+ const int on = 1;
+ adWrite(on);
+ mTurnedOff = false;
+ }
+
return true;
}
bool AssertiveDisplay::draw(hwc_context_t *ctx, int fd, uint32_t offset) {
- if(!isDoable() || !isModeOn()) {
+ if(!isDoable()) {
return false;
}
diff --git a/msm8226/libhwcomposer/hwc_ad.h b/msm8226/libhwcomposer/hwc_ad.h
index 3bfde17..0be5f5d 100644
--- a/msm8226/libhwcomposer/hwc_ad.h
+++ b/msm8226/libhwcomposer/hwc_ad.h
@@ -50,17 +50,16 @@
mDest = overlay::utils::OV_INVALID;
}
bool isDoable() const { return mDoable; }
- bool isModeOn() const { return (mWbFd >= 0); }
int getDstFd() const;
uint32_t getDstOffset() const;
private:
- //State of feature turned on and off
- int mWbFd;
bool mDoable;
+ bool mTurnedOff;
//State of feature existence on certain devices and configs.
bool mFeatureEnabled;
overlay::utils::eDest mDest;
+ void turnOffAD();
};
}
diff --git a/msm8226/libhwcomposer/hwc_copybit.cpp b/msm8226/libhwcomposer/hwc_copybit.cpp
index 38b0ff6..4652b3d 100644
--- a/msm8226/libhwcomposer/hwc_copybit.cpp
+++ b/msm8226/libhwcomposer/hwc_copybit.cpp
@@ -40,7 +40,7 @@
region_iterator(hwc_region_t region) {
mRegion = region;
- r.end = region.numRects;
+ r.end = (int)region.numRects;
r.current = 0;
this->next = iterate;
}
@@ -131,6 +131,144 @@
return renderArea;
}
+int CopyBit::getLayersChanging(hwc_context_t *ctx,
+ hwc_display_contents_1_t *list,
+ int dpy){
+
+ int changingLayerIndex = -1;
+ if(mLayerCache.layerCount != ctx->listStats[dpy].numAppLayers) {
+ mLayerCache.reset();
+ mFbCache.reset();
+ mLayerCache.updateCounts(ctx,list,dpy);
+ return -1;
+ }
+
+ int updatingLayerCount = 0;
+ for (int k = ctx->listStats[dpy].numAppLayers-1; k >= 0 ; k--){
+ //swap rect will kick in only for single updating layer
+ if(mLayerCache.hnd[k] != list->hwLayers[k].handle){
+ updatingLayerCount ++;
+ if(updatingLayerCount == 1)
+ changingLayerIndex = k;
+ }
+ }
+ //since we are using more than one framebuffers,we have to
+ //kick in swap rect only if we are getting continuous same
+ //dirty rect for same layer at least equal of number of
+ //framebuffers
+
+ if ( updatingLayerCount == 1 ) {
+ hwc_rect_t dirtyRect = list->hwLayers[changingLayerIndex].displayFrame;
+#ifdef QCOM_BSP
+ dirtyRect = list->hwLayers[changingLayerIndex].dirtyRect;
+#endif
+
+ for (int k = ctx->listStats[dpy].numAppLayers-1; k >= 0 ; k--){
+ //disable swap rect for overlapping visible layer(s)
+ hwc_rect_t displayFrame = list->hwLayers[k].displayFrame;
+ hwc_rect_t result = getIntersection(displayFrame,dirtyRect);
+ if((k != changingLayerIndex) && isValidRect(result)){
+ return -1;
+ }
+ }
+ mFbCache.insertAndUpdateFbCache(dirtyRect);
+ if(mFbCache.getUnchangedFbDRCount(dirtyRect) <
+ NUM_RENDER_BUFFERS)
+ changingLayerIndex = -1;
+ }else {
+ mFbCache.reset();
+ changingLayerIndex = -1;
+ }
+ mLayerCache.updateCounts(ctx,list,dpy);
+ return changingLayerIndex;
+}
+
+int CopyBit::checkDirtyRect(hwc_context_t *ctx,
+ hwc_display_contents_1_t *list,
+ int dpy) {
+
+ //dirty rect will enable only if
+ //1.Only single layer is updating.
+ //2.No overlapping
+ //3.No scaling
+ //4.No video layer
+ if(mSwapRectEnable == false)
+ return -1;
+ int changingLayerIndex = getLayersChanging(ctx, list, dpy);
+ //swap rect will kick in only for single updating layer
+ if(changingLayerIndex == -1){
+ return -1;
+ }
+ if(!needsScaling(&list->hwLayers[changingLayerIndex])){
+ private_handle_t *hnd =
+ (private_handle_t *)list->hwLayers[changingLayerIndex].handle;
+ if( hnd && !isYuvBuffer(hnd))
+ return changingLayerIndex;
+ }
+ return -1;
+}
+
+bool CopyBit::prepareOverlap(hwc_context_t *ctx,
+ hwc_display_contents_1_t *list) {
+
+ if (ctx->mMDP.version < qdutils::MDP_V4_0) {
+ ALOGE("%s: Invalid request", __FUNCTION__);
+ return false;
+ }
+
+ if (mEngine == NULL || !(validateParams(ctx, list))) {
+ ALOGE("%s: Invalid Params", __FUNCTION__);
+ return false;
+ }
+ PtorInfo* ptorInfo = &(ctx->mPtorInfo);
+
+ // Allocate render buffers if they're not allocated
+ int alignW = 0, alignH = 0;
+ int finalW = 0, finalH = 0;
+ for (int i = 0; i < ptorInfo->count; i++) {
+ int ovlapIndex = ptorInfo->layerIndex[i];
+ hwc_rect_t overlap = list->hwLayers[ovlapIndex].displayFrame;
+ // render buffer width will be the max of two layers
+ // Align Widht and height to 32, Mdp would be configured
+ // with Aligned overlap w/h
+ finalW = max(finalW, ALIGN((overlap.right - overlap.left), 32));
+ finalH += ALIGN((overlap.bottom - overlap.top), 32);
+ if(finalH > ALIGN((overlap.bottom - overlap.top), 32)) {
+ // Calculate the offset for RGBA(4BPP)
+ ptorInfo->mRenderBuffOffset[i] = finalW *
+ (finalH - ALIGN((overlap.bottom - overlap.top), 32)) * 4;
+ // Calculate the dest top, left will always be zero
+ ptorInfo->displayFrame[i].top = (finalH -
+ (ALIGN((overlap.bottom - overlap.top), 32)));
+ }
+ // calculate the right and bottom values
+ ptorInfo->displayFrame[i].right = ptorInfo->displayFrame[i].left +
+ (overlap.right - overlap.left);
+ ptorInfo->displayFrame[i].bottom = ptorInfo->displayFrame[i].top +
+ (overlap.bottom - overlap.top);
+ }
+
+ getBufferSizeAndDimensions(finalW, finalH, HAL_PIXEL_FORMAT_RGBA_8888,
+ alignW, alignH);
+
+ if ((mAlignedWidth != alignW) || (mAlignedHeight != alignH)) {
+ // Overlap rect has changed, so free render buffers
+ freeRenderBuffers();
+ }
+
+ int ret = allocRenderBuffers(alignW, alignH, HAL_PIXEL_FORMAT_RGBA_8888);
+
+ if (ret < 0) {
+ ALOGE("%s: Render buffer allocation failed", __FUNCTION__);
+ return false;
+ }
+
+ mAlignedWidth = alignW;
+ mAlignedHeight = alignH;
+ mCurRenderBufferIndex = (mCurRenderBufferIndex + 1) % NUM_RENDER_BUFFERS;
+ return true;
+}
+
bool CopyBit::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list,
int dpy) {
@@ -195,8 +333,8 @@
__FUNCTION__, dst_w,src_w,dst_h,src_h);
return false;
}
- dx = (float)dst_w/src_w;
- dy = (float)dst_h/src_h;
+ dx = (float)dst_w/(float)src_w;
+ dy = (float)dst_h/(float)src_h;
if (dx > MAX_SCALE_FACTOR || dx < MIN_SCALE_FACTOR)
return false;
@@ -209,8 +347,8 @@
//Allocate render buffers if they're not allocated
if (ctx->mMDP.version != qdutils::MDP_V3_0_4 &&
(useCopybitForYUV || useCopybitForRGB)) {
- int ret = allocRenderBuffers(mAlignedFBWidth,
- mAlignedFBHeight,
+ int ret = allocRenderBuffers(mAlignedWidth,
+ mAlignedHeight,
HAL_PIXEL_FORMAT_RGBA_8888);
if (ret < 0) {
return false;
@@ -232,11 +370,11 @@
// Mark all layers to be drawn by copybit
for (int i = ctx->listStats[dpy].numAppLayers-1; i >= 0 ; i--) {
layerProp[i].mFlags |= HWC_COPYBIT;
- if (ctx->mMDP.version == qdutils::MDP_V3_0_4) {
- LOG_ALWAYS_FATAL("Cannot handle HWC_BLIT");
- //list->hwLayers[i].compositionType = HWC_BLIT;
- }
+#ifdef QCOM_BSP
+ if (ctx->mMDP.version == qdutils::MDP_V3_0_4)
+ list->hwLayers[i].compositionType = HWC_BLIT;
else
+#endif
list->hwLayers[i].compositionType = HWC_OVERLAY;
}
}
@@ -263,8 +401,81 @@
return ret;
}
-bool CopyBit::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
- int dpy, int32_t *fd) {
+bool CopyBit::drawUsingAppBufferComposition(hwc_context_t *ctx,
+ hwc_display_contents_1_t *list,
+ int dpy, int *copybitFd) {
+ int layerCount = 0;
+ uint32_t last = (uint32_t)list->numHwLayers - 1;
+ hwc_layer_1_t *fbLayer = &list->hwLayers[last];
+ private_handle_t *fbhnd = (private_handle_t *)fbLayer->handle;
+
+ if(ctx->enableABC == false)
+ return false;
+
+ if(ctx->listStats[dpy].numAppLayers > MAX_LAYERS_FOR_ABC )
+ return false;
+
+ layerCount = ctx->listStats[dpy].numAppLayers;
+ //bottom most layer should
+ //equal to FB
+ hwc_layer_1_t *tmpLayer = &list->hwLayers[0];
+ private_handle_t *hnd = (private_handle_t *)tmpLayer->handle;
+ if(hnd && fbhnd && (hnd->size == fbhnd->size) &&
+ (hnd->width == fbhnd->width) && (hnd->height == fbhnd->height)){
+ if(tmpLayer->transform ||
+ (!(hnd->format == HAL_PIXEL_FORMAT_RGBA_8888 ||
+ hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)) ||
+ (needsScaling(tmpLayer) == true)) {
+ return false;
+ }else {
+ ctx->listStats[dpy].renderBufIndexforABC = 0;
+ }
+ }
+
+ if(ctx->listStats[dpy].renderBufIndexforABC == 0) {
+ if(layerCount == 1)
+ return true;
+
+ if(layerCount == MAX_LAYERS_FOR_ABC) {
+ int abcRenderBufIdx = ctx->listStats[dpy].renderBufIndexforABC;
+ //enable ABC only for non intersecting layers.
+ hwc_rect_t displayFrame =
+ list->hwLayers[abcRenderBufIdx].displayFrame;
+ for (int i = abcRenderBufIdx + 1; i < layerCount; i++) {
+ hwc_rect_t tmpDisplayFrame = list->hwLayers[i].displayFrame;
+ hwc_rect_t result = getIntersection(displayFrame,tmpDisplayFrame);
+ if (isValidRect(result)) {
+ ctx->listStats[dpy].renderBufIndexforABC = -1;
+ return false;
+ }
+ }
+ // Pass the Acquire Fence FD to driver for base layer
+ private_handle_t *renderBuffer =
+ (private_handle_t *)list->hwLayers[abcRenderBufIdx].handle;
+ copybit_device_t *copybit = getCopyBitDevice();
+ if(list->hwLayers[abcRenderBufIdx].acquireFenceFd >=0){
+ copybit->set_sync(copybit,
+ list->hwLayers[abcRenderBufIdx].acquireFenceFd);
+ }
+ for(int i = abcRenderBufIdx + 1; i < layerCount; i++){
+ int retVal = drawLayerUsingCopybit(ctx,
+ &(list->hwLayers[i]),renderBuffer, 0);
+ if(retVal < 0) {
+ ALOGE("%s : Copybit failed", __FUNCTION__);
+ }
+ }
+ // Get Release Fence FD of copybit for the App layer(s)
+ copybit->flush_get_fence(copybit, copybitFd);
+ close(list->hwLayers[abcRenderBufIdx].acquireFenceFd);
+ list->hwLayers[abcRenderBufIdx].acquireFenceFd = -1;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool CopyBit::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+ int dpy, int32_t *fd) {
// draw layers marked for COPYBIT
int retVal = true;
int copybitLayerCount = 0;
@@ -272,12 +483,17 @@
LayerProp *layerProp = ctx->layerProp[dpy];
private_handle_t *renderBuffer;
- if(mCopyBitDraw == false) // there is no layer marked for copybit
- return false ;
+ if(mCopyBitDraw == false){
+ mFbCache.reset(); // there is no layer marked for copybit
+ return false ;
+ }
+ if(drawUsingAppBufferComposition(ctx, list, dpy, fd)) {
+ return true;
+ }
//render buffer
if (ctx->mMDP.version == qdutils::MDP_V3_0_4) {
- last = list->numHwLayers - 1;
+ last = (uint32_t)list->numHwLayers - 1;
renderBuffer = (private_handle_t *)list->hwLayers[last].handle;
} else {
renderBuffer = getCurrentRenderBuffer();
@@ -301,21 +517,29 @@
}
}
- //Clear the transparent or left out region on the render buffer
- hwc_rect_t clearRegion = {0,0,0,0};
- if(CBUtils::getuiClearRegion(list, clearRegion, layerProp))
- clear(renderBuffer, clearRegion);
+ mDirtyLayerIndex = checkDirtyRect(ctx, list, dpy);
+ if( mDirtyLayerIndex != -1){
+ hwc_layer_1_t *layer = &list->hwLayers[mDirtyLayerIndex];
+#ifdef QCOM_BSP
+ clear(renderBuffer,layer->dirtyRect);
+#else
+ clear(renderBuffer,layer->displayFrame);
+#endif
+ } else {
+ hwc_rect_t clearRegion = {0,0,0,0};
+ if(CBUtils::getuiClearRegion(list, clearRegion, layerProp))
+ clear(renderBuffer, clearRegion);
+ }
// numAppLayers-1, as we iterate from 0th layer index with HWC_COPYBIT flag
for (int i = 0; i <= (ctx->listStats[dpy].numAppLayers-1); i++) {
- hwc_layer_1_t *layer = &list->hwLayers[i];
if(!(layerProp[i].mFlags & HWC_COPYBIT)) {
ALOGD_IF(DEBUG_COPYBIT, "%s: Not Marked for copybit", __FUNCTION__);
continue;
}
- if(layer->flags & HWC_SKIP_HWC_COMPOSITION){
+ //skip non updating layers
+ if((mDirtyLayerIndex != -1) && (mDirtyLayerIndex != i) )
continue;
- }
int ret = -1;
if (list->hwLayers[i].acquireFenceFd != -1
&& ctx->mMDP.version >= qdutils::MDP_V4_0) {
@@ -329,7 +553,7 @@
list->hwLayers[i].acquireFenceFd = -1;
}
retVal = drawLayerUsingCopybit(ctx, &(list->hwLayers[i]),
- renderBuffer, !i);
+ renderBuffer, !i);
copybitLayerCount++;
if(retVal < 0) {
ALOGE("%s : drawLayerUsingCopybit failed", __FUNCTION__);
@@ -349,6 +573,149 @@
return true;
}
+int CopyBit::drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
+ int fd = -1;
+ PtorInfo* ptorInfo = &(ctx->mPtorInfo);
+
+ if (ctx->mMDP.version < qdutils::MDP_V4_0) {
+ ALOGE("%s: Invalid request", __FUNCTION__);
+ return fd;
+ }
+
+ private_handle_t *renderBuffer = getCurrentRenderBuffer();
+
+ if (!renderBuffer) {
+ ALOGE("%s: Render buffer layer handle is NULL", __FUNCTION__);
+ return fd;
+ }
+
+ int copybitLayerCount = 0;
+ for(int j = 0; j < ptorInfo->count; j++) {
+ int ovlapIndex = ptorInfo->layerIndex[j];
+ hwc_rect_t overlap = list->hwLayers[ovlapIndex].displayFrame;
+
+ // Draw overlapped content of layers on render buffer
+ for (int i = 0; i <= ovlapIndex; i++) {
+ hwc_layer_1_t *layer = &list->hwLayers[i];
+ if(!isValidRect(getIntersection(layer->displayFrame,
+ overlap))) {
+ continue;
+ }
+ if ((list->hwLayers[i].acquireFenceFd != -1)) {
+ // Wait for acquire fence on the App buffers.
+ if(sync_wait(list->hwLayers[i].acquireFenceFd, 1000) < 0) {
+ ALOGE("%s: sync_wait error!! error no = %d err str = %s",
+ __FUNCTION__, errno, strerror(errno));
+ }
+ close(list->hwLayers[i].acquireFenceFd);
+ list->hwLayers[i].acquireFenceFd = -1;
+ }
+
+ int retVal = drawRectUsingCopybit(ctx, layer, renderBuffer, overlap,
+ ptorInfo->displayFrame[j]);
+ copybitLayerCount++;
+ if(retVal < 0) {
+ ALOGE("%s: drawRectUsingCopybit failed", __FUNCTION__);
+ copybitLayerCount = 0;
+ }
+ }
+ }
+
+ if (copybitLayerCount) {
+ copybit_device_t *copybit = getCopyBitDevice();
+ copybit->flush_get_fence(copybit, &fd);
+ }
+
+ ALOGD_IF(DEBUG_COPYBIT, "%s: done! copybitLayerCount = %d", __FUNCTION__,
+ copybitLayerCount);
+ return fd;
+}
+
+int CopyBit::drawRectUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
+ private_handle_t *renderBuffer, hwc_rect_t overlap,
+ hwc_rect_t destRect)
+{
+ hwc_context_t* ctx = (hwc_context_t*)(dev);
+ if (!ctx) {
+ ALOGE("%s: null context ", __FUNCTION__);
+ return -1;
+ }
+
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ if (!hnd) {
+ ALOGE("%s: invalid handle", __FUNCTION__);
+ return -1;
+ }
+
+ private_handle_t *dstHandle = (private_handle_t *)renderBuffer;
+ if (!dstHandle) {
+ ALOGE("%s: RenderBuffer handle is NULL", __FUNCTION__);
+ return -1;
+ }
+
+ // Set the Copybit Source
+ copybit_image_t src;
+ src.handle = (native_handle_t *)layer->handle;
+ src.w = hnd->width;
+ src.h = hnd->height;
+ src.base = (void *)hnd->base;
+ src.format = hnd->format;
+ src.horiz_padding = 0;
+ src.vert_padding = 0;
+
+
+ hwc_rect_t dispFrame = layer->displayFrame;
+ hwc_rect_t iRect = getIntersection(dispFrame, overlap);
+ hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
+ qhwc::calculate_crop_rects(crop, dispFrame, iRect,
+ layer->transform);
+
+ // Copybit source rect
+ copybit_rect_t srcRect = {crop.left, crop.top, crop.right,
+ crop.bottom};
+
+ // Copybit destination rect
+ copybit_rect_t dstRect = {destRect.left, destRect.top, destRect.right,
+ destRect.bottom};
+
+ // Copybit dst
+ copybit_image_t dst;
+ dst.handle = (native_handle_t *)dstHandle;
+ dst.w = ALIGN(dstHandle->width, 32);
+ dst.h = dstHandle->height;
+ dst.base = (void *)dstHandle->base;
+ dst.format = dstHandle->format;
+
+ copybit_device_t *copybit = mEngine;
+
+ // Copybit region is the destRect
+ hwc_rect_t regRect = {dstRect.l,dstRect.t, dstRect.r, dstRect.b};
+ hwc_region_t region;
+ region.numRects = 1;
+ region.rects = ®Rect;
+ region_iterator copybitRegion(region);
+ int acquireFd = layer->acquireFenceFd;
+
+ 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->planeAlpha);
+ copybit->set_parameter(copybit, COPYBIT_BLEND_MODE, layer->blending);
+ copybit->set_parameter(copybit, COPYBIT_DITHER,
+ (dst.format == HAL_PIXEL_FORMAT_RGB_565) ? COPYBIT_ENABLE :
+ COPYBIT_DISABLE);
+ copybit->set_sync(copybit, acquireFd);
+ int err = copybit->stretch(copybit, &dst, &src, &dstRect, &srcRect,
+ ©bitRegion);
+
+ if (err < 0)
+ ALOGE("%s: copybit stretch failed",__FUNCTION__);
+
+ return err;
+}
+
int CopyBit::drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
private_handle_t *renderBuffer, bool isFG)
{
@@ -429,7 +796,16 @@
copybit_rect_t dstRect = {displayFrame.left, displayFrame.top,
displayFrame.right,
displayFrame.bottom};
-
+#ifdef QCOM_BSP
+ //change src and dst with dirtyRect
+ if(mDirtyLayerIndex != -1) {
+ srcRect.l = layer->dirtyRect.left;
+ srcRect.t = layer->dirtyRect.top;
+ srcRect.r = layer->dirtyRect.right;
+ srcRect.b = layer->dirtyRect.bottom;
+ dstRect = srcRect;
+ }
+#endif
// Copybit dst
copybit_image_t dst;
dst.w = ALIGN(fbHandle->width,32);
@@ -466,8 +842,8 @@
return -1;
}
- float dsdx = (float)screen_w/src_crop_width;
- float dtdy = (float)screen_h/src_crop_height;
+ float dsdx = (float)screen_w/(float)src_crop_width;
+ float dtdy = (float)screen_h/(float)src_crop_height;
float scaleLimitMax = copybitsMaxScale * copybitsMaxScale;
float scaleLimitMin = copybitsMinScale * copybitsMinScale;
@@ -498,14 +874,14 @@
int tmp_h = src_crop_height;
if (dsdx > copybitsMaxScale || dtdy > copybitsMaxScale ){
- tmp_w = src_crop_width*copybitsMaxScale;
- tmp_h = src_crop_height*copybitsMaxScale;
+ tmp_w = (int)((float)src_crop_width*copybitsMaxScale);
+ tmp_h = (int)((float)src_crop_height*copybitsMaxScale);
}else if (dsdx < 1/copybitsMinScale ||dtdy < 1/copybitsMinScale ){
// ceil the tmp_w and tmp_h value to maintain proper ratio
// b/w src and dst (should not cross the desired scale limit
// due to float -> int )
- tmp_w = ceil(src_crop_width/copybitsMinScale);
- tmp_h = ceil(src_crop_height/copybitsMinScale);
+ tmp_w = (int)ceil((float)src_crop_width/copybitsMinScale);
+ tmp_h = (int)ceil((float)src_crop_height/copybitsMinScale);
}
ALOGD("%s:%d::tmp_w = %d,tmp_h = %d",__FUNCTION__,__LINE__,tmp_w,tmp_h);
@@ -710,18 +1086,30 @@
mRelFd[mCurRenderBufferIndex] = dup(fd);
}
+void CopyBit::setReleaseFdSync(int fd) {
+ if (mRelFd[mCurRenderBufferIndex] >=0) {
+ int ret = -1;
+ ret = sync_wait(mRelFd[mCurRenderBufferIndex], 1000);
+ if (ret < 0)
+ ALOGE("%s: sync_wait error! errno = %d, err str = %s",
+ __FUNCTION__, errno, strerror(errno));
+ close(mRelFd[mCurRenderBufferIndex]);
+ }
+ mRelFd[mCurRenderBufferIndex] = dup(fd);
+}
+
struct copybit_device_t* CopyBit::getCopyBitDevice() {
return mEngine;
}
-CopyBit::CopyBit(hwc_context_t *ctx, const int& dpy) : mIsModeOn(false),
- mCopyBitDraw(false), mCurRenderBufferIndex(0) {
+CopyBit::CopyBit(hwc_context_t *ctx, const int& dpy) : mEngine(0),
+ mIsModeOn(false), mCopyBitDraw(false), mCurRenderBufferIndex(0) {
getBufferSizeAndDimensions(ctx->dpyAttr[dpy].xres,
ctx->dpyAttr[dpy].yres,
HAL_PIXEL_FORMAT_RGBA_8888,
- mAlignedFBWidth,
- mAlignedFBHeight);
+ mAlignedWidth,
+ mAlignedHeight);
hw_module_t const *module;
for (int i = 0; i < NUM_RENDER_BUFFERS; i++) {
@@ -733,6 +1121,9 @@
property_get("debug.hwc.dynThreshold", value, "2");
mDynThreshold = atof(value);
+ property_get("debug.sf.swaprect", value, "0");
+ mSwapRectEnable = atoi(value) ? true:false ;
+ mDirtyLayerIndex = -1;
if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
if(copybit_open(module, &mEngine) < 0) {
ALOGE("FATAL ERROR: copybit open failed.");
@@ -751,4 +1142,43 @@
mEngine = NULL;
}
}
+CopyBit::LayerCache::LayerCache() {
+ reset();
+}
+void CopyBit::LayerCache::reset() {
+ memset(&hnd, 0, sizeof(hnd));
+ layerCount = 0;
+}
+void CopyBit::LayerCache::updateCounts(hwc_context_t *ctx,
+ hwc_display_contents_1_t *list, int dpy)
+{
+ layerCount = ctx->listStats[dpy].numAppLayers;
+ for (int i=0; i<ctx->listStats[dpy].numAppLayers; i++){
+ hnd[i] = list->hwLayers[i].handle;
+ }
+}
+
+CopyBit::FbCache::FbCache() {
+ reset();
+}
+void CopyBit::FbCache::reset() {
+ memset(&FbdirtyRect, 0, sizeof(FbdirtyRect));
+ FbIndex =0;
+}
+
+void CopyBit::FbCache::insertAndUpdateFbCache(hwc_rect_t dirtyRect) {
+ FbIndex = FbIndex % NUM_RENDER_BUFFERS;
+ FbdirtyRect[FbIndex] = dirtyRect;
+ FbIndex++;
+}
+
+int CopyBit::FbCache::getUnchangedFbDRCount(hwc_rect_t dirtyRect){
+ int sameDirtyCount = 0;
+ for (int i = 0 ; i < NUM_RENDER_BUFFERS ; i++ ){
+ if( FbdirtyRect[i] == dirtyRect)
+ sameDirtyCount++;
+ }
+ return sameDirtyCount;
+}
+
}; //namespace qhwc
diff --git a/msm8226/libhwcomposer/hwc_copybit.h b/msm8226/libhwcomposer/hwc_copybit.h
index f7be644..99a39c8 100644
--- a/msm8226/libhwcomposer/hwc_copybit.h
+++ b/msm8226/libhwcomposer/hwc_copybit.h
@@ -27,7 +27,7 @@
//twice
#define MAX_SCALE_FACTOR 16
#define MIN_SCALE_FACTOR 0.0625
-
+#define MAX_LAYERS_FOR_ABC 2
namespace qhwc {
class CopyBit {
@@ -49,12 +49,46 @@
void setReleaseFd(int fd);
+ void setReleaseFdSync(int fd);
+
+ bool prepareOverlap(hwc_context_t *ctx, hwc_display_contents_1_t *list);
+
+ int drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t *list);
+
private:
+ /* cached data */
+ struct LayerCache {
+ int layerCount;
+ buffer_handle_t hnd[MAX_NUM_APP_LAYERS];
+ /* c'tor */
+ LayerCache();
+ /* clear caching info*/
+ void reset();
+ void updateCounts(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+ int dpy);
+ };
+ /* framebuffer cache*/
+ struct FbCache {
+ hwc_rect_t FbdirtyRect[NUM_RENDER_BUFFERS];
+ int FbIndex;
+ FbCache();
+ void reset();
+ void insertAndUpdateFbCache(hwc_rect_t dirtyRect);
+ int getUnchangedFbDRCount(hwc_rect_t dirtyRect);
+ };
+
// holds the copybit device
struct copybit_device_t *mEngine;
+ bool drawUsingAppBufferComposition(hwc_context_t *ctx,
+ hwc_display_contents_1_t *list,
+ int dpy, int *fd);
// Helper functions for copybit composition
int drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
private_handle_t *renderBuffer, bool isFG);
+ // Helper function to draw copybit layer for PTOR comp
+ int drawRectUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
+ private_handle_t *renderBuffer, hwc_rect_t overlap,
+ hwc_rect_t destRect);
int fillColorUsingCopybit(hwc_layer_1_t *layer,
private_handle_t *renderBuffer);
bool canUseCopybitForYUV (hwc_context_t *ctx);
@@ -89,8 +123,16 @@
//Dynamic composition threshold for deciding copybit usage.
double mDynThreshold;
- int mAlignedFBWidth;
- int mAlignedFBHeight;
+ bool mSwapRectEnable;
+ int mAlignedWidth;
+ int mAlignedHeight;
+ int mDirtyLayerIndex;
+ LayerCache mLayerCache;
+ FbCache mFbCache;
+ int getLayersChanging(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+ int dpy);
+ int checkDirtyRect(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+ int dpy);
};
}; //namespace qhwc
diff --git a/msm8226/libhwcomposer/hwc_dump_layers.cpp b/msm8226/libhwcomposer/hwc_dump_layers.cpp
index b7bc731..c8ebac9 100644
--- a/msm8226/libhwcomposer/hwc_dump_layers.cpp
+++ b/msm8226/libhwcomposer/hwc_dump_layers.cpp
@@ -36,6 +36,10 @@
#include <cutils/log.h>
#include <sys/stat.h>
#include <comptype.h>
+#ifdef QCOM_BSP
+#include <SkBitmap.h>
+#include <SkImageEncoder.h>
+#endif
#ifdef STDC_FORMAT_MACROS
#include <inttypes.h>
#endif
@@ -209,7 +213,7 @@
void HwcDebug::logLayer(size_t layerIndex, hwc_layer_1_t hwLayers[])
{
if (NULL == hwLayers) {
- ALOGE("Display[%s] Layer[%d] Error. No hwc layers to log.",
+ ALOGE("Display[%s] Layer[%zu] Error. No hwc layers to log.",
mDisplayName, layerIndex);
return;
}
@@ -236,7 +240,7 @@
getHalPixelFormatStr(hnd->format, pixFormatStr);
// Log Line 1
- ALOGI("Display[%s] Layer[%d] SrcBuff[%dx%d] SrcCrop[%dl, %dt, %dr, %db] "
+ ALOGI("Display[%s] Layer[%zu] SrcBuff[%dx%d] SrcCrop[%dl, %dt, %dr, %db] "
"DispFrame[%dl, %dt, %dr, %db] VisRegsScr%s", mDisplayName, layerIndex,
(hnd)? getWidth(hnd) : -1, (hnd)? getHeight(hnd) : -1,
sourceCrop.left, sourceCrop.top,
@@ -245,7 +249,7 @@
displayFrame.right, displayFrame.bottom,
hwcVisRegsScrLog.string());
// Log Line 2
- ALOGI("Display[%s] Layer[%d] LayerCompType = %s, Format = %s, "
+ ALOGI("Display[%s] Layer[%zu] LayerCompType = %s, Format = %s, "
"Orientation = %s, Flags = %s%s%s, Hints = %s%s%s, "
"Blending = %s%s%s", mDisplayName, layerIndex,
(layer->compositionType == HWC_FRAMEBUFFER)? "Framebuffer(GPU)":
@@ -272,19 +276,25 @@
{
char dumpLogStrPng[128] = "";
char dumpLogStrRaw[128] = "";
+ bool needDumpPng = (mDumpCntrPng <= mDumpCntLimPng)? true:false;
bool needDumpRaw = (mDumpCntrRaw <= mDumpCntLimRaw)? true:false;
+ if (needDumpPng) {
+ snprintf(dumpLogStrPng, sizeof(dumpLogStrPng),
+ "[png-dump-frame: %03d of %03d]", mDumpCntrPng,
+ mDumpCntLimPng);
+ }
if (needDumpRaw) {
snprintf(dumpLogStrRaw, sizeof(dumpLogStrRaw),
"[raw-dump-frame: %03d of %03d]", mDumpCntrRaw,
mDumpCntLimRaw);
}
- if (!needDumpRaw)
+ if (!(needDumpPng || needDumpRaw))
return;
if (NULL == hwLayers) {
- ALOGE("Display[%s] Layer[%d] %s%s Error: No hwc layers to dump.",
+ ALOGE("Display[%s] Layer[%zu] %s%s Error: No hwc layers to dump.",
mDisplayName, layerIndex, dumpLogStrRaw, dumpLogStrPng);
return;
}
@@ -294,18 +304,57 @@
char pixFormatStr[32] = "None";
if (NULL == hnd) {
- ALOGI("Display[%s] Layer[%d] %s%s Skipping dump: Bufferless layer.",
+ ALOGI("Display[%s] Layer[%zu] %s%s Skipping dump: Bufferless layer.",
mDisplayName, layerIndex, dumpLogStrRaw, dumpLogStrPng);
return;
}
getHalPixelFormatStr(hnd->format, pixFormatStr);
+#ifdef QCOM_BSP
+ if (needDumpPng && hnd->base) {
+ bool bResult = false;
+ char dumpFilename[PATH_MAX];
+ SkBitmap *tempSkBmp = new SkBitmap();
+ SkBitmap::Config tempSkBmpConfig = SkBitmap::kNo_Config;
+ snprintf(dumpFilename, sizeof(dumpFilename),
+ "%s/sfdump%03d.layer%zu.%s.png", mDumpDirPng,
+ mDumpCntrPng, layerIndex, mDisplayName);
+ switch (hnd->format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ tempSkBmpConfig = SkBitmap::kARGB_8888_Config;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ tempSkBmpConfig = SkBitmap::kRGB_565_Config;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_888:
+ default:
+ tempSkBmpConfig = SkBitmap::kNo_Config;
+ break;
+ }
+ if (SkBitmap::kNo_Config != tempSkBmpConfig) {
+ tempSkBmp->setConfig(tempSkBmpConfig, getWidth(hnd), getHeight(hnd));
+ tempSkBmp->setPixels((void*)hnd->base);
+ bResult = SkImageEncoder::EncodeFile(dumpFilename,
+ *tempSkBmp, SkImageEncoder::kPNG_Type, 100);
+ ALOGI("Display[%s] Layer[%zu] %s Dump to %s: %s",
+ mDisplayName, layerIndex, dumpLogStrPng,
+ dumpFilename, bResult ? "Success" : "Fail");
+ } else {
+ ALOGI("Display[%s] Layer[%zu] %s Skipping dump: Unsupported layer"
+ " format %s for png encoder",
+ mDisplayName, layerIndex, dumpLogStrPng, pixFormatStr);
+ }
+ delete tempSkBmp; // Calls SkBitmap::freePixels() internally.
+ }
+#endif
if (needDumpRaw && hnd->base) {
char dumpFilename[PATH_MAX];
bool bResult = false;
snprintf(dumpFilename, sizeof(dumpFilename),
- "%s/sfdump%03d.layer%d.%dx%d.%s.%s.raw",
+ "%s/sfdump%03d.layer%zu.%dx%d.%s.%s.raw",
mDumpDirRaw, mDumpCntrRaw,
layerIndex, getWidth(hnd), getHeight(hnd),
pixFormatStr, mDisplayName);
@@ -314,7 +363,7 @@
bResult = (bool) fwrite((void*)hnd->base, hnd->size, 1, fp);
fclose(fp);
}
- ALOGI("Display[%s] Layer[%d] %s Dump to %s: %s",
+ ALOGI("Display[%s] Layer[%zu] %s Dump to %s: %s",
mDisplayName, layerIndex, dumpLogStrRaw,
dumpFilename, bResult ? "Success" : "Fail");
}
@@ -385,7 +434,8 @@
strlcpy(pixFormatStr, "YCbCr_420_SP_VENUS", sizeof(pixFormatStr));
break;
default:
- snprintf(pixFormatStr, sizeof(pixFormatStr), "Unknown0x%X", format);
+ size_t len = sizeof(pixFormatStr);
+ snprintf(pixFormatStr, len, "Unknown0x%X", format);
break;
}
}
diff --git a/msm8226/libhwcomposer/hwc_fbupdate.cpp b/msm8226/libhwcomposer/hwc_fbupdate.cpp
index bf2aee5..de4cd05 100644
--- a/msm8226/libhwcomposer/hwc_fbupdate.cpp
+++ b/msm8226/libhwcomposer/hwc_fbupdate.cpp
@@ -38,19 +38,25 @@
namespace ovutils = overlay::utils;
IFBUpdate* IFBUpdate::getObject(hwc_context_t *ctx, const int& dpy) {
- if(isDisplaySplit(ctx, dpy)) {
- if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
- return new FBSrcSplit(ctx, dpy);
- }
+ if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
+ return new FBSrcSplit(ctx, dpy);
+ } else if(isDisplaySplit(ctx, dpy)) {
return new FBUpdateSplit(ctx, dpy);
}
return new FBUpdateNonSplit(ctx, dpy);
}
IFBUpdate::IFBUpdate(hwc_context_t *ctx, const int& dpy) : mDpy(dpy) {
- size_t size = 0;
- getBufferAttributes(ctx->dpyAttr[mDpy].xres,
- ctx->dpyAttr[mDpy].yres,
+ unsigned int size = 0;
+ uint32_t xres = ctx->dpyAttr[mDpy].xres;
+ uint32_t yres = ctx->dpyAttr[mDpy].yres;
+ if (ctx->dpyAttr[dpy].customFBSize) {
+ //GPU will render and compose at new resolution
+ //So need to have FB at new resolution
+ xres = ctx->dpyAttr[mDpy].xres_new;
+ yres = ctx->dpyAttr[mDpy].yres_new;
+ }
+ getBufferAttributes((int)xres, (int)yres,
HAL_PIXEL_FORMAT_RGBA_8888,
0,
mAlignedFBWidth,
@@ -66,8 +72,9 @@
bool IFBUpdate::prepareAndValidate(hwc_context_t *ctx,
hwc_display_contents_1 *list, int fbZorder) {
hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
- return prepare(ctx, list, layer->displayFrame, fbZorder) &&
+ mModeOn = prepare(ctx, list, layer->displayFrame, fbZorder) &&
ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd);
+ return mModeOn;
}
//================= Low res====================================
@@ -91,6 +98,7 @@
if(mDpy && (extOrient & HWC_TRANSFORM_ROT_90)) {
mRot = ctx->mRotMgr->getNext();
if(mRot == NULL) return false;
+ ctx->mLayerRotMap[mDpy]->add(layer, mRot);
// Composed FB content will have black bars, if the viewFrame of the
// external is different from {0, 0, fbWidth, fbHeight}, so intersect
// viewFrame with sourceCrop to avoid those black bars
@@ -101,9 +109,7 @@
mRot = NULL;
return false;
}
- ctx->mLayerRotMap[mDpy]->add(layer, mRot);
- info.format = (mRot)->getDstFormat();
- updateSource(orient, info, sourceCrop);
+ updateSource(orient, info, sourceCrop, mRot);
rotFlags |= ovutils::ROT_PREROTATED;
}
return true;
@@ -138,14 +144,14 @@
ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888,
mTileEnabled));
- //Request a pipe
- ovutils::eMdpPipeType type = ovutils::OV_MDP_PIPE_ANY;
- if((qdutils::MDPVersion::getInstance().is8x26() ||
- qdutils::MDPVersion::getInstance().is8x16()) && mDpy) {
- //For 8x26 external always use DMA pipe
- type = ovutils::OV_MDP_PIPE_DMA;
- }
- ovutils::eDest dest = ov.nextPipe(type, mDpy, Overlay::MIXER_DEFAULT);
+ Overlay::PipeSpecs pipeSpecs;
+ pipeSpecs.formatClass = Overlay::FORMAT_RGB;
+ pipeSpecs.needsScaling = qhwc::needsScaling(layer);
+ pipeSpecs.dpy = mDpy;
+ pipeSpecs.mixer = Overlay::MIXER_DEFAULT;
+ pipeSpecs.fb = true;
+
+ ovutils::eDest dest = ov.getPipe(pipeSpecs);
if(dest == ovutils::OV_INVALID) { //None available
ALOGE("%s: No pipes available to configure fb for dpy %d",
__FUNCTION__, mDpy);
@@ -191,7 +197,7 @@
(mDpy && !extOrient
&& !ctx->dpyAttr[mDpy].mDownScaleMode))
&& (extOnlyLayerIndex == -1)) {
- if(!qdutils::MDPVersion::getInstance().is8x26() &&
+ if(ctx->mOverlay->isUIScalingOnExternalSupported() &&
!ctx->dpyAttr[mDpy].customFBSize) {
getNonWormholeRegion(list, sourceCrop);
displayFrame = sourceCrop;
@@ -201,14 +207,12 @@
transform, orient);
//Store the displayFrame, will be used in getDisplayViewFrame
ctx->dpyAttr[mDpy].mDstRect = displayFrame;
- setMdpFlags(layer, mdpFlags, 0, transform);
+ setMdpFlags(ctx, layer, mdpFlags, 0, transform);
// For External use rotator if there is a rotation value set
ret = preRotateExtDisplay(ctx, layer, info,
sourceCrop, mdpFlags, rotFlags);
if(!ret) {
ALOGE("%s: preRotate for external Failed!", __FUNCTION__);
- ctx->mOverlay->clear(mDpy);
- ctx->mLayerRotMap[mDpy]->clear();
return false;
}
//For the mdp, since either we are pre-rotating or MDP does flips
@@ -223,7 +227,6 @@
if(configMdp(ctx->mOverlay, parg, orient, sourceCrop, displayFrame,
NULL, mDest) < 0) {
ALOGE("%s: configMdp failed for dpy %d", __FUNCTION__, mDpy);
- ctx->mLayerRotMap[mDpy]->clear();
ret = false;
}
}
@@ -239,7 +242,7 @@
overlay::Overlay& ov = *(ctx->mOverlay);
ovutils::eDest dest = mDest;
int fd = hnd->fd;
- uint32_t offset = hnd->offset;
+ uint32_t offset = (uint32_t)hnd->offset;
if(mRot) {
if(!mRot->queueBuffer(fd, offset))
return false;
@@ -271,8 +274,8 @@
__FUNCTION__);
return false;
}
- ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn);
mModeOn = configure(ctx, list, fbUpdatingRect, fbZorder);
+ ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn);
return mModeOn;
}
@@ -307,10 +310,16 @@
hwc_rect_t displayFrame = fbUpdatingRect;
ret = true;
+ Overlay::PipeSpecs pipeSpecs;
+ pipeSpecs.formatClass = Overlay::FORMAT_RGB;
+ pipeSpecs.needsScaling = qhwc::needsScaling(layer);
+ pipeSpecs.dpy = mDpy;
+ pipeSpecs.fb = true;
+
/* Configure left pipe */
if(displayFrame.left < lSplit) {
- ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy,
- Overlay::MIXER_LEFT);
+ pipeSpecs.mixer = Overlay::MIXER_LEFT;
+ ovutils::eDest destL = ov.getPipe(pipeSpecs);
if(destL == ovutils::OV_INVALID) { //None available
ALOGE("%s: No pipes available to configure fb for dpy %d's left"
" mixer", __FUNCTION__, mDpy);
@@ -343,8 +352,8 @@
/* Configure right pipe */
if(displayFrame.right > lSplit) {
- ovutils::eDest destR = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy,
- Overlay::MIXER_RIGHT);
+ pipeSpecs.mixer = Overlay::MIXER_RIGHT;
+ ovutils::eDest destR = ov.getPipe(pipeSpecs);
if(destR == ovutils::OV_INVALID) { //None available
ALOGE("%s: No pipes available to configure fb for dpy %d's"
" right mixer", __FUNCTION__, mDpy);
@@ -380,10 +389,6 @@
ret = false;
}
}
-
- if(ret == false) {
- ctx->mLayerRotMap[mDpy]->clear();
- }
}
return ret;
}
@@ -396,14 +401,14 @@
bool ret = true;
overlay::Overlay& ov = *(ctx->mOverlay);
if(mDestLeft != ovutils::OV_INVALID) {
- if (!ov.queueBuffer(hnd->fd, hnd->offset, mDestLeft)) {
+ if (!ov.queueBuffer(hnd->fd, (uint32_t)hnd->offset, mDestLeft)) {
ALOGE("%s: queue failed for left of dpy = %d",
__FUNCTION__, mDpy);
ret = false;
}
}
if(mDestRight != ovutils::OV_INVALID) {
- if (!ov.queueBuffer(hnd->fd, hnd->offset, mDestRight)) {
+ if (!ov.queueBuffer(hnd->fd, (uint32_t)hnd->offset, mDestRight)) {
ALOGE("%s: queue failed for right of dpy = %d",
__FUNCTION__, mDpy);
ret = false;
@@ -418,7 +423,6 @@
bool FBSrcSplit::configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
hwc_rect_t fbUpdatingRect, int fbZorder) {
- bool ret = false;
hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
int extOnlyLayerIndex = ctx->listStats[mDpy].extOnlyLayerIndex;
// ext only layer present..
@@ -426,35 +430,13 @@
layer = &list->hwLayers[extOnlyLayerIndex];
layer->compositionType = HWC_OVERLAY;
}
+
overlay::Overlay& ov = *(ctx->mOverlay);
ovutils::Whf info(mAlignedFBWidth,
mAlignedFBHeight,
ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888,
mTileEnabled));
- //Request left pipe, VG first owing to higher prio
- ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, mDpy,
- Overlay::MIXER_DEFAULT);
- if(destL == ovutils::OV_INVALID) {
- destL = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy,
- Overlay::MIXER_DEFAULT);
- if(destL == ovutils::OV_INVALID) {
- ALOGE("%s: No pipes available to configure fb for dpy %d's left"
- " mixer", __FUNCTION__, mDpy);
- return false;
- }
- }
- //Request right pipe
- ovutils::eDest destR = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy,
- Overlay::MIXER_DEFAULT);
- if(destR == ovutils::OV_INVALID) {
- ALOGE("%s: No pipes available to configure fb for dpy %d's right"
- " mixer", __FUNCTION__, mDpy);
- return false;
- }
-
- mDestLeft = destL;
- mDestRight = destR;
ovutils::eMdpFlags mdpFlags = OV_MDP_BLEND_FG_PREMULT;
ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
@@ -467,46 +449,79 @@
ovutils::DEFAULT_PLANE_ALPHA,
(ovutils::eBlending)
getBlending(layer->blending));
- ov.setSource(parg, destL);
- ov.setSource(parg, destR);
-
- //Crop and Position are same for FB
- ovutils::Dim cropPosL(
- fbUpdatingRect.left,
- fbUpdatingRect.top,
- (fbUpdatingRect.right - fbUpdatingRect.left) / 2,
- fbUpdatingRect.bottom - fbUpdatingRect.top);
-
- ovutils::Dim cropPosR(
- cropPosL.x + cropPosL.w,
- cropPosL.y,
- cropPosL.w,
- cropPosL.h);
-
- ov.setCrop(cropPosL, destL);
- ov.setCrop(cropPosR, destR);
- ov.setPosition(cropPosL, destL);
- ov.setPosition(cropPosR, destR);
int transform = layer->transform;
ovutils::eTransform orient =
static_cast<ovutils::eTransform>(transform);
- ov.setTransform(orient, destL);
- ov.setTransform(orient, destR);
- ret = true;
- if (!ov.commit(destL)) {
- ALOGE("%s: commit fails for left", __FUNCTION__);
- ret = false;
+ hwc_rect_t cropL = fbUpdatingRect;
+ hwc_rect_t cropR = fbUpdatingRect;
+
+ //Request left pipe (or 1 by default)
+ Overlay::PipeSpecs pipeSpecs;
+ pipeSpecs.formatClass = Overlay::FORMAT_RGB;
+ pipeSpecs.needsScaling = qhwc::needsScaling(layer);
+ pipeSpecs.dpy = mDpy;
+ pipeSpecs.mixer = Overlay::MIXER_DEFAULT;
+ pipeSpecs.fb = true;
+ ovutils::eDest destL = ov.getPipe(pipeSpecs);
+ if(destL == ovutils::OV_INVALID) {
+ ALOGE("%s: No pipes available to configure fb for dpy %d's left"
+ " mixer", __FUNCTION__, mDpy);
+ return false;
}
- if (!ov.commit(destR)) {
- ALOGE("%s: commit fails for right", __FUNCTION__);
- ret = false;
+
+ ovutils::eDest destR = ovutils::OV_INVALID;
+
+ /* Use 2 pipes IF
+ a) FB's width is > 2048 or
+ b) On primary, driver has indicated with caps to split always. This is
+ based on an empirically derived value of panel height.
+ */
+
+ bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and
+ qdutils::MDPVersion::getInstance().isSrcSplitAlways();
+
+ if(((fbUpdatingRect.right - fbUpdatingRect.left) >
+ qdutils::MAX_DISPLAY_DIM) or
+ primarySplitAlways) {
+ destR = ov.getPipe(pipeSpecs);
+ if(destR == ovutils::OV_INVALID) {
+ ALOGE("%s: No pipes available to configure fb for dpy %d's right"
+ " mixer", __FUNCTION__, mDpy);
+ return false;
+ }
+
+ if(ctx->mOverlay->comparePipePriority(destL, destR) == -1) {
+ qhwc::swap(destL, destR);
+ }
+
+ //Split crop equally when using 2 pipes
+ cropL.right = (fbUpdatingRect.right + fbUpdatingRect.left) / 2;
+ cropR.left = cropL.right;
}
- if(ret == false) {
- ctx->mLayerRotMap[mDpy]->clear();
+
+ mDestLeft = destL;
+ mDestRight = destR;
+
+ if(destL != OV_INVALID) {
+ if(configMdp(ctx->mOverlay, parg, orient,
+ cropL, cropL, NULL /*metadata*/, destL) < 0) {
+ ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
+ return false;
+ }
}
- return ret;
+
+ //configure right pipe
+ if(destR != OV_INVALID) {
+ if(configMdp(ctx->mOverlay, parg, orient,
+ cropR, cropR, NULL /*metadata*/, destR) < 0) {
+ ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
+ return false;
+ }
+ }
+
+ return true;
}
//---------------------------------------------------------------------
diff --git a/msm8226/libhwcomposer/hwc_mdpcomp.cpp b/msm8226/libhwcomposer/hwc_mdpcomp.cpp
index 95b477f..bbc6981 100644
--- a/msm8226/libhwcomposer/hwc_mdpcomp.cpp
+++ b/msm8226/libhwcomposer/hwc_mdpcomp.cpp
@@ -26,6 +26,7 @@
#include "hwc_fbupdate.h"
#include "hwc_ad.h"
#include <overlayRotator.h>
+#include "hwc_copybit.h"
using namespace overlay;
using namespace qdutils;
@@ -42,17 +43,15 @@
bool MDPComp::sDebugLogs = false;
bool MDPComp::sEnabled = false;
bool MDPComp::sEnableMixedMode = true;
-bool MDPComp::sEnablePartialFrameUpdate = false;
+int MDPComp::sSimulationFlags = 0;
int MDPComp::sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
bool MDPComp::sEnable4k2kYUVSplit = false;
bool MDPComp::sSrcSplitEnabled = false;
MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
-
- if(isDisplaySplit(ctx, dpy)) {
- if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
- sSrcSplitEnabled = true;
- return new MDPCompSrcSplit(dpy);
- }
+ if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
+ sSrcSplitEnabled = true;
+ return new MDPCompSrcSplit(dpy);
+ } else if(isDisplaySplit(ctx, dpy)) {
return new MDPCompSplit(dpy);
}
return new MDPCompNonSplit(dpy);
@@ -60,7 +59,7 @@
MDPComp::MDPComp(int dpy):mDpy(dpy){};
-void MDPComp::dump(android::String8& buf)
+void MDPComp::dump(android::String8& buf, hwc_context_t *ctx)
{
if(mCurrentFrame.layerCount > MAX_NUM_APP_LAYERS)
return;
@@ -74,6 +73,21 @@
dumpsys_log(buf,"needsFBRedraw:%3s pipesUsed:%2d MaxPipesPerMixer: %d \n",
(mCurrentFrame.needsRedraw? "YES" : "NO"),
mCurrentFrame.mdpCount, sMaxPipesPerMixer);
+ if(isDisplaySplit(ctx, mDpy)) {
+ dumpsys_log(buf, "Programmed ROI's: Left: [%d, %d, %d, %d] "
+ "Right: [%d, %d, %d, %d] \n",
+ ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
+ ctx->listStats[mDpy].lRoi.right,
+ ctx->listStats[mDpy].lRoi.bottom,
+ ctx->listStats[mDpy].rRoi.left,ctx->listStats[mDpy].rRoi.top,
+ ctx->listStats[mDpy].rRoi.right,
+ ctx->listStats[mDpy].rRoi.bottom);
+ } else {
+ dumpsys_log(buf, "Programmed ROI: [%d, %d, %d, %d] \n",
+ ctx->listStats[mDpy].lRoi.left,ctx->listStats[mDpy].lRoi.top,
+ ctx->listStats[mDpy].lRoi.right,
+ ctx->listStats[mDpy].lRoi.bottom);
+ }
dumpsys_log(buf," --------------------------------------------- \n");
dumpsys_log(buf," listIdx | cached? | mdpIndex | comptype | Z \n");
dumpsys_log(buf," --------------------------------------------- \n");
@@ -113,19 +127,6 @@
sEnableMixedMode = false;
}
- if(property_get("debug.mdpcomp.logs", property, NULL) > 0) {
- if(atoi(property) != 0)
- sDebugLogs = true;
- }
-
- if(property_get("persist.hwc.partialupdate", property, NULL) > 0) {
- if((atoi(property) != 0) && ctx->mMDP.panel == MIPI_CMD_PANEL &&
- qdutils::MDPVersion::getInstance().is8x74v2())
- sEnablePartialFrameUpdate = true;
- }
- ALOGE_IF(isDebug(), "%s: Partial Update applicable?: %d",__FUNCTION__,
- sEnablePartialFrameUpdate);
-
sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
if(property_get("debug.mdpcomp.maxpermixer", property, "-1") > 0) {
int val = atoi(property);
@@ -149,15 +150,25 @@
ALOGE("%s: failed to instantiate idleInvalidator object",
__FUNCTION__);
} else {
- idleInvalidator->init(timeout_handler, ctx, idle_timeout);
+ idleInvalidator->init(timeout_handler, ctx,
+ (unsigned int)idle_timeout);
}
}
- if((property_get("debug.mdpcomp.4k2kSplit", property, "0") > 0) &&
- (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
- (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+ if(!qdutils::MDPVersion::getInstance().isSrcSplit() &&
+ property_get("persist.mdpcomp.4k2kSplit", property, "0") > 0 &&
+ (!strncmp(property, "1", PROPERTY_VALUE_MAX) ||
+ !strncasecmp(property,"true", PROPERTY_VALUE_MAX))) {
sEnable4k2kYUVSplit = true;
}
+
+ if ((property_get("persist.hwc.ptor.enable", property, NULL) > 0) &&
+ ((!strncasecmp(property, "true", PROPERTY_VALUE_MAX )) ||
+ (!strncmp(property, "1", PROPERTY_VALUE_MAX )))) {
+ ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit(ctx,
+ HWC_DISPLAY_PRIMARY);
+ }
+
return true;
}
@@ -168,6 +179,11 @@
ctx->mLayerRotMap[mDpy]->clear();
}
+void MDPComp::reset() {
+ sHandleTimeout = false;
+ mModeOn = false;
+}
+
void MDPComp::timeout_handler(void *udata) {
struct hwc_context_t* ctx = (struct hwc_context_t*)(udata);
@@ -269,7 +285,7 @@
}
void MDPComp::LayerCache::cacheAll(hwc_display_contents_1_t* list) {
- const int numAppLayers = list->numHwLayers - 1;
+ const int numAppLayers = (int)list->numHwLayers - 1;
for(int i = 0; i < numAppLayers; i++) {
hnd[i] = list->hwLayers[i].handle;
}
@@ -300,7 +316,7 @@
bool MDPComp::isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer) {
private_handle_t *hnd = (private_handle_t *)layer->handle;
- if((not isYuvBuffer(hnd) and has90Transform(layer)) or
+ if((has90Transform(layer) and (not isRotationDoable(ctx, hnd))) ||
(not isValidDimension(ctx,layer))
//More conditions here, SKIP, sRGB+Blend etc
) {
@@ -327,8 +343,9 @@
hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
hwc_rect_t dst = layer->displayFrame;
- int crop_w = crop.right - crop.left;
- int crop_h = crop.bottom - crop.top;
+ bool rotated90 = (bool)(layer->transform & HAL_TRANSFORM_ROT_90);
+ int crop_w = rotated90 ? crop.bottom - crop.top : crop.right - crop.left;
+ int crop_h = rotated90 ? crop.right - crop.left : crop.bottom - crop.top;
int dst_w = dst.right - dst.left;
int dst_h = dst.bottom - dst.top;
float w_scale = ((float)crop_w / (float)dst_w);
@@ -393,44 +410,15 @@
return true;
}
-ovutils::eDest MDPComp::getMdpPipe(hwc_context_t *ctx, ePipeType type,
- int mixer) {
- overlay::Overlay& ov = *ctx->mOverlay;
- ovutils::eDest mdp_pipe = ovutils::OV_INVALID;
-
- switch(type) {
- case MDPCOMP_OV_DMA:
- mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_DMA, mDpy, mixer);
- if(mdp_pipe != ovutils::OV_INVALID) {
- return mdp_pipe;
- }
- case MDPCOMP_OV_ANY:
- case MDPCOMP_OV_RGB:
- mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy, mixer);
- if(mdp_pipe != ovutils::OV_INVALID) {
- return mdp_pipe;
- }
-
- if(type == MDPCOMP_OV_RGB) {
- //Requested only for RGB pipe
- break;
- }
- case MDPCOMP_OV_VG:
- return ov.nextPipe(ovutils::OV_MDP_PIPE_VG, mDpy, mixer);
- default:
- ALOGE("%s: Invalid pipe type",__FUNCTION__);
- return ovutils::OV_INVALID;
- };
- return ovutils::OV_INVALID;
-}
-
bool MDPComp::isFrameDoable(hwc_context_t *ctx) {
bool ret = true;
if(!isEnabled()) {
ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
ret = false;
- } else if(qdutils::MDPVersion::getInstance().is8x26() &&
+ } else if((qdutils::MDPVersion::getInstance().is8x26() ||
+ qdutils::MDPVersion::getInstance().is8x16() ||
+ qdutils::MDPVersion::getInstance().is8x39()) &&
ctx->mVideoTransFlag &&
isSecondaryConnected(ctx)) {
//1 Padding round to shift pipes across mixers
@@ -449,23 +437,21 @@
return ret;
}
-/*
- * 1) Identify layers that are not visible in the updating ROI and drop them
- * from composition.
- * 2) If we have a scaling layers which needs cropping against generated ROI.
- * Reset ROI to full resolution.
- */
-bool MDPComp::validateAndApplyROI(hwc_context_t *ctx,
- hwc_display_contents_1_t* list, hwc_rect_t roi) {
+void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) {
+ hwc_rect_t roi = ctx->listStats[mDpy].lRoi;
+ fbRect = getIntersection(fbRect, roi);
+}
+
+/* 1) Identify layers that are not visible or lying outside the updating ROI and
+ * drop them from composition.
+ * 2) If we have a scaling layer which needs cropping against generated
+ * ROI, reset ROI to full resolution. */
+bool MDPCompNonSplit::validateAndApplyROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
int numAppLayers = ctx->listStats[mDpy].numAppLayers;
-
- if(!isValidRect(roi))
- return false;
-
- hwc_rect_t visibleRect = roi;
+ hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
for(int i = numAppLayers - 1; i >= 0; i--){
-
if(!isValidRect(visibleRect)) {
mCurrentFrame.drop[i] = true;
mCurrentFrame.dropCount++;
@@ -473,24 +459,16 @@
}
const hwc_layer_1_t* layer = &list->hwLayers[i];
-
hwc_rect_t dstRect = layer->displayFrame;
- hwc_rect_t srcRect = integerizeSourceCrop(layer->sourceCropf);
-
hwc_rect_t res = getIntersection(visibleRect, dstRect);
- int res_w = res.right - res.left;
- int res_h = res.bottom - res.top;
- int dst_w = dstRect.right - dstRect.left;
- int dst_h = dstRect.bottom - dstRect.top;
-
if(!isValidRect(res)) {
mCurrentFrame.drop[i] = true;
mCurrentFrame.dropCount++;
- }else {
+ } else {
/* Reset frame ROI when any layer which needs scaling also needs ROI
* cropping */
- if((res_w != dst_w || res_h != dst_h) && needsScaling (layer)) {
+ if(!isSameRect(res, dstRect) && needsScaling (layer)) {
ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
mCurrentFrame.dropCount = 0;
@@ -505,51 +483,190 @@
return true;
}
-void MDPComp::generateROI(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
+ * are updating. If DirtyRegion is applicable, calculate it by accounting all
+ * the changing layer's dirtyRegion. */
+void MDPCompNonSplit::generateROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
int numAppLayers = ctx->listStats[mDpy].numAppLayers;
-
- if(!sEnablePartialFrameUpdate) {
- return;
- }
-
- if(mDpy || isDisplaySplit(ctx, mDpy)){
- ALOGE_IF(isDebug(), "%s: ROI not supported for"
- "the (1) external / virtual display's (2) dual DSI displays",
- __FUNCTION__);
- return;
- }
-
- if(isSkipPresent(ctx, mDpy))
- return;
-
- if(list->flags & HWC_GEOMETRY_CHANGED)
+ if(!canPartialUpdate(ctx, list))
return;
struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
- for(int index = 0; index < numAppLayers; index++ ) {
- if ((mCachedFrame.hnd[index] != list->hwLayers[index].handle) ||
- isYuvBuffer((private_handle_t *)list->hwLayers[index].handle)) {
- hwc_rect_t dstRect = list->hwLayers[index].displayFrame;
- hwc_rect_t srcRect = integerizeSourceCrop(
- list->hwLayers[index].sourceCropf);
+ hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
+ (int)ctx->dpyAttr[mDpy].yres};
- /* Intersect against display boundaries */
- roi = getUnion(roi, dstRect);
+ for(int index = 0; index < numAppLayers; index++ ) {
+ hwc_layer_1_t* layer = &list->hwLayers[index];
+ if ((mCachedFrame.hnd[index] != layer->handle) ||
+ isYuvBuffer((private_handle_t *)layer->handle)) {
+ hwc_rect_t dst = layer->displayFrame;
+ hwc_rect_t updatingRect = dst;
+
+#ifdef QCOM_BSP
+ if(!needsScaling(layer) && !layer->transform)
+ {
+ hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
+ int x_off = dst.left - src.left;
+ int y_off = dst.top - src.top;
+ updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
+ }
+#endif
+
+ roi = getUnion(roi, updatingRect);
}
}
- if(!validateAndApplyROI(ctx, list, roi)){
- roi = (struct hwc_rect) {0, 0,
- (int)ctx->dpyAttr[mDpy].xres, (int)ctx->dpyAttr[mDpy].yres};
- }
+ /* No layer is updating. Still SF wants a refresh.*/
+ if(!isValidRect(roi))
+ return;
- ctx->listStats[mDpy].roi.x = roi.left;
- ctx->listStats[mDpy].roi.y = roi.top;
- ctx->listStats[mDpy].roi.w = roi.right - roi.left;
- ctx->listStats[mDpy].roi.h = roi.bottom - roi.top;
+ // Align ROI coordinates to panel restrictions
+ roi = getSanitizeROI(roi, fullFrame);
+
+ ctx->listStats[mDpy].lRoi = roi;
+ if(!validateAndApplyROI(ctx, list))
+ resetROI(ctx, mDpy);
ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d]", __FUNCTION__,
- roi.left, roi.top, roi.right, roi.bottom);
+ ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
+ ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom);
+}
+
+void MDPCompSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) {
+ hwc_rect l_roi = ctx->listStats[mDpy].lRoi;
+ hwc_rect r_roi = ctx->listStats[mDpy].rRoi;
+
+ hwc_rect_t l_fbRect = getIntersection(fbRect, l_roi);
+ hwc_rect_t r_fbRect = getIntersection(fbRect, r_roi);
+ fbRect = getUnion(l_fbRect, r_fbRect);
+}
+/* 1) Identify layers that are not visible or lying outside BOTH the updating
+ * ROI's and drop them from composition. If a layer is spanning across both
+ * the halves of the screen but needed by only ROI, the non-contributing
+ * half will not be programmed for MDP.
+ * 2) If we have a scaling layer which needs cropping against generated
+ * ROI, reset ROI to full resolution. */
+bool MDPCompSplit::validateAndApplyROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
+
+ int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+
+ hwc_rect_t visibleRectL = ctx->listStats[mDpy].lRoi;
+ hwc_rect_t visibleRectR = ctx->listStats[mDpy].rRoi;
+
+ for(int i = numAppLayers - 1; i >= 0; i--){
+ if(!isValidRect(visibleRectL) && !isValidRect(visibleRectR))
+ {
+ mCurrentFrame.drop[i] = true;
+ mCurrentFrame.dropCount++;
+ continue;
+ }
+
+ const hwc_layer_1_t* layer = &list->hwLayers[i];
+ hwc_rect_t dstRect = layer->displayFrame;
+
+ hwc_rect_t l_res = getIntersection(visibleRectL, dstRect);
+ hwc_rect_t r_res = getIntersection(visibleRectR, dstRect);
+ hwc_rect_t res = getUnion(l_res, r_res);
+
+ if(!isValidRect(l_res) && !isValidRect(r_res)) {
+ mCurrentFrame.drop[i] = true;
+ mCurrentFrame.dropCount++;
+ } else {
+ /* Reset frame ROI when any layer which needs scaling also needs ROI
+ * cropping */
+ if(!isSameRect(res, dstRect) && needsScaling (layer)) {
+ memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
+ mCurrentFrame.dropCount = 0;
+ return false;
+ }
+
+ if (layer->blending == HWC_BLENDING_NONE) {
+ visibleRectL = deductRect(visibleRectL, l_res);
+ visibleRectR = deductRect(visibleRectR, r_res);
+ }
+ }
+ }
+ return true;
+}
+/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
+ * are updating. If DirtyRegion is applicable, calculate it by accounting all
+ * the changing layer's dirtyRegion. */
+void MDPCompSplit::generateROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
+ if(!canPartialUpdate(ctx, list))
+ return;
+
+ int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+ int lSplit = getLeftSplit(ctx, mDpy);
+
+ int hw_h = (int)ctx->dpyAttr[mDpy].yres;
+ int hw_w = (int)ctx->dpyAttr[mDpy].xres;
+
+ struct hwc_rect l_frame = (struct hwc_rect){0, 0, lSplit, hw_h};
+ struct hwc_rect r_frame = (struct hwc_rect){lSplit, 0, hw_w, hw_h};
+
+ struct hwc_rect l_roi = (struct hwc_rect){0, 0, 0, 0};
+ struct hwc_rect r_roi = (struct hwc_rect){0, 0, 0, 0};
+
+ for(int index = 0; index < numAppLayers; index++ ) {
+ hwc_layer_1_t* layer = &list->hwLayers[index];
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ if ((mCachedFrame.hnd[index] != layer->handle) ||
+ isYuvBuffer(hnd)) {
+ hwc_rect_t dst = layer->displayFrame;
+ hwc_rect_t updatingRect = dst;
+
+#ifdef QCOM_BSP
+ if(!needsScaling(layer) && !layer->transform)
+ {
+ hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
+ int x_off = dst.left - src.left;
+ int y_off = dst.top - src.top;
+ updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
+ }
+#endif
+
+ hwc_rect_t l_dst = getIntersection(l_frame, updatingRect);
+ if(isValidRect(l_dst))
+ l_roi = getUnion(l_roi, l_dst);
+
+ hwc_rect_t r_dst = getIntersection(r_frame, updatingRect);
+ if(isValidRect(r_dst))
+ r_roi = getUnion(r_roi, r_dst);
+ }
+ }
+
+ /* For panels that cannot accept commands in both the interfaces, we cannot
+ * send two ROI's (for each half). We merge them into single ROI and split
+ * them across lSplit for MDP mixer use. The ROI's will be merged again
+ * finally before udpating the panel in the driver. */
+ if(qdutils::MDPVersion::getInstance().needsROIMerge()) {
+ hwc_rect_t temp_roi = getUnion(l_roi, r_roi);
+ l_roi = getIntersection(temp_roi, l_frame);
+ r_roi = getIntersection(temp_roi, r_frame);
+ }
+
+ /* No layer is updating. Still SF wants a refresh. */
+ if(!isValidRect(l_roi) && !isValidRect(r_roi))
+ return;
+
+ l_roi = getSanitizeROI(l_roi, l_frame);
+ r_roi = getSanitizeROI(r_roi, r_frame);
+
+ ctx->listStats[mDpy].lRoi = l_roi;
+ ctx->listStats[mDpy].rRoi = r_roi;
+
+ if(!validateAndApplyROI(ctx, list))
+ resetROI(ctx, mDpy);
+
+ ALOGD_IF(isDebug(),"%s: generated L_ROI: [%d, %d, %d, %d]"
+ "R_ROI: [%d, %d, %d, %d]", __FUNCTION__,
+ ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
+ ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
+ ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
+ ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
}
/* Checks for conditions where all the layers marked for MDP comp cannot be
@@ -594,7 +711,7 @@
hwc_layer_1_t* layer = &list->hwLayers[i];
private_handle_t *hnd = (private_handle_t *)layer->handle;
- if(isYuvBuffer(hnd) && has90Transform(layer)) {
+ if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
if(!canUseRotator(ctx, mDpy)) {
ALOGD_IF(isDebug(), "%s: Can't use rotator for dpy %d",
__FUNCTION__, mDpy);
@@ -619,6 +736,8 @@
bool ret = false;
if(fullMDPComp(ctx, list)) {
ret = true;
+ } else if(fullMDPCompWithPTOR(ctx, list)) {
+ ret = true;
} else if(partialMDPComp(ctx, list)) {
ret = true;
}
@@ -627,6 +746,10 @@
}
bool MDPComp::fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+
+ if(sSimulationFlags & MDPCOMP_AVOID_FULL_MDP)
+ return false;
+
//Will benefit presentation / secondary-only layer.
if((mDpy > HWC_DISPLAY_PRIMARY) &&
(list->numHwLayers - 1) > MAX_SEC_LAYERS) {
@@ -637,19 +760,11 @@
const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
for(int i = 0; i < numAppLayers; i++) {
hwc_layer_1_t* layer = &list->hwLayers[i];
- if(not isSupportedForMDPComp(ctx, layer)) {
+ if(not mCurrentFrame.drop[i] and
+ not isSupportedForMDPComp(ctx, layer)) {
ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
return false;
}
-
- //For 8x26, if there is only one layer which needs scale for secondary
- //while no scale for primary display, DMA pipe is occupied by primary.
- //If need to fall back to GLES composition, virtual display lacks DMA
- //pipe and error is reported.
- if(qdutils::MDPVersion::getInstance().is8x26() &&
- mDpy >= HWC_DISPLAY_EXTERNAL &&
- qhwc::needsScaling(layer))
- return false;
}
mCurrentFrame.fbCount = 0;
@@ -667,10 +782,182 @@
reset(ctx);
return false;
}
-
+ ALOGD_IF(sSimulationFlags,"%s: FULL_MDP_COMP SUCCEEDED",
+ __FUNCTION__);
return true;
}
+/* Full MDP Composition with Peripheral Tiny Overlap Removal.
+ * MDP bandwidth limitations can be avoided, if the overlap region
+ * covered by the smallest layer at a higher z-order, gets composed
+ * by Copybit on a render buffer, which can be queued to MDP.
+ */
+bool MDPComp::fullMDPCompWithPTOR(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) {
+
+ const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+ const int stagesForMDP = min(sMaxPipesPerMixer,
+ ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
+
+ // Hard checks where we cannot use this mode
+ if (mDpy || !ctx->mCopyBit[mDpy] || isDisplaySplit(ctx, mDpy)) {
+ ALOGD_IF(isDebug(), "%s: Feature not supported!", __FUNCTION__);
+ return false;
+ }
+
+ // Frame level checks
+ if ((numAppLayers > stagesForMDP) || isSkipPresent(ctx, mDpy) ||
+ isYuvPresent(ctx, mDpy) || mCurrentFrame.dropCount ||
+ isSecurePresent(ctx, mDpy)) {
+ ALOGD_IF(isDebug(), "%s: Frame not supported!", __FUNCTION__);
+ return false;
+ }
+ // MDP comp checks
+ for(int i = 0; i < numAppLayers; i++) {
+ hwc_layer_1_t* layer = &list->hwLayers[i];
+ if(not isSupportedForMDPComp(ctx, layer)) {
+ ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
+ return false;
+ }
+ }
+
+ /* We cannot use this composition mode, if:
+ 1. A below layer needs scaling.
+ 2. Overlap is not peripheral to display.
+ 3. Overlap or a below layer has 90 degree transform.
+ 4. Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
+ */
+
+ int minLayerIndex[MAX_PTOR_LAYERS] = { -1, -1};
+ hwc_rect_t overlapRect[MAX_PTOR_LAYERS];
+ memset(overlapRect, 0, sizeof(overlapRect));
+ int layerPixelCount, minPixelCount = 0;
+ int numPTORLayersFound = 0;
+ for (int i = numAppLayers-1; (i >= 0 &&
+ numPTORLayersFound < MAX_PTOR_LAYERS); i--) {
+ hwc_layer_1_t* layer = &list->hwLayers[i];
+ hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
+ hwc_rect_t dispFrame = layer->displayFrame;
+ layerPixelCount = (crop.right - crop.left) * (crop.bottom - crop.top);
+ // PTOR layer should be peripheral and cannot have transform
+ if (!isPeripheral(dispFrame, ctx->mViewFrame[mDpy]) ||
+ has90Transform(layer)) {
+ continue;
+ }
+ if((3 * (layerPixelCount + minPixelCount)) >
+ ((int)ctx->dpyAttr[mDpy].xres * (int)ctx->dpyAttr[mDpy].yres)) {
+ // Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
+ continue;
+ }
+ // Found the PTOR layer
+ bool found = true;
+ for (int j = i-1; j >= 0; j--) {
+ // Check if the layers below this layer qualifies for PTOR comp
+ hwc_layer_1_t* layer = &list->hwLayers[j];
+ hwc_rect_t disFrame = layer->displayFrame;
+ //layer below PTOR is intersecting and has 90 degree transform or
+ // needs scaling cannot be supported.
+ if ((isValidRect(getIntersection(dispFrame, disFrame)))
+ && (has90Transform(layer) || needsScaling(layer))) {
+ found = false;
+ break;
+ }
+ }
+ // Store the minLayer Index
+ if(found) {
+ minLayerIndex[numPTORLayersFound] = i;
+ overlapRect[numPTORLayersFound] = list->hwLayers[i].displayFrame;
+ minPixelCount += layerPixelCount;
+ numPTORLayersFound++;
+ }
+ }
+
+ if(isValidRect(getIntersection(overlapRect[0], overlapRect[1]))) {
+ ALOGD_IF(isDebug(), "%s: Ignore Rect2 its intersects with Rect1",
+ __FUNCTION__);
+ // reset second minLayerIndex[1];
+ minLayerIndex[1] = -1;
+ numPTORLayersFound--;
+ }
+
+ // No overlap layers
+ if (!numPTORLayersFound)
+ return false;
+
+ ctx->mPtorInfo.count = numPTORLayersFound;
+ for(int i = 0; i < MAX_PTOR_LAYERS; i++) {
+ ctx->mPtorInfo.layerIndex[i] = minLayerIndex[i];
+ }
+
+ if (!ctx->mCopyBit[mDpy]->prepareOverlap(ctx, list)) {
+ // reset PTOR
+ ctx->mPtorInfo.count = 0;
+ return false;
+ }
+ // Store the displayFrame and the sourceCrops of the layers
+ hwc_rect_t displayFrame[numAppLayers];
+ hwc_rect_t sourceCrop[numAppLayers];
+ for(int i = 0; i < numAppLayers; i++) {
+ hwc_layer_1_t* layer = &list->hwLayers[i];
+ displayFrame[i] = layer->displayFrame;
+ sourceCrop[i] = integerizeSourceCrop(layer->sourceCropf);
+ }
+
+ for(int j = 0; j < numPTORLayersFound; j++) {
+ int index = ctx->mPtorInfo.layerIndex[j];
+ // Remove overlap from crop & displayFrame of below layers
+ for (int i = 0; i < index && index !=-1; i++) {
+ hwc_layer_1_t* layer = &list->hwLayers[i];
+ if(!isValidRect(getIntersection(layer->displayFrame,
+ overlapRect[j]))) {
+ continue;
+ }
+ // Update layer attributes
+ hwc_rect_t srcCrop = integerizeSourceCrop(layer->sourceCropf);
+ hwc_rect_t destRect = deductRect(layer->displayFrame,
+ overlapRect[j]);
+ qhwc::calculate_crop_rects(srcCrop, layer->displayFrame, destRect,
+ layer->transform);
+ layer->sourceCropf.left = (float)srcCrop.left;
+ layer->sourceCropf.top = (float)srcCrop.top;
+ layer->sourceCropf.right = (float)srcCrop.right;
+ layer->sourceCropf.bottom = (float)srcCrop.bottom;
+ }
+ }
+
+ mCurrentFrame.mdpCount = numAppLayers;
+ mCurrentFrame.fbCount = 0;
+ mCurrentFrame.fbZ = -1;
+
+ for (int j = 0; j < numAppLayers; j++)
+ mCurrentFrame.isFBComposed[j] = false;
+
+ bool result = postHeuristicsHandling(ctx, list);
+
+ // Restore layer attributes
+ for(int i = 0; i < numAppLayers; i++) {
+ hwc_layer_1_t* layer = &list->hwLayers[i];
+ layer->displayFrame = displayFrame[i];
+ layer->sourceCropf.left = (float)sourceCrop[i].left;
+ layer->sourceCropf.top = (float)sourceCrop[i].top;
+ layer->sourceCropf.right = (float)sourceCrop[i].right;
+ layer->sourceCropf.bottom = (float)sourceCrop[i].bottom;
+ }
+
+ if (!result) {
+ // reset PTOR
+ ctx->mPtorInfo.count = 0;
+ reset(ctx);
+ } else {
+ ALOGD_IF(isDebug(), "%s: PTOR Indexes: %d and %d", __FUNCTION__,
+ ctx->mPtorInfo.layerIndex[0], ctx->mPtorInfo.layerIndex[1]);
+ }
+
+ ALOGD_IF(isDebug(), "%s: Postheuristics %s!", __FUNCTION__,
+ (result ? "successful" : "failed"));
+ return result;
+}
+
bool MDPComp::partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list)
{
if(!sEnableMixedMode) {
@@ -692,6 +979,9 @@
bool MDPComp::cacheBasedComp(hwc_context_t *ctx,
hwc_display_contents_1_t* list) {
+ if(sSimulationFlags & MDPCOMP_AVOID_CACHE_MDP)
+ return false;
+
int numAppLayers = ctx->listStats[mDpy].numAppLayers;
mCurrentFrame.reset(numAppLayers);
updateLayerCache(ctx, list);
@@ -736,12 +1026,17 @@
reset(ctx);
return false;
}
+ ALOGD_IF(sSimulationFlags,"%s: CACHE_MDP_COMP SUCCEEDED",
+ __FUNCTION__);
return true;
}
bool MDPComp::loadBasedComp(hwc_context_t *ctx,
hwc_display_contents_1_t* list) {
+ if(sSimulationFlags & MDPCOMP_AVOID_LOAD_MDP)
+ return false;
+
if(not isLoadBasedCompDoable(ctx)) {
return false;
}
@@ -813,7 +1108,9 @@
if(postHeuristicsHandling(ctx, list)) {
ALOGD_IF(isDebug(), "%s: Postheuristics handling succeeded",
- __FUNCTION__);
+ __FUNCTION__);
+ ALOGD_IF(sSimulationFlags,"%s: LOAD_MDP_COMP SUCCEEDED",
+ __FUNCTION__);
return true;
}
@@ -833,6 +1130,18 @@
return true;
}
+bool MDPComp::canPartialUpdate(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list){
+ if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() ||
+ isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED) ||
+ mDpy ) {
+ return false;
+ }
+ if(ctx->listStats[mDpy].secureUI)
+ return false;
+ return true;
+}
+
bool MDPComp::tryVideoOnly(hwc_context_t *ctx,
hwc_display_contents_1_t* list) {
const bool secureOnly = true;
@@ -842,9 +1151,12 @@
bool MDPComp::videoOnlyComp(hwc_context_t *ctx,
hwc_display_contents_1_t* list, bool secureOnly) {
+ if(sSimulationFlags & MDPCOMP_AVOID_VIDEO_ONLY)
+ return false;
int numAppLayers = ctx->listStats[mDpy].numAppLayers;
mCurrentFrame.reset(numAppLayers);
+ mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
updateYUV(ctx, list, secureOnly);
int mdpCount = mCurrentFrame.mdpCount;
@@ -873,6 +1185,8 @@
return false;
}
+ ALOGD_IF(sSimulationFlags,"%s: VIDEO_ONLY_COMP SUCCEEDED",
+ __FUNCTION__);
return true;
}
@@ -883,7 +1197,7 @@
return false;
}
- if(layer->transform & HWC_TRANSFORM_ROT_90 && !canUseRotator(ctx,mDpy)) {
+ if(has90Transform(layer) && !canUseRotator(ctx, mDpy)) {
ALOGD_IF(isDebug(), "%s: no free DMA pipe",__FUNCTION__);
return false;
}
@@ -1129,7 +1443,6 @@
hwc_rect_t MDPComp::getUpdatingFBRect(hwc_context_t *ctx,
hwc_display_contents_1_t* list){
hwc_rect_t fbRect = (struct hwc_rect){0, 0, 0, 0};
- hwc_layer_1_t *fbLayer = &list->hwLayers[mCurrentFrame.layerCount];
/* Update only the region of FB needed for composition */
for(int i = 0; i < mCurrentFrame.layerCount; i++ ) {
@@ -1139,6 +1452,7 @@
fbRect = getUnion(fbRect, dst);
}
}
+ trimAgainstROI(ctx, fbRect);
return fbRect;
}
@@ -1220,13 +1534,31 @@
return true;
}
-bool MDPComp::resourceCheck(hwc_context_t *ctx,
- hwc_display_contents_1_t *list) {
+bool MDPComp::resourceCheck(hwc_context_t* ctx,
+ hwc_display_contents_1_t* list) {
const bool fbUsed = mCurrentFrame.fbCount;
if(mCurrentFrame.mdpCount > sMaxPipesPerMixer - fbUsed) {
ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
return false;
}
+ // Init rotCount to number of rotate sessions used by other displays
+ int rotCount = ctx->mRotMgr->getNumActiveSessions();
+ // Count the number of rotator sessions required for current display
+ for (int index = 0; index < mCurrentFrame.layerCount; index++) {
+ if(!mCurrentFrame.isFBComposed[index]) {
+ hwc_layer_1_t* layer = &list->hwLayers[index];
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
+ rotCount++;
+ }
+ }
+ }
+ // if number of layers to rotate exceeds max rotator sessions, bail out.
+ if(rotCount > RotMgr::MAX_ROT_SESS) {
+ ALOGD_IF(isDebug(), "%s: Exceeds max rotator sessions %d",
+ __FUNCTION__, mDpy);
+ return false;
+ }
return true;
}
@@ -1274,8 +1606,27 @@
int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
int ret = 0;
+ char property[PROPERTY_VALUE_MAX];
+
+ if(!ctx || !list) {
+ ALOGE("%s: Invalid context or list",__FUNCTION__);
+ mCachedFrame.reset();
+ return -1;
+ }
+
const int numLayers = ctx->listStats[mDpy].numAppLayers;
- MDPVersion& mdpVersion = qdutils::MDPVersion::getInstance();
+
+ if(property_get("debug.hwc.simulate", property, NULL) > 0) {
+ int currentFlags = atoi(property);
+ if(currentFlags != sSimulationFlags) {
+ sSimulationFlags = currentFlags;
+ ALOGE("%s: Simulation Flag read: 0x%x (%d)", __FUNCTION__,
+ sSimulationFlags, sSimulationFlags);
+ }
+ }
+ // reset PTOR
+ if(!mDpy)
+ memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
//Do not cache the information for next draw cycle.
if(numLayers > MAX_NUM_APP_LAYERS or (!numLayers)) {
@@ -1310,9 +1661,11 @@
if(isFrameDoable(ctx)) {
generateROI(ctx, list);
- if(tryFullFrame(ctx, list) || tryVideoOnly(ctx, list)) {
+ mModeOn = tryFullFrame(ctx, list) || tryVideoOnly(ctx, list);
+ if(mModeOn) {
setMDPCompLayerFlags(ctx, list);
} else {
+ resetROI(ctx, mDpy);
reset(ctx);
memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
mCurrentFrame.dropCount = 0;
@@ -1328,7 +1681,7 @@
ALOGD("GEOMETRY change: %d",
(list->flags & HWC_GEOMETRY_CHANGED));
android::String8 sDump("");
- dump(sDump);
+ dump(sDump, ctx);
ALOGD("%s",sDump.string());
}
@@ -1345,18 +1698,23 @@
info.pipeInfo = new MdpYUVPipeInfo;
info.rot = NULL;
MdpYUVPipeInfo& pipe_info = *(MdpYUVPipeInfo*)info.pipeInfo;
- ePipeType type = MDPCOMP_OV_VG;
pipe_info.lIndex = ovutils::OV_INVALID;
pipe_info.rIndex = ovutils::OV_INVALID;
- pipe_info.lIndex = getMdpPipe(ctx, type, Overlay::MIXER_DEFAULT);
+ Overlay::PipeSpecs pipeSpecs;
+ pipeSpecs.formatClass = Overlay::FORMAT_YUV;
+ pipeSpecs.needsScaling = true;
+ pipeSpecs.dpy = mDpy;
+ pipeSpecs.fb = false;
+
+ pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
if(pipe_info.lIndex == ovutils::OV_INVALID){
bRet = false;
ALOGD_IF(isDebug(),"%s: allocating first VG pipe failed",
__FUNCTION__);
}
- pipe_info.rIndex = getMdpPipe(ctx, type, Overlay::MIXER_DEFAULT);
+ pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
if(pipe_info.rIndex == ovutils::OV_INVALID){
bRet = false;
ALOGD_IF(isDebug(),"%s: allocating second VG pipe failed",
@@ -1364,25 +1722,45 @@
}
return bRet;
}
+
+int MDPComp::drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+ int fd = -1;
+ if (ctx->mPtorInfo.isActive()) {
+ fd = ctx->mCopyBit[mDpy]->drawOverlap(ctx, list);
+ if (fd < 0) {
+ ALOGD_IF(isDebug(),"%s: failed", __FUNCTION__);
+ }
+ }
+ return fd;
+}
//=============MDPCompNonSplit==================================================
void MDPCompNonSplit::adjustForSourceSplit(hwc_context_t *ctx,
- hwc_display_contents_1_t*) {
- //As we split 4kx2k yuv layer and program to 2 VG pipes
- //(if available) increase mdpcount accordingly
- mCurrentFrame.mdpCount += ctx->listStats[mDpy].yuv4k2kCount;
-
+ hwc_display_contents_1_t* list) {
//If 4k2k Yuv layer split is possible, and if
//fbz is above 4k2k layer, increment fb zorder by 1
//as we split 4k2k layer and increment zorder for right half
//of the layer
+ if(!ctx)
+ return;
if(mCurrentFrame.fbZ >= 0) {
- int n4k2kYuvCount = ctx->listStats[mDpy].yuv4k2kCount;
- for(int index = 0; index < n4k2kYuvCount; index++){
- int n4k2kYuvIndex =
- ctx->listStats[mDpy].yuv4k2kIndices[index];
- if(mCurrentFrame.fbZ > n4k2kYuvIndex){
- mCurrentFrame.fbZ += 1;
+ for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
+ index++) {
+ if(!mCurrentFrame.isFBComposed[index]) {
+ if(mdpNextZOrder == mCurrentFrame.fbZ) {
+ mdpNextZOrder++;
+ }
+ mdpNextZOrder++;
+ hwc_layer_1_t* layer = &list->hwLayers[index];
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ if(is4kx2kYuvBuffer(hnd)) {
+ if(mdpNextZOrder <= mCurrentFrame.fbZ)
+ mCurrentFrame.fbZ += 1;
+ mdpNextZOrder++;
+ //As we split 4kx2k yuv layer and program to 2 VG pipes
+ //(if available) increase mdpcount by 1.
+ mCurrentFrame.mdpCount++;
+ }
}
}
}
@@ -1426,28 +1804,21 @@
info.pipeInfo = new MdpPipeInfoNonSplit;
info.rot = NULL;
MdpPipeInfoNonSplit& pipe_info = *(MdpPipeInfoNonSplit*)info.pipeInfo;
- ePipeType type = MDPCOMP_OV_ANY;
- if(isYuvBuffer(hnd)) {
- type = MDPCOMP_OV_VG;
- } else if(qdutils::MDPVersion::getInstance().is8x26() &&
- (ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres > 1024)) {
- if(qhwc::needsScaling(layer))
- type = MDPCOMP_OV_RGB;
- } else if(!qhwc::needsScaling(layer)
- && Overlay::getDMAMode() != Overlay::DMA_BLOCK_MODE
- && ctx->mMDP.version >= qdutils::MDSS_V5) {
- type = MDPCOMP_OV_DMA;
- } else if(qhwc::needsScaling(layer) &&
- !(ctx->listStats[mDpy].yuvCount) &&
- ! qdutils::MDPVersion::getInstance().isRGBScalarSupported()){
- type = MDPCOMP_OV_VG;
- }
+ Overlay::PipeSpecs pipeSpecs;
+ pipeSpecs.formatClass = isYuvBuffer(hnd) ?
+ Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
+ pipeSpecs.needsScaling = qhwc::needsScaling(layer) or
+ (qdutils::MDPVersion::getInstance().is8x26() and
+ ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres > 1024);
+ pipeSpecs.dpy = mDpy;
+ pipeSpecs.fb = false;
+ pipeSpecs.numActiveDisplays = ctx->numActiveDisplays;
- pipe_info.index = getMdpPipe(ctx, type, Overlay::MIXER_DEFAULT);
+ pipe_info.index = ctx->mOverlay->getPipe(pipeSpecs);
+
if(pipe_info.index == ovutils::OV_INVALID) {
- ALOGD_IF(isDebug(), "%s: Unable to get pipe type = %d",
- __FUNCTION__, (int) type);
+ ALOGD_IF(isDebug(), "%s: Unable to get pipe", __FUNCTION__);
return false;
}
}
@@ -1470,18 +1841,8 @@
bool MDPCompNonSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
- if(!isEnabled()) {
- ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
- return true;
- }
-
- if(!ctx || !list) {
- ALOGE("%s: invalid contxt or list",__FUNCTION__);
- return false;
- }
-
- if(ctx->listStats[mDpy].numAppLayers > MAX_NUM_APP_LAYERS) {
- ALOGD_IF(isDebug(),"%s: Exceeding max layer count", __FUNCTION__);
+ if(!isEnabled() or !mModeOn) {
+ ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
return true;
}
@@ -1520,7 +1881,7 @@
ovutils::eDest indexL = pipe_info.lIndex;
ovutils::eDest indexR = pipe_info.rIndex;
int fd = hnd->fd;
- uint32_t offset = hnd->offset;
+ uint32_t offset = (uint32_t)hnd->offset;
if(rot) {
rot->queueBuffer(fd, offset);
fd = rot->getDstMemId();
@@ -1561,13 +1922,20 @@
continue;
}
+ int fd = hnd->fd;
+ uint32_t offset = (uint32_t)hnd->offset;
+ int index = ctx->mPtorInfo.getPTORArrayIndex(i);
+ if (!mDpy && (index != -1)) {
+ hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
+ fd = hnd->fd;
+ // Use the offset of the RenderBuffer
+ offset = ctx->mPtorInfo.mRenderBuffOffset[index];
+ }
+
ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
using pipe: %d", __FUNCTION__, layer,
hnd, dest );
- int fd = hnd->fd;
- uint32_t offset = hnd->offset;
-
Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
if(rot) {
if(!rot->queueBuffer(fd, offset))
@@ -1594,38 +1962,61 @@
hwc_display_contents_1_t* list){
//if 4kx2k yuv layer is totally present in either in left half
//or right half then try splitting the yuv layer to avoid decimation
- int n4k2kYuvCount = ctx->listStats[mDpy].yuv4k2kCount;
const int lSplit = getLeftSplit(ctx, mDpy);
- for(int index = 0; index < n4k2kYuvCount; index++){
- int n4k2kYuvIndex = ctx->listStats[mDpy].yuv4k2kIndices[index];
- hwc_layer_1_t* layer = &list->hwLayers[n4k2kYuvIndex];
- hwc_rect_t dst = layer->displayFrame;
- if((dst.left > lSplit) || (dst.right < lSplit)) {
- mCurrentFrame.mdpCount += 1;
- }
- if(mCurrentFrame.fbZ > n4k2kYuvIndex){
- mCurrentFrame.fbZ += 1;
+ if(mCurrentFrame.fbZ >= 0) {
+ for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
+ index++) {
+ if(!mCurrentFrame.isFBComposed[index]) {
+ if(mdpNextZOrder == mCurrentFrame.fbZ) {
+ mdpNextZOrder++;
+ }
+ mdpNextZOrder++;
+ hwc_layer_1_t* layer = &list->hwLayers[index];
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
+ if(is4kx2kYuvBuffer(hnd)) {
+ hwc_rect_t dst = layer->displayFrame;
+ if((dst.left > lSplit) || (dst.right < lSplit)) {
+ mCurrentFrame.mdpCount += 1;
+ }
+ if(mdpNextZOrder <= mCurrentFrame.fbZ)
+ mCurrentFrame.fbZ += 1;
+ mdpNextZOrder++;
+ }
+ }
}
}
}
bool MDPCompSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
- MdpPipeInfoSplit& pipe_info,
- ePipeType type) {
- const int lSplit = getLeftSplit(ctx, mDpy);
+ MdpPipeInfoSplit& pipe_info) {
+ const int lSplit = getLeftSplit(ctx, mDpy);
+ private_handle_t *hnd = (private_handle_t *)layer->handle;
hwc_rect_t dst = layer->displayFrame;
pipe_info.lIndex = ovutils::OV_INVALID;
pipe_info.rIndex = ovutils::OV_INVALID;
- if (dst.left < lSplit) {
- pipe_info.lIndex = getMdpPipe(ctx, type, Overlay::MIXER_LEFT);
+ Overlay::PipeSpecs pipeSpecs;
+ pipeSpecs.formatClass = isYuvBuffer(hnd) ?
+ Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
+ pipeSpecs.needsScaling = qhwc::needsScalingWithSplit(ctx, layer, mDpy);
+ pipeSpecs.dpy = mDpy;
+ pipeSpecs.mixer = Overlay::MIXER_LEFT;
+ pipeSpecs.fb = false;
+
+ // Acquire pipe only for the updating half
+ hwc_rect_t l_roi = ctx->listStats[mDpy].lRoi;
+ hwc_rect_t r_roi = ctx->listStats[mDpy].rRoi;
+
+ if (dst.left < lSplit && isValidRect(getIntersection(dst, l_roi))) {
+ pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
if(pipe_info.lIndex == ovutils::OV_INVALID)
return false;
}
- if(dst.right > lSplit) {
- pipe_info.rIndex = getMdpPipe(ctx, type, Overlay::MIXER_RIGHT);
+ if(dst.right > lSplit && isValidRect(getIntersection(dst, r_roi))) {
+ pipeSpecs.mixer = Overlay::MIXER_RIGHT;
+ pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
if(pipe_info.rIndex == ovutils::OV_INVALID)
return false;
}
@@ -1655,19 +2046,10 @@
info.pipeInfo = new MdpPipeInfoSplit;
info.rot = NULL;
MdpPipeInfoSplit& pipe_info = *(MdpPipeInfoSplit*)info.pipeInfo;
- ePipeType type = MDPCOMP_OV_ANY;
- if(isYuvBuffer(hnd)) {
- type = MDPCOMP_OV_VG;
- } else if(!qhwc::needsScalingWithSplit(ctx, layer, mDpy)
- && Overlay::getDMAMode() != Overlay::DMA_BLOCK_MODE
- && ctx->mMDP.version >= qdutils::MDSS_V5) {
- type = MDPCOMP_OV_DMA;
- }
-
- if(!acquireMDPPipes(ctx, layer, pipe_info, type)) {
- ALOGD_IF(isDebug(), "%s: Unable to get pipe for type = %d",
- __FUNCTION__, (int) type);
+ if(!acquireMDPPipes(ctx, layer, pipe_info)) {
+ ALOGD_IF(isDebug(), "%s: Unable to get pipe for type",
+ __FUNCTION__);
return false;
}
}
@@ -1717,18 +2099,8 @@
bool MDPCompSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
- if(!isEnabled()) {
- ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
- return true;
- }
-
- if(!ctx || !list) {
- ALOGE("%s: invalid contxt or list",__FUNCTION__);
- return false;
- }
-
- if(ctx->listStats[mDpy].numAppLayers > MAX_NUM_APP_LAYERS) {
- ALOGD_IF(isDebug(),"%s: Exceeding max layer count", __FUNCTION__);
+ if(!isEnabled() or !mModeOn) {
+ ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
return true;
}
@@ -1766,7 +2138,7 @@
ovutils::eDest indexL = pipe_info.lIndex;
ovutils::eDest indexR = pipe_info.rIndex;
int fd = hnd->fd;
- uint32_t offset = hnd->offset;
+ uint32_t offset = (uint32_t)hnd->offset;
if(rot) {
rot->queueBuffer(fd, offset);
fd = rot->getDstMemId();
@@ -1803,13 +2175,17 @@
ovutils::eDest indexR = pipe_info.rIndex;
int fd = hnd->fd;
- int offset = hnd->offset;
+ uint32_t offset = (uint32_t)hnd->offset;
+ int index = ctx->mPtorInfo.getPTORArrayIndex(i);
+ if (!mDpy && (index != -1)) {
+ hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
+ fd = hnd->fd;
+ offset = ctx->mPtorInfo.mRenderBuffOffset[index];
+ }
- if(ctx->mAD->isModeOn()) {
- if(ctx->mAD->draw(ctx, fd, offset)) {
- fd = ctx->mAD->getDstFd();
- offset = ctx->mAD->getDstOffset();
- }
+ if(ctx->mAD->draw(ctx, fd, offset)) {
+ fd = ctx->mAD->getDstFd();
+ offset = ctx->mAD->getDstOffset();
}
if(rot) {
@@ -1851,7 +2227,7 @@
//================MDPCompSrcSplit==============================================
bool MDPCompSrcSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
- MdpPipeInfoSplit& pipe_info, ePipeType /*type*/) {
+ MdpPipeInfoSplit& pipe_info) {
private_handle_t *hnd = (private_handle_t *)layer->handle;
hwc_rect_t dst = layer->displayFrame;
hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
@@ -1861,56 +2237,52 @@
//If 2 pipes are staged on a single stage of a mixer, then the left pipe
//should have a higher priority than the right one. Pipe priorities are
//starting with VG0, VG1 ... , RGB0 ..., DMA1
- //TODO Currently we acquire VG pipes for left side and RGB/DMA for right to
- //make sure pipe priorities are satisfied. A better way is to have priority
- //as part of overlay object and acquire any 2 pipes. Assign the higher
- //priority one to left side and lower to right side.
+
+ Overlay::PipeSpecs pipeSpecs;
+ pipeSpecs.formatClass = isYuvBuffer(hnd) ?
+ Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
+ pipeSpecs.needsScaling = qhwc::needsScaling(layer);
+ pipeSpecs.dpy = mDpy;
+ pipeSpecs.fb = false;
//1 pipe by default for a layer
- pipe_info.lIndex = getMdpPipe(ctx, MDPCOMP_OV_VG, Overlay::MIXER_DEFAULT);
+ pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
if(pipe_info.lIndex == ovutils::OV_INVALID) {
- if(isYuvBuffer(hnd)) {
- return false;
- }
- pipe_info.lIndex = getMdpPipe(ctx, MDPCOMP_OV_ANY,
- Overlay::MIXER_DEFAULT);
- if(pipe_info.lIndex == ovutils::OV_INVALID) {
- return false;
- }
+ return false;
}
- //If layer's crop width or dest width > 2048, use 2 pipes
- if((dst.right - dst.left) > qdutils::MAX_DISPLAY_DIM or
- (crop.right - crop.left) > qdutils::MAX_DISPLAY_DIM) {
- ePipeType rightType = isYuvBuffer(hnd) ?
- MDPCOMP_OV_VG : MDPCOMP_OV_ANY;
- pipe_info.rIndex = getMdpPipe(ctx, rightType, Overlay::MIXER_DEFAULT);
+ /* Use 2 pipes IF
+ a) Layer's crop width is > 2048 or
+ b) Layer's dest width > 2048 or
+ c) On primary, driver has indicated with caps to split always. This is
+ based on an empirically derived value of panel height. Applied only
+ if the layer's width is > mixer's width
+ */
+
+ bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and
+ qdutils::MDPVersion::getInstance().isSrcSplitAlways();
+ int lSplit = getLeftSplit(ctx, mDpy);
+ int dstWidth = dst.right - dst.left;
+ int cropWidth = crop.right - crop.left;
+
+ if(dstWidth > qdutils::MAX_DISPLAY_DIM or
+ cropWidth > qdutils::MAX_DISPLAY_DIM or
+ (primarySplitAlways and (cropWidth > lSplit))) {
+ pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
if(pipe_info.rIndex == ovutils::OV_INVALID) {
return false;
}
- }
- return true;
-}
-
-bool MDPCompSrcSplit::allocLayerPipes(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
- for(int index = 0 ; index < mCurrentFrame.layerCount; index++) {
- if(mCurrentFrame.isFBComposed[index]) continue;
- hwc_layer_1_t* layer = &list->hwLayers[index];
- int mdpIndex = mCurrentFrame.layerToMDP[index];
- PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
- info.pipeInfo = new MdpPipeInfoSplit;
- info.rot = NULL;
- MdpPipeInfoSplit& pipe_info = *(MdpPipeInfoSplit*)info.pipeInfo;
-
- ePipeType type = MDPCOMP_OV_ANY;
- if(!acquireMDPPipes(ctx, layer, pipe_info, type)) {
- ALOGD_IF(isDebug(), "%s: Unable to get pipe for type = %d",
- __FUNCTION__, (int) type);
- return false;
+ // Return values
+ // 1 Left pipe is higher priority, do nothing.
+ // 0 Pipes of same priority.
+ //-1 Right pipe is of higher priority, needs swap.
+ if(ctx->mOverlay->comparePipePriority(pipe_info.lIndex,
+ pipe_info.rIndex) == -1) {
+ qhwc::swap(pipe_info.lIndex, pipe_info.rIndex);
}
}
+
return true;
}
@@ -1949,26 +2321,28 @@
whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
}
- eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
- setMdpFlags(layer, mdpFlagsL, 0, transform);
- eMdpFlags mdpFlagsR = mdpFlagsL;
+ eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
+ setMdpFlags(ctx, layer, mdpFlags, 0, transform);
if(lDest != OV_INVALID && rDest != OV_INVALID) {
//Enable overfetch
- setMdpFlags(mdpFlagsL, OV_MDSS_MDP_DUAL_PIPE);
+ setMdpFlags(mdpFlags, OV_MDSS_MDP_DUAL_PIPE);
}
- if(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) {
+ if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
(*rot) = ctx->mRotMgr->getNext();
if((*rot) == NULL) return -1;
+ ctx->mLayerRotMap[mDpy]->add(layer, *rot);
+ //If the video is using a single pipe, enable BWC
+ if(rDest == OV_INVALID) {
+ BwcPM::setBwc(crop, dst, transform, mdpFlags);
+ }
//Configure rotator for pre-rotation
- if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
+ if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
ALOGE("%s: configRotator failed!", __FUNCTION__);
return -1;
}
- ctx->mLayerRotMap[mDpy]->add(layer, *rot);
- whf.format = (*rot)->getDstFormat();
- updateSource(orient, whf, crop);
+ updateSource(orient, whf, crop, *rot);
rotFlags |= ROT_PREROTATED;
}
@@ -1999,7 +2373,7 @@
//configure left pipe
if(lDest != OV_INVALID) {
- PipeArgs pargL(mdpFlagsL, whf, z, isFg,
+ PipeArgs pargL(mdpFlags, whf, z, isFg,
static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
(ovutils::eBlending) getBlending(layer->blending));
@@ -2012,7 +2386,7 @@
//configure right pipe
if(rDest != OV_INVALID) {
- PipeArgs pargR(mdpFlagsR, whf, z, isFg,
+ PipeArgs pargR(mdpFlags, whf, z, isFg,
static_cast<eRotFlags>(rotFlags),
layer->planeAlpha,
(ovutils::eBlending) getBlending(layer->blending));
diff --git a/msm8226/libhwcomposer/hwc_mdpcomp.h b/msm8226/libhwcomposer/hwc_mdpcomp.h
index 2d65755..1ebe0bd 100644
--- a/msm8226/libhwcomposer/hwc_mdpcomp.h
+++ b/msm8226/libhwcomposer/hwc_mdpcomp.h
@@ -43,17 +43,20 @@
int prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list);
/* draw */
virtual bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list) = 0;
+ //Reset values
+ void reset();
/* dumpsys */
- void dump(android::String8& buf);
+ void dump(android::String8& buf, hwc_context_t *ctx);
bool isGLESOnlyComp() { return (mCurrentFrame.mdpCount == 0); }
+ int drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t* list);
static MDPComp* getObject(hwc_context_t *ctx, const int& dpy);
/* Handler to invoke frame redraw on Idle Timer expiry */
static void timeout_handler(void *udata);
/* Initialize MDP comp*/
static bool init(hwc_context_t *ctx);
static void resetIdleFallBack() { sIdleFallBack = false; }
- static void reset() { sHandleTimeout = false; };
static bool isIdleFallback() { return sIdleFallBack; }
+ static void dynamicDebug(bool enable){ sDebugLogs = enable; }
protected:
enum { MAX_SEC_LAYERS = 1 }; //TODO add property support
@@ -65,6 +68,14 @@
MDPCOMP_OV_ANY,
};
+ //Simulation flags
+ enum {
+ MDPCOMP_AVOID_FULL_MDP = 0x001,
+ MDPCOMP_AVOID_CACHE_MDP = 0x002,
+ MDPCOMP_AVOID_LOAD_MDP = 0x004,
+ MDPCOMP_AVOID_VIDEO_ONLY = 0x008,
+ };
+
/* mdp pipe data */
struct MdpPipeInfo {
int zOrder;
@@ -132,8 +143,6 @@
/* allocates pipe from pipe book */
virtual bool allocLayerPipes(hwc_context_t *ctx,
hwc_display_contents_1_t* list) = 0;
- /* allocate MDP pipes from overlay */
- ovutils::eDest getMdpPipe(hwc_context_t *ctx, ePipeType type, int mixer);
/* configures MPD pipes */
virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
PipeLayerPair& pipeLayerPair) = 0;
@@ -144,6 +153,15 @@
/* configures 4kx2k yuv layer*/
virtual int configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
PipeLayerPair& PipeLayerPair) = 0;
+ /* generates ROI based on the modified area of the frame */
+ virtual void generateROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) = 0;
+ /* validates the ROI generated for fallback conditions */
+ virtual bool validateAndApplyROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list) = 0;
+ /* Trims fbRect calculated against ROI generated */
+ virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) = 0;
+
/* set/reset flags for MDPComp */
void setMDPCompLayerFlags(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
@@ -155,6 +173,8 @@
bool tryFullFrame(hwc_context_t *ctx, hwc_display_contents_1_t* list);
/* checks if full MDP comp can be done */
bool fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+ /* Full MDP Composition with Peripheral Tiny Overlap Removal */
+ bool fullMDPCompWithPTOR(hwc_context_t *ctx,hwc_display_contents_1_t* list);
/* check if we can use layer cache to do at least partial MDP comp */
bool partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
/* Partial MDP comp that uses caching to save power as primary goal */
@@ -175,11 +195,6 @@
/* checks if MDP/MDSS can process current list w.r.to HW limitations
* All peculiar HW limitations should go here */
bool hwLimitationsCheck(hwc_context_t* ctx, hwc_display_contents_1_t* list);
- /* generates ROI based on the modified area of the frame */
- void generateROI(hwc_context_t *ctx, hwc_display_contents_1_t* list);
- bool validateAndApplyROI(hwc_context_t *ctx, hwc_display_contents_1_t* list,
- hwc_rect_t roi);
-
/* Is debug enabled */
static bool isDebug() { return sDebugLogs ? true : false; };
/* Is feature enabled */
@@ -213,15 +228,16 @@
hwc_display_contents_1_t* list);
void reset(hwc_context_t *ctx);
bool isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer);
- bool resourceCheck(hwc_context_t *ctx, hwc_display_contents_1_t *list);
+ bool resourceCheck(hwc_context_t* ctx, hwc_display_contents_1_t* list);
hwc_rect_t getUpdatingFBRect(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
+ /* checks for conditions to enable partial udpate */
+ bool canPartialUpdate(hwc_context_t *ctx, hwc_display_contents_1_t* list);
int mDpy;
static bool sEnabled;
static bool sEnableMixedMode;
- /* Enables Partial frame composition */
- static bool sEnablePartialFrameUpdate;
+ static int sSimulationFlags;
static bool sDebugLogs;
static bool sIdleFallBack;
/* Handles the timeout event from kernel, if the value is set to true */
@@ -233,6 +249,7 @@
struct LayerCache mCachedFrame;
//Enable 4kx2k yuv layer split
static bool sEnable4k2kYUVSplit;
+ bool mModeOn; // if prepare happened
bool allocSplitVGPipesfor4k2k(hwc_context_t *ctx, int index);
};
@@ -264,6 +281,14 @@
/* configures 4kx2k yuv layer to 2 VG pipes*/
virtual int configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
PipeLayerPair& PipeLayerPair);
+ /* generates ROI based on the modified area of the frame */
+ virtual void generateROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list);
+ /* validates the ROI generated for fallback conditions */
+ virtual bool validateAndApplyROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list);
+ /* Trims fbRect calculated against ROI generated */
+ virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect);
};
class MDPCompSplit : public MDPComp {
@@ -280,7 +305,7 @@
};
virtual bool acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
- MdpPipeInfoSplit& pipe_info, ePipeType type);
+ MdpPipeInfoSplit& pipe_info);
/* configure's overlay pipes for the frame */
virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
@@ -289,7 +314,6 @@
/* allocates pipes to selected candidates */
virtual bool allocLayerPipes(hwc_context_t *ctx,
hwc_display_contents_1_t* list);
-
private:
/* Increments mdpCount if 4k2k yuv layer split is enabled.
* updates framebuffer z order if fb lies above source-split layer */
@@ -299,6 +323,14 @@
/* configures 4kx2k yuv layer*/
virtual int configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
PipeLayerPair& PipeLayerPair);
+ /* generates ROI based on the modified area of the frame */
+ virtual void generateROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list);
+ /* validates the ROI generated for fallback conditions */
+ virtual bool validateAndApplyROI(hwc_context_t *ctx,
+ hwc_display_contents_1_t* list);
+ /* Trims fbRect calculated against ROI generated */
+ virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect);
};
class MDPCompSrcSplit : public MDPCompSplit {
@@ -307,10 +339,7 @@
virtual ~MDPCompSrcSplit(){};
private:
virtual bool acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
- MdpPipeInfoSplit& pipe_info, ePipeType type);
-
- virtual bool allocLayerPipes(hwc_context_t *ctx,
- hwc_display_contents_1_t* list);
+ MdpPipeInfoSplit& pipe_info);
virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
PipeLayerPair& pipeLayerPair);
diff --git a/msm8226/libhwcomposer/hwc_qclient.cpp b/msm8226/libhwcomposer/hwc_qclient.cpp
index 5313795..892e9c0 100644
--- a/msm8226/libhwcomposer/hwc_qclient.cpp
+++ b/msm8226/libhwcomposer/hwc_qclient.cpp
@@ -31,6 +31,7 @@
#include <IQService.h>
#include <hwc_utils.h>
#include <mdp_version.h>
+#include <hwc_mdpcomp.h>
#define QCLIENT_DEBUG 0
@@ -108,8 +109,13 @@
Parcel* outParcel) {
int dpy = inParcel->readInt32();
outParcel->writeInt32(ctx->dpyAttr[dpy].vsync_period);
- outParcel->writeInt32(ctx->dpyAttr[dpy].xres);
- outParcel->writeInt32(ctx->dpyAttr[dpy].yres);
+ if (ctx->dpyAttr[dpy].customFBSize) {
+ outParcel->writeInt32(ctx->dpyAttr[dpy].xres_new);
+ outParcel->writeInt32(ctx->dpyAttr[dpy].yres_new);
+ } else {
+ outParcel->writeInt32(ctx->dpyAttr[dpy].xres);
+ outParcel->writeInt32(ctx->dpyAttr[dpy].yres);
+ }
outParcel->writeFloat(ctx->dpyAttr[dpy].xdpi);
outParcel->writeFloat(ctx->dpyAttr[dpy].ydpi);
//XXX: Need to check what to return for HDMI
@@ -157,6 +163,9 @@
}
static void pauseWFD(hwc_context_t *ctx, uint32_t pause) {
+ /* TODO: Will remove pauseWFD once all the clients start using
+ * setWfdStatus to indicate the status of WFD display
+ */
int dpy = HWC_DISPLAY_VIRTUAL;
if(pause) {
//WFD Pause
@@ -167,6 +176,64 @@
}
}
+static void setWfdStatus(hwc_context_t *ctx, uint32_t wfdStatus) {
+
+ ALOGD_IF(HWC_WFDDISPSYNC_LOG,
+ "%s: Received a binder call that WFD state is %s",
+ __FUNCTION__,getExternalDisplayState(wfdStatus));
+ int dpy = HWC_DISPLAY_VIRTUAL;
+
+ if(wfdStatus == EXTERNAL_OFFLINE) {
+ ctx->mWfdSyncLock.lock();
+ ctx->mWfdSyncLock.signal();
+ ctx->mWfdSyncLock.unlock();
+ } else if(wfdStatus == EXTERNAL_PAUSE) {
+ handle_pause(ctx, dpy);
+ } else if(wfdStatus == EXTERNAL_RESUME) {
+ handle_resume(ctx, dpy);
+ }
+}
+
+
+static status_t setViewFrame(hwc_context_t* ctx, const Parcel* inParcel) {
+ int dpy = inParcel->readInt32();
+ if(dpy >= HWC_DISPLAY_PRIMARY && dpy <= HWC_DISPLAY_VIRTUAL) {
+ Locker::Autolock _sl(ctx->mDrawLock);
+ ctx->mViewFrame[dpy].left = inParcel->readInt32();
+ ctx->mViewFrame[dpy].top = inParcel->readInt32();
+ ctx->mViewFrame[dpy].right = inParcel->readInt32();
+ ctx->mViewFrame[dpy].bottom = inParcel->readInt32();
+ ALOGD_IF(QCLIENT_DEBUG, "%s: mViewFrame[%d] = [%d %d %d %d]",
+ __FUNCTION__, dpy,
+ ctx->mViewFrame[dpy].left, ctx->mViewFrame[dpy].top,
+ ctx->mViewFrame[dpy].right, ctx->mViewFrame[dpy].bottom);
+ return NO_ERROR;
+ } else {
+ ALOGE("In %s: invalid dpy index %d", __FUNCTION__, dpy);
+ return BAD_VALUE;
+ }
+}
+
+static void toggleDynamicDebug(hwc_context_t* ctx, const Parcel* inParcel) {
+ int debug_type = inParcel->readInt32();
+ bool enable = !!inParcel->readInt32();
+ ALOGD("%s: debug_type: %d enable:%d",
+ __FUNCTION__, debug_type, enable);
+ Locker::Autolock _sl(ctx->mDrawLock);
+ switch (debug_type) {
+ //break is ignored for DEBUG_ALL to toggle all of them at once
+ case IQService::DEBUG_ALL:
+ case IQService::DEBUG_MDPCOMP:
+ qhwc::MDPComp::dynamicDebug(enable);
+ if (debug_type != IQService::DEBUG_ALL)
+ break;
+ case IQService::DEBUG_VSYNC:
+ ctx->vstate.debug = enable;
+ if (debug_type != IQService::DEBUG_ALL)
+ break;
+ }
+}
+
status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
Parcel* outParcel) {
status_t ret = NO_ERROR;
@@ -199,15 +266,23 @@
break;
case IQService::SET_HSIC_DATA:
setHSIC(inParcel);
+ break;
case IQService::PAUSE_WFD:
pauseWFD(mHwcContext, inParcel->readInt32());
break;
+ case IQService::SET_WFD_STATUS:
+ setWfdStatus(mHwcContext,inParcel->readInt32());
+ break;
+ case IQService::SET_VIEW_FRAME:
+ setViewFrame(mHwcContext, inParcel);
+ break;
+ case IQService::DYNAMIC_DEBUG:
+ toggleDynamicDebug(mHwcContext, inParcel);
+ break;
default:
ret = NO_ERROR;
}
return ret;
}
-
-
}
diff --git a/msm8226/libhwcomposer/hwc_uevents.cpp b/msm8226/libhwcomposer/hwc_uevents.cpp
index e51a1a4..fed6f3c 100644
--- a/msm8226/libhwcomposer/hwc_uevents.cpp
+++ b/msm8226/libhwcomposer/hwc_uevents.cpp
@@ -32,20 +32,13 @@
#include "comptype.h"
#include "external.h"
#include "virtual.h"
+#include "hwc_virtual.h"
#include "mdp_version.h"
using namespace overlay;
namespace qhwc {
#define HWC_UEVENT_SWITCH_STR "change@/devices/virtual/switch/"
#define HWC_UEVENT_THREAD_NAME "hwcUeventThread"
-/* External Display states */
-enum {
- EXTERNAL_OFFLINE = 0,
- EXTERNAL_ONLINE,
- EXTERNAL_PAUSE,
- EXTERNAL_RESUME
-};
-
static void setup(hwc_context_t* ctx, int dpy)
{
ctx->mFBUpdate[dpy] = IFBUpdate::getObject(ctx, dpy);
@@ -107,53 +100,15 @@
}
void handle_pause(hwc_context_t* ctx, int dpy) {
- {
- Locker::Autolock _l(ctx->mDrawLock);
- ctx->dpyAttr[dpy].isActive = true;
- ctx->dpyAttr[dpy].isPause = true;
- ctx->proc->invalidate(ctx->proc);
- }
- usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
- * 2 / 1000);
- // At this point all the pipes used by External have been
- // marked as UNSET.
- {
- Locker::Autolock _l(ctx->mDrawLock);
- // Perform commit to unstage the pipes.
- if (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
- ALOGE("%s: display commit fail! for %d dpy",
- __FUNCTION__, dpy);
- }
+ if(ctx->mHWCVirtual) {
+ ctx->mHWCVirtual->pause(ctx, dpy);
}
return;
}
void handle_resume(hwc_context_t* ctx, int dpy) {
- //Treat Resume as Online event
- //Since external didnt have any pipes, force primary to give up
- //its pipes; we don't allow inter-mixer pipe transfers.
- {
- Locker::Autolock _l(ctx->mDrawLock);
-
- // A dynamic resolution change (DRC) can be made for a WiFi
- // display. In order to support the resolution change, we
- // need to reconfigure the corresponding display attributes.
- // Since DRC is only on WiFi display, we only need to call
- // configure() on the VirtualDisplay device.
- if(dpy == HWC_DISPLAY_VIRTUAL)
- ctx->mVirtualDisplay->configure();
-
- ctx->dpyAttr[dpy].isConfiguring = true;
- ctx->dpyAttr[dpy].isActive = true;
- ctx->proc->invalidate(ctx->proc);
- }
- usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
- * 2 / 1000);
- //At this point external has all the pipes it would need.
- {
- Locker::Autolock _l(ctx->mDrawLock);
- ctx->dpyAttr[dpy].isPause = false;
- ctx->proc->invalidate(ctx->proc);
+ if(ctx->mHWCVirtual) {
+ ctx->mHWCVirtual->resume(ctx, dpy);
}
return;
}
@@ -182,9 +137,24 @@
ctx->mVirtualonExtActive = false;
}
}
- /* Wait for few frames for SF to tear down the WFD session. */
- usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
- * 2 / 1000);
+
+ if(ctx->mVDSEnabled) {
+ ctx->mWfdSyncLock.lock();
+ ALOGD_IF(HWC_WFDDISPSYNC_LOG,
+ "%s: Waiting for wfd-teardown to be signalled",__FUNCTION__);
+ ctx->mWfdSyncLock.wait();
+ ALOGD_IF(HWC_WFDDISPSYNC_LOG,
+ "%s: Teardown signalled. Completed waiting in uevent thread",
+ __FUNCTION__);
+ ctx->mWfdSyncLock.unlock();
+ } else {
+ /*TODO: Remove this else block and have wait rather than usleep
+ once wfd module issues binder call on teardown.*/
+
+ /* For now, Wait for few frames for SF to tear down the WFD session.*/
+ usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
+ * 2 / 1000);
+ }
}
static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
@@ -203,7 +173,7 @@
int switch_state = getConnectedState(udata, len);
- ALOGE_IF(UEVENT_DEBUG,"%s: uevent recieved: %s switch state: %d",
+ ALOGE_IF(UEVENT_DEBUG,"%s: uevent received: %s switch state: %d",
__FUNCTION__,udata, switch_state);
switch(switch_state) {
@@ -360,7 +330,7 @@
}
while(1) {
- len = uevent_next_event(udata, sizeof(udata) - 2);
+ len = uevent_next_event(udata, (int)sizeof(udata) - 2);
handle_uevent(ctx, udata, len);
}
diff --git a/msm8226/libhwcomposer/hwc_utils.cpp b/msm8226/libhwcomposer/hwc_utils.cpp
index 4377725..36de703 100644
--- a/msm8226/libhwcomposer/hwc_utils.cpp
+++ b/msm8226/libhwcomposer/hwc_utils.cpp
@@ -83,23 +83,29 @@
(xres < MIN_DISPLAY_XRES || yres < MIN_DISPLAY_YRES));
}
-void changeResolution(hwc_context_t *ctx, int xres_orig, int yres_orig) {
+void changeResolution(hwc_context_t *ctx, int xres_orig, int yres_orig,
+ int width, int height) {
//Store original display resolution.
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres_orig = xres_orig;
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres_orig = yres_orig;
+ ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres_new = xres_orig;
+ ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres_new = yres_orig;
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].customFBSize = false;
-
char property[PROPERTY_VALUE_MAX] = {'\0'};
char *yptr = NULL;
if (property_get("debug.hwc.fbsize", property, NULL) > 0) {
yptr = strcasestr(property,"x");
- int xres = atoi(property);
- int yres = atoi(yptr + 1);
- if (isValidResolution(ctx,xres,yres) &&
- xres != xres_orig && yres != yres_orig) {
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres = xres;
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres = yres;
+ int xres_new = atoi(property);
+ int yres_new = atoi(yptr + 1);
+ if (isValidResolution(ctx,xres_new,yres_new) &&
+ xres_new != xres_orig && yres_new != yres_orig) {
+ ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres_new = xres_new;
+ ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres_new = yres_new;
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].customFBSize = true;
+
+ //Caluculate DPI according to changed resolution.
+ float xdpi = ((float)xres_new * 25.4f) / (float)width;
+ float ydpi = ((float)yres_new * 25.4f) / (float)height;
+ ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xdpi = xdpi;
+ ctx->dpyAttr[HWC_DISPLAY_PRIMARY].ydpi = ydpi;
}
}
}
@@ -125,12 +131,12 @@
if (int(info.width) <= 0 || int(info.height) <= 0) {
// the driver doesn't return that information
// default to 160 dpi
- info.width = ((info.xres * 25.4f)/160.0f + 0.5f);
- info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
+ info.width = (int)(((float)info.xres * 25.4f)/160.0f + 0.5f);
+ info.height = (int)(((float)info.yres * 25.4f)/160.0f + 0.5f);
}
- float xdpi = (info.xres * 25.4f) / info.width;
- float ydpi = (info.yres * 25.4f) / info.height;
+ float xdpi = ((float)info.xres * 25.4f) / (float)info.width;
+ float ydpi = ((float)info.yres * 25.4f) / (float)info.height;
#ifdef MSMFB_METADATA_GET
struct msmfb_metadata metadata;
@@ -144,7 +150,7 @@
return -errno;
}
- float fps = metadata.data.panel_frame_rate;
+ float fps = (float)metadata.data.panel_frame_rate;
#else
//XXX: Remove reserved field usage on all baselines
//The reserved[3] field is used to store FPS by the driver.
@@ -165,10 +171,11 @@
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres = info.yres;
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xdpi = xdpi;
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].ydpi = ydpi;
- ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period = 1000000000l / fps;
+ ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period =
+ (uint32_t)(1000000000l / fps);
//To change resolution of primary display
- changeResolution(ctx, info.xres, info.yres);
+ changeResolution(ctx, info.xres, info.yres, info.width, info.height);
//Unblank primary on first boot
if(ioctl(fb_fd, FBIOBLANK,FB_BLANK_UNBLANK) < 0) {
@@ -183,6 +190,7 @@
void initContext(hwc_context_t *ctx)
{
openFramebufferDevice(ctx);
+ char value[PROPERTY_VALUE_MAX];
ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
@@ -224,7 +232,21 @@
ctx->mMDPComp[HWC_DISPLAY_PRIMARY] =
MDPComp::getObject(ctx, HWC_DISPLAY_PRIMARY);
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].connected = true;
- ctx->mHWCVirtual = HWCVirtualBase::getObject();
+ //Initialize the primary display viewFrame info
+ ctx->mViewFrame[HWC_DISPLAY_PRIMARY].left = 0;
+ ctx->mViewFrame[HWC_DISPLAY_PRIMARY].top = 0;
+ ctx->mViewFrame[HWC_DISPLAY_PRIMARY].right =
+ (int)ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
+ ctx->mViewFrame[HWC_DISPLAY_PRIMARY].bottom =
+ (int)ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
+
+ ctx->mVDSEnabled = false;
+ if((property_get("persist.hwc.enable_vds", value, NULL) > 0)) {
+ if(atoi(value) != 0) {
+ ctx->mVDSEnabled = true;
+ }
+ }
+ ctx->mHWCVirtual = HWCVirtualBase::getObject(ctx->mVDSEnabled);
for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
ctx->mHwcDebug[i] = new HwcDebug(i);
@@ -261,12 +283,15 @@
// Read the system property to determine if downscale feature is enabled.
ctx->mMDPDownscaleEnabled = false;
- char value[PROPERTY_VALUE_MAX];
if(property_get("sys.hwc.mdp_downscale_enabled", value, "false")
&& !strcmp(value, "true")) {
ctx->mMDPDownscaleEnabled = true;
}
+ ctx->enableABC = false;
+ property_get("debug.sf.hwc.canUseABC", value, "0");
+ ctx->enableABC = atoi(value) ? true : false;
+
// Initialize gpu perfomance hint related parameters
property_get("sys.hwc.gpu_perf_mode", value, "0");
#ifdef QCOM_BSP
@@ -274,9 +299,10 @@
ctx->mGPUHintInfo.mEGLDisplay = NULL;
ctx->mGPUHintInfo.mEGLContext = NULL;
- ctx->mGPUHintInfo.mPrevCompositionGLES = false;
+ ctx->mGPUHintInfo.mCompositionState = COMPOSITION_STATE_MDP;
ctx->mGPUHintInfo.mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
#endif
+ memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
ALOGI("Initializing Qualcomm Hardware Composer");
ALOGI("MDP version: %d", ctx->mMDP.version);
}
@@ -391,26 +417,26 @@
float asX = 0;
float asY = 0;
- float asW = fbWidth;
- float asH = fbHeight;
+ float asW = (float)fbWidth;
+ float asH = (float)fbHeight;
// based on the action safe ratio, get the Action safe rectangle
- asW = fbWidth * (1.0f - asWidthRatio / 100.0f);
- asH = fbHeight * (1.0f - asHeightRatio / 100.0f);
- asX = (fbWidth - asW) / 2;
- asY = (fbHeight - asH) / 2;
+ asW = ((float)fbWidth * (1.0f - (float)asWidthRatio / 100.0f));
+ asH = ((float)fbHeight * (1.0f - (float)asHeightRatio / 100.0f));
+ asX = ((float)fbWidth - asW) / 2;
+ asY = ((float)fbHeight - asH) / 2;
// calculate the position ratio
- xRatio = (float)x/fbWidth;
- yRatio = (float)y/fbHeight;
- wRatio = (float)w/fbWidth;
- hRatio = (float)h/fbHeight;
+ xRatio = (float)x/(float)fbWidth;
+ yRatio = (float)y/(float)fbHeight;
+ wRatio = (float)w/(float)fbWidth;
+ hRatio = (float)h/(float)fbHeight;
//Calculate the position...
- x = (xRatio * asW) + asX;
- y = (yRatio * asH) + asY;
- w = (wRatio * asW);
- h = (hRatio * asH);
+ x = int((xRatio * asW) + asX);
+ y = int((yRatio * asH) + asY);
+ w = int(wRatio * asW);
+ h = int(hRatio * asH);
// Convert it back to hwc_rect_t
rect.left = x;
@@ -425,10 +451,9 @@
// based on the position and aspect ratio with orientation
void getAspectRatioPosition(hwc_context_t* ctx, int dpy, int extOrientation,
hwc_rect_t& inRect, hwc_rect_t& outRect) {
- hwc_rect_t viewFrame = ctx->mViewFrame[dpy];
// Physical display resolution
- float fbWidth = ctx->dpyAttr[dpy].xres;
- float fbHeight = ctx->dpyAttr[dpy].yres;
+ float fbWidth = (float)ctx->dpyAttr[dpy].xres;
+ float fbHeight = (float)ctx->dpyAttr[dpy].yres;
//display position(x,y,w,h) in correct aspectratio after rotation
int xPos = 0;
int yPos = 0;
@@ -449,7 +474,7 @@
Dim outPos(outRect.left, outRect.top, outRect.right - outRect.left,
outRect.bottom - outRect.top);
- Whf whf(fbWidth, fbHeight, 0);
+ Whf whf((uint32_t)fbWidth, (uint32_t)fbHeight, 0);
eTransform extorient = static_cast<eTransform>(extOrientation);
// To calculate the destination co-ordinates in the new orientation
preRotateSource(extorient, whf, inPos);
@@ -457,30 +482,23 @@
if(extOrientation & HAL_TRANSFORM_ROT_90) {
// Swap width/height for input position
swapWidthHeight(actualWidth, actualHeight);
- getAspectRatioPosition(fbWidth, fbHeight, (int)actualWidth,
+ getAspectRatioPosition((int)fbWidth, (int)fbHeight, (int)actualWidth,
(int)actualHeight, rect);
xPos = rect.left;
yPos = rect.top;
- width = rect.right - rect.left;
- height = rect.bottom - rect.top;
- // swap viewframe coordinates for 90 degree rotation.
- swap(viewFrame.left, viewFrame.top);
- swap(viewFrame.right, viewFrame.bottom);
+ width = float(rect.right - rect.left);
+ height = float(rect.bottom - rect.top);
}
- // if viewframe left and top coordinates are non zero value then exclude it
- // during the computation of xRatio and yRatio
- xRatio = (inPos.x - viewFrame.left)/actualWidth;
- yRatio = (inPos.y - viewFrame.top)/actualHeight;
- // Use viewframe width and height to compute wRatio and hRatio.
- wRatio = (float)inPos.w/(float)(viewFrame.right - viewFrame.left);
- hRatio = (float)inPos.h/(float)(viewFrame.bottom - viewFrame.top);
+ xRatio = (float)((float)inPos.x/actualWidth);
+ yRatio = (float)((float)inPos.y/actualHeight);
+ wRatio = (float)((float)inPos.w/actualWidth);
+ hRatio = (float)((float)inPos.h/actualHeight);
-
- //Calculate the position...
- outPos.x = (xRatio * width) + xPos;
- outPos.y = (yRatio * height) + yPos;
- outPos.w = wRatio * width;
- outPos.h = hRatio * height;
+ //Calculate the pos9ition...
+ outPos.x = uint32_t((xRatio * width) + (float)xPos);
+ outPos.y = uint32_t((yRatio * height) + (float)yPos);
+ outPos.w = uint32_t(wRatio * width);
+ outPos.h = uint32_t(hRatio * height);
ALOGD_IF(HWC_UTILS_DEBUG, "%s: Calculated AspectRatio Position: x = %d,"
"y = %d w = %d h = %d", __FUNCTION__, outPos.x, outPos.y,
outPos.w, outPos.h);
@@ -493,22 +511,23 @@
isOrientationPortrait(ctx)) {
hwc_rect_t r = {0, 0, 0, 0};
//Calculate the position
- xRatio = (outPos.x - xPos)/width;
+ xRatio = (float)(outPos.x - xPos)/width;
// GetaspectRatio -- tricky to get the correct aspect ratio
// But we need to do this.
- getAspectRatioPosition(width, height, width, height, r);
+ getAspectRatioPosition((int)width, (int)height,
+ (int)width,(int)height, r);
xPos = r.left;
yPos = r.top;
- float tempHeight = r.bottom - r.top;
- yRatio = yPos/height;
- wRatio = outPos.w/width;
+ float tempHeight = float(r.bottom - r.top);
+ yRatio = (float)yPos/height;
+ wRatio = (float)outPos.w/width;
hRatio = tempHeight/height;
//Map the coordinates back to Framebuffer domain
- outPos.x = (xRatio * fbWidth);
- outPos.y = (yRatio * fbHeight);
- outPos.w = wRatio * fbWidth;
- outPos.h = hRatio * fbHeight;
+ outPos.x = uint32_t(xRatio * fbWidth);
+ outPos.y = uint32_t(yRatio * fbHeight);
+ outPos.w = uint32_t(wRatio * fbWidth);
+ outPos.h = uint32_t(hRatio * fbHeight);
ALOGD_IF(HWC_UTILS_DEBUG, "%s: Calculated AspectRatio for device in"
"portrait: x = %d,y = %d w = %d h = %d", __FUNCTION__,
@@ -521,18 +540,18 @@
ctx->mExtDisplay->getAttributes(extW, extH);
else
ctx->mVirtualDisplay->getAttributes(extW, extH);
- fbWidth = ctx->dpyAttr[dpy].xres;
- fbHeight = ctx->dpyAttr[dpy].yres;
+ fbWidth = (float)ctx->dpyAttr[dpy].xres;
+ fbHeight = (float)ctx->dpyAttr[dpy].yres;
//Calculate the position...
- xRatio = outPos.x/fbWidth;
- yRatio = outPos.y/fbHeight;
- wRatio = outPos.w/fbWidth;
- hRatio = outPos.h/fbHeight;
+ xRatio = (float)outPos.x/fbWidth;
+ yRatio = (float)outPos.y/fbHeight;
+ wRatio = (float)outPos.w/fbWidth;
+ hRatio = (float)outPos.h/fbHeight;
- outPos.x = xRatio * extW;
- outPos.y = yRatio * extH;
- outPos.w = wRatio * extW;
- outPos.h = hRatio * extH;
+ outPos.x = uint32_t(xRatio * (float)extW);
+ outPos.y = uint32_t(yRatio * (float)extH);
+ outPos.w = uint32_t(wRatio * (float)extW);
+ outPos.h = uint32_t(hRatio * (float)extH);
}
// Convert Dim to hwc_rect_t
outRect.left = outPos.x;
@@ -568,7 +587,7 @@
ovutils::eTransform& orient) {
// Swap width and height when there is a 90deg transform
int extOrient = getExtOrientation(ctx);
- if(dpy && !qdutils::MDPVersion::getInstance().is8x26()) {
+ if(dpy && ctx->mOverlay->isUIScalingOnExternalSupported()) {
if(!isYuvBuffer(hnd)) {
if(extOrient & HWC_TRANSFORM_ROT_90) {
int dstWidth = ctx->dpyAttr[dpy].xres;
@@ -595,8 +614,8 @@
int extW, extH;
// if downscale is enabled, map the co-ordinates to new
// domain(downscaled)
- float fbWidth = ctx->dpyAttr[dpy].xres;
- float fbHeight = ctx->dpyAttr[dpy].yres;
+ float fbWidth = (float)ctx->dpyAttr[dpy].xres;
+ float fbHeight = (float)ctx->dpyAttr[dpy].yres;
// query MDP configured attributes
if(dpy == HWC_DISPLAY_EXTERNAL)
ctx->mExtDisplay->getAttributes(extW, extH);
@@ -607,10 +626,10 @@
float hRatio = ((float)extH)/fbHeight;
//convert Dim to hwc_rect_t
- displayFrame.left *= wRatio;
- displayFrame.top *= hRatio;
- displayFrame.right *= wRatio;
- displayFrame.bottom *= hRatio;
+ displayFrame.left = int(wRatio*(float)displayFrame.left);
+ displayFrame.top = int(hRatio*(float)displayFrame.top);
+ displayFrame.right = int(wRatio*(float)displayFrame.right);
+ displayFrame.bottom = int(hRatio*(float)displayFrame.bottom);
}
}else {
if(extOrient || ctx->dpyAttr[dpy].mDownScaleMode) {
@@ -648,6 +667,21 @@
return extOrientation;
}
+/* Get External State names */
+const char* getExternalDisplayState(uint32_t external_state) {
+ static const char* externalStates[EXTERNAL_MAXSTATES] = {0};
+ externalStates[EXTERNAL_OFFLINE] = STR(EXTERNAL_OFFLINE);
+ externalStates[EXTERNAL_ONLINE] = STR(EXTERNAL_ONLINE);
+ externalStates[EXTERNAL_PAUSE] = STR(EXTERNAL_PAUSE);
+ externalStates[EXTERNAL_RESUME] = STR(EXTERNAL_RESUME);
+
+ if(external_state >= EXTERNAL_MAXSTATES) {
+ return "EXTERNAL_INVALID";
+ }
+
+ return externalStates[external_state];
+}
+
bool isDownscaleRequired(hwc_layer_1_t const* layer) {
hwc_rect_t displayFrame = layer->displayFrame;
hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
@@ -775,41 +809,19 @@
list->hwLayers[i].transform,
(hwc_rect_t&)crop,
(hwc_rect_t&)list->hwLayers[i].displayFrame);
- layer->sourceCropf.left = crop.left;
- layer->sourceCropf.right = crop.right;
- layer->sourceCropf.top = crop.top;
- layer->sourceCropf.bottom = crop.bottom;
+ layer->sourceCropf.left = (float)crop.left;
+ layer->sourceCropf.right = (float)crop.right;
+ layer->sourceCropf.top = (float)crop.top;
+ layer->sourceCropf.bottom = (float)crop.bottom;
}
}
-hwc_rect_t calculateDisplayViewFrame(hwc_context_t *ctx, int dpy) {
- int dstWidth = ctx->dpyAttr[dpy].xres;
- int dstHeight = ctx->dpyAttr[dpy].yres;
- int srcWidth = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
- int srcHeight = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
- // default we assume viewframe as a full frame for primary display
- hwc_rect outRect = {0, 0, dstWidth, dstHeight};
- if(dpy) {
- // swap srcWidth and srcHeight, if the device orientation is 90 or 270.
- if(ctx->deviceOrientation & 0x1) {
- swap(srcWidth, srcHeight);
- }
- // Get Aspect Ratio for external
- getAspectRatioPosition(dstWidth, dstHeight, srcWidth,
- srcHeight, outRect);
- }
- ALOGD_IF(HWC_UTILS_DEBUG, "%s: view frame for dpy %d is [%d %d %d %d]",
- __FUNCTION__, dpy, outRect.left, outRect.top,
- outRect.right, outRect.bottom);
- return outRect;
-}
-
void setListStats(hwc_context_t *ctx,
hwc_display_contents_1_t *list, int dpy) {
const int prevYuvCount = ctx->listStats[dpy].yuvCount;
memset(&ctx->listStats[dpy], 0, sizeof(ListStats));
- ctx->listStats[dpy].numAppLayers = list->numHwLayers - 1;
- ctx->listStats[dpy].fbLayerIndex = list->numHwLayers - 1;
+ ctx->listStats[dpy].numAppLayers = (int)list->numHwLayers - 1;
+ ctx->listStats[dpy].fbLayerIndex = (int)list->numHwLayers - 1;
ctx->listStats[dpy].skipCount = 0;
ctx->listStats[dpy].preMultipliedAlpha = false;
ctx->listStats[dpy].isSecurePresent = false;
@@ -817,20 +829,15 @@
char property[PROPERTY_VALUE_MAX];
ctx->listStats[dpy].extOnlyLayerIndex = -1;
ctx->listStats[dpy].isDisplayAnimating = false;
- ctx->listStats[dpy].roi = ovutils::Dim(0, 0,
- (int)ctx->dpyAttr[dpy].xres, (int)ctx->dpyAttr[dpy].yres);
ctx->listStats[dpy].secureUI = false;
ctx->listStats[dpy].yuv4k2kCount = 0;
- ctx->mViewFrame[dpy] = (hwc_rect_t){0, 0, 0, 0};
ctx->dpyAttr[dpy].mActionSafePresent = isActionSafePresent(ctx, dpy);
+ ctx->listStats[dpy].renderBufIndexforABC = -1;
+
+ resetROI(ctx, dpy);
trimList(ctx, list, dpy);
optimizeLayerRects(list);
-
- // Calculate view frame of ext display from primary resolution
- // and primary device orientation.
- ctx->mViewFrame[dpy] = calculateDisplayViewFrame(ctx, dpy);
-
for (size_t i = 0; i < (size_t)ctx->listStats[dpy].numAppLayers; i++) {
hwc_layer_1_t const* layer = &list->hwLayers[i];
private_handle_t *hnd = (private_handle_t *)layer->handle;
@@ -861,30 +868,21 @@
if (UNLIKELY(isYuvBuffer(hnd))) {
int& yuvCount = ctx->listStats[dpy].yuvCount;
- ctx->listStats[dpy].yuvIndices[yuvCount] = i;
+ ctx->listStats[dpy].yuvIndices[yuvCount] = (int)i;
yuvCount++;
if(UNLIKELY(is4kx2kYuvBuffer(hnd))){
int& yuv4k2kCount = ctx->listStats[dpy].yuv4k2kCount;
- ctx->listStats[dpy].yuv4k2kIndices[yuv4k2kCount] = i;
+ ctx->listStats[dpy].yuv4k2kIndices[yuv4k2kCount] = (int)i;
yuv4k2kCount++;
}
-
- if((layer->transform & HWC_TRANSFORM_ROT_90) &&
- canUseRotator(ctx, dpy)) {
- if( (dpy == HWC_DISPLAY_PRIMARY) &&
- ctx->mOverlay->isPipeTypeAttached(OV_MDP_PIPE_DMA)) {
- ctx->isPaddingRound = true;
- }
- Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE);
- }
}
if(layer->blending == HWC_BLENDING_PREMULT)
ctx->listStats[dpy].preMultipliedAlpha = true;
if(UNLIKELY(isExtOnly(hnd))){
- ctx->listStats[dpy].extOnlyLayerIndex = i;
+ ctx->listStats[dpy].extOnlyLayerIndex = (int)i;
}
}
if(ctx->listStats[dpy].yuvCount > 0) {
@@ -900,25 +898,6 @@
}
}
}
- if(dpy) {
- //uncomment the below code for testing purpose.
- /* char value[PROPERTY_VALUE_MAX];
- property_get("sys.ext_orientation", value, "0");
- // Assuming the orientation value is in terms of HAL_TRANSFORM,
- // This needs mapping to HAL, if its in different convention
- ctx->mExtOrientation = atoi(value); */
- // Assuming the orientation value is in terms of HAL_TRANSFORM,
- // This needs mapping to HAL, if its in different convention
- if(ctx->mExtOrientation || ctx->mBufferMirrorMode) {
- ALOGD_IF(HWC_UTILS_DEBUG, "%s: ext orientation = %d"
- "BufferMirrorMode = %d", __FUNCTION__,
- ctx->mExtOrientation, ctx->mBufferMirrorMode);
- if(ctx->mOverlay->isPipeTypeAttached(OV_MDP_PIPE_DMA)) {
- ctx->isPaddingRound = true;
- }
- Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE);
- }
- }
//The marking of video begin/end is useful on some targets where we need
//to have a padding round to be able to shift pipes across mixers.
@@ -982,6 +961,32 @@
return false;
}
+bool isRotatorSupportedFormat(private_handle_t *hnd) {
+ // Following rotator src formats are supported by mdp driver
+ // TODO: Add more formats in future, if mdp driver adds support
+ switch(hnd->format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_RGB_888:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ return true;
+ default:
+ return false;
+ }
+ return false;
+}
+
+bool isRotationDoable(hwc_context_t *ctx, private_handle_t *hnd) {
+ // Rotate layers, if it is YUV type or rendered by CPU and not
+ // for the MDP versions below MDP5
+ if((isCPURendered(hnd) && isRotatorSupportedFormat(hnd) &&
+ !ctx->mMDP.version < qdutils::MDSS_V5)
+ || isYuvBuffer(hnd)) {
+ return true;
+ }
+ return false;
+}
+
// returns true if Action safe dimensions are set and target supports Actionsafe
bool isActionSafePresent(hwc_context_t *ctx, int dpy) {
// if external supports underscan, do nothing
@@ -1081,11 +1086,39 @@
return isValidRect(irect);
}
+bool isSameRect(const hwc_rect& rect1, const hwc_rect& rect2)
+{
+ return ((rect1.left == rect2.left) && (rect1.top == rect2.top) &&
+ (rect1.right == rect2.right) && (rect1.bottom == rect2.bottom));
+}
+
bool isValidRect(const hwc_rect& rect)
{
return ((rect.bottom > rect.top) && (rect.right > rect.left)) ;
}
+bool operator ==(const hwc_rect_t& lhs, const hwc_rect_t& rhs) {
+ if(lhs.left == rhs.left && lhs.top == rhs.top &&
+ lhs.right == rhs.right && lhs.bottom == rhs.bottom )
+ return true ;
+ return false;
+}
+
+hwc_rect_t moveRect(const hwc_rect_t& rect, const int& x_off, const int& y_off)
+{
+ hwc_rect_t res;
+
+ if(!isValidRect(rect))
+ return (hwc_rect_t){0, 0, 0, 0};
+
+ res.left = rect.left + x_off;
+ res.top = rect.top + y_off;
+ res.right = rect.right + x_off;
+ res.bottom = rect.bottom + y_off;
+
+ return res;
+}
+
/* computes the intersection of two rects */
hwc_rect_t getIntersection(const hwc_rect_t& rect1, const hwc_rect_t& rect2)
{
@@ -1150,7 +1183,7 @@
}
void optimizeLayerRects(const hwc_display_contents_1_t *list) {
- int i=list->numHwLayers-2;
+ int i= (int)list->numHwLayers-2;
while(i > 0) {
//see if there is no blending required.
//If it is opaque see if we can substract this region from below
@@ -1175,10 +1208,15 @@
qhwc::calculate_crop_rects(bottomCrop, bottomframe,
dest_rect, transform);
//Update layer sourceCropf
- layer->sourceCropf.left = bottomCrop.left;
- layer->sourceCropf.top = bottomCrop.top;
- layer->sourceCropf.right = bottomCrop.right;
- layer->sourceCropf.bottom = bottomCrop.bottom;
+ layer->sourceCropf.left =(float)bottomCrop.left;
+ layer->sourceCropf.top = (float)bottomCrop.top;
+ layer->sourceCropf.right = (float)bottomCrop.right;
+ layer->sourceCropf.bottom = (float)bottomCrop.bottom;
+#ifdef QCOM_BSP
+ //Update layer dirtyRect
+ layer->dirtyRect = getIntersection(bottomCrop,
+ layer->dirtyRect);
+#endif
}
}
j--;
@@ -1191,7 +1229,7 @@
void getNonWormholeRegion(hwc_display_contents_1_t* list,
hwc_rect_t& nwr)
{
- uint32_t last = list->numHwLayers - 1;
+ size_t last = list->numHwLayers - 1;
hwc_rect_t fbDisplayFrame = list->hwLayers[last].displayFrame;
//Initiliaze nwr to first frame
nwr.left = list->hwLayers[0].displayFrame.left;
@@ -1199,7 +1237,7 @@
nwr.right = list->hwLayers[0].displayFrame.right;
nwr.bottom = list->hwLayers[0].displayFrame.bottom;
- for (uint32_t i = 1; i < last; i++) {
+ for (size_t i = 1; i < last; i++) {
hwc_rect_t displayFrame = list->hwLayers[i].displayFrame;
nwr = getUnion(nwr, displayFrame);
}
@@ -1273,11 +1311,15 @@
&currLayer->acquireFenceFd;
rotData.rel_fen_fd = &rotReleaseFd; //driver to populate this
rotData.session_id = currRot->getSessId();
+ if(currLayer->acquireFenceFd >= 0) {
+ rotData.acq_fen_fd_cnt = 1; //1 ioctl call per rot session
+ }
int ret = 0;
ret = ioctl(rotFd, MSMFB_BUFFER_SYNC, &rotData);
if(ret < 0) {
ALOGE("%s: ioctl MSMFB_BUFFER_SYNC failed for rot sync, err=%s",
__FUNCTION__, strerror(errno));
+ close(rotReleaseFd);
} else {
close(currLayer->acquireFenceFd);
//For MDP to wait on.
@@ -1297,11 +1339,20 @@
}
for(uint32_t i = 0; i < list->numHwLayers; i++) {
- if(list->hwLayers[i].compositionType == HWC_OVERLAY &&
+ if(((isAbcInUse(ctx)== true ) ||
+ (list->hwLayers[i].compositionType == HWC_OVERLAY)) &&
list->hwLayers[i].acquireFenceFd >= 0) {
if(UNLIKELY(swapzero))
acquireFd[count++] = -1;
- else
+ // if ABC is enabled for more than one layer.
+ // renderBufIndexforABC will work as FB.Hence
+ // set the acquireFD from fd - which is coming from copybit
+ else if(fd >= 0 && (isAbcInUse(ctx) == true)) {
+ if(ctx->listStats[dpy].renderBufIndexforABC ==(int32_t)i)
+ acquireFd[count++] = fd;
+ else
+ continue;
+ } else
acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
}
if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
@@ -1318,28 +1369,36 @@
}
}
+ if ((fd >= 0) && !dpy && ctx->mPtorInfo.isActive()) {
+ // Acquire c2d fence of Overlap render buffer
+ acquireFd[count++] = fd;
+ }
+
data.acq_fen_fd_cnt = count;
fbFd = ctx->dpyAttr[dpy].fd;
//Waits for acquire fences, returns a release fence
if(LIKELY(!swapzero)) {
- uint64_t start = systemTime();
ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data);
- ALOGD_IF(HWC_UTILS_DEBUG, "%s: time taken for MSMFB_BUFFER_SYNC IOCTL = %d",
- __FUNCTION__, (size_t) ns2ms(systemTime() - start));
}
if(ret < 0) {
ALOGE("%s: ioctl MSMFB_BUFFER_SYNC failed, err=%s",
__FUNCTION__, strerror(errno));
- ALOGE("%s: acq_fen_fd_cnt=%d flags=%d fd=%d dpy=%d numHwLayers=%d",
+ ALOGE("%s: acq_fen_fd_cnt=%d flags=%d fd=%d dpy=%d numHwLayers=%zu",
__FUNCTION__, data.acq_fen_fd_cnt, data.flags, fbFd,
dpy, list->numHwLayers);
+ close(releaseFd);
+ releaseFd = -1;
+ close(retireFd);
+ retireFd = -1;
}
- LayerProp *layerProp = ctx->layerProp[dpy];
for(uint32_t i = 0; i < list->numHwLayers; i++) {
if(list->hwLayers[i].compositionType == HWC_OVERLAY ||
+#ifdef QCOM_BSP
+ list->hwLayers[i].compositionType == HWC_BLIT ||
+#endif
list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
//Populate releaseFenceFds.
if(UNLIKELY(swapzero)) {
@@ -1349,8 +1408,24 @@
// if animation is in progress.
list->hwLayers[i].releaseFenceFd = -1;
} else if(list->hwLayers[i].releaseFenceFd < 0 ) {
+#ifdef QCOM_BSP
//If rotator has not already populated this field
- list->hwLayers[i].releaseFenceFd = dup(releaseFd);
+ // & if it's a not VPU layer
+
+ // if ABC is enabled for more than one layer
+ if(fd >= 0 && (isAbcInUse(ctx) == true) &&
+ ctx->listStats[dpy].renderBufIndexforABC !=(int32_t)i){
+ list->hwLayers[i].releaseFenceFd = dup(fd);
+ } else if((list->hwLayers[i].compositionType == HWC_BLIT)&&
+ (isAbcInUse(ctx) == false)){
+ //For Blit, the app layers should be released when the Blit
+ //is complete. This fd was passed from copybit->draw
+ list->hwLayers[i].releaseFenceFd = dup(fd);
+ } else
+#endif
+ {
+ list->hwLayers[i].releaseFenceFd = dup(releaseFd);
+ }
}
}
}
@@ -1360,8 +1435,12 @@
fd = -1;
}
- if (ctx->mCopyBit[dpy])
- ctx->mCopyBit[dpy]->setReleaseFd(releaseFd);
+ if (!dpy && ctx->mCopyBit[dpy]) {
+ if (ctx->mPtorInfo.isActive())
+ ctx->mCopyBit[dpy]->setReleaseFdSync(releaseFd);
+ else
+ ctx->mCopyBit[dpy]->setReleaseFd(releaseFd);
+ }
//Signals when MDP finishes reading rotator buffers.
ctx->mLayerRotMap[dpy]->setReleaseFd(releaseFd);
@@ -1376,7 +1455,7 @@
return ret;
}
-void setMdpFlags(hwc_layer_1_t *layer,
+void setMdpFlags(hwc_context_t *ctx, hwc_layer_1_t *layer,
ovutils::eMdpFlags &mdpFlags,
int rotDownscale, int transform) {
private_handle_t *hnd = (private_handle_t *)layer->handle;
@@ -1397,11 +1476,6 @@
ovutils::setMdpFlags(mdpFlags,
ovutils::OV_MDP_DEINTERLACE);
}
- //Pre-rotation will be used using rotator.
- if(transform & HWC_TRANSFORM_ROT_90) {
- ovutils::setMdpFlags(mdpFlags,
- ovutils::OV_MDP_SOURCE_ROTATED_90);
- }
}
if(isSecureDisplayBuffer(hnd)) {
@@ -1411,6 +1485,12 @@
ovutils::setMdpFlags(mdpFlags,
ovutils::OV_MDP_SECURE_DISPLAY_OVERLAY_SESSION);
}
+
+ //Pre-rotation will be used using rotator.
+ if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
+ ovutils::setMdpFlags(mdpFlags,
+ ovutils::OV_MDP_SOURCE_ROTATED_90);
+ }
//No 90 component and no rot-downscale then flips done by MDP
//If we use rot then it might as well do flips
if(!(transform & HWC_TRANSFORM_ROT_90) && !rotDownscale) {
@@ -1445,18 +1525,8 @@
if (qdutils::MDPVersion::getInstance().getMDPVersion() >=
qdutils::MDSS_V5) {
- uint32_t crop_w = (crop.right - crop.left);
- uint32_t crop_h = (crop.bottom - crop.top);
- if (ovutils::isYuv(whf.format)) {
- ovutils::normalizeCrop((uint32_t&)crop.left, crop_w);
- ovutils::normalizeCrop((uint32_t&)crop.top, crop_h);
- // For interlaced, crop.h should be 4-aligned
- if ((mdpFlags & ovutils::OV_MDP_DEINTERLACE) && (crop_h % 4))
- crop_h = ovutils::aligndown(crop_h, 4);
- crop.right = crop.left + crop_w;
- crop.bottom = crop.top + crop_h;
- }
- Dim rotCrop(crop.left, crop.top, crop_w, crop_h);
+ Dim rotCrop(crop.left, crop.top, crop.right - crop.left,
+ crop.bottom - crop.top);
rot->setCrop(rotCrop);
}
@@ -1531,28 +1601,27 @@
}
void updateSource(eTransform& orient, Whf& whf,
- hwc_rect_t& crop) {
- Dim srcCrop(crop.left, crop.top,
+ hwc_rect_t& crop, Rotator *rot) {
+ Dim transformedCrop(crop.left, crop.top,
crop.right - crop.left,
crop.bottom - crop.top);
- orient = static_cast<eTransform>(ovutils::getMdpOrient(orient));
- preRotateSource(orient, whf, srcCrop);
if (qdutils::MDPVersion::getInstance().getMDPVersion() >=
qdutils::MDSS_V5) {
- // Source for overlay will be the cropped (and rotated)
- crop.left = 0;
- crop.top = 0;
- crop.right = srcCrop.w;
- crop.bottom = srcCrop.h;
- // Set width & height equal to sourceCrop w & h
- whf.w = srcCrop.w;
- whf.h = srcCrop.h;
+ //B-family rotator internally could modify destination dimensions if
+ //downscaling is supported
+ whf = rot->getDstWhf();
+ transformedCrop = rot->getDstDimensions();
} else {
- crop.left = srcCrop.x;
- crop.top = srcCrop.y;
- crop.right = srcCrop.x + srcCrop.w;
- crop.bottom = srcCrop.y + srcCrop.h;
+ //A-family rotator rotates entire buffer irrespective of crop, forcing
+ //us to recompute the crop based on transform
+ orient = static_cast<eTransform>(ovutils::getMdpOrient(orient));
+ preRotateSource(orient, whf, transformedCrop);
}
+
+ crop.left = transformedCrop.x;
+ crop.top = transformedCrop.y;
+ crop.right = transformedCrop.x + transformedCrop.w;
+ crop.bottom = transformedCrop.y + transformedCrop.h;
}
int configureNonSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
@@ -1579,7 +1648,7 @@
int downscale = 0;
int rotFlags = ovutils::ROT_FLAGS_NONE;
uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
- Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
+ Whf whf(getWidth(hnd), getHeight(hnd), format, (uint32_t)hnd->size);
// Handle R/B swap
if (layer->flags & HWC_FORMAT_RB_SWAP) {
@@ -1603,22 +1672,22 @@
}
}
- setMdpFlags(layer, mdpFlags, downscale, transform);
+ setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
- if(isYuvBuffer(hnd) && //if 90 component or downscale, use rot
- ((transform & HWC_TRANSFORM_ROT_90) || downscale)) {
+ //if 90 component or downscale, use rot
+ if((has90Transform(layer) && isRotationDoable(ctx, hnd)) || downscale) {
*rot = ctx->mRotMgr->getNext();
if(*rot == NULL) return -1;
- if(!dpy)
+ ctx->mLayerRotMap[dpy]->add(layer, *rot);
+ // BWC is not tested for other formats So enable it only for YUV format
+ if(!dpy && isYuvBuffer(hnd))
BwcPM::setBwc(crop, dst, transform, mdpFlags);
//Configure rotator for pre-rotation
if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
ALOGE("%s: configRotator failed!", __FUNCTION__);
return -1;
}
- ctx->mLayerRotMap[dpy]->add(layer, *rot);
- whf.format = (*rot)->getDstFormat();
- updateSource(orient, whf, crop);
+ updateSource(orient, whf, crop, *rot);
rotFlags |= ovutils::ROT_PREROTATED;
}
@@ -1686,7 +1755,7 @@
const int downscale = 0;
int rotFlags = ROT_FLAGS_NONE;
uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
- Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
+ Whf whf(getWidth(hnd), getHeight(hnd), format, (uint32_t)hnd->size);
// Handle R/B swap
if (layer->flags & HWC_FORMAT_RB_SWAP) {
@@ -1700,7 +1769,7 @@
ActionSafe, and extorientation features. */
calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
- setMdpFlags(layer, mdpFlagsL, 0, transform);
+ setMdpFlags(ctx, layer, mdpFlagsL, 0, transform);
if(lDest != OV_INVALID && rDest != OV_INVALID) {
//Enable overfetch
@@ -1714,17 +1783,16 @@
whf.format = wb->getOutputFormat();
}
- if(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) {
+ if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
(*rot) = ctx->mRotMgr->getNext();
if((*rot) == NULL) return -1;
+ ctx->mLayerRotMap[dpy]->add(layer, *rot);
//Configure rotator for pre-rotation
if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
ALOGE("%s: configRotator failed!", __FUNCTION__);
return -1;
}
- ctx->mLayerRotMap[dpy]->add(layer, *rot);
- whf.format = (*rot)->getDstFormat();
- updateSource(orient, whf, crop);
+ updateSource(orient, whf, crop, *rot);
rotFlags |= ROT_PREROTATED;
}
@@ -1736,14 +1804,17 @@
const int lSplit = getLeftSplit(ctx, dpy);
- if(lDest != OV_INVALID) {
+ // Calculate Left rects
+ if(dst.left < lSplit) {
tmp_cropL = crop;
tmp_dstL = dst;
hwc_rect_t scissor = {0, 0, lSplit, hw_h };
scissor = getIntersection(ctx->mViewFrame[dpy], scissor);
qhwc::calculate_crop_rects(tmp_cropL, tmp_dstL, scissor, 0);
}
- if(rDest != OV_INVALID) {
+
+ // Calculate Right rects
+ if(dst.right > lSplit) {
tmp_cropR = crop;
tmp_dstR = dst;
hwc_rect_t scissor = {lSplit, 0, hw_w, hw_h };
@@ -1756,8 +1827,8 @@
//When buffer is H-flipped, contents of mixer config also needs to swapped
//Not needed if the layer is confined to one half of the screen.
//If rotator has been used then it has also done the flips, so ignore them.
- if((orient & OVERLAY_TRANSFORM_FLIP_H) && lDest != OV_INVALID
- && rDest != OV_INVALID && (*rot) == NULL) {
+ if((orient & OVERLAY_TRANSFORM_FLIP_H) && (dst.left < lSplit) &&
+ (dst.right > lSplit) && (*rot) == NULL) {
hwc_rect_t new_cropR;
new_cropR.left = tmp_cropL.left;
new_cropR.right = new_cropR.left + (tmp_cropR.right - tmp_cropR.left);
@@ -1833,28 +1904,28 @@
eZorder rz = (eZorder)(z + 1);
Whf whf(getWidth(hnd), getHeight(hnd),
- getMdpFormat(hnd->format), hnd->size);
+ getMdpFormat(hnd->format), (uint32_t)hnd->size);
/* Calculate the external display position based on MDP downscale,
ActionSafe, and extorientation features. */
calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
- setMdpFlags(layer, mdpFlagsL, 0, transform);
+ setMdpFlags(ctx, layer, mdpFlagsL, 0, transform);
trimLayer(ctx, dpy, transform, crop, dst);
- if(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) {
+ if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
(*rot) = ctx->mRotMgr->getNext();
if((*rot) == NULL) return -1;
- if(!dpy)
+ ctx->mLayerRotMap[dpy]->add(layer, *rot);
+ // BWC is not tested for other formats So enable it only for YUV format
+ if(!dpy && isYuvBuffer(hnd))
BwcPM::setBwc(crop, dst, transform, mdpFlagsL);
//Configure rotator for pre-rotation
if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
ALOGE("%s: configRotator failed!", __FUNCTION__);
return -1;
}
- ctx->mLayerRotMap[dpy]->add(layer, *rot);
- whf.format = (*rot)->getDstFormat();
- updateSource(orient, whf, crop);
+ updateSource(orient, whf, crop, *rot);
rotFlags |= ROT_PREROTATED;
}
@@ -1934,10 +2005,10 @@
}
bool canUseRotator(hwc_context_t *ctx, int dpy) {
- if(qdutils::MDPVersion::getInstance().is8x26() &&
+ if(ctx->mOverlay->isDMAMultiplexingSupported() &&
isSecondaryConnected(ctx) &&
!ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isPause) {
- /* 8x26 mdss driver supports multiplexing of DMA pipe
+ /* mdss driver on certain targets support multiplexing of DMA pipe
* in LINE and BLOCK modes for writeback panels.
*/
if(dpy == HWC_DISPLAY_PRIMARY)
@@ -1980,30 +2051,26 @@
ctx->layerProp[dpy] = new LayerProp[numAppLayers];
}
-/* Since we fake non-Hybrid WFD solution as external display, this
- * function helps us in determining the priority between external
- * (hdmi/non-Hybrid WFD display) and virtual display devices(SSD/
- * screenrecord). This can be removed once wfd-client migrates to
- * using virtual-display api's.
- */
-bool canUseMDPforVirtualDisplay(hwc_context_t* ctx,
- const hwc_display_contents_1_t *list) {
+bool isAbcInUse(hwc_context_t *ctx){
+ return (ctx->enableABC && ctx->listStats[0].renderBufIndexforABC == 0);
+}
- /* We rely on the fact that for pure virtual display solution
- * list->outbuf will be a non-NULL handle.
- *
- * If there are three active displays (which means there is one
- * primary, one external and one virtual active display)
- * we give mdss/mdp hw resources(pipes,smp,etc) for external
- * display(hdmi/non-Hybrid WFD display) rather than for virtual
- * display(SSD/screenrecord)
- */
-
- if(list->outbuf and (ctx->numActiveDisplays == HWC_NUM_DISPLAY_TYPES)) {
- return false;
+void dumpBuffer(private_handle_t *ohnd, char *bufferName) {
+ if (ohnd != NULL && ohnd->base) {
+ char dumpFilename[PATH_MAX];
+ bool bResult = false;
+ snprintf(dumpFilename, sizeof(dumpFilename), "/data/%s.%s.%dx%d.raw",
+ bufferName,
+ overlay::utils::getFormatString(utils::getMdpFormat(ohnd->format)),
+ getWidth(ohnd), getHeight(ohnd));
+ FILE* fp = fopen(dumpFilename, "w+");
+ if (NULL != fp) {
+ bResult = (bool) fwrite((void*)ohnd->base, ohnd->size, 1, fp);
+ fclose(fp);
+ }
+ ALOGD("Buffer[%s] Dump to %s: %s",
+ bufferName, dumpFilename, bResult ? "Success" : "Fail");
}
-
- return true;
}
bool isGLESComp(hwc_context_t *ctx,
@@ -2040,7 +2107,8 @@
}
}
if(isGLESComp(ctx, list)) {
- if(!gpuHint->mPrevCompositionGLES && !MDPComp::isIdleFallback()) {
+ if(gpuHint->mCompositionState != COMPOSITION_STATE_GPU
+ && !MDPComp::isIdleFallback()) {
EGLint attr_list[] = {EGL_GPU_HINT_1,
EGL_GPU_LEVEL_3,
EGL_NONE };
@@ -2050,7 +2118,7 @@
ALOGW("eglGpuPerfHintQCOM failed for Built in display");
} else {
gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_3;
- gpuHint->mPrevCompositionGLES = true;
+ gpuHint->mCompositionState = COMPOSITION_STATE_GPU;
}
} else {
EGLint attr_list[] = {EGL_GPU_HINT_1,
@@ -2063,6 +2131,9 @@
} else {
gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
}
+ if(MDPComp::isIdleFallback()) {
+ gpuHint->mCompositionState = COMPOSITION_STATE_IDLE_FALLBACK;
+ }
}
} else {
/* set the GPU hint flag to default for MDP composition */
@@ -2076,11 +2147,25 @@
} else {
gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
}
- gpuHint->mPrevCompositionGLES = false;
+ gpuHint->mCompositionState = COMPOSITION_STATE_MDP;
}
#endif
}
+bool isPeripheral(const hwc_rect_t& rect1, const hwc_rect_t& rect2) {
+ // To be peripheral, 3 boundaries should match.
+ uint8_t eqBounds = 0;
+ if (rect1.left == rect2.left)
+ eqBounds++;
+ if (rect1.top == rect2.top)
+ eqBounds++;
+ if (rect1.right == rect2.right)
+ eqBounds++;
+ if (rect1.bottom == rect2.bottom)
+ eqBounds++;
+ return (eqBounds == 3);
+}
+
void BwcPM::setBwc(const hwc_rect_t& crop,
const hwc_rect_t& dst, const int& transform,
ovutils::eMdpFlags& mdpFlags) {
@@ -2088,30 +2173,23 @@
if(!qdutils::MDPVersion::getInstance().supportsBWC()) {
return;
}
+ int src_w = crop.right - crop.left;
+ int src_h = crop.bottom - crop.top;
+ int dst_w = dst.right - dst.left;
+ int dst_h = dst.bottom - dst.top;
+ if(transform & HAL_TRANSFORM_ROT_90) {
+ swap(src_w, src_h);
+ }
//src width > MAX mixer supported dim
- if((crop.right - crop.left) > qdutils::MAX_DISPLAY_DIM) {
+ if(src_w > qdutils::MAX_DISPLAY_DIM) {
return;
}
//Decimation necessary, cannot use BWC. H/W requirement.
if(qdutils::MDPVersion::getInstance().supportsDecimation()) {
- int src_w = crop.right - crop.left;
- int src_h = crop.bottom - crop.top;
- int dst_w = dst.right - dst.left;
- int dst_h = dst.bottom - dst.top;
- if(transform & HAL_TRANSFORM_ROT_90) {
- swap(src_w, src_h);
- }
- float horDscale = 0.0f;
- float verDscale = 0.0f;
- int horzDeci = 0;
- int vertDeci = 0;
- ovutils::getDecimationFactor(src_w, src_h, dst_w, dst_h, horDscale,
- verDscale);
- //TODO Use log2f once math.h has it
- if((int)horDscale)
- horzDeci = (int)(log(horDscale) / log(2));
- if((int)verDscale)
- vertDeci = (int)(log(verDscale) / log(2));
+ uint8_t horzDeci = 0;
+ uint8_t vertDeci = 0;
+ ovutils::getDecimationFactor(src_w, src_h, dst_w, dst_h, horzDeci,
+ vertDeci);
if(horzDeci || vertDeci) return;
}
//Property
@@ -2148,4 +2226,88 @@
}
}
+void resetROI(hwc_context_t *ctx, const int dpy) {
+ const int fbXRes = (int)ctx->dpyAttr[dpy].xres;
+ const int fbYRes = (int)ctx->dpyAttr[dpy].yres;
+ if(isDisplaySplit(ctx, dpy)) {
+ const int lSplit = getLeftSplit(ctx, dpy);
+ ctx->listStats[dpy].lRoi = (struct hwc_rect){0, 0, lSplit, fbYRes};
+ ctx->listStats[dpy].rRoi = (struct hwc_rect){lSplit, 0, fbXRes, fbYRes};
+ } else {
+ ctx->listStats[dpy].lRoi = (struct hwc_rect){0, 0,fbXRes, fbYRes};
+ ctx->listStats[dpy].rRoi = (struct hwc_rect){0, 0, 0, 0};
+ }
+}
+
+hwc_rect_t getSanitizeROI(struct hwc_rect roi, hwc_rect boundary)
+{
+ if(!isValidRect(roi))
+ return roi;
+
+ struct hwc_rect t_roi = roi;
+
+ const int LEFT_ALIGN = qdutils::MDPVersion::getInstance().getLeftAlign();
+ const int WIDTH_ALIGN = qdutils::MDPVersion::getInstance().getWidthAlign();
+ const int TOP_ALIGN = qdutils::MDPVersion::getInstance().getTopAlign();
+ const int HEIGHT_ALIGN = qdutils::MDPVersion::getInstance().getHeightAlign();
+ const int MIN_WIDTH = qdutils::MDPVersion::getInstance().getMinROIWidth();
+ const int MIN_HEIGHT = qdutils::MDPVersion::getInstance().getMinROIHeight();
+
+ /* Align to minimum width recommended by the panel */
+ if((t_roi.right - t_roi.left) < MIN_WIDTH) {
+ if((t_roi.left + MIN_WIDTH) > boundary.right)
+ t_roi.left = t_roi.right - MIN_WIDTH;
+ else
+ t_roi.right = t_roi.left + MIN_WIDTH;
+ }
+
+ /* Align to minimum height recommended by the panel */
+ if((t_roi.bottom - t_roi.top) < MIN_HEIGHT) {
+ if((t_roi.top + MIN_HEIGHT) > boundary.bottom)
+ t_roi.top = t_roi.bottom - MIN_HEIGHT;
+ else
+ t_roi.bottom = t_roi.top + MIN_HEIGHT;
+ }
+
+ /* Align left and width to meet panel restrictions */
+ if(LEFT_ALIGN)
+ t_roi.left = t_roi.left - (t_roi.left % LEFT_ALIGN);
+
+ if(WIDTH_ALIGN) {
+ int width = t_roi.right - t_roi.left;
+ width = WIDTH_ALIGN * ((width + (WIDTH_ALIGN - 1)) / WIDTH_ALIGN);
+ t_roi.right = t_roi.left + width;
+
+ if(t_roi.right > boundary.right) {
+ t_roi.right = boundary.right;
+ t_roi.left = t_roi.right - width;
+
+ if(LEFT_ALIGN)
+ t_roi.left = t_roi.left - (t_roi.left % LEFT_ALIGN);
+ }
+ }
+
+
+ /* Align top and height to meet panel restrictions */
+ if(TOP_ALIGN)
+ t_roi.top = t_roi.top - (t_roi.top % TOP_ALIGN);
+
+ if(HEIGHT_ALIGN) {
+ int height = t_roi.bottom - t_roi.top;
+ height = HEIGHT_ALIGN * ((height + (HEIGHT_ALIGN - 1)) / HEIGHT_ALIGN);
+ t_roi.bottom = t_roi.top + height;
+
+ if(t_roi.bottom > boundary.bottom) {
+ t_roi.bottom = boundary.bottom;
+ t_roi.top = t_roi.bottom - height;
+
+ if(TOP_ALIGN)
+ t_roi.top = t_roi.top - (t_roi.top % TOP_ALIGN);
+ }
+ }
+
+
+ return t_roi;
+}
+
};//namespace qhwc
diff --git a/msm8226/libhwcomposer/hwc_utils.h b/msm8226/libhwcomposer/hwc_utils.h
index ad023ad..dd55f8b 100644
--- a/msm8226/libhwcomposer/hwc_utils.h
+++ b/msm8226/libhwcomposer/hwc_utils.h
@@ -39,6 +39,10 @@
#define MAX_NUM_APP_LAYERS 32
#define MIN_DISPLAY_XRES 200
#define MIN_DISPLAY_YRES 200
+#define HWC_WFDDISPSYNC_LOG 0
+#define STR(f) #f;
+// Max number of PTOR layers handled
+#define MAX_PTOR_LAYERS 2
//Fwrd decls
struct hwc_context_t;
@@ -102,8 +106,8 @@
//If property fbsize set via adb shell debug.hwc.fbsize = XRESxYRES
//following fields are used.
bool customFBSize;
- uint32_t xres_orig;
- uint32_t yres_orig;
+ uint32_t xres_new;
+ uint32_t yres_new;
};
@@ -121,9 +125,29 @@
// Notifies hwcomposer about the start and end of animation
// This will be set to true during animation, otherwise false.
bool isDisplayAnimating;
- ovutils::Dim roi;
bool secureUI; // Secure display layer
bool isSecurePresent;
+ hwc_rect_t lRoi; //left ROI
+ hwc_rect_t rRoi; //right ROI. Unused in single DSI panels.
+ //App Buffer Composition index
+ int renderBufIndexforABC;
+};
+
+//PTOR Comp info
+struct PtorInfo {
+ int count;
+ int layerIndex[MAX_PTOR_LAYERS];
+ int mRenderBuffOffset[MAX_PTOR_LAYERS];
+ hwc_rect_t displayFrame[MAX_PTOR_LAYERS];
+ bool isActive() { return (count>0); }
+ int getPTORArrayIndex(int index) {
+ int idx = -1;
+ for(int i = 0; i < count; i++) {
+ if(index == layerIndex[i])
+ idx = i;
+ }
+ return idx;
+ }
};
struct LayerProp {
@@ -134,6 +158,7 @@
struct VsyncState {
bool enable;
bool fakevsync;
+ bool debug;
};
struct BwcPM {
@@ -154,6 +179,15 @@
HWC_FORMAT_RB_SWAP = 0x00000040,
};
+/* External Display states */
+enum {
+ EXTERNAL_OFFLINE = 0,
+ EXTERNAL_ONLINE,
+ EXTERNAL_PAUSE,
+ EXTERNAL_RESUME,
+ EXTERNAL_MAXSTATES
+};
+
class LayerRotMap {
public:
LayerRotMap() { reset(); }
@@ -189,7 +223,7 @@
}
inline hwc_rect_t integerizeSourceCrop(const hwc_frect_t& cropF) {
- hwc_rect_t cropI = {0};
+ hwc_rect_t cropI = {0,0,0,0};
cropI.left = int(ceilf(cropF.left));
cropI.top = int(ceilf(cropF.top));
cropI.right = int(floorf(cropF.right));
@@ -210,11 +244,6 @@
// -----------------------------------------------------------------------------
// Utility functions - implemented in hwc_utils.cpp
void dumpLayer(hwc_layer_1_t const* l);
-
-// Calculate viewframe for external/primary display from primary resolution and
-// primary device orientation
-hwc_rect_t calculateDisplayViewFrame(hwc_context_t *ctx, int dpy);
-
void setListStats(hwc_context_t *ctx, hwc_display_contents_1_t *list,
int dpy);
void initContext(hwc_context_t *ctx);
@@ -226,6 +255,10 @@
hwc_rect_t& nwr);
bool isSecuring(hwc_context_t* ctx, hwc_layer_1_t const* layer);
bool isSecureModePolicy(int mdpVersion);
+// Returns true, if the input layer format is supported by rotator
+bool isRotatorSupportedFormat(private_handle_t *hnd);
+//Returns true, if the layer is YUV or the layer has been rendered by CPU
+bool isRotationDoable(hwc_context_t *ctx, private_handle_t *hnd);
bool isExternalActive(hwc_context_t* ctx);
bool isAlphaScaled(hwc_layer_1_t const* layer);
bool needsScaling(hwc_layer_1_t const* layer);
@@ -239,9 +272,9 @@
int getBlending(int blending);
bool isGLESOnlyComp(hwc_context_t *ctx, const int& dpy);
void reset_layer_prop(hwc_context_t* ctx, int dpy, int numAppLayers);
+bool isAbcInUse(hwc_context_t *ctx);
-bool canUseMDPforVirtualDisplay(hwc_context_t* ctx,
- const hwc_display_contents_1_t *list);
+void dumpBuffer(private_handle_t *ohnd, char *bufferName);
//Helper function to dump logs
void dumpsys_log(android::String8& buf, const char* fmt, ...);
@@ -249,11 +282,14 @@
int getExtOrientation(hwc_context_t* ctx);
bool isValidRect(const hwc_rect_t& rect);
hwc_rect_t deductRect(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
+bool isSameRect(const hwc_rect& rect1, const hwc_rect& rect2);
+hwc_rect_t moveRect(const hwc_rect_t& rect, const int& x_off, const int& y_off);
hwc_rect_t getIntersection(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
hwc_rect_t getUnion(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
void optimizeLayerRects(const hwc_display_contents_1_t *list);
bool areLayersIntersecting(const hwc_layer_1_t* layer1,
const hwc_layer_1_t* layer2);
+bool operator ==(const hwc_rect_t& lhs, const hwc_rect_t& rhs);
// returns true if Action safe dimensions are set and target supports Actionsafe
bool isActionSafePresent(hwc_context_t *ctx, int dpy);
@@ -280,6 +316,15 @@
// BufferMirrirMode(Sidesync)
int getMirrorModeOrientation(hwc_context_t *ctx);
+/* Get External State names */
+const char* getExternalDisplayState(uint32_t external_state);
+
+// Resets display ROI to full panel resoluion
+void resetROI(hwc_context_t *ctx, const int dpy);
+
+// Aligns updating ROI to panel restrictions
+hwc_rect_t getSanitizeROI(struct hwc_rect roi, hwc_rect boundary);
+
// Handles wfd Pause and resume events
void handle_pause(hwc_context_t *ctx, int dpy);
void handle_resume(hwc_context_t *ctx, int dpy);
@@ -292,7 +337,7 @@
int fd);
//Sets appropriate mdp flags for a layer.
-void setMdpFlags(hwc_layer_1_t *layer,
+void setMdpFlags(hwc_context_t *ctx, hwc_layer_1_t *layer,
ovutils::eMdpFlags &mdpFlags,
int rotDownscale, int transform);
@@ -310,7 +355,7 @@
ovutils::eIsFg& isFg, const ovutils::eDest& dest);
void updateSource(ovutils::eTransform& orient, ovutils::Whf& whf,
- hwc_rect_t& crop);
+ hwc_rect_t& crop, overlay::Rotator *rot);
//Routine to configure low resolution panels (<= 2048 width)
int configureNonSplit(hwc_context_t *ctx, hwc_layer_1_t *layer, const int& dpy,
@@ -349,6 +394,9 @@
// due to idle fallback or MDP composition.
void setGPUHint(hwc_context_t* ctx, hwc_display_contents_1_t* list);
+// Returns true if rect1 is peripheral to rect2, false otherwise.
+bool isPeripheral(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
+
// Inline utility functions
static inline bool isSkipLayer(const hwc_layer_1_t* l) {
return (UNLIKELY(l && (l->flags & HWC_SKIP_LAYER)));
@@ -374,6 +422,10 @@
return (hnd && (private_handle_t::PRIV_FLAGS_TILE_RENDERED & hnd->flags));
}
+static inline bool isCPURendered(const private_handle_t* hnd) {
+ return (hnd && (private_handle_t::PRIV_FLAGS_CPU_RENDERED & hnd->flags));
+}
+
//Return true if buffer is marked locked
static inline bool isBufferLocked(const private_handle_t* hnd) {
return (hnd && (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags));
@@ -447,14 +499,20 @@
ANIMATION_STARTED,
};
+enum eCompositionState {
+ COMPOSITION_STATE_MDP = 0, // Set if composition type is MDP
+ COMPOSITION_STATE_GPU, // Set if composition type is GPU or MIXED
+ COMPOSITION_STATE_IDLE_FALLBACK, // Set if it is idlefallback
+};
+
// Structure holds the information about the GPU hint.
struct gpu_hint_info {
// system level flag to enable gpu_perf_mode
bool mGpuPerfModeEnable;
// Stores the current GPU performance mode DEFAULT/HIGH
bool mCurrGPUPerfMode;
- // true if previous composition used GPU
- bool mPrevCompositionGLES;
+ // Stores the compositon state GPU, MDP or IDLE_FALLBACK
+ bool mCompositionState;
// Stores the EGLContext of current process
EGLContext mEGLContext;
// Stores the EGLDisplay of current process
@@ -516,15 +574,26 @@
//Used for SideSync feature
//which overrides the mExtOrientation
bool mBufferMirrorMode;
+ // Used to synchronize between WFD and Display modules
+ mutable Locker mWfdSyncLock;
+
qhwc::LayerRotMap *mLayerRotMap[HWC_NUM_DISPLAY_TYPES];
// Panel reset flag will be set if BTA check fails
bool mPanelResetStatus;
// number of active Displays
int numActiveDisplays;
- // Downscale feature switch, set via system the property
+ // Downscale feature switch, set via system property
// sys.hwc.mdp_downscale_enabled
bool mMDPDownscaleEnabled;
+ // Is WFD enabled through VDS solution ?
+ // This can be set via system property
+ // persist.hwc.enable_vds
+ bool mVDSEnabled;
struct gpu_hint_info mGPUHintInfo;
+ //App Buffer Composition
+ bool enableABC;
+ // PTOR Info
+ qhwc::PtorInfo mPtorInfo;
};
namespace qhwc {
@@ -536,7 +605,7 @@
return ctx->listStats[dpy].yuvCount;
}
-static inline bool has90Transform(hwc_layer_1_t *layer) {
+static inline bool has90Transform(hwc_layer_1_t const* layer) {
return ((layer->transform & HWC_TRANSFORM_ROT_90) &&
!(layer->flags & HWC_COLOR_FILL));
}
diff --git a/msm8226/libhwcomposer/hwc_virtual.cpp b/msm8226/libhwcomposer/hwc_virtual.cpp
index cc29d45..f8f3b45 100644
--- a/msm8226/libhwcomposer/hwc_virtual.cpp
+++ b/msm8226/libhwcomposer/hwc_virtual.cpp
@@ -29,25 +29,34 @@
#include "hwc_dump_layers.h"
#include "hwc_copybit.h"
#include "hwc_virtual.h"
+#include "sync/sync.h"
#define HWCVIRTUAL_LOG 0
using namespace qhwc;
using namespace overlay;
-HWCVirtualBase* HWCVirtualBase::getObject() {
- char property[PROPERTY_VALUE_MAX];
+HWCVirtualBase* HWCVirtualBase::getObject(bool isVDSEnabled) {
- if((property_get("persist.hwc.enable_vds", property, NULL) > 0)) {
- if(atoi(property) != 0) {
- ALOGD_IF(HWCVIRTUAL_LOG, "%s: VDS is enabled for Virtual display",
- __FUNCTION__);
- return new HWCVirtualVDS();
+ if(isVDSEnabled) {
+ ALOGD_IF(HWCVIRTUAL_LOG, "%s: VDS is enabled for Virtual display",
+ __FUNCTION__);
+ return new HWCVirtualVDS();
+ } else {
+ ALOGD_IF(HWCVIRTUAL_LOG, "%s: V4L2 is enabled for Virtual display",
+ __FUNCTION__);
+ return new HWCVirtualV4L2();
+ }
+}
+
+HWCVirtualVDS::HWCVirtualVDS() {
+ char value[PROPERTY_VALUE_MAX];
+ mVDSDumpEnabled = false;
+ if((property_get("debug.hwc.enable_vds_dump", value, NULL) > 0)) {
+ if(atoi(value) != 0) {
+ mVDSDumpEnabled = true;
}
}
- ALOGD_IF(HWCVIRTUAL_LOG, "%s: V4L2 is enabled for Virtual display",
- __FUNCTION__);
- return new HWCVirtualV4L2();
}
void HWCVirtualVDS::init(hwc_context_t *ctx) {
@@ -69,6 +78,7 @@
//Cleanup virtual display objs, since there is no explicit disconnect
if(ctx->dpyAttr[dpy].connected && (displays[dpy] == NULL)) {
ctx->dpyAttr[dpy].connected = false;
+ ctx->dpyAttr[dpy].isPause = false;
if(ctx->mFBUpdate[dpy]) {
delete ctx->mFBUpdate[dpy];
@@ -83,6 +93,9 @@
if(!Writeback::getInstance()->setSecure(false)) {
ALOGE("Failure while attempting to reset WB session.");
}
+ ctx->mWfdSyncLock.lock();
+ ctx->mWfdSyncLock.signal();
+ ctx->mWfdSyncLock.unlock();
}
}
@@ -94,8 +107,8 @@
const int dpy = HWC_DISPLAY_VIRTUAL;
if (list && list->outbuf && list->numHwLayers > 0) {
- reset_layer_prop(ctx, dpy, list->numHwLayers - 1);
- uint32_t last = list->numHwLayers - 1;
+ reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
+ uint32_t last = (uint32_t)list->numHwLayers - 1;
hwc_layer_1_t *fbLayer = &list->hwLayers[last];
int fbWidth = 0, fbHeight = 0;
getLayerResolution(fbLayer, fbWidth, fbHeight);
@@ -104,6 +117,7 @@
if(ctx->dpyAttr[dpy].connected == false) {
ctx->dpyAttr[dpy].connected = true;
+ ctx->dpyAttr[dpy].isPause = false;
// We set the vsync period to the primary refresh rate, leaving
// it up to the consumer to decide how fast to consume frames.
ctx->dpyAttr[dpy].vsync_period
@@ -113,16 +127,32 @@
// allow one padding round to free up resources but this breaks
// certain use cases.
}
+ if(!ctx->dpyAttr[dpy].isPause) {
+ ctx->dpyAttr[dpy].isConfiguring = false;
+ ctx->dpyAttr[dpy].fd = Writeback::getInstance()->getFbFd();
+ private_handle_t *ohnd = (private_handle_t *)list->outbuf;
+ Writeback::getInstance()->configureDpyInfo(ohnd->width,
+ ohnd->height);
+ setListStats(ctx, list, dpy);
- ctx->dpyAttr[dpy].isConfiguring = false;
- ctx->dpyAttr[dpy].fd = Writeback::getInstance()->getFbFd();
- private_handle_t *ohnd = (private_handle_t *)list->outbuf;
- Writeback::getInstance()->configureDpyInfo(ohnd->width, ohnd->height);
- setListStats(ctx, list, dpy);
-
- if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
- const int fbZ = 0;
- ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
+ if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
+ const int fbZ = 0;
+ if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
+ {
+ ctx->mOverlay->clear(dpy);
+ ctx->mLayerRotMap[dpy]->clear();
+ }
+ }
+ } else {
+ /* Virtual Display is in Pause state.
+ * Mark all application layers as OVERLAY so that
+ * GPU will not compose.
+ */
+ Writeback::getInstance(); //Ensure that WB is active during pause
+ for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) {
+ hwc_layer_1_t *layer = &list->hwLayers[i];
+ layer->compositionType = HWC_OVERLAY;
+ }
}
}
return 0;
@@ -134,10 +164,12 @@
const int dpy = HWC_DISPLAY_VIRTUAL;
if (list && list->outbuf && list->numHwLayers > 0) {
- uint32_t last = list->numHwLayers - 1;
+ uint32_t last = (uint32_t)list->numHwLayers - 1;
hwc_layer_1_t *fbLayer = &list->hwLayers[last];
- if(ctx->dpyAttr[dpy].connected) {
+ if(ctx->dpyAttr[dpy].connected
+ && (!ctx->dpyAttr[dpy].isPause))
+ {
private_handle_t *ohnd = (private_handle_t *)list->outbuf;
int format = ohnd->format;
if (format == HAL_PIXEL_FORMAT_RGBA_8888)
@@ -157,6 +189,10 @@
int fd = -1; //FenceFD from the Copybit
hwc_sync(ctx, list, dpy, fd);
+ // Dump the layers for virtual
+ if(ctx->mHwcDebug[dpy])
+ ctx->mHwcDebug[dpy]->dumpLayers(list);
+
if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
ALOGE("%s: MDPComp draw failed", __FUNCTION__);
ret = -1;
@@ -173,12 +209,26 @@
ret = -1;
}
- Writeback::getInstance()->queueBuffer(ohnd->fd, ohnd->offset);
+ Writeback::getInstance()->queueBuffer(ohnd->fd,
+ (uint32_t)ohnd->offset);
if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
ALOGE("%s: display commit fail!", __FUNCTION__);
ret = -1;
}
+ if(mVDSDumpEnabled) {
+ char bufferName[128];
+ // Dumping frame buffer
+ sync_wait(fbLayer->acquireFenceFd, 1000);
+ snprintf(bufferName, sizeof(bufferName), "vds.fb");
+ dumpBuffer((private_handle_t *)fbLayer->handle, bufferName);
+ // Dumping WB output for non-secure session
+ if(!isSecureBuffer(ohnd)) {
+ sync_wait(list->retireFenceFd, 1000);
+ snprintf(bufferName, sizeof(bufferName), "vds.wb");
+ dumpBuffer(ohnd, bufferName);
+ }
+ }
} else if(list->outbufAcquireFenceFd >= 0) {
//If we dont handle the frame, set retireFenceFd to outbufFenceFd,
//which will make sure, the framework waits on it and closes it.
@@ -194,6 +244,47 @@
return ret;
}
+void HWCVirtualVDS::pause(hwc_context_t* ctx, int dpy) {
+ {
+ Locker::Autolock _l(ctx->mDrawLock);
+ ctx->dpyAttr[dpy].isActive = true;
+ ctx->dpyAttr[dpy].isPause = true;
+ ctx->proc->invalidate(ctx->proc);
+ }
+ usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
+ * 2 / 1000);
+ // At this point all the pipes used by External have been
+ // marked as UNSET.
+ {
+ Locker::Autolock _l(ctx->mDrawLock);
+ // Perform commit to unstage the pipes.
+ if (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
+ ALOGE("%s: display commit fail! for %d dpy",
+ __FUNCTION__, dpy);
+ }
+ ctx->proc->invalidate(ctx->proc);
+ }
+ return;
+}
+
+void HWCVirtualVDS::resume(hwc_context_t* ctx, int dpy) {
+ {
+ Locker::Autolock _l(ctx->mDrawLock);
+ ctx->dpyAttr[dpy].isConfiguring = true;
+ ctx->dpyAttr[dpy].isActive = true;
+ ctx->proc->invalidate(ctx->proc);
+ }
+ usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
+ * 2 / 1000);
+ //At this point external has all the pipes it would need.
+ {
+ Locker::Autolock _l(ctx->mDrawLock);
+ ctx->dpyAttr[dpy].isPause = false;
+ ctx->proc->invalidate(ctx->proc);
+ }
+ return;
+}
+
/* Implementation for HWCVirtualV4L2 class */
int HWCVirtualV4L2::prepare(hwc_composer_device_1 *dev,
@@ -205,15 +296,18 @@
if (LIKELY(list && list->numHwLayers > 1) &&
ctx->dpyAttr[dpy].isActive &&
- ctx->dpyAttr[dpy].connected &&
- canUseMDPforVirtualDisplay(ctx,list)) {
- reset_layer_prop(ctx, dpy, list->numHwLayers - 1);
+ ctx->dpyAttr[dpy].connected) {
+ reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
if(!ctx->dpyAttr[dpy].isPause) {
ctx->dpyAttr[dpy].isConfiguring = false;
setListStats(ctx, list, dpy);
if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
const int fbZ = 0;
- ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
+ if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
+ {
+ ctx->mOverlay->clear(dpy);
+ ctx->mLayerRotMap[dpy]->clear();
+ }
}
} else {
/* Virtual Display is in Pause state.
@@ -237,9 +331,8 @@
if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
ctx->dpyAttr[dpy].connected &&
- (!ctx->dpyAttr[dpy].isPause) &&
- canUseMDPforVirtualDisplay(ctx,list)) {
- uint32_t last = list->numHwLayers - 1;
+ !ctx->dpyAttr[dpy].isPause) {
+ uint32_t last = (uint32_t)list->numHwLayers - 1;
hwc_layer_1_t *fbLayer = &list->hwLayers[last];
int fd = -1; //FenceFD from the Copybit(valid in async mode)
bool copybitDone = false;
@@ -294,3 +387,56 @@
return ret;
}
+
+void HWCVirtualV4L2::pause(hwc_context_t* ctx, int dpy) {
+ {
+ Locker::Autolock _l(ctx->mDrawLock);
+ ctx->dpyAttr[dpy].isActive = true;
+ ctx->dpyAttr[dpy].isPause = true;
+ ctx->proc->invalidate(ctx->proc);
+ }
+ usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
+ * 2 / 1000);
+ // At this point all the pipes used by External have been
+ // marked as UNSET.
+ {
+ Locker::Autolock _l(ctx->mDrawLock);
+ // Perform commit to unstage the pipes.
+ if (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
+ ALOGE("%s: display commit fail! for %d dpy",
+ __FUNCTION__, dpy);
+ }
+ }
+ return;
+}
+
+void HWCVirtualV4L2::resume(hwc_context_t* ctx, int dpy){
+ //Treat Resume as Online event
+ //Since external didnt have any pipes, force primary to give up
+ //its pipes; we don't allow inter-mixer pipe transfers.
+ {
+ Locker::Autolock _l(ctx->mDrawLock);
+
+ // A dynamic resolution change (DRC) can be made for a WiFi
+ // display. In order to support the resolution change, we
+ // need to reconfigure the corresponding display attributes.
+ // Since DRC is only on WiFi display, we only need to call
+ // configure() on the VirtualDisplay device.
+ //TODO: clean up
+ if(dpy == HWC_DISPLAY_VIRTUAL)
+ ctx->mVirtualDisplay->configure();
+
+ ctx->dpyAttr[dpy].isConfiguring = true;
+ ctx->dpyAttr[dpy].isActive = true;
+ ctx->proc->invalidate(ctx->proc);
+ }
+ usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
+ * 2 / 1000);
+ //At this point external has all the pipes it would need.
+ {
+ Locker::Autolock _l(ctx->mDrawLock);
+ ctx->dpyAttr[dpy].isPause = false;
+ ctx->proc->invalidate(ctx->proc);
+ }
+ return;
+}
diff --git a/msm8226/libhwcomposer/hwc_virtual.h b/msm8226/libhwcomposer/hwc_virtual.h
index 26f401f..26d89c9 100644
--- a/msm8226/libhwcomposer/hwc_virtual.h
+++ b/msm8226/libhwcomposer/hwc_virtual.h
@@ -22,6 +22,7 @@
#define HWC_VIRTUAL
#include <hwc_utils.h>
+#include <virtual.h>
namespace qhwc {
namespace ovutils = overlay::utils;
@@ -32,18 +33,20 @@
explicit HWCVirtualBase(){};
virtual ~HWCVirtualBase(){};
// instantiates and returns the pointer to VDS or V4L2 object.
- static HWCVirtualBase* getObject();
+ static HWCVirtualBase* getObject(bool isVDSEnabled);
virtual int prepare(hwc_composer_device_1 *dev,
hwc_display_contents_1_t* list) = 0;
virtual int set(hwc_context_t *ctx, hwc_display_contents_1_t *list) = 0;
virtual void init(hwc_context_t *ctx) = 0;
virtual void destroy(hwc_context_t *ctx, size_t numDisplays,
hwc_display_contents_1_t** displays) = 0;
+ virtual void pause(hwc_context_t* ctx, int dpy) = 0;
+ virtual void resume(hwc_context_t* ctx, int dpy) = 0;
};
class HWCVirtualVDS : public HWCVirtualBase {
public:
- explicit HWCVirtualVDS(){};
+ explicit HWCVirtualVDS();
virtual ~HWCVirtualVDS(){};
// Chooses composition type and configures pipe for each layer in virtual
// display list
@@ -59,6 +62,14 @@
// during virtual display disconnect.
virtual void destroy(hwc_context_t *ctx, size_t numDisplays,
hwc_display_contents_1_t** displays);
+ virtual void pause(hwc_context_t* ctx, int dpy);
+ virtual void resume(hwc_context_t* ctx, int dpy);
+private:
+ // If WFD is enabled through VDS solution
+ // we can dump the frame buffer and WB
+ // output buffer by setting the property
+ // debug.hwc.enable_vds_dump
+ bool mVDSDumpEnabled;
};
class HWCVirtualV4L2 : public HWCVirtualBase {
@@ -80,6 +91,8 @@
// during virtual display disconnect. This function is no-op for V4L2 design
virtual void destroy(hwc_context_t *, size_t ,
hwc_display_contents_1_t** ) {};
+ virtual void pause(hwc_context_t* ctx, int dpy);
+ virtual void resume(hwc_context_t* ctx, int dpy);
};
}; //namespace
diff --git a/msm8226/libhwcomposer/hwc_vsync.cpp b/msm8226/libhwcomposer/hwc_vsync.cpp
index 7fb89c5..d902e55 100644
--- a/msm8226/libhwcomposer/hwc_vsync.cpp
+++ b/msm8226/libhwcomposer/hwc_vsync.cpp
@@ -40,7 +40,6 @@
#define PANEL_ON_STR "panel_power_on ="
#define ARRAY_LENGTH(array) (sizeof((array))/sizeof((array)[0]))
const int MAX_DATA = 64;
-bool logvsync = false;
int hwc_vsync_control(hwc_context_t* ctx, int dpy, int enable)
{
@@ -63,7 +62,7 @@
timestamp = strtoull(data + strlen("VSYNC="), NULL, 0);
}
// send timestamp to SurfaceFlinger
- ALOGD_IF (logvsync, "%s: timestamp %"PRIu64" sent to SF for dpy=%d",
+ ALOGD_IF (ctx->vstate.debug, "%s: timestamp %"PRIu64" sent to SF for dpy=%d",
__FUNCTION__, timestamp, dpy);
ctx->proc->vsync(ctx->proc, dpy, timestamp);
}
@@ -71,8 +70,8 @@
static void handle_blank_event(hwc_context_t* ctx, int dpy, char *data)
{
if (!strncmp(data, PANEL_ON_STR, strlen(PANEL_ON_STR))) {
- uint32_t poweron = strtoul(data + strlen(PANEL_ON_STR), NULL, 0);
- ALOGI("%s: dpy:%d panel power state: %d", __FUNCTION__, dpy, poweron);
+ unsigned long int poweron = strtoul(data + strlen(PANEL_ON_STR), NULL, 0);
+ ALOGI("%s: dpy:%d panel power state: %ld", __FUNCTION__, dpy, poweron);
ctx->dpyAttr[dpy].isActive = poweron ? true: false;
}
}
@@ -111,11 +110,6 @@
ctx->vstate.fakevsync = true;
}
- if(property_get("debug.hwc.logvsync", property, 0) > 0) {
- if(atoi(property) == 1)
- logvsync = true;
- }
-
char node_path[MAX_SYSFS_FILE_PATH];
#ifdef VSYNC_FAILURE_FALLBACK
int fake_vsync_switch_cnt = 0;
@@ -155,13 +149,13 @@
if (LIKELY(!ctx->vstate.fakevsync)) {
do {
- int err = poll(*pfd, num_displays * num_events, -1);
+ int err = poll(*pfd, (int)(num_displays * num_events), -1);
if(err > 0) {
for (int dpy = HWC_DISPLAY_PRIMARY; dpy < num_displays; dpy++) {
for(size_t ev = 0; ev < num_events; ev++) {
if (pfd[dpy][ev].revents & POLLPRI) {
- err = pread(pfd[dpy][ev].fd, vdata, MAX_DATA, 0);
- if (UNLIKELY(err < 0)) {
+ ssize_t len = pread(pfd[dpy][ev].fd, vdata, MAX_DATA, 0);
+ if (UNLIKELY(len < 0)) {
// If the read was just interrupted - it is not
// a fatal error. Just continue in this case
ALOGE ("%s: Unable to read event:%zu for \
diff --git a/msm8226/liblight/Android.mk b/msm8226/liblight/Android.mk
index 40115d5..977fc55 100644
--- a/msm8226/liblight/Android.mk
+++ b/msm8226/liblight/Android.mk
@@ -18,7 +18,7 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES := lights.c
-LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdlights\"
LOCAL_MODULE := lights.$(TARGET_BOARD_PLATFORM)
diff --git a/msm8226/liblight/lights.c b/msm8226/liblight/lights.c
index 1aa0b58..615ddd8 100644
--- a/msm8226/liblight/lights.c
+++ b/msm8226/liblight/lights.c
@@ -83,7 +83,7 @@
fd = open(path, O_RDWR);
if (fd >= 0) {
char buffer[20];
- int bytes = sprintf(buffer, "%d\n", value);
+ int bytes = snprintf(buffer, sizeof(buffer), "%d\n", value);
ssize_t amt = write(fd, buffer, (size_t)bytes);
close(fd);
return amt == -1 ? -errno : 0;
@@ -168,12 +168,18 @@
}
if (blink) {
- if (red)
- write_int(RED_BLINK_FILE, blink);
- if (green)
- write_int(GREEN_BLINK_FILE, blink);
- if (blue)
- write_int(BLUE_BLINK_FILE, blink);
+ if (red) {
+ if (write_int(RED_BLINK_FILE, blink))
+ write_int(RED_LED_FILE, 0);
+ }
+ if (green) {
+ if (write_int(GREEN_BLINK_FILE, blink))
+ write_int(GREEN_LED_FILE, 0);
+ }
+ if (blue) {
+ if (write_int(BLUE_BLINK_FILE, blink))
+ write_int(BLUE_LED_FILE, 0);
+ }
} else {
write_int(RED_LED_FILE, red);
write_int(GREEN_LED_FILE, green);
@@ -194,6 +200,17 @@
}
static int
+set_light_battery(struct light_device_t* dev,
+ struct light_state_t const* state)
+{
+ pthread_mutex_lock(&g_lock);
+ g_battery = *state;
+ handle_speaker_battery_locked(dev);
+ pthread_mutex_unlock(&g_lock);
+ return 0;
+}
+
+static int
set_light_notifications(struct light_device_t* dev,
struct light_state_t const* state)
{
@@ -259,6 +276,8 @@
if (0 == strcmp(LIGHT_ID_BACKLIGHT, name))
set_light = set_light_backlight;
+ else if (0 == strcmp(LIGHT_ID_BATTERY, name))
+ set_light = set_light_battery;
else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name))
set_light = set_light_notifications;
else if (0 == strcmp(LIGHT_ID_BUTTONS, name))
@@ -271,6 +290,10 @@
pthread_once(&g_init, init_globals);
struct light_device_t *dev = malloc(sizeof(struct light_device_t));
+
+ if(!dev)
+ return -ENOMEM;
+
memset(dev, 0, sizeof(*dev));
dev->common.tag = HARDWARE_DEVICE_TAG;
diff --git a/msm8226/libmemtrack/Android.mk b/msm8226/libmemtrack/Android.mk
index 306eb07..2fda0b7 100644
--- a/msm8226/libmemtrack/Android.mk
+++ b/msm8226/libmemtrack/Android.mk
@@ -18,7 +18,7 @@
# hw/<POWERS_HARDWARE_MODULE_ID>.<ro.hardware>.so
include $(CLEAR_VARS)
-LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_C_INCLUDES += hardware/libhardware/include
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_SRC_FILES := memtrack_msm.c kgsl.c
diff --git a/msm8226/libmemtrack/kgsl.c b/msm8226/libmemtrack/kgsl.c
index 974f3e6..e4943e8 100644
--- a/msm8226/libmemtrack/kgsl.c
+++ b/msm8226/libmemtrack/kgsl.c
@@ -47,7 +47,6 @@
size_t allocated_records = min(*num_records, ARRAY_SIZE(record_templates));
int i;
FILE *fp;
- FILE *smaps_fp = NULL;
char line[1024];
char tmp[128];
bool is_surfaceflinger = false;
@@ -81,20 +80,15 @@
return -errno;
}
- if (type == MEMTRACK_TYPE_GL) {
- snprintf(tmp, sizeof(tmp), "/proc/%d/smaps", pid);
- smaps_fp = fopen(tmp, "r");
- if (smaps_fp == NULL) {
- fclose(fp);
- return -errno;
- }
- }
-
+ /* Go through each line of <pid>/mem file and for every entry of type "gpumem"
+ * check if the gpubuffer entry is usermapped or not. If the entry is usermapped
+ * count the entry as accounted else count the entry as unaccounted.
+ */
while (1) {
- unsigned long uaddr;
unsigned long size;
char line_type[7];
char line_usage[19];
+ char flags[7];
int ret;
if (fgets(line, sizeof(line), fp) == NULL) {
@@ -103,49 +97,21 @@
/* Format:
* gpuaddr useraddr size id flags type usage sglen
- * 545ba000 545ba000 4096 1 ----p gpumem arraybuffer 1
+ * 545ba000 545ba000 4096 1 ----pY gpumem arraybuffer 1
*/
- ret = sscanf(line, "%*x %lx %lu %*d %*s %6s %18s %*d\n",
- &uaddr, &size, line_type, line_usage);
+ ret = sscanf(line, "%*x %*x %lu %*d %6s %6s %*s %*d\n",
+ &size, flags, line_type);
if (ret != 4) {
continue;
}
if (type == MEMTRACK_TYPE_GL && strcmp(line_type, "gpumem") == 0) {
- bool accounted = false;
- /*
- * We need to cross reference the user address against smaps,
- * luckily both are sorted.
- */
- while (smaps_addr <= uaddr) {
- unsigned long start;
- unsigned long end;
- unsigned long smaps_size;
- if (fgets(line, sizeof(line), smaps_fp) == NULL) {
- break;
- }
-
- if (sscanf(line, "%8lx-%8lx", &start, &end) == 2) {
- smaps_addr = start;
- continue;
- }
-
- if (smaps_addr != uaddr) {
- continue;
- }
-
- if (sscanf(line, "Rss: %lu kB", &smaps_size) == 1) {
- if (smaps_size) {
- accounted = true;
- accounted_size += size;
- break;
- }
- }
- }
- if (!accounted) {
+ if (flags[6] == 'Y')
+ accounted_size += size;
+ else
unaccounted_size += size;
- }
+
} else if (type == MEMTRACK_TYPE_GRAPHICS && strcmp(line_type, "ion") == 0) {
if (!is_surfaceflinger || strcmp(line_usage, "egl_image") != 0) {
unaccounted_size += size;
@@ -160,8 +126,6 @@
records[1].size_in_bytes = unaccounted_size;
}
- if (smaps_fp)
- fclose(smaps_fp);
fclose(fp);
return 0;
diff --git a/msm8226/liboverlay/Android.mk b/msm8226/liboverlay/Android.mk
index d8c2ab5..aa1ea24 100644
--- a/msm8226/liboverlay/Android.mk
+++ b/msm8226/liboverlay/Android.mk
@@ -3,15 +3,11 @@
include $(CLEAR_VARS)
LOCAL_MODULE := liboverlay
-LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
LOCAL_SHARED_LIBRARIES := $(common_libs) libqdutils libmemalloc \
libsync libdl
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdoverlay\"
-ifeq ($(TARGET_USES_QSEED_SCALAR),true)
- LOCAL_CFLAGS += -DUSES_QSEED_SCALAR
-endif
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
LOCAL_SRC_FILES := \
overlay.cpp \
diff --git a/msm8226/liboverlay/mdpWrapper.h b/msm8226/liboverlay/mdpWrapper.h
index 1bfa058..e24ad6a 100644
--- a/msm8226/liboverlay/mdpWrapper.h
+++ b/msm8226/liboverlay/mdpWrapper.h
@@ -30,6 +30,8 @@
#ifndef MDP_WRAPPER_H
#define MDP_WRAPPER_H
+#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+
/*
* In order to make overlay::mdp_wrapper shorter, please do something like:
* namespace mdpwrap = overlay::mdp_wrapper;
@@ -39,6 +41,7 @@
#include <linux/msm_rotator.h>
#include <sys/ioctl.h>
#include <utils/Log.h>
+#include <utils/Trace.h>
#include <errno.h>
#include "overlayUtils.h"
@@ -80,9 +83,6 @@
/* MSMFB_OVERLAY_PLAY */
bool play(int fd, msmfb_overlay_data& od);
-/* MSMFB_OVERLAY_3D */
-bool set3D(int fd, msmfb_overlay_3d& ov);
-
/* MSMFB_DISPLAY_COMMIT */
bool displayCommit(int fd);
@@ -119,6 +119,7 @@
//---------------Inlines -------------------------------------
inline bool getFScreenInfo(int fd, fb_fix_screeninfo& finfo) {
+ ATRACE_CALL();
if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) < 0) {
ALOGE("Failed to call ioctl FBIOGET_FSCREENINFO err=%s",
strerror(errno));
@@ -128,6 +129,7 @@
}
inline bool getVScreenInfo(int fd, fb_var_screeninfo& vinfo) {
+ ATRACE_CALL();
if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {
ALOGE("Failed to call ioctl FBIOGET_VSCREENINFO err=%s",
strerror(errno));
@@ -137,6 +139,7 @@
}
inline bool setVScreenInfo(int fd, fb_var_screeninfo& vinfo) {
+ ATRACE_CALL();
if (ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo) < 0) {
ALOGE("Failed to call ioctl FBIOPUT_VSCREENINFO err=%s",
strerror(errno));
@@ -146,6 +149,7 @@
}
inline bool startRotator(int fd, msm_rotator_img_info& rot) {
+ ATRACE_CALL();
if (ioctl(fd, MSM_ROTATOR_IOCTL_START, &rot) < 0){
ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_START err=%s",
strerror(errno));
@@ -155,6 +159,7 @@
}
inline bool rotate(int fd, msm_rotator_data_info& rot) {
+ ATRACE_CALL();
if (ioctl(fd, MSM_ROTATOR_IOCTL_ROTATE, &rot) < 0) {
ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_ROTATE err=%s",
strerror(errno));
@@ -164,6 +169,7 @@
}
inline bool setOverlay(int fd, mdp_overlay& ov) {
+ ATRACE_CALL();
if (ioctl(fd, MSMFB_OVERLAY_SET, &ov) < 0) {
ALOGE("Failed to call ioctl MSMFB_OVERLAY_SET err=%s",
strerror(errno));
@@ -173,6 +179,7 @@
}
inline bool validateAndSet(const int& fd, mdp_overlay_list& list) {
+ ATRACE_CALL();
if (ioctl(fd, MSMFB_OVERLAY_PREPARE, &list) < 0) {
ALOGD_IF(IOCTL_DEBUG, "Failed to call ioctl MSMFB_OVERLAY_PREPARE "
"err=%s", strerror(errno));
@@ -182,6 +189,7 @@
}
inline bool endRotator(int fd, uint32_t sessionId) {
+ ATRACE_CALL();
if (ioctl(fd, MSM_ROTATOR_IOCTL_FINISH, &sessionId) < 0) {
ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_FINISH err=%s",
strerror(errno));
@@ -191,6 +199,7 @@
}
inline bool unsetOverlay(int fd, int ovId) {
+ ATRACE_CALL();
if (ioctl(fd, MSMFB_OVERLAY_UNSET, &ovId) < 0) {
ALOGE("Failed to call ioctl MSMFB_OVERLAY_UNSET err=%s",
strerror(errno));
@@ -200,6 +209,7 @@
}
inline bool getOverlay(int fd, mdp_overlay& ov) {
+ ATRACE_CALL();
if (ioctl(fd, MSMFB_OVERLAY_GET, &ov) < 0) {
ALOGE("Failed to call ioctl MSMFB_OVERLAY_GET err=%s",
strerror(errno));
@@ -209,6 +219,7 @@
}
inline bool play(int fd, msmfb_overlay_data& od) {
+ ATRACE_CALL();
if (ioctl(fd, MSMFB_OVERLAY_PLAY, &od) < 0) {
ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY err=%s",
strerror(errno));
@@ -217,16 +228,8 @@
return true;
}
-inline bool set3D(int fd, msmfb_overlay_3d& ov) {
- if (ioctl(fd, MSMFB_OVERLAY_3D, &ov) < 0) {
- ALOGE("Failed to call ioctl MSMFB_OVERLAY_3D err=%s",
- strerror(errno));
- return false;
- }
- return true;
-}
-
inline bool displayCommit(int fd, mdp_display_commit& info) {
+ ATRACE_CALL();
if(ioctl(fd, MSMFB_DISPLAY_COMMIT, &info) == -1) {
ALOGE("Failed to call ioctl MSMFB_DISPLAY_COMMIT err=%s",
strerror(errno));
@@ -236,6 +239,7 @@
}
inline bool wbInitStart(int fbfd) {
+ ATRACE_CALL();
if(ioctl(fbfd, MSMFB_WRITEBACK_INIT, NULL) < 0) {
ALOGE("Failed to call ioctl MSMFB_WRITEBACK_INIT err=%s",
strerror(errno));
@@ -250,6 +254,7 @@
}
inline bool wbStopTerminate(int fbfd) {
+ ATRACE_CALL();
if(ioctl(fbfd, MSMFB_WRITEBACK_STOP, NULL) < 0) {
ALOGE("Failed to call ioctl MSMFB_WRITEBACK_STOP err=%s",
strerror(errno));
@@ -264,6 +269,7 @@
}
inline bool wbQueueBuffer(int fbfd, struct msmfb_data& fbData) {
+ ATRACE_CALL();
if(ioctl(fbfd, MSMFB_WRITEBACK_QUEUE_BUFFER, &fbData) < 0) {
ALOGE("Failed to call ioctl MSMFB_WRITEBACK_QUEUE_BUFFER err=%s",
strerror(errno));
@@ -273,6 +279,7 @@
}
inline bool wbDequeueBuffer(int fbfd, struct msmfb_data& fbData) {
+ ATRACE_CALL();
if(ioctl(fbfd, MSMFB_WRITEBACK_DEQUEUE_BUFFER, &fbData) < 0) {
ALOGE("Failed to call ioctl MSMFB_WRITEBACK_DEQUEUE_BUFFER err=%s",
strerror(errno));
diff --git a/msm8226/liboverlay/overlay.cpp b/msm8226/liboverlay/overlay.cpp
index 265aa9f..de880c6 100644
--- a/msm8226/liboverlay/overlay.cpp
+++ b/msm8226/liboverlay/overlay.cpp
@@ -33,16 +33,11 @@
#include "mdp_version.h"
#include "qdMetaData.h"
-#ifdef USES_QSEED_SCALAR
-#include <scale/scale.h>
-using namespace scale;
-#endif
-
#define PIPE_DEBUG 0
namespace overlay {
using namespace utils;
-
+using namespace qdutils;
Overlay::Overlay() {
int numPipes = qdutils::MDPVersion::getInstance().getTotalPipes();
@@ -158,6 +153,107 @@
return dest;
}
+utils::eDest Overlay::getPipe(const PipeSpecs& pipeSpecs) {
+ if(MDPVersion::getInstance().is8x26()) {
+ return getPipe_8x26(pipeSpecs);
+ } else if(MDPVersion::getInstance().is8x16()) {
+ return getPipe_8x16(pipeSpecs);
+ } else if(MDPVersion::getInstance().is8x39()) {
+ return getPipe_8x39(pipeSpecs);
+ }
+
+ eDest dest = OV_INVALID;
+
+ //The default behavior is to assume RGB and VG pipes have scalars
+ if(pipeSpecs.formatClass == FORMAT_YUV) {
+ return nextPipe(OV_MDP_PIPE_VG, pipeSpecs.dpy, pipeSpecs.mixer);
+ } else if(pipeSpecs.fb == false) { //RGB App layers
+ if(not pipeSpecs.needsScaling) {
+ dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs.dpy, pipeSpecs.mixer);
+ }
+ if(dest == OV_INVALID) {
+ dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs.dpy, pipeSpecs.mixer);
+ }
+ if(dest == OV_INVALID) {
+ dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs.dpy, pipeSpecs.mixer);
+ }
+ } else { //FB layer
+ dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs.dpy, pipeSpecs.mixer);
+ if(dest == OV_INVALID) {
+ dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs.dpy, pipeSpecs.mixer);
+ }
+ //Some features can cause FB to have scaling as well.
+ //If we ever come to this block with FB needing scaling,
+ //the screen will be black for a frame, since the FB won't get a pipe
+ //but atleast this will prevent a hang
+ if(dest == OV_INVALID and (not pipeSpecs.needsScaling)) {
+ dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs.dpy, pipeSpecs.mixer);
+ }
+ }
+ return dest;
+}
+
+utils::eDest Overlay::getPipe_8x26(const PipeSpecs& pipeSpecs) {
+ //Use this to hide all the 8x26 requirements that cannot be humanly
+ //described in a generic way
+ eDest dest = OV_INVALID;
+ if(pipeSpecs.formatClass == FORMAT_YUV) { //video
+ return nextPipe(OV_MDP_PIPE_VG, pipeSpecs.dpy, pipeSpecs.mixer);
+ } else if(pipeSpecs.fb == false) { //RGB app layers
+ if((not pipeSpecs.needsScaling) and
+ (not (pipeSpecs.numActiveDisplays > 1 &&
+ pipeSpecs.dpy == DPY_PRIMARY))) {
+ dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs.dpy, pipeSpecs.mixer);
+ }
+ if(dest == OV_INVALID) {
+ dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs.dpy, pipeSpecs.mixer);
+ }
+ if(dest == OV_INVALID) {
+ dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs.dpy, pipeSpecs.mixer);
+ }
+ } else { //FB layer
+ //For 8x26 Secondary we use DMA always for FB for inline rotation
+ if(pipeSpecs.dpy == DPY_PRIMARY) {
+ dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs.dpy, pipeSpecs.mixer);
+ if(dest == OV_INVALID) {
+ dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs.dpy, pipeSpecs.mixer);
+ }
+ }
+ if(dest == OV_INVALID and (not pipeSpecs.needsScaling) and
+ (not (pipeSpecs.numActiveDisplays > 1 &&
+ pipeSpecs.dpy == DPY_PRIMARY))) {
+ dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs.dpy, pipeSpecs.mixer);
+ }
+ }
+ return dest;
+}
+
+utils::eDest Overlay::getPipe_8x16(const PipeSpecs& pipeSpecs) {
+ //Having such functions help keeping the interface generic but code specific
+ //and rife with assumptions
+ eDest dest = OV_INVALID;
+ if(pipeSpecs.formatClass == FORMAT_YUV or pipeSpecs.needsScaling) {
+ return nextPipe(OV_MDP_PIPE_VG, pipeSpecs.dpy, pipeSpecs.mixer);
+ } else {
+ //Since this is a specific func, we can assume stuff like RGB pipe not
+ //having scalar blocks
+ dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs.dpy, pipeSpecs.mixer);
+ if(dest == OV_INVALID) {
+ dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs.dpy, pipeSpecs.mixer);
+ }
+ if(dest == OV_INVALID) {
+ dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs.dpy, pipeSpecs.mixer);
+ }
+ }
+ return dest;
+}
+
+utils::eDest Overlay::getPipe_8x39(const PipeSpecs& pipeSpecs) {
+ //8x16 & 8x36 has same number of pipes, pipe-types & scaling capabilities.
+ //Rely on 8x16 until we see a need to change.
+ return getPipe_8x16(pipeSpecs);
+}
+
void Overlay::endAllSessions() {
for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
if(mPipeBook[i].valid() && mPipeBook[i].mSession==PipeBook::START)
@@ -175,16 +271,28 @@
return false;
}
+int Overlay::comparePipePriority(utils::eDest pipe1Index,
+ utils::eDest pipe2Index) {
+ validate((int)pipe1Index);
+ validate((int)pipe2Index);
+ uint8_t pipe1Prio = mPipeBook[(int)pipe1Index].mPipe->getPriority();
+ uint8_t pipe2Prio = mPipeBook[(int)pipe2Index].mPipe->getPriority();
+ if(pipe1Prio > pipe2Prio)
+ return -1;
+ if(pipe1Prio < pipe2Prio)
+ return 1;
+ return 0;
+}
+
bool Overlay::commit(utils::eDest dest) {
bool ret = false;
- int index = (int)dest;
- validate(index);
+ validate((int)dest);
- if(mPipeBook[index].mPipe->commit()) {
+ if(mPipeBook[dest].mPipe->commit()) {
ret = true;
PipeBook::setUse((int)dest);
} else {
- int dpy = mPipeBook[index].mDisplay;
+ int dpy = mPipeBook[dest].mDisplay;
for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
if (mPipeBook[i].mDisplay == dpy) {
PipeBook::resetAllocation(i);
@@ -197,73 +305,59 @@
bool Overlay::queueBuffer(int fd, uint32_t offset,
utils::eDest dest) {
- int index = (int)dest;
bool ret = false;
- validate(index);
+ validate((int)dest);
//Queue only if commit() has succeeded (and the bit set)
if(PipeBook::isUsed((int)dest)) {
- ret = mPipeBook[index].mPipe->queueBuffer(fd, offset);
+ ret = mPipeBook[dest].mPipe->queueBuffer(fd, offset);
}
return ret;
}
void Overlay::setCrop(const utils::Dim& d,
utils::eDest dest) {
- int index = (int)dest;
- validate(index);
- mPipeBook[index].mPipe->setCrop(d);
+ validate((int)dest);
+ mPipeBook[dest].mPipe->setCrop(d);
}
void Overlay::setColor(const uint32_t color,
utils::eDest dest) {
- int index = (int)dest;
- validate(index);
- mPipeBook[index].mPipe->setColor(color);
+ validate((int)dest);
+ mPipeBook[dest].mPipe->setColor(color);
}
void Overlay::setPosition(const utils::Dim& d,
utils::eDest dest) {
- int index = (int)dest;
- validate(index);
- mPipeBook[index].mPipe->setPosition(d);
+ validate((int)dest);
+ mPipeBook[dest].mPipe->setPosition(d);
}
void Overlay::setTransform(const int orient,
utils::eDest dest) {
- int index = (int)dest;
- validate(index);
+ validate((int)dest);
utils::eTransform transform =
static_cast<utils::eTransform>(orient);
- mPipeBook[index].mPipe->setTransform(transform);
+ mPipeBook[dest].mPipe->setTransform(transform);
}
void Overlay::setSource(const utils::PipeArgs args,
utils::eDest dest) {
- int index = (int)dest;
- validate(index);
+ validate((int)dest);
- PipeArgs newArgs(args);
- if(PipeBook::getPipeType(dest) == OV_MDP_PIPE_VG) {
- setMdpFlags(newArgs.mdpFlags, OV_MDP_PIPE_SHARE);
- } else {
- clearMdpFlags(newArgs.mdpFlags, OV_MDP_PIPE_SHARE);
- }
-
- if(PipeBook::getPipeType(dest) == OV_MDP_PIPE_DMA) {
- setMdpFlags(newArgs.mdpFlags, OV_MDP_PIPE_FORCE_DMA);
- } else {
- clearMdpFlags(newArgs.mdpFlags, OV_MDP_PIPE_FORCE_DMA);
- }
-
- mPipeBook[index].mPipe->setSource(newArgs);
+ setPipeType(dest, PipeBook::getPipeType(dest));
+ mPipeBook[dest].mPipe->setSource(args);
}
void Overlay::setVisualParams(const MetaData_t& metadata, utils::eDest dest) {
- int index = (int)dest;
- validate(index);
- mPipeBook[index].mPipe->setVisualParams(metadata);
+ validate((int)dest);
+ mPipeBook[dest].mPipe->setVisualParams(metadata);
+}
+
+void Overlay::setPipeType(utils::eDest pipeIndex,
+ const utils::eMdpPipeType pType) {
+ mPipeBook[pipeIndex].mPipe->setPipeType(pType);
}
Overlay* Overlay::getInstance() {
@@ -365,19 +459,24 @@
}
bool Overlay::displayCommit(const int& fd) {
- utils::Dim roi;
- return displayCommit(fd, roi);
+ utils::Dim lRoi, rRoi;
+ return displayCommit(fd, lRoi, rRoi);
}
-bool Overlay::displayCommit(const int& fd, const utils::Dim& roi) {
+bool Overlay::displayCommit(const int& fd, const utils::Dim& lRoi,
+ const utils::Dim& rRoi) {
//Commit
struct mdp_display_commit info;
memset(&info, 0, sizeof(struct mdp_display_commit));
info.flags = MDP_DISPLAY_COMMIT_OVERLAY;
- info.roi.x = roi.x;
- info.roi.y = roi.y;
- info.roi.w = roi.w;
- info.roi.h = roi.h;
+ info.l_roi.x = lRoi.x;
+ info.l_roi.y = lRoi.y;
+ info.l_roi.w = lRoi.w;
+ info.l_roi.h = lRoi.h;
+ info.r_roi.x = rRoi.x;
+ info.r_roi.y = rRoi.y;
+ info.r_roi.w = rRoi.w;
+ info.r_roi.h = rRoi.h;
if(!mdp_wrapper::displayCommit(fd, info)) {
ALOGE("%s: commit failed", __func__);
@@ -424,7 +523,7 @@
bool Overlay::validateAndSet(const int& dpy, const int& fbFd) {
GenericPipe* pipeArray[PipeBook::NUM_PIPES];
- memset(&pipeArray, 0, sizeof(pipeArray));
+ memset(pipeArray, 0, sizeof(GenericPipe*)*(PipeBook::NUM_PIPES));
int num = 0;
for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
@@ -439,39 +538,20 @@
}
void Overlay::initScalar() {
-#ifdef USES_QSEED_SCALAR
if(sLibScaleHandle == NULL) {
sLibScaleHandle = dlopen("libscale.so", RTLD_NOW);
- }
-
- if(sLibScaleHandle) {
- if(sScale == NULL) {
- Scale* (*getInstance)();
- *(void **) &getInstance = dlsym(sLibScaleHandle, "getInstance");
- if(getInstance) {
- sScale = getInstance();
- }
+ if(sLibScaleHandle) {
+ *(void **) &sFnProgramScale =
+ dlsym(sLibScaleHandle, "programScale");
}
}
-#endif
}
void Overlay::destroyScalar() {
-#ifdef USES_QSEED_SCALAR
if(sLibScaleHandle) {
- if(sScale) {
- void (*destroyInstance)(Scale*);
- *(void **) &destroyInstance = dlsym(sLibScaleHandle,
- "destroyInstance");
- if(destroyInstance) {
- destroyInstance(sScale);
- sScale = NULL;
- }
- }
dlclose(sLibScaleHandle);
sLibScaleHandle = NULL;
}
-#endif
}
void Overlay::PipeBook::init() {
@@ -501,6 +581,6 @@
utils::eMdpPipeType Overlay::PipeBook::pipeTypeLUT[utils::OV_MAX] =
{utils::OV_MDP_PIPE_ANY};
void *Overlay::sLibScaleHandle = NULL;
-scale::Scale *Overlay::sScale = NULL;
+int (*Overlay::sFnProgramScale)(struct mdp_overlay_list *) = NULL;
}; // namespace overlay
diff --git a/msm8226/liboverlay/overlay.h b/msm8226/liboverlay/overlay.h
index d8615cd..c8f68b0 100644
--- a/msm8226/liboverlay/overlay.h
+++ b/msm8226/liboverlay/overlay.h
@@ -35,9 +35,6 @@
#include "utils/threads.h"
struct MetaData_t;
-namespace scale {
-class Scale;
-};
namespace overlay {
class GenericPipe;
@@ -53,6 +50,18 @@
enum { MIXER_LEFT, MIXER_RIGHT, MIXER_UNUSED };
enum { MIXER_DEFAULT = MIXER_LEFT, MIXER_MAX = MIXER_UNUSED };
enum { MAX_FB_DEVICES = DPY_MAX };
+ enum { FORMAT_YUV, FORMAT_RGB };
+
+ struct PipeSpecs {
+ PipeSpecs() : formatClass(FORMAT_RGB), needsScaling(false), fb(false),
+ dpy(DPY_PRIMARY), mixer(MIXER_DEFAULT), numActiveDisplays(1) {}
+ int formatClass;
+ bool needsScaling;
+ bool fb;
+ int dpy;
+ int mixer;
+ int numActiveDisplays;
+ };
/* dtor close */
~Overlay();
@@ -69,14 +78,10 @@
*/
void configDone();
- /* Returns an available pipe based on the type of pipe requested. When ANY
- * is requested, the first available VG or RGB is returned. If no pipe is
- * available for the display "dpy" then INV is returned. Note: If a pipe is
- * assigned to a certain display, then it cannot be assigned to another
- * display without being garbage-collected once. To add if a pipe is
- * asisgned to a mixer within a display it cannot be reused for another
- * mixer without being UNSET once*/
- utils::eDest nextPipe(utils::eMdpPipeType, int dpy, int mixer);
+ /* Get a pipe that supported the specified format class (yuv, rgb) and has
+ * scaling capabilities.
+ */
+ utils::eDest getPipe(const PipeSpecs& pipeSpecs);
/* Returns the eDest corresponding to an already allocated pipeid.
* Useful for the reservation case, when libvpu reserves the pipe at its
* end, and expect the overlay to allocate a given pipe for a layer.
@@ -114,9 +119,19 @@
* displays
*/
bool isPipeTypeAttached(utils::eMdpPipeType type);
+ /* Compare pipe priorities and return
+ * 1 if 1st pipe has a higher priority
+ * 0 if both have the same priority
+ *-1 if 2nd pipe has a higher priority
+ */
+ int comparePipePriority(utils::eDest pipe1Index, utils::eDest pipe2Index);
/* Returns pipe dump. Expects a NULL terminated buffer of big enough size
* to populate.
*/
+ /* Returns if DMA pipe multiplexing is supported by the mdss driver */
+ static bool isDMAMultiplexingSupported();
+ /* Returns if UI scaling on external is supported on the targets */
+ static bool isUIScalingOnExternalSupported();
void getDump(char *buf, size_t len);
/* Reset usage and allocation bits on all pipes for given display */
void clear(int dpy);
@@ -131,8 +146,12 @@
static int getDMAMode();
/* Returns the framebuffer node backing up the display */
static int getFbForDpy(const int& dpy);
- static bool displayCommit(const int& fd, const utils::Dim& roi);
+
static bool displayCommit(const int& fd);
+ /* Overloads display commit with ROI's of each halves.
+ * Single interface panels will only update left ROI. */
+ static bool displayCommit(const int& fd, const utils::Dim& lRoi,
+ const utils::Dim& rRoi);
private:
/* Ctor setup */
@@ -141,12 +160,27 @@
void validate(int index);
static void setDMAMultiplexingSupported();
void dump() const;
- /* Returns the scalar object */
- static scale::Scale *getScalar();
+ /* Returns an available pipe based on the type of pipe requested. When ANY
+ * is requested, the first available VG or RGB is returned. If no pipe is
+ * available for the display "dpy" then INV is returned. Note: If a pipe is
+ * assigned to a certain display, then it cannot be assigned to another
+ * display without being garbage-collected once. To add if a pipe is
+ * asisgned to a mixer within a display it cannot be reused for another
+ * mixer without being UNSET once*/
+ utils::eDest nextPipe(utils::eMdpPipeType, int dpy, int mixer);
+ /* Helpers that enfore target specific policies while returning pipes */
+ utils::eDest getPipe_8x26(const PipeSpecs& pipeSpecs);
+ utils::eDest getPipe_8x16(const PipeSpecs& pipeSpecs);
+ utils::eDest getPipe_8x39(const PipeSpecs& pipeSpecs);
+
+ /* Returns the handle to libscale.so's programScale function */
+ static int (*getFnProgramScale())(struct mdp_overlay_list *);
/* Creates a scalar object using libscale.so */
static void initScalar();
/* Destroys the scalar object using libscale.so */
static void destroyScalar();
+ /* Sets the pipe type RGB/VG/DMA*/
+ void setPipeType(utils::eDest pipeIndex, const utils::eMdpPipeType pType);
/* Just like a Facebook for pipes, but much less profile info */
struct PipeBook {
@@ -213,7 +247,7 @@
static int sDMAMode;
static bool sDMAMultiplexingSupported;
static void *sLibScaleHandle;
- static scale::Scale *sScale;
+ static int (*sFnProgramScale)(struct mdp_overlay_list *);
friend class MdpCtrl;
};
@@ -281,6 +315,19 @@
sDMAMultiplexingSupported = true;
}
+inline bool Overlay::isDMAMultiplexingSupported() {
+ return sDMAMultiplexingSupported;
+}
+
+inline bool Overlay::isUIScalingOnExternalSupported() {
+ if(qdutils::MDPVersion::getInstance().is8x26() or
+ qdutils::MDPVersion::getInstance().is8x16() or
+ qdutils::MDPVersion::getInstance().is8x39()) {
+ return false;
+ }
+ return true;
+}
+
inline int Overlay::getDMAMode() {
return sDMAMode;
}
@@ -290,8 +337,8 @@
return sDpyFbMap[dpy];
}
-inline scale::Scale *Overlay::getScalar() {
- return sScale;
+inline int (*Overlay::getFnProgramScale())(struct mdp_overlay_list *) {
+ return sFnProgramScale;
}
inline bool Overlay::PipeBook::valid() {
diff --git a/msm8226/liboverlay/overlayCtrlData.h b/msm8226/liboverlay/overlayCtrlData.h
index 26202ec..2eec98c 100644
--- a/msm8226/liboverlay/overlayCtrlData.h
+++ b/msm8226/liboverlay/overlayCtrlData.h
@@ -65,6 +65,8 @@
void setPosition(const utils::Dim& dim);
/* set mdp visual params using metadata */
bool setVisualParams(const MetaData_t &metadata);
+ /* set pipe type RGB/DMA/VG */
+ void setPipeType(const utils::eMdpPipeType& pType);
/* mdp set overlay/commit changes */
bool commit();
@@ -75,10 +77,10 @@
/* retrieve crop data */
utils::Dim getCrop() const;
utils::Dim getPosition() const;
- /* Set downscale */
- void setDownscale(int dscale_factor);
/* Update the src format based on rotator's dest */
void updateSrcFormat(const uint32_t& rotDstFormat);
+ /* return pipe priority */
+ uint8_t getPriority() const;
/* dump the state of the object */
void dump() const;
/* Return the dump in the specified buffer */
@@ -157,6 +159,11 @@
return true;
}
+inline void Ctrl::setPipeType(const utils::eMdpPipeType& pType)
+{
+ mMdp->setPipeType(pType);
+}
+
inline void Ctrl::dump() const {
ALOGE("== Dump Ctrl start ==");
mMdp->dump();
@@ -204,8 +211,8 @@
return mMdp->getDstRectDim();
}
-inline void Ctrl::setDownscale(int dscale_factor) {
- mMdp->setDownscale(dscale_factor);
+inline uint8_t Ctrl::getPriority() const {
+ return mMdp->getPriority();
}
inline void Ctrl::getDump(char *buf, size_t len) {
diff --git a/msm8226/liboverlay/overlayMdp.cpp b/msm8226/liboverlay/overlayMdp.cpp
index 3e26cdf..7f9f136 100644
--- a/msm8226/liboverlay/overlayMdp.cpp
+++ b/msm8226/liboverlay/overlayMdp.cpp
@@ -22,11 +22,6 @@
#include "mdp_version.h"
#include <overlay.h>
-#ifdef USES_QSEED_SCALAR
-#include <scale/scale.h>
-using namespace scale;
-#endif
-
#define HSIC_SETTINGS_DEBUG 0
using namespace qdutils;
@@ -59,7 +54,6 @@
utils::memset0(mOVInfo);
mOVInfo.id = MSMFB_NEW_REQUEST;
mOrientation = utils::OVERLAY_TRANSFORM_0;
- mDownscale = 0;
mDpy = 0;
#ifdef USES_POST_PROCESSING
memset(&mParams, 0, sizeof(struct compute_params));
@@ -125,6 +119,23 @@
mOrientation = static_cast<utils::eTransform>(rot);
}
+void MdpCtrl::setPipeType(const utils::eMdpPipeType& pType){
+ switch((int) pType){
+ case utils::OV_MDP_PIPE_RGB:
+ mOVInfo.pipe_type = PIPE_TYPE_RGB;
+ break;
+ case utils::OV_MDP_PIPE_VG:
+ mOVInfo.pipe_type = PIPE_TYPE_VIG;
+ break;
+ case utils::OV_MDP_PIPE_DMA:
+ mOVInfo.pipe_type = PIPE_TYPE_DMA;
+ break;
+ default:
+ mOVInfo.pipe_type = PIPE_TYPE_AUTO;
+ break;
+ }
+}
+
void MdpCtrl::doTransform() {
setRotationFlags();
utils::Whf whf = getSrcWhf();
@@ -135,39 +146,10 @@
}
void MdpCtrl::doDownscale() {
- int mdpVersion = MDPVersion::getInstance().getMDPVersion();
- if(mdpVersion < MDSS_V5) {
- mOVInfo.src_rect.x >>= mDownscale;
- mOVInfo.src_rect.y >>= mDownscale;
- mOVInfo.src_rect.w >>= mDownscale;
- mOVInfo.src_rect.h >>= mDownscale;
- } else if(MDPVersion::getInstance().supportsDecimation()) {
- //Decimation + MDP Downscale
- mOVInfo.horz_deci = 0;
- mOVInfo.vert_deci = 0;
- int minHorDeci = 0;
- if(mOVInfo.src_rect.w > 2048) {
- //If the client sends us something > what a layer mixer supports
- //then it means it doesn't want to use split-pipe but wants us to
- //decimate. A minimum decimation of 2 will ensure that the width is
- //always within layer mixer limits.
- minHorDeci = 2;
- }
-
- float horDscale = 0.0f;
- float verDscale = 0.0f;
-
+ if(MDPVersion::getInstance().supportsDecimation()) {
utils::getDecimationFactor(mOVInfo.src_rect.w, mOVInfo.src_rect.h,
- mOVInfo.dst_rect.w, mOVInfo.dst_rect.h, horDscale, verDscale);
-
- if(horDscale < minHorDeci)
- horDscale = minHorDeci;
-
- if((int)horDscale)
- mOVInfo.horz_deci = (int)log2f(horDscale);
-
- if((int)verDscale)
- mOVInfo.vert_deci = (int)log2f(verDscale);
+ mOVInfo.dst_rect.w, mOVInfo.dst_rect.h, mOVInfo.horz_deci,
+ mOVInfo.vert_deci);
}
}
@@ -187,6 +169,10 @@
if (!(mOVInfo.flags & MDP_SOURCE_ROTATED_90) &&
(mOVInfo.src_rect.h % 4))
mOVInfo.src_rect.h = utils::aligndown(mOVInfo.src_rect.h, 4);
+ // For interlaced, width must be multiple of 4 when rotated 90deg.
+ else if ((mOVInfo.flags & MDP_SOURCE_ROTATED_90) &&
+ (mOVInfo.src_rect.w % 4))
+ mOVInfo.src_rect.w = utils::aligndown(mOVInfo.src_rect.w, 4);
}
} else {
if (mdpVersion >= MDSS_V5) {
@@ -231,12 +217,6 @@
ovutils::getDump(buf, len, "Data", mOvData);
}
-void MdpCtrl3D::dump() const {
- ALOGE("== Dump MdpCtrl start ==");
- mFd.dump();
- ALOGE("== Dump MdpCtrl end ==");
-}
-
bool MdpCtrl::setVisualParams(const MetaData_t& data) {
ALOGD_IF(0, "In %s: data.operation = %d", __FUNCTION__, data.operation);
#ifdef USES_POST_PROCESSING
@@ -367,15 +347,15 @@
list.num_overlays = count;
list.overlay_list = ovArray;
-#ifdef USES_QSEED_SCALAR
- Scale *scalar = Overlay::getScalar();
- if(scalar) {
- scalar->applyScale(&list);
+ int (*fnProgramScale)(struct mdp_overlay_list *) =
+ Overlay::getFnProgramScale();
+ if(fnProgramScale) {
+ fnProgramScale(&list);
}
-#endif
if(!mdp_wrapper::validateAndSet(fbFd, list)) {
- if(list.processed_overlays < list.num_overlays) {
+ /* No dump for failure due to insufficient resource */
+ if(errno != E2BIG) {
mdp_wrapper::dump("Bad ov dump: ",
*list.overlay_list[list.processed_overlays]);
}
diff --git a/msm8226/liboverlay/overlayMdp.h b/msm8226/liboverlay/overlayMdp.h
index 843556b..cb8e057 100644
--- a/msm8226/liboverlay/overlayMdp.h
+++ b/msm8226/liboverlay/overlayMdp.h
@@ -64,8 +64,6 @@
void setPosition(const utils::Dim& dim);
/* using user_data, sets/unsets roationvalue in mdp flags */
void setRotationFlags();
- /* Performs downscale calculations */
- void setDownscale(int dscale_factor);
/* Update the src format with rotator's dest*/
void updateSrcFormat(const uint32_t& rotDstFormat);
/* dump state of the object */
@@ -80,8 +78,12 @@
utils::Dim getDstRectDim() const;
/* returns a copy to src rect dim */
utils::Dim getSrcRectDim() const;
+ /* return pipe priority */
+ uint8_t getPriority() const;
/* setVisualParam */
bool setVisualParams(const MetaData_t& data);
+ /* sets pipe type RGB/DMA/VG */
+ void setPipeType(const utils::eMdpPipeType& pType);
static bool validateAndSet(MdpCtrl* mdpCtrlArray[], const int& count,
const int& fbFd);
@@ -121,7 +123,6 @@
mdp_overlay mOVInfo;
/* FD for the mdp fbnum */
OvFD mFd;
- int mDownscale;
int mDpy;
#ifdef USES_POST_PROCESSING
@@ -130,31 +131,6 @@
#endif
};
-
-/* MDP 3D related ctrl */
-class MdpCtrl3D {
-public:
- /* ctor reset data */
- MdpCtrl3D();
- /* calls MSMFB_OVERLAY_3D */
- bool close();
- /* set w/h. format is ignored*/
- void setWh(const utils::Whf& whf);
- /* set is_3d calls MSMFB_OVERLAY_3D */
- bool useVirtualFB();
- /* set fd to be used in ioctl */
- void setFd(int fd);
- /* dump */
- void dump() const;
-private:
- /* reset */
- void reset();
- /* actual MSM 3D info */
- msmfb_overlay_3d m3DOVInfo;
- /* FD for the mdp 3D */
- OvFD mFd;
-};
-
/* MDP data */
class MdpData {
public:
@@ -232,10 +208,6 @@
mOVInfo.is_fg = isFg;
}
-inline void MdpCtrl::setDownscale(int dscale) {
- mDownscale = dscale;
-}
-
inline void MdpCtrl::setPlaneAlpha(int planeAlpha) {
mOVInfo.alpha = planeAlpha;
}
@@ -304,44 +276,8 @@
mOVInfo.flags |= MDP_SOURCE_ROTATED_90;
}
-/////// MdpCtrl3D //////
-
-inline MdpCtrl3D::MdpCtrl3D() { reset(); }
-inline bool MdpCtrl3D::close() {
- if (m3DOVInfo.is_3d) {
- m3DOVInfo.is_3d = 0;
- if(!mdp_wrapper::set3D(mFd.getFD(), m3DOVInfo)) {
- ALOGE("MdpCtrl3D close failed set3D with 0");
- return false;
- }
- }
- reset();
- return true;
-}
-inline void MdpCtrl3D::reset() {
- utils::memset0(m3DOVInfo);
-}
-
-inline void MdpCtrl3D::setFd(int fd) {
- mFd.copy(fd);
- OVASSERT(mFd.valid(), "MdpCtrl3D setFd, FD should be valid");
-}
-
-inline void MdpCtrl3D::setWh(const utils::Whf& whf) {
- // ignore fmt. Needed for useVirtualFB callflow
- m3DOVInfo.width = whf.w;
- m3DOVInfo.height = whf.h;
-}
-
-inline bool MdpCtrl3D::useVirtualFB() {
- if(!m3DOVInfo.is_3d) {
- m3DOVInfo.is_3d = 1;
- if(!mdp_wrapper::set3D(mFd.getFD(), m3DOVInfo)) {
- ALOGE("MdpCtrl3D close failed set3D with 0");
- return false;
- }
- }
- return true;
+inline uint8_t MdpCtrl::getPriority() const {
+ return mOVInfo.priority;
}
/////// MdpData //////
diff --git a/msm8226/liboverlay/overlayMdpRot.cpp b/msm8226/liboverlay/overlayMdpRot.cpp
index 38b0a92..bb985d7 100755
--- a/msm8226/liboverlay/overlayMdpRot.cpp
+++ b/msm8226/liboverlay/overlayMdpRot.cpp
@@ -19,6 +19,7 @@
#include "overlayUtils.h"
#include "overlayRotator.h"
+#include "gr.h"
namespace ovutils = overlay::utils;
@@ -33,7 +34,7 @@
bool MdpRot::enabled() const { return mRotImgInfo.enable; }
-void MdpRot::setRotations(uint32_t r) { mRotImgInfo.rotations = r; }
+void MdpRot::setRotations(uint32_t r) { mRotImgInfo.rotations = (uint8_t)r; }
int MdpRot::getDstMemId() const {
return mRotDataInfo.dst.memory_id;
@@ -47,6 +48,24 @@
return mRotImgInfo.dst.format;
}
+//Added for completeness. Not expected to be called.
+utils::Whf MdpRot::getDstWhf() const {
+ int alW = 0, alH = 0;
+ int halFormat = ovutils::getHALFormat(mRotImgInfo.dst.format);
+ getBufferSizeAndDimensions(mRotImgInfo.dst.width, mRotImgInfo.dst.height,
+ halFormat, alW, alH);
+ return utils::Whf(alW, alH, mRotImgInfo.dst.format);
+}
+
+//Added for completeness. Not expected to be called.
+utils::Dim MdpRot::getDstDimensions() const {
+ int alW = 0, alH = 0;
+ int halFormat = ovutils::getHALFormat(mRotImgInfo.dst.format);
+ getBufferSizeAndDimensions(mRotImgInfo.dst.width, mRotImgInfo.dst.height,
+ halFormat, alW, alH);
+ return utils::Dim(0, 0, alW, alH);
+}
+
uint32_t MdpRot::getSessId() const { return mRotImgInfo.session_id; }
void MdpRot::setDownscale(int ds) {
diff --git a/msm8226/liboverlay/overlayMdssRot.cpp b/msm8226/liboverlay/overlayMdssRot.cpp
index ce9d9d5..5783dcb 100644
--- a/msm8226/liboverlay/overlayMdssRot.cpp
+++ b/msm8226/liboverlay/overlayMdssRot.cpp
@@ -37,6 +37,8 @@
namespace ovutils = overlay::utils;
namespace overlay {
+using namespace utils;
+
MdssRot::MdssRot() {
reset();
init();
@@ -61,6 +63,21 @@
return mRotInfo.src.format;
}
+utils::Whf MdssRot::getDstWhf() const {
+ //For Mdss dst_rect itself represents buffer dimensions. We ignore actual
+ //aligned values during buffer allocation. Also the driver overwrites the
+ //src.format field if destination format is different.
+ //This implementation detail makes it possible to retrieve w,h even before
+ //buffer allocation, which happens in queueBuffer.
+ return utils::Whf(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h,
+ mRotInfo.src.format);
+}
+
+utils::Dim MdssRot::getDstDimensions() const {
+ return utils::Dim(mRotInfo.dst_rect.x, mRotInfo.dst_rect.y,
+ mRotInfo.dst_rect.w, mRotInfo.dst_rect.h);
+}
+
uint32_t MdssRot::getSessId() const { return mRotInfo.id; }
bool MdssRot::init() {
@@ -80,16 +97,10 @@
}
void MdssRot::setCrop(const utils::Dim& crop) {
-
mRotInfo.src_rect.x = crop.x;
mRotInfo.src_rect.y = crop.y;
mRotInfo.src_rect.w = crop.w;
mRotInfo.src_rect.h = crop.h;
-
- mRotInfo.dst_rect.x = 0;
- mRotInfo.dst_rect.y = 0;
- mRotInfo.dst_rect.w = crop.w;
- mRotInfo.dst_rect.h = crop.h;
}
void MdssRot::setDownscale(int /*ds*/) {
@@ -117,7 +128,22 @@
}
bool MdssRot::commit() {
+ if (utils::isYuv(mRotInfo.src.format)) {
+ utils::normalizeCrop(mRotInfo.src_rect.x, mRotInfo.src_rect.w);
+ utils::normalizeCrop(mRotInfo.src_rect.y, mRotInfo.src_rect.h);
+ // For interlaced, crop.h should be 4-aligned
+ if ((mRotInfo.flags & utils::OV_MDP_DEINTERLACE) and
+ (mRotInfo.src_rect.h % 4))
+ mRotInfo.src_rect.h = utils::aligndown(mRotInfo.src_rect.h, 4);
+ }
+
+ mRotInfo.dst_rect.x = 0;
+ mRotInfo.dst_rect.y = 0;
+ mRotInfo.dst_rect.w = mRotInfo.src_rect.w;
+ mRotInfo.dst_rect.h = mRotInfo.src_rect.h;
+
doTransform();
+
mRotInfo.flags |= MDSS_MDP_ROT_ONLY;
mEnabled = true;
if(!overlay::mdp_wrapper::setOverlay(mFd.getFD(), mRotInfo)) {
@@ -265,19 +291,52 @@
// Calculate the compressed o/p buffer size for BWC
uint32_t MdssRot::calcCompressedBufSize(const ovutils::Whf& destWhf) {
uint32_t bufSize = 0;
+ //Worst case alignments
int aWidth = ovutils::align(destWhf.w, 64);
int aHeight = ovutils::align(destWhf.h, 4);
- int rau_cnt = aWidth/64;
- int stride0 = (64 * 4 * rau_cnt) + rau_cnt/8;
- int stride1 = ((64 * 2 * rau_cnt) + rau_cnt/8) * 2;
- int stride0_off = (aHeight/4);
- int stride1_off = (aHeight/2);
+ /*
+ Format | RAU size (width x height)
+ ----------------------------------------------
+ ARGB | 32 pixel x 4 line
+ RGB888 | 32 pixel x 4 line
+ Y (Luma) | 64 pixel x 4 line
+ CRCB 420 | 32 pixel x 2 line
+ CRCB 422 H2V1 | 32 pixel x 4 line
+ CRCB 422 H1V2 | 64 pixel x 2 line
- //New o/p size for BWC
- bufSize = (stride0 * stride0_off + stride1 * stride1_off) +
- (rau_cnt * 2 * (stride0_off + stride1_off));
- ALOGD_IF(DEBUG_MDSS_ROT, "%s: width = %d, height = %d raucount = %d"
- "opBufSize = %d ", __FUNCTION__, aWidth, aHeight, rau_cnt, bufSize);
+ Metadata requirements:-
+ 1 byte meta data for every 8 RAUs
+ 2 byte meta data per RAU
+ */
+
+ //These blocks attempt to allocate for the worst case in each of the
+ //respective format classes, yuv/rgb. The table above is for reference
+ if(utils::isYuv(destWhf.format)) {
+ int yRauCount = aWidth / 64; //Y
+ int cRauCount = aWidth / 32; //C
+ int yStride = (64 * 4 * yRauCount) + alignup(yRauCount, 8) / 8;
+ int cStride = ((32 * 2 * cRauCount) + alignup(cRauCount, 8) / 8) * 2;
+ int yStrideOffset = (aHeight / 4);
+ int cStrideOffset = (aHeight / 2);
+ bufSize = (yStride * yStrideOffset + cStride * cStrideOffset) +
+ (yRauCount * yStrideOffset * 2) +
+ (cRauCount * cStrideOffset * 2) * 2;
+ ALOGD_IF(DEBUG_MDSS_ROT, "%s:YUV Y RAU Count = %d C RAU Count = %d",
+ __FUNCTION__, yRauCount, cRauCount);
+ } else {
+ int rauCount = aWidth / 32;
+ //Single plane
+ int stride = (32 * 4 * rauCount) + alignup(rauCount, 8) / 8;
+ int strideOffset = (aHeight / 4);
+ bufSize = (stride * strideOffset * 4 /*bpp*/) +
+ (rauCount * strideOffset * 2);
+ ALOGD_IF(DEBUG_MDSS_ROT, "%s:RGB RAU count = %d", __FUNCTION__,
+ rauCount);
+ }
+
+ ALOGD_IF(DEBUG_MDSS_ROT, "%s: aligned width = %d, aligned height = %d "
+ "Buf Size = %d", __FUNCTION__, aWidth, aHeight, bufSize);
+
return bufSize;
}
diff --git a/msm8226/liboverlay/overlayRotator.cpp b/msm8226/liboverlay/overlayRotator.cpp
index 43b2877..99efc5d 100644
--- a/msm8226/liboverlay/overlayRotator.cpp
+++ b/msm8226/liboverlay/overlayRotator.cpp
@@ -146,7 +146,7 @@
//Return a rot object, creating one if necessary
overlay::Rotator *rot = NULL;
if(mUseCount >= MAX_ROT_SESS) {
- ALOGE("%s, MAX rotator sessions reached", __func__);
+ ALOGW("%s, MAX rotator sessions reached, request rejected", __func__);
} else {
if(mRot[mUseCount] == NULL)
mRot[mUseCount] = overlay::Rotator::getRotator();
diff --git a/msm8226/liboverlay/overlayRotator.h b/msm8226/liboverlay/overlayRotator.h
index 53c54e6..64387cd 100644
--- a/msm8226/liboverlay/overlayRotator.h
+++ b/msm8226/liboverlay/overlayRotator.h
@@ -74,9 +74,14 @@
virtual void setTransform(const utils::eTransform& rot) = 0;
virtual bool commit() = 0;
virtual void setDownscale(int ds) = 0;
+ //Mem id and offset should be retrieved only after rotator kickoff
virtual int getDstMemId() const = 0;
virtual uint32_t getDstOffset() const = 0;
+ //Destination width, height, format, position should be retrieved only after
+ //rotator configuration is committed via commit API
virtual uint32_t getDstFormat() const = 0;
+ virtual utils::Whf getDstWhf() const = 0;
+ virtual utils::Dim getDstDimensions() const = 0;
virtual uint32_t getSessId() const = 0;
virtual bool queueBuffer(int fd, uint32_t offset) = 0;
virtual void dump() const = 0;
@@ -112,6 +117,8 @@
virtual int getDstMemId() const;
virtual uint32_t getDstOffset() const;
virtual uint32_t getDstFormat() const;
+ virtual utils::Whf getDstWhf() const;
+ virtual utils::Dim getDstDimensions() const;
virtual uint32_t getSessId() const;
virtual bool queueBuffer(int fd, uint32_t offset);
virtual void dump() const;
@@ -169,6 +176,8 @@
virtual int getDstMemId() const;
virtual uint32_t getDstOffset() const;
virtual uint32_t getDstFormat() const;
+ virtual utils::Whf getDstWhf() const;
+ virtual utils::Dim getDstDimensions() const;
virtual uint32_t getSessId() const;
virtual bool queueBuffer(int fd, uint32_t offset);
virtual void dump() const;
@@ -210,9 +219,10 @@
// Holder of rotator objects. Manages lifetimes
class RotMgr {
public:
- //Maximum sessions based on VG pipes, since rotator is used only for videos.
- //Even though we can have 4 mixer stages, that much may be unnecessary.
- enum { MAX_ROT_SESS = 3 };
+ //Virtually we can support as many rotator sessions as possible, However
+ // more number of rotator sessions leads to performance issues, so
+ // restricting the max rotator session to 4
+ enum { MAX_ROT_SESS = 4 };
~RotMgr();
void configBegin();
diff --git a/msm8226/liboverlay/overlayUtils.cpp b/msm8226/liboverlay/overlayUtils.cpp
index ddba868..0e063ab 100644
--- a/msm8226/liboverlay/overlayUtils.cpp
+++ b/msm8226/liboverlay/overlayUtils.cpp
@@ -74,12 +74,6 @@
//----------From class Res ------------------------------
const char* const Res::fbPath = "/dev/graphics/fb%u";
const char* const Res::rotPath = "/dev/msm_rotator";
-const char* const Res::format3DFile =
- "/sys/class/graphics/fb1/format_3d";
-const char* const Res::edid3dInfoFile =
- "/sys/class/graphics/fb1/3d_present";
-const char* const Res::barrierFile =
- "/sys/devices/platform/mipi_novatek.0/enable_3d_barrier";
//--------------------------------------------------------
@@ -284,16 +278,13 @@
return dscale_factor;
}
-//Since this is unavailable on Android, defining it in terms of base 10
-static inline float log2f(const float& x) {
- return log(x) / log(2);
-}
-
void getDecimationFactor(const int& src_w, const int& src_h,
- const int& dst_w, const int& dst_h, float& horDscale,
- float& verDscale) {
- horDscale = ceilf((float)src_w / (float)dst_w);
- verDscale = ceilf((float)src_h / (float)dst_h);
+ const int& dst_w, const int& dst_h, uint8_t& horzDeci,
+ uint8_t& vertDeci) {
+ horzDeci = 0;
+ vertDeci = 0;
+ float horDscale = ceilf((float)src_w / (float)dst_w);
+ float verDscale = ceilf((float)src_h / (float)dst_h);
//Next power of 2, if not already
horDscale = powf(2.0f, ceilf(log2f(horDscale)));
@@ -303,6 +294,21 @@
//between decimator and MDP downscale
horDscale /= 4.0f;
verDscale /= 4.0f;
+
+ if((int)horDscale)
+ horzDeci = (uint8_t)log2f(horDscale);
+
+ if((int)verDscale)
+ vertDeci = (uint8_t)log2f(verDscale);
+
+ if(src_w > 2048) {
+ //If the client sends us something > what a layer mixer supports
+ //then it means it doesn't want to use split-pipe but wants us to
+ //decimate. A minimum decimation of 2 will ensure that the width is
+ //always within layer mixer limits.
+ if(horzDeci < 2)
+ horzDeci = 2;
+ }
}
static inline int compute(const uint32_t& x, const uint32_t& y,
@@ -328,86 +334,6 @@
}
}
-bool is3DTV() {
- char is3DTV = '0';
- IOFile fp(Res::edid3dInfoFile, "r");
- (void)fp.read(is3DTV, 1);
- ALOGI("3DTV EDID flag: %d", is3DTV);
- return (is3DTV == '0') ? false : true;
-}
-
-bool isPanel3D() {
- OvFD fd;
- if(!overlay::open(fd, 0 /*fb*/, Res::fbPath)){
- ALOGE("isPanel3D Can't open framebuffer 0");
- return false;
- }
- fb_fix_screeninfo finfo;
- if(!mdp_wrapper::getFScreenInfo(fd.getFD(), finfo)) {
- ALOGE("isPanel3D read fb0 failed");
- }
- fd.close();
- return (FB_TYPE_3D_PANEL == finfo.type) ? true : false;
-}
-
-bool usePanel3D() {
- if(!isPanel3D())
- return false;
- char value[PROPERTY_VALUE_MAX];
- property_get("persist.user.panel3D", value, "0");
- int usePanel3D = atoi(value);
- return usePanel3D ? true : false;
-}
-
-bool send3DInfoPacket (uint32_t format3D) {
- IOFile fp(Res::format3DFile, "wb");
- (void)fp.write("%d", format3D);
- if(!fp.valid()) {
- ALOGE("send3DInfoPacket: no sysfs entry for setting 3d mode");
- return false;
- }
- return true;
-}
-
-bool enableBarrier (uint32_t orientation) {
- IOFile fp(Res::barrierFile, "wb");
- (void)fp.write("%d", orientation);
- if(!fp.valid()) {
- ALOGE("enableBarrier no sysfs entry for "
- "enabling barriers on 3D panel");
- return false;
- }
- return true;
-}
-
-uint32_t getS3DFormat(uint32_t fmt) {
- // The S3D is part of the HAL_PIXEL_FORMAT_YV12 value. Add
- // an explicit check for the format
- if (fmt == HAL_PIXEL_FORMAT_YV12) {
- return 0;
- }
- uint32_t fmt3D = format3D(fmt);
- uint32_t fIn3D = format3DInput(fmt3D); // MSB 2 bytes - inp
- uint32_t fOut3D = format3DOutput(fmt3D); // LSB 2 bytes - out
- fmt3D = fIn3D | fOut3D;
- if (!fIn3D) {
- fmt3D |= fOut3D << SHIFT_TOT_3D; //Set the input format
- }
- if (!fOut3D) {
- switch (fIn3D) {
- case HAL_3D_IN_SIDE_BY_SIDE_L_R:
- case HAL_3D_IN_SIDE_BY_SIDE_R_L:
- // For all side by side formats, set the output
- // format as Side-by-Side i.e 0x1
- fmt3D |= HAL_3D_IN_SIDE_BY_SIDE_L_R >> SHIFT_TOT_3D;
- break;
- default:
- fmt3D |= fIn3D >> SHIFT_TOT_3D; //Set the output format
- }
- }
- return fmt3D;
-}
-
void getDump(char *buf, size_t len, const char *prefix,
const mdp_overlay& ov) {
char str[256] = {'\0'};
diff --git a/msm8226/liboverlay/overlayUtils.h b/msm8226/liboverlay/overlayUtils.h
index c2649f3..530377b 100644
--- a/msm8226/liboverlay/overlayUtils.h
+++ b/msm8226/liboverlay/overlayUtils.h
@@ -120,40 +120,9 @@
const NoCopy& operator=(const NoCopy&);
};
-
-/* 3D related utils, defines etc...
- * The compound format passed to the overlay is
- * ABCCC where A is the input 3D format
- * B is the output 3D format
- * CCC is the color format e.g YCbCr420SP YCrCb420SP etc */
-enum { SHIFT_OUT_3D = 12,
- SHIFT_TOT_3D = 16 };
-enum { INPUT_3D_MASK = 0xFFFF0000,
- OUTPUT_3D_MASK = 0x0000FFFF };
-enum { BARRIER_LAND = 1,
- BARRIER_PORT = 2 };
-
-inline uint32_t format3D(uint32_t x) { return x & 0xFF000; }
-inline uint32_t format3DOutput(uint32_t x) {
- return (x & 0xF000) >> SHIFT_OUT_3D; }
-inline uint32_t format3DInput(uint32_t x) { return x & 0xF0000; }
-
-bool isHDMIConnected ();
-bool is3DTV();
-bool isPanel3D();
-bool usePanel3D();
-bool send3DInfoPacket (uint32_t fmt);
-bool enableBarrier (uint32_t orientation);
-uint32_t getS3DFormat(uint32_t fmt);
bool isMdssRotator();
void normalizeCrop(uint32_t& xy, uint32_t& wh);
-template <int CHAN>
-bool getPositionS3D(const Whf& whf, Dim& out);
-
-template <int CHAN>
-bool getCropS3D(const Dim& in, Dim& out, uint32_t fmt);
-
template <class Type>
void swapWidthHeight(Type& width, Type& height);
@@ -413,8 +382,8 @@
int getDownscaleFactor(const int& src_w, const int& src_h,
const int& dst_w, const int& dst_h);
void getDecimationFactor(const int& src_w, const int& src_h,
- const int& dst_w, const int& dst_h, float& horDscale,
- float& verDscale);
+ const int& dst_w, const int& dst_h, uint8_t& horzDeci,
+ uint8_t& vertDeci);
/* flip is upside down and such. V, H flip
* rotation is 90, 180 etc
@@ -446,39 +415,6 @@
return a ? ((value + (a-1)) & ~(a-1)) : value;
}
-enum eRotOutFmt {
- ROT_OUT_FMT_DEFAULT,
- ROT_OUT_FMT_Y_CRCB_H2V2
-};
-
-template <int ROT_OUT_FMT> struct RotOutFmt;
-
-// FIXME, taken from gralloc_priv.h. Need to
-// put it back as soon as overlay takes place of the old one
-/* possible formats for 3D content*/
-enum {
- HAL_NO_3D = 0x0000,
- HAL_3D_IN_SIDE_BY_SIDE_L_R = 0x10000,
- HAL_3D_IN_TOP_BOTTOM = 0x20000,
- HAL_3D_IN_INTERLEAVE = 0x40000,
- HAL_3D_IN_SIDE_BY_SIDE_R_L = 0x80000,
- HAL_3D_OUT_SIDE_BY_SIDE = 0x1000,
- HAL_3D_OUT_TOP_BOTTOM = 0x2000,
- HAL_3D_OUT_INTERLEAVE = 0x4000,
- HAL_3D_OUT_MONOSCOPIC = 0x8000
-};
-
-enum { HAL_3D_OUT_SBS_MASK =
- HAL_3D_OUT_SIDE_BY_SIDE >> overlay::utils::SHIFT_OUT_3D,
- HAL_3D_OUT_TOP_BOT_MASK =
- HAL_3D_OUT_TOP_BOTTOM >> overlay::utils::SHIFT_OUT_3D,
- HAL_3D_OUT_INTERL_MASK =
- HAL_3D_OUT_INTERLEAVE >> overlay::utils::SHIFT_OUT_3D,
- HAL_3D_OUT_MONOS_MASK =
- HAL_3D_OUT_MONOSCOPIC >> overlay::utils::SHIFT_OUT_3D
-};
-
-
inline bool isYuv(uint32_t format) {
switch(format){
case MDP_Y_CBCR_H2V1:
@@ -577,105 +513,6 @@
ALOGE("== Dump Dim x=%d y=%d w=%d h=%d start/end ==", x, y, w, h);
}
-// FB0
-template <int CHAN>
-inline Dim getPositionS3DImpl(const Whf& whf)
-{
- switch (whf.format & OUTPUT_3D_MASK)
- {
- case HAL_3D_OUT_SBS_MASK:
- // x, y, w, h
- return Dim(0, 0, whf.w/2, whf.h);
- case HAL_3D_OUT_TOP_BOT_MASK:
- return Dim(0, 0, whf.w, whf.h/2);
- case HAL_3D_OUT_MONOS_MASK:
- return Dim();
- case HAL_3D_OUT_INTERL_MASK:
- // FIXME error?
- ALOGE("%s HAL_3D_OUT_INTERLEAVE_MASK", __FUNCTION__);
- return Dim();
- default:
- ALOGE("%s Unsupported 3D output format %d", __FUNCTION__,
- whf.format);
- }
- return Dim();
-}
-
-template <>
-inline Dim getPositionS3DImpl<utils::OV_RIGHT_SPLIT>(const Whf& whf)
-{
- switch (whf.format & OUTPUT_3D_MASK)
- {
- case HAL_3D_OUT_SBS_MASK:
- return Dim(whf.w/2, 0, whf.w/2, whf.h);
- case HAL_3D_OUT_TOP_BOT_MASK:
- return Dim(0, whf.h/2, whf.w, whf.h/2);
- case HAL_3D_OUT_MONOS_MASK:
- return Dim(0, 0, whf.w, whf.h);
- case HAL_3D_OUT_INTERL_MASK:
- // FIXME error?
- ALOGE("%s HAL_3D_OUT_INTERLEAVE_MASK", __FUNCTION__);
- return Dim();
- default:
- ALOGE("%s Unsupported 3D output format %d", __FUNCTION__,
- whf.format);
- }
- return Dim();
-}
-
-template <int CHAN>
-inline bool getPositionS3D(const Whf& whf, Dim& out) {
- out = getPositionS3DImpl<CHAN>(whf);
- return (out != Dim());
-}
-
-template <int CHAN>
-inline Dim getCropS3DImpl(const Dim& in, uint32_t fmt) {
- switch (fmt & INPUT_3D_MASK)
- {
- case HAL_3D_IN_SIDE_BY_SIDE_L_R:
- return Dim(0, 0, in.w/2, in.h);
- case HAL_3D_IN_SIDE_BY_SIDE_R_L:
- return Dim(in.w/2, 0, in.w/2, in.h);
- case HAL_3D_IN_TOP_BOTTOM:
- return Dim(0, 0, in.w, in.h/2);
- case HAL_3D_IN_INTERLEAVE:
- ALOGE("%s HAL_3D_IN_INTERLEAVE", __FUNCTION__);
- break;
- default:
- ALOGE("%s Unsupported 3D format %d", __FUNCTION__, fmt);
- break;
- }
- return Dim();
-}
-
-template <>
-inline Dim getCropS3DImpl<utils::OV_RIGHT_SPLIT>(const Dim& in, uint32_t fmt) {
- switch (fmt & INPUT_3D_MASK)
- {
- case HAL_3D_IN_SIDE_BY_SIDE_L_R:
- return Dim(in.w/2, 0, in.w/2, in.h);
- case HAL_3D_IN_SIDE_BY_SIDE_R_L:
- return Dim(0, 0, in.w/2, in.h);
- case HAL_3D_IN_TOP_BOTTOM:
- return Dim(0, in.h/2, in.w, in.h/2);
- case HAL_3D_IN_INTERLEAVE:
- ALOGE("%s HAL_3D_IN_INTERLEAVE", __FUNCTION__);
- break;
- default:
- ALOGE("%s Unsupported 3D format %d", __FUNCTION__, fmt);
- break;
- }
- return Dim();
-}
-
-template <int CHAN>
-inline bool getCropS3D(const Dim& in, Dim& out, uint32_t fmt)
-{
- out = getCropS3DImpl<CHAN>(in, fmt);
- return (out != Dim());
-}
-
template <class Type>
void swapWidthHeight(Type& width, Type& height) {
Type tmp = width;
@@ -706,6 +543,14 @@
value--;
}
+/* Prerotation adjusts crop co-ordinates to the new transformed values within
+ * destination buffer. This is necessary only when the entire buffer is rotated
+ * irrespective of crop (A-family). If only the crop portion of the buffer is
+ * rotated into a destination buffer matching the size of crop, we don't need to
+ * use this helper (B-family).
+ * @Deprecated as of now, retained for the case where a full buffer needs
+ * transform and also as a reference.
+ */
void preRotateSource(const eTransform& tr, Whf& whf, Dim& srcCrop);
void getDump(char *buf, size_t len, const char *prefix, const mdp_overlay& ov);
void getDump(char *buf, size_t len, const char *prefix, const msmfb_img& ov);
@@ -728,12 +573,6 @@
static const char* const fbPath;
// /dev/msm_rotator
static const char* const rotPath;
- // /sys/class/graphics/fb1/format_3d
- static const char* const format3DFile;
- // /sys/class/graphics/fb1/3d_present
- static const char* const edid3dInfoFile;
- // /sys/devices/platform/mipi_novatek.0/enable_3d_barrier
- static const char* const barrierFile;
};
diff --git a/msm8226/liboverlay/pipes/overlay3DPipe.h b/msm8226/liboverlay/pipes/overlay3DPipe.h
deleted file mode 100644
index 4e5630e..0000000
--- a/msm8226/liboverlay/pipes/overlay3DPipe.h
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
-* Copyright (c) 2011-2012, The Linux Foundation. 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 The Linux Foundation 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 OVERLAY_M3D_EXT_PIPE_H
-#define OVERLAY_M3D_EXT_PIPE_H
-
-#include "overlayGenPipe.h"
-#include "overlayUtils.h"
-
-namespace overlay {
-
-///////////// M3DExt Pipe ////////////////////////////
-/**
-* A specific impl of GenericPipe for 3D.
-* Whenever needed to have a pass through - we do it.
-* If there is a special need for special/diff behavior
-* do it here
-* PANEL is always EXTERNAL for this pipe.
-* CHAN = 0,1 it's either Channel 1 or channel 2 needed for
-* 3D crop and position */
-template <int CHAN>
-class M3DExtPipe : utils::NoCopy {
-public:
- /* Please look at overlayGenPipe.h for info */
- explicit M3DExtPipe();
- ~M3DExtPipe();
- bool init(RotatorBase* rot);
- bool close();
- bool commit();
- bool queueBuffer(int fd, uint32_t offset);
- bool setCrop(const utils::Dim& d);
- bool setPosition(const utils::Dim& dim);
- bool setTransform(const utils::eTransform& param);
- bool setSource(const utils::PipeArgs& args);
- void dump() const;
-private:
- overlay::GenericPipe<utils::EXTERNAL> mM3d;
- // Cache the M3D format
- uint32_t mM3Dfmt;
-};
-
-///////////// M3DPrimary Pipe ////////////////////////////
-/**
-* A specific impl of GenericPipe for 3D.
-* Whenever needed to have a pass through - we do it.
-* If there is a special need for special/diff behavior
-* do it here
-* PANEL is always PRIMARY for this pipe.
-* CHAN = 0,1 it's either Channel 1 or channel 2 needed for
-* 3D crop and position */
-template <int CHAN>
-class M3DPrimaryPipe : utils::NoCopy {
-public:
- /* Please look at overlayGenPipe.h for info */
- explicit M3DPrimaryPipe();
- ~M3DPrimaryPipe();
- bool init(RotatorBase* rot);
- bool close();
- bool commit();
- bool queueBuffer(int fd, uint32_t offset);
- bool setCrop(const utils::Dim& d);
- bool setPosition(const utils::Dim& dim);
- bool setTransform(const utils::eTransform& param);
- bool setSource(const utils::PipeArgs& args);
- void dump() const;
-private:
- overlay::GenericPipe<utils::PRIMARY> mM3d;
- // Cache the M3D format
- uint32_t mM3Dfmt;
-};
-
-///////////// S3DExt Pipe ////////////////////////////////
-/**
-* A specific impl of GenericPipe for 3D.
-* Whenever needed to have a pass through - we do it.
-* If there is a special need for special/diff behavior
-* do it here.
-* PANEL is always EXTERNAL for this pipe.
-* CHAN = 0,1 it's either Channel 1 or channel 2 needed for
-* 3D crop and position */
-template <int CHAN>
-class S3DExtPipe : utils::NoCopy {
-public:
- /* Please look at overlayGenPipe.h for info */
- explicit S3DExtPipe();
- ~S3DExtPipe();
- bool init(RotatorBase* rot);
- bool close();
- bool commit();
- bool queueBuffer(int fd, uint32_t offset);
- bool setCrop(const utils::Dim& d);
- bool setPosition(const utils::Dim& dim);
- bool setTransform(const utils::eTransform& param);
- bool setSource(const utils::PipeArgs& args);
- void dump() const;
-private:
- overlay::GenericPipe<utils::EXTERNAL> mS3d;
- // Cache the 3D format
- uint32_t mS3Dfmt;
-};
-
-///////////// S3DPrimary Pipe ////////////////////////////
-/**
-* A specific impl of GenericPipe for 3D.
-* Whenever needed to have a pass through - we do it.
-* If there is a special need for special/diff behavior
-* do it here
-* PANEL is always PRIMARY for this pipe.
-* CHAN = 0,1 it's either Channel 1 or channel 2 needed for
-* 3D crop and position */
-template <int CHAN>
-class S3DPrimaryPipe : utils::NoCopy {
-public:
- /* Please look at overlayGenPipe.h for info */
- explicit S3DPrimaryPipe();
- ~S3DPrimaryPipe();
- bool init(RotatorBase* rot);
- bool close();
- bool commit();
- bool queueBuffer(int fd, uint32_t offset);
- bool setCrop(const utils::Dim& d);
- bool setPosition(const utils::Dim& dim);
- bool setTransform(const utils::eTransform& param);
- bool setSource(const utils::PipeArgs& args);
- void dump() const;
-private:
- /* needed for 3D related IOCTL */
- MdpCtrl3D mCtrl3D;
- overlay::GenericPipe<utils::PRIMARY> mS3d;
- // Cache the 3D format
- uint32_t mS3Dfmt;
-};
-
-
-
-
-//------------------------Inlines and Templates--------------------------
-
-
-///////////// M3DExt Pipe ////////////////////////////
-template <int CHAN>
-inline M3DExtPipe<CHAN>::M3DExtPipe() : mM3Dfmt(0) {}
-template <int CHAN>
-inline M3DExtPipe<CHAN>::~M3DExtPipe() { close(); }
-template <int CHAN>
-inline bool M3DExtPipe<CHAN>::init(RotatorBase* rot) {
- ALOGE_IF(DEBUG_OVERLAY, "M3DExtPipe init");
- if(!mM3d.init(rot)) {
- ALOGE("3Dpipe failed to init");
- return false;
- }
- return true;
-}
-template <int CHAN>
-inline bool M3DExtPipe<CHAN>::close() {
- return mM3d.close();
-}
-template <int CHAN>
-inline bool M3DExtPipe<CHAN>::commit() { return mM3d.commit(); }
-template <int CHAN>
-inline bool M3DExtPipe<CHAN>::queueBuffer(int fd, uint32_t offset) {
- return mM3d.queueBuffer(fd, offset);
-}
-template <int CHAN>
-inline bool M3DExtPipe<CHAN>::setCrop(const utils::Dim& d) {
- utils::Dim _dim;
- if(!utils::getCropS3D<CHAN>(d, _dim, mM3Dfmt)){
- ALOGE("M3DExtPipe setCrop failed to getCropS3D");
- _dim = d;
- }
- return mM3d.setCrop(_dim);
-}
-
-template <int CHAN>
-inline bool M3DExtPipe<CHAN>::setPosition(const utils::Dim& d) {
- utils::Dim _dim;
- // original setPositionHandleState has getPositionS3D(...,true)
- // which means format is HAL_3D_OUT_SBS_MASK
- // HAL_3D_OUT_SBS_MASK is 0x1000 >> 12 == 0x1 as the orig
- // code suggets
- utils::Whf _whf(mM3d.getScreenInfo().mFBWidth,
- mM3d.getScreenInfo().mFBHeight,
- mM3Dfmt);
- if(!utils::getPositionS3D<CHAN>(_whf, _dim)) {
- ALOGE("S3DPrimaryPipe setPosition err in getPositionS3D");
- _dim = d;
- }
- return mM3d.setPosition(_dim);
-}
-template <int CHAN>
-inline bool M3DExtPipe<CHAN>::setTransform(const utils::eTransform& param) {
- return mM3d.setTransform(param);
-}
-template <int CHAN>
-inline bool M3DExtPipe<CHAN>::setSource(const utils::PipeArgs& args)
-{
- // extract 3D fmt
- mM3Dfmt = utils::format3DInput(utils::getS3DFormat(args.whf.format)) |
- utils::HAL_3D_OUT_MONOS_MASK;
- return mM3d.setSource(args);
-}
-template <int CHAN>
-inline void M3DExtPipe<CHAN>::dump() const {
- ALOGE("M3DExtPipe Pipe fmt=%d", mM3Dfmt);
- mM3d.dump();
-}
-
-
-///////////// M3DPrimary Pipe ////////////////////////////
-template <int CHAN>
-inline M3DPrimaryPipe<CHAN>::M3DPrimaryPipe() : mM3Dfmt(0) {}
-template <int CHAN>
-inline M3DPrimaryPipe<CHAN>::~M3DPrimaryPipe() { close(); }
-template <int CHAN>
-inline bool M3DPrimaryPipe<CHAN>::init(RotatorBase* rot) {
- ALOGE_IF(DEBUG_OVERLAY, "M3DPrimaryPipe init");
- if(!mM3d.init(rot)) {
- ALOGE("3Dpipe failed to init");
- return false;
- }
- return true;
-}
-template <int CHAN>
-inline bool M3DPrimaryPipe<CHAN>::close() {
- return mM3d.close();
-}
-template <int CHAN>
-inline bool M3DPrimaryPipe<CHAN>::commit() { return mM3d.commit(); }
-template <int CHAN>
-inline bool M3DPrimaryPipe<CHAN>::queueBuffer(int fd, uint32_t offset) {
- return mM3d.queueBuffer(fd, offset);
-}
-template <int CHAN>
-inline bool M3DPrimaryPipe<CHAN>::setCrop(const utils::Dim& d) {
- utils::Dim _dim;
- if(!utils::getCropS3D<CHAN>(d, _dim, mM3Dfmt)){
- ALOGE("M3DPrimaryPipe setCrop failed to getCropS3D");
- _dim = d;
- }
- return mM3d.setCrop(_dim);
-}
-template <int CHAN>
-inline bool M3DPrimaryPipe<CHAN>::setPosition(const utils::Dim& d) {
- return mM3d.setPosition(d);
-}
-template <int CHAN>
-inline bool M3DPrimaryPipe<CHAN>::setTransform(const utils::eTransform& param) {
- return mM3d.setTransform(param);
-}
-template <int CHAN>
-inline bool M3DPrimaryPipe<CHAN>::setSource(const utils::PipeArgs& args)
-{
- // extract 3D fmt
- mM3Dfmt = utils::format3DInput(utils::getS3DFormat(args.whf.format)) |
- utils::HAL_3D_OUT_MONOS_MASK;
- return mM3d.setSource(args);
-}
-template <int CHAN>
-inline void M3DPrimaryPipe<CHAN>::dump() const {
- ALOGE("M3DPrimaryPipe Pipe fmt=%d", mM3Dfmt);
- mM3d.dump();
-}
-
-///////////// S3DExt Pipe ////////////////////////////////
-template <int CHAN>
-inline S3DExtPipe<CHAN>::S3DExtPipe() : mS3Dfmt(0) {}
-template <int CHAN>
-inline S3DExtPipe<CHAN>::~S3DExtPipe() { close(); }
-template <int CHAN>
-inline bool S3DExtPipe<CHAN>::init(RotatorBase* rot) {
- ALOGE_IF(DEBUG_OVERLAY, "S3DExtPipe init");
- if(!mS3d.init(rot)) {
- ALOGE("3Dpipe failed to init");
- return false;
- }
- return true;
-}
-template <int CHAN>
-inline bool S3DExtPipe<CHAN>::close() {
- if(!utils::send3DInfoPacket(0)) {
- ALOGE("S3DExtPipe close failed send3D info packet");
- }
- return mS3d.close();
-}
-template <int CHAN>
-inline bool S3DExtPipe<CHAN>::commit() { return mS3d.commit(); }
-template <int CHAN>
-inline bool S3DExtPipe<CHAN>::queueBuffer(int fd, uint32_t offset) {
- return mS3d.queueBuffer(fd, offset);
-}
-template <int CHAN>
-inline bool S3DExtPipe<CHAN>::setCrop(const utils::Dim& d) {
- utils::Dim _dim;
- if(!utils::getCropS3D<CHAN>(d, _dim, mS3Dfmt)){
- ALOGE("S3DExtPipe setCrop failed to getCropS3D");
- _dim = d;
- }
- return mS3d.setCrop(_dim);
-}
-template <int CHAN>
-inline bool S3DExtPipe<CHAN>::setPosition(const utils::Dim& d)
-{
- utils::Dim _dim;
- utils::Whf _whf(mS3d.getScreenInfo().mFBWidth,
- mS3d.getScreenInfo().mFBHeight,
- mS3Dfmt);
- if(!utils::getPositionS3D<CHAN>(_whf, _dim)) {
- ALOGE("S3DExtPipe setPosition err in getPositionS3D");
- _dim = d;
- }
- return mS3d.setPosition(_dim);
-}
-template <int CHAN>
-inline bool S3DExtPipe<CHAN>::setTransform(const utils::eTransform& param) {
- return mS3d.setTransform(param);
-}
-template <int CHAN>
-inline bool S3DExtPipe<CHAN>::setSource(const utils::PipeArgs& args) {
- mS3Dfmt = utils::getS3DFormat(args.whf.format);
- return mS3d.setSource(args);
-}
-template <int CHAN>
-inline void S3DExtPipe<CHAN>::dump() const {
- ALOGE("S3DExtPipe Pipe fmt=%d", mS3Dfmt);
- mS3d.dump();
-}
-
-///////////// S3DPrimary Pipe ////////////////////////////
-template <int CHAN>
-inline S3DPrimaryPipe<CHAN>::S3DPrimaryPipe() : mS3Dfmt(0) {}
-template <int CHAN>
-inline S3DPrimaryPipe<CHAN>::~S3DPrimaryPipe() { close(); }
-template <int CHAN>
-inline bool S3DPrimaryPipe<CHAN>::init(RotatorBase* rot) {
- ALOGE_IF(DEBUG_OVERLAY, "S3DPrimaryPipe init");
- if(!mS3d.init(rot)) {
- ALOGE("3Dpipe failed to init");
- return false;
- }
- // set the ctrl fd
- mCtrl3D.setFd(mS3d.getCtrlFd());
- return true;
-}
-template <int CHAN>
-inline bool S3DPrimaryPipe<CHAN>::close() {
- if(!utils::enableBarrier(0)) {
- ALOGE("S3DExtPipe close failed enable barrier");
- }
- mCtrl3D.close();
- return mS3d.close();
-}
-
-template <int CHAN>
-inline bool S3DPrimaryPipe<CHAN>::commit() {
- uint32_t fmt = mS3Dfmt & utils::OUTPUT_3D_MASK;
- if(!utils::send3DInfoPacket(fmt)){
- ALOGE("Error S3DExtPipe start error send3DInfoPacket %d", fmt);
- return false;
- }
- return mS3d.commit();
-}
-template <int CHAN>
-inline bool S3DPrimaryPipe<CHAN>::queueBuffer(int fd, uint32_t offset) {
- return mS3d.queueBuffer(fd, offset);
-}
-template <int CHAN>
-inline bool S3DPrimaryPipe<CHAN>::setCrop(const utils::Dim& d) {
- utils::Dim _dim;
- if(!utils::getCropS3D<CHAN>(d, _dim, mS3Dfmt)){
- ALOGE("S3DPrimaryPipe setCrop failed to getCropS3D");
- _dim = d;
- }
- return mS3d.setCrop(_dim);
-}
-template <int CHAN>
-inline bool S3DPrimaryPipe<CHAN>::setPosition(const utils::Dim& d)
-{
- utils::Whf fbwhf(mS3d.getScreenInfo().mFBWidth,
- mS3d.getScreenInfo().mFBHeight,
- 0 /* fmt dont care*/);
- mCtrl3D.setWh(fbwhf);
- if(!mCtrl3D.useVirtualFB()) {
- ALOGE("Failed to use VFB on %d (non fatal)", utils::FB0);
- return false;
- }
- utils::Dim _dim;
- // original setPositionHandleState has getPositionS3D(...,true)
- // which means format is HAL_3D_OUT_SBS_MASK
- // HAL_3D_OUT_SBS_MASK is 0x1000 >> 12 == 0x1 as the orig
- // code suggets
- utils::Whf _whf(d.w, d.h, utils::HAL_3D_OUT_SBS_MASK);
- if(!utils::getPositionS3D<CHAN>(_whf, _dim)) {
- ALOGE("S3DPrimaryPipe setPosition err in getPositionS3D");
- _dim = d;
- }
- return mS3d.setPosition(_dim);
-}
-
-/* for S3DPrimaryPipe, we need to have barriers once
-* So the easiest way to achieve it, is to make sure FB0 is having it before
-* setParam is running */
-template <>
-inline bool S3DPrimaryPipe<utils::OV_PIPE0>::setTransform(
- const utils::eTransform& param) {
- uint32_t barrier=0;
- switch(param) {
- case utils::OVERLAY_TRANSFORM_ROT_90:
- case utils::OVERLAY_TRANSFORM_ROT_270:
- barrier = utils::BARRIER_LAND;
- break;
- default:
- barrier = utils::BARRIER_PORT;
- break;
- }
- if(!utils::enableBarrier(barrier)) {
- ALOGE("S3DPrimaryPipe setTransform failed to enable barrier");
- }
- return mS3d.setTransform(param);
-}
-
-template <int CHAN>
-inline bool S3DPrimaryPipe<CHAN>::setTransform(const utils::eTransform& param) {
- return mS3d.setTransform(param);
-}
-template <int CHAN>
-inline bool S3DPrimaryPipe<CHAN>::setSource(const utils::PipeArgs& args)
-{
- mS3Dfmt = utils::getS3DFormat(args.whf.format);
- return mS3d.setSource(args);
-}
-template <int CHAN>
-inline void S3DPrimaryPipe<CHAN>::dump() const {
- ALOGE("S3DPrimaryPipe Pipe fmt=%d", mS3Dfmt);
- mS3d.dump();
-}
-
-} // overlay
-
-#endif // OVERLAY_M3D_EXT_PIPE_H
diff --git a/msm8226/liboverlay/pipes/overlayGenPipe.cpp b/msm8226/liboverlay/pipes/overlayGenPipe.cpp
index 9e57223..aebaebf 100644
--- a/msm8226/liboverlay/pipes/overlayGenPipe.cpp
+++ b/msm8226/liboverlay/pipes/overlayGenPipe.cpp
@@ -32,18 +32,16 @@
namespace overlay {
-GenericPipe::GenericPipe(const int& dpy) : mDpy(dpy), mRotDownscaleOpt(false),
- pipeState(CLOSED), mCtrl(new Ctrl(dpy)), mData(new Data(dpy)) {
+GenericPipe::GenericPipe(const int& dpy) : mDpy(dpy),
+ mCtrl(new Ctrl(dpy)), mData(new Data(dpy)) {
}
GenericPipe::~GenericPipe() {
delete mCtrl;
delete mData;
- setClosed();
}
void GenericPipe::setSource(const utils::PipeArgs& args) {
- mRotDownscaleOpt = args.rotFlags & utils::ROT_DOWNSCALE_ENABLED;
mCtrl->setSource(args);
}
@@ -68,27 +66,15 @@
return mCtrl->setVisualParams(metadata);
}
+void GenericPipe::setPipeType(const utils::eMdpPipeType& pType) {
+ mCtrl->setPipeType(pType);
+}
+
bool GenericPipe::commit() {
- bool ret = false;
- int downscale_factor = utils::ROT_DS_NONE;
-
- if(mRotDownscaleOpt) {
- ovutils::Dim src(mCtrl->getCrop());
- ovutils::Dim dst(mCtrl->getPosition());
- downscale_factor = ovutils::getDownscaleFactor(
- src.w, src.h, dst.w, dst.h);
- }
-
- mCtrl->setDownscale(downscale_factor);
- ret = mCtrl->commit();
-
- pipeState = ret ? OPEN : CLOSED;
- return ret;
+ return mCtrl->commit();
}
bool GenericPipe::queueBuffer(int fd, uint32_t offset) {
- //TODO Move pipe-id transfer to CtrlData class. Make ctrl and data private.
- OVASSERT(isOpen(), "State is closed, cannot queueBuffer");
int pipeId = mCtrl->getPipeId();
OVASSERT(-1 != pipeId, "Ctrl ID should not be -1");
// set pipe id from ctrl to data
@@ -97,19 +83,18 @@
return mData->queueBuffer(fd, offset);
}
-int GenericPipe::getCtrlFd() const {
- return mCtrl->getFd();
-}
-
utils::Dim GenericPipe::getCrop() const
{
return mCtrl->getCrop();
}
+uint8_t GenericPipe::getPriority() const {
+ return mCtrl->getPriority();
+}
+
void GenericPipe::dump() const
{
ALOGE("== Dump Generic pipe start ==");
- ALOGE("pipe state = %d", (int)pipeState);
mCtrl->dump();
mData->dump();
ALOGE("== Dump Generic pipe end ==");
@@ -120,19 +105,6 @@
mData->getDump(buf, len);
}
-bool GenericPipe::isClosed() const {
- return (pipeState == CLOSED);
-}
-
-bool GenericPipe::isOpen() const {
- return (pipeState == OPEN);
-}
-
-bool GenericPipe::setClosed() {
- pipeState = CLOSED;
- return true;
-}
-
int GenericPipe::getPipeId() {
return mCtrl->getPipeId();
}
diff --git a/msm8226/liboverlay/pipes/overlayGenPipe.h b/msm8226/liboverlay/pipes/overlayGenPipe.h
index 813a2b3..0a2639a 100644
--- a/msm8226/liboverlay/pipes/overlayGenPipe.h
+++ b/msm8226/liboverlay/pipes/overlayGenPipe.h
@@ -54,6 +54,8 @@
void setPosition(const utils::Dim& dim);
/* set visual param */
bool setVisualParams(const MetaData_t &metadata);
+ /* set pipe type RGB/DMA/VG */
+ void setPipeType(const utils::eMdpPipeType& pType);
/* commit changes to the overlay "set"*/
bool commit();
/* Data APIs */
@@ -63,12 +65,8 @@
const utils::PipeArgs& getArgs() const;
/* retrieve cached crop data */
utils::Dim getCrop() const;
- /* is closed */
- bool isClosed() const;
- /* is open */
- bool isOpen() const;
- /* return Ctrl fd. Used for S3D */
- int getCtrlFd() const;
+ /* return pipe priority */
+ uint8_t getPriority() const;
/* dump the state of the object */
void dump() const;
/* Return the dump in the specified buffer */
@@ -78,19 +76,7 @@
static bool validateAndSet(GenericPipe* pipeArray[], const int& count,
const int& fbFd);
private:
- /* set Closed pipe */
- bool setClosed();
-
int mDpy;
- //Whether we will do downscale opt. This is just a request. If the frame is
- //not a candidate, we might not do it.
- bool mRotDownscaleOpt;
- /* Pipe open or closed */
- enum ePipeState {
- CLOSED,
- OPEN
- };
- ePipeState pipeState;
Ctrl *mCtrl;
Data *mData;
};
diff --git a/msm8226/libqdutils/Android.mk b/msm8226/libqdutils/Android.mk
index 2907ccf..212c8d8 100644
--- a/msm8226/libqdutils/Android.mk
+++ b/msm8226/libqdutils/Android.mk
@@ -21,7 +21,6 @@
LOCAL_COPY_HEADERS_TO := $(common_header_export_path)
LOCAL_COPY_HEADERS := qdMetaData.h
-LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
LOCAL_SHARED_LIBRARIES := liblog libcutils
LOCAL_C_INCLUDES := $(common_includes)
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
diff --git a/msm8226/libqdutils/display_config.cpp b/msm8226/libqdutils/display_config.cpp
index 60f1f68..7ff106f 100644
--- a/msm8226/libqdutils/display_config.cpp
+++ b/msm8226/libqdutils/display_config.cpp
@@ -113,4 +113,25 @@
return err;
}
+int setViewFrame(int dpy, int l, int t, int r, int b) {
+ status_t err = (status_t) FAILED_TRANSACTION;
+ sp<IQService> binder = getBinder();
+ Parcel inParcel, outParcel;
+ inParcel.writeInt32(dpy);
+ inParcel.writeInt32(l);
+ inParcel.writeInt32(t);
+ inParcel.writeInt32(r);
+ inParcel.writeInt32(b);
+
+ if(binder != NULL) {
+ err = binder->dispatch(IQService::SET_VIEW_FRAME,
+ &inParcel, &outParcel);
+ }
+ if(err)
+ ALOGE("%s: Failed to set view frame for dpy %d err=%d",
+ __FUNCTION__, dpy, err);
+
+ return err;
+}
+
}; //namespace
diff --git a/msm8226/libqdutils/display_config.h b/msm8226/libqdutils/display_config.h
index 29edbef..a69265b 100644
--- a/msm8226/libqdutils/display_config.h
+++ b/msm8226/libqdutils/display_config.h
@@ -73,4 +73,7 @@
// get the active visible region for the display
// Returns 0 on success, negative values on errors
int getDisplayVisibleRegion(int dpy, hwc_rect_t &rect);
+
+// set the view frame information in hwc context from surfaceflinger
+int setViewFrame(int dpy, int l, int t, int r, int b);
}; //namespace
diff --git a/msm8226/libqdutils/idle_invalidator.cpp b/msm8226/libqdutils/idle_invalidator.cpp
index d30375e..86191e9 100644
--- a/msm8226/libqdutils/idle_invalidator.cpp
+++ b/msm8226/libqdutils/idle_invalidator.cpp
@@ -103,7 +103,7 @@
char data[64];
// Consume the node by reading it
ssize_t len = pread(pFd.fd, data, 64, 0);
- ALOGD_IF(II_DEBUG, "IdleInvalidator::%s Idle Timeout fired len %zu",
+ ALOGD_IF(II_DEBUG, "IdleInvalidator::%s Idle Timeout fired len %zd",
__FUNCTION__, len);
mHandler((void*)mHwcContext);
}
diff --git a/msm8226/libqdutils/mdp_version.cpp b/msm8226/libqdutils/mdp_version.cpp
index a757e69..6b53522 100644
--- a/msm8226/libqdutils/mdp_version.cpp
+++ b/msm8226/libqdutils/mdp_version.cpp
@@ -37,24 +37,41 @@
#define TOKEN_PARAMS_DELIM "="
-#ifndef MDSS_MDP_REV
-enum mdp_rev {
- MDSS_MDP_HW_REV_100 = 0x10000000, //8974 v1
- MDSS_MDP_HW_REV_101 = 0x10010000, //8x26
- MDSS_MDP_HW_REV_102 = 0x10020000, //8974 v2
- MDSS_MDP_HW_REV_103 = 0x10030000, //8084
- MDSS_MDP_HW_REV_104 = 0x10040000, //Next version
- MDSS_MDP_HW_REV_105 = 0x10050000, //Next version
- MDSS_MDP_HW_REV_106 = 0x10060000, //8x16
- MDSS_MDP_HW_REV_200 = 0x20000000, //8092
- MDSS_MDP_HW_REV_206 = 0x20060000, //Future
-};
-#else
-enum mdp_rev {
- MDSS_MDP_HW_REV_104 = 0x10040000, //Next version
- MDSS_MDP_HW_REV_206 = 0x20060000, //Future
- MDSS_MDP_HW_REV_107 = 0x10070000, //Next version
-};
+#ifndef MDSS_MDP_HW_REV_100
+#define MDSS_MDP_HW_REV_100 0x10000000 //8974 v1
+#endif
+#ifndef MDSS_MDP_HW_REV_101
+#define MDSS_MDP_HW_REV_101 0x10010000 //8x26
+#endif
+#ifndef MDSS_MDP_HW_REV_102
+#define MDSS_MDP_HW_REV_102 0x10020000 //8974 v2
+#endif
+#ifndef MDSS_MDP_HW_REV_103
+#define MDSS_MDP_HW_REV_103 0x10030000 //8084
+#endif
+#ifndef MDSS_MDP_HW_REV_104
+#define MDSS_MDP_HW_REV_104 0x10040000 //Next version
+#endif
+#ifndef MDSS_MDP_HW_REV_105
+#define MDSS_MDP_HW_REV_105 0x10050000 //8994
+#endif
+#ifndef MDSS_MDP_HW_REV_106
+#define MDSS_MDP_HW_REV_106 0x10060000 //8x16
+#endif
+#ifndef MDSS_MDP_HW_REV_107
+#define MDSS_MDP_HW_REV_107 0x10070000 //Next version
+#endif
+#ifndef MDSS_MDP_HW_REV_108
+#define MDSS_MDP_HW_REV_108 0x10080000 //8x39 & 8x36
+#endif
+#ifndef MDSS_MDP_HW_REV_109
+#define MDSS_MDP_HW_REV_109 0x10090000 //Next version
+#endif
+#ifndef MDSS_MDP_HW_REV_200
+#define MDSS_MDP_HW_REV_200 0x20000000 //8092
+#endif
+#ifndef MDSS_MDP_HW_REV_206
+#define MDSS_MDP_HW_REV_206 0x20060000 //Future
#endif
MDPVersion::MDPVersion()
@@ -71,7 +88,9 @@
mLowBw = 0;
mHighBw = 0;
mSourceSplit = false;
+ mSourceSplitAlways = false;
mRGBHasNoScalar = false;
+ mRotDownscale = false;
updatePanelInfo();
@@ -119,7 +138,6 @@
FILE *panelInfoNodeFP = NULL;
const int MAX_FRAME_BUFFER_NAME_SIZE = 128;
char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
- char panelInfo[MAX_FRAME_BUFFER_NAME_SIZE];
const char *strCmdPanel = "mipi dsi cmd panel";
const char *strVideoPanel = "mipi dsi video panel";
const char *strLVDSPanel = "lvds panel";
@@ -165,7 +183,7 @@
mPanelInfo.mPartialUpdateEnable? "Enabled" :
"Disabled");
}
- if(!strncmp(tokens[0], "xalign", strlen("xalign"))) {
+ if(!strncmp(tokens[0], "xstart", strlen("xstart"))) {
mPanelInfo.mLeftAlign = atoi(tokens[1]);
ALOGI("Left Align: %d", mPanelInfo.mLeftAlign);
}
@@ -181,6 +199,18 @@
mPanelInfo.mHeightAlign = atoi(tokens[1]);
ALOGI("Height Align: %d", mPanelInfo.mHeightAlign);
}
+ if(!strncmp(tokens[0], "min_w", strlen("min_w"))) {
+ mPanelInfo.mMinROIWidth = atoi(tokens[1]);
+ ALOGI("Min ROI Width: %d", mPanelInfo.mMinROIWidth);
+ }
+ if(!strncmp(tokens[0], "min_h", strlen("min_h"))) {
+ mPanelInfo.mMinROIHeight = atoi(tokens[1]);
+ ALOGI("Min ROI Height: %d", mPanelInfo.mMinROIHeight);
+ }
+ if(!strncmp(tokens[0], "roi_merge", strlen("roi_merge"))) {
+ mPanelInfo.mNeedsROIMerge = atoi(tokens[1]);
+ ALOGI("Needs ROI Merge: %d", mPanelInfo.mNeedsROIMerge);
+ }
}
}
fclose(panelInfoNodeFP);
@@ -253,22 +283,22 @@
for(int i=1; i<index;i++) {
if(!strncmp(tokens[i], "bwc", strlen("bwc"))) {
mFeatures |= MDP_BWC_EN;
- }
- else if(!strncmp(tokens[i], "decimation",
+ } else if(!strncmp(tokens[i], "decimation",
strlen("decimation"))) {
mFeatures |= MDP_DECIMATION_EN;
- }
- else if(!strncmp(tokens[i], "tile_format",
+ } else if(!strncmp(tokens[i], "tile_format",
strlen("tile_format"))) {
if(enableMacroTile)
mMacroTileEnabled = true;
} else if(!strncmp(tokens[i], "src_split",
strlen("src_split"))) {
mSourceSplit = true;
- }
- else if(!strncmp(tokens[i], "non_scalar_rgb",
+ } else if(!strncmp(tokens[i], "non_scalar_rgb",
strlen("non_scalar_rgb"))) {
mRGBHasNoScalar = true;
+ } else if(!strncmp(tokens[i], "rotator_downscale",
+ strlen("rotator_downscale"))) {
+ mRotDownscale = true;
}
}
}
@@ -277,6 +307,30 @@
free(line);
fclose(sysfsFd);
}
+
+ if(mSourceSplit) {
+ memset(sysfsPath, 0, sizeof(sysfsPath));
+ snprintf(sysfsPath , sizeof(sysfsPath),
+ "/sys/class/graphics/fb0/msm_fb_src_split_info");
+
+ sysfsFd = fopen(sysfsPath, "rb");
+ if (sysfsFd == NULL) {
+ ALOGE("%s: Opening file %s failed with error %s", __FUNCTION__,
+ sysfsPath, strerror(errno));
+ return false;
+ } else {
+ line = (char *) malloc(len);
+ if((read = getline(&line, &len, sysfsFd)) != -1) {
+ if(!strncmp(line, "src_split_always",
+ strlen("src_split_always"))) {
+ mSourceSplitAlways = true;
+ }
+ }
+ free(line);
+ fclose(sysfsFd);
+ }
+ }
+
ALOGD_IF(DEBUG, "%s: mMDPVersion: %d mMdpRev: %x mRGBPipes:%d,"
"mVGPipes:%d", __FUNCTION__, mMDPVersion, mMdpRev,
mRGBPipes, mVGPipes);
@@ -342,6 +396,10 @@
return mSourceSplit;
}
+bool MDPVersion::isSrcSplitAlways() const {
+ return mSourceSplitAlways;
+}
+
bool MDPVersion::isRGBScalarSupported() const {
return (!mRGBHasNoScalar);
}
@@ -366,10 +424,21 @@
mMdpRev < MDSS_MDP_HW_REV_206);
}
+bool MDPVersion::is8994() {
+ return (mMdpRev >= MDSS_MDP_HW_REV_105 and
+ mMdpRev < MDSS_MDP_HW_REV_106);
+}
+
bool MDPVersion::is8x16() {
return (mMdpRev >= MDSS_MDP_HW_REV_106 and
mMdpRev < MDSS_MDP_HW_REV_107);
}
+bool MDPVersion::is8x39() {
+ return (mMdpRev >= MDSS_MDP_HW_REV_108 and
+ mMdpRev < MDSS_MDP_HW_REV_109);
+}
+
+
}; //namespace qdutils
diff --git a/msm8226/libqdutils/mdp_version.h b/msm8226/libqdutils/mdp_version.h
index aab8643..6c4a3f4 100644
--- a/msm8226/libqdutils/mdp_version.h
+++ b/msm8226/libqdutils/mdp_version.h
@@ -99,8 +99,12 @@
int mWidthAlign; // ROI width alignment restriction
int mTopAlign; // ROI top alignment restriction
int mHeightAlign; // ROI height alignment restriction
+ int mMinROIWidth; // Min width needed for ROI
+ int mMinROIHeight; // Min height needed for ROI
+ bool mNeedsROIMerge; // Merge ROI's of both the DSI's
PanelInfo() : mType(NO_PANEL), mPartialUpdateEnable(0),
- mLeftAlign(0), mWidthAlign(0), mTopAlign(0), mHeightAlign(0){}
+ mLeftAlign(0), mWidthAlign(0), mTopAlign(0), mHeightAlign(0),
+ mMinROIWidth(0), mMinROIHeight(0), mNeedsROIMerge(false){}
friend class MDPVersion;
};
@@ -125,20 +129,27 @@
bool supportsMacroTile();
int getLeftSplit() { return mSplit.left(); }
int getRightSplit() { return mSplit.right(); }
- int isPartialUpdateEnabled() { return mPanelInfo.mPartialUpdateEnable; }
+ bool isPartialUpdateEnabled() { return mPanelInfo.mPartialUpdateEnable; }
int getLeftAlign() { return mPanelInfo.mLeftAlign; }
int getWidthAlign() { return mPanelInfo.mWidthAlign; }
int getTopAlign() { return mPanelInfo.mTopAlign; }
int getHeightAlign() { return mPanelInfo.mHeightAlign; }
+ int getMinROIWidth() { return mPanelInfo.mMinROIWidth; }
+ int getMinROIHeight() { return mPanelInfo.mMinROIHeight; }
+ bool needsROIMerge() { return mPanelInfo.mNeedsROIMerge; }
unsigned long getLowBw() { return mLowBw; }
unsigned long getHighBw() { return mHighBw; }
+ bool isRotDownscaleEnabled() { return mRotDownscale; }
bool isSrcSplit() const;
+ bool isSrcSplitAlways() const;
bool isRGBScalarSupported() const;
bool is8x26();
bool is8x74v2();
bool is8084();
bool is8092();
+ bool is8994();
bool is8x16();
+ bool is8x39();
private:
bool updateSysFsInfo();
@@ -162,7 +173,10 @@
unsigned long mLowBw; //kbps
unsigned long mHighBw; //kbps
bool mSourceSplit;
+ //Additional property on top of source split
+ bool mSourceSplitAlways;
bool mRGBHasNoScalar;
+ bool mRotDownscale;
};
}; //namespace qdutils
#endif //INCLUDE_LIBQCOMUTILS_MDPVER
diff --git a/msm8226/libqdutils/qdMetaData.cpp b/msm8226/libqdutils/qdMetaData.cpp
index 0390599..dbd6f10 100644
--- a/msm8226/libqdutils/qdMetaData.cpp
+++ b/msm8226/libqdutils/qdMetaData.cpp
@@ -27,6 +27,7 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <errno.h>
#include <string.h>
#include <sys/mman.h>
#include <cutils/log.h>
@@ -52,8 +53,8 @@
unsigned long size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
void *base = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED,
handle->fd_metadata, 0);
- if (!base) {
- ALOGE("%s: mmap() failed: Base addr is NULL!", __func__);
+ if (base == reinterpret_cast<void*>(MAP_FAILED)) {
+ ALOGE("%s: mmap() failed: error is %s!", __func__, strerror(errno));
return -1;
}
MetaData_t *data = reinterpret_cast <MetaData_t *>(base);
diff --git a/msm8226/libqservice/Android.mk b/msm8226/libqservice/Android.mk
index 0c6123b..78b1d77 100644
--- a/msm8226/libqservice/Android.mk
+++ b/msm8226/libqservice/Android.mk
@@ -3,7 +3,6 @@
include $(CLEAR_VARS)
LOCAL_MODULE := libqservice
-LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
LOCAL_SHARED_LIBRARIES := $(common_libs) libbinder
diff --git a/msm8226/libqservice/IQService.h b/msm8226/libqservice/IQService.h
index 6c1bba6..c222eb9 100644
--- a/msm8226/libqservice/IQService.h
+++ b/msm8226/libqservice/IQService.h
@@ -50,6 +50,9 @@
SET_HSIC_DATA, // Set HSIC on dspp
GET_DISPLAY_VISIBLE_REGION, // Get the visibleRegion for dpy
PAUSE_WFD, // Pause/Resume WFD
+ SET_WFD_STATUS, // Set if wfd connection is on/off
+ SET_VIEW_FRAME, // Set view frame of display
+ DYNAMIC_DEBUG, // Enable more logging on the fly
COMMAND_LIST_END = 400,
};
@@ -58,6 +61,12 @@
START,
};
+ enum {
+ DEBUG_ALL,
+ DEBUG_MDPCOMP,
+ DEBUG_VSYNC,
+ };
+
// Register a client that can be notified
virtual void connect(const android::sp<qClient::IQClient>& client) = 0;
// Generic function to dispatch binder commands
diff --git a/msm8226/libqservice/QService.cpp b/msm8226/libqservice/QService.cpp
index e4af422..12dd995 100644
--- a/msm8226/libqservice/QService.cpp
+++ b/msm8226/libqservice/QService.cpp
@@ -28,6 +28,8 @@
*/
#include <QService.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
#define QSERVICE_DEBUG 0
@@ -55,6 +57,10 @@
status_t QService::dispatch(uint32_t command, const Parcel* inParcel,
Parcel* outParcel) {
status_t err = (status_t) FAILED_TRANSACTION;
+ IPCThreadState* ipc = IPCThreadState::self();
+ //Rewind parcel in case we're calling from the same process
+ if (ipc->getCallingPid() == getpid())
+ inParcel->setDataPosition(0);
if (mClient.get()) {
ALOGD_IF(QSERVICE_DEBUG, "Dispatching command: %d", command);
err = mClient->notifyCallback(command, inParcel, outParcel);
diff --git a/msm8226/libqservice/QServiceUtils.h b/msm8226/libqservice/QServiceUtils.h
index 699164d..08cab31 100644
--- a/msm8226/libqservice/QServiceUtils.h
+++ b/msm8226/libqservice/QServiceUtils.h
@@ -87,4 +87,7 @@
return sendSingleParam(qService::IQService::PAUSE_WFD, pause);
}
+inline android::status_t setWfdStatus(uint32_t wfdStatus) {
+ return sendSingleParam(qService::IQService::SET_WFD_STATUS, wfdStatus);
+}
#endif /* end of include guard: QSERVICEUTILS_H */
diff --git a/msm8226/libvirtual/Android.mk b/msm8226/libvirtual/Android.mk
index beeef25..a41ef33 100644
--- a/msm8226/libvirtual/Android.mk
+++ b/msm8226/libvirtual/Android.mk
@@ -3,7 +3,6 @@
include $(CLEAR_VARS)
LOCAL_MODULE := libvirtual
-LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
LOCAL_SHARED_LIBRARIES := $(common_libs) liboverlay libqdutils
diff --git a/msm8226/libvirtual/virtual.cpp b/msm8226/libvirtual/virtual.cpp
index 5453e3a..264d045 100644
--- a/msm8226/libvirtual/virtual.cpp
+++ b/msm8226/libvirtual/virtual.cpp
@@ -47,7 +47,6 @@
#include "virtual.h"
#include "overlayUtils.h"
#include "overlay.h"
-#include "mdp_version.h"
#include "qd_utils.h"
using namespace android;
@@ -177,14 +176,14 @@
uint32_t priW = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
uint32_t priH = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
- initResolution(extW, extH);
-
// Dynamic Resolution Change depends on MDP downscaling.
// MDP downscale property will be ignored to exercise DRC use case.
// If DRC is in progress, ext WxH will have non-zero values.
- bool isDRC = (extW > 0) && (extH > 0);
+ bool isDRC = (extW > mVInfo.xres) && (extH > mVInfo.yres);
- if(!qdutils::MDPVersion::getInstance().is8x26()
+ initResolution(extW, extH);
+
+ if(mHwcContext->mOverlay->isUIScalingOnExternalSupported()
&& (mHwcContext->mMDPDownscaleEnabled || isDRC)) {
// maxArea represents the maximum resolution between
@@ -195,6 +194,13 @@
setDownScaleMode(maxArea);
}
+ //Initialize the display viewFrame info
+ mHwcContext->mViewFrame[HWC_DISPLAY_VIRTUAL].left = 0;
+ mHwcContext->mViewFrame[HWC_DISPLAY_VIRTUAL].top = 0;
+ mHwcContext->mViewFrame[HWC_DISPLAY_VIRTUAL].right =
+ (int)mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].xres;
+ mHwcContext->mViewFrame[HWC_DISPLAY_VIRTUAL].bottom =
+ (int)mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].yres;
mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].vsync_period =
1000000000l /60;
ALOGD_IF(DEBUG,"%s: Setting Virtual Attr: res(%d x %d)",__FUNCTION__,
diff --git a/msm8960/libgralloc/alloc_controller.cpp b/msm8960/libgralloc/alloc_controller.cpp
index eadc5b8..32f3b38 100644
--- a/msm8960/libgralloc/alloc_controller.cpp
+++ b/msm8960/libgralloc/alloc_controller.cpp
@@ -284,9 +284,16 @@
// The chroma plane is subsampled,
// but the pitch in bytes is unchanged
// The GPU needs 4K alignment, but the video decoder needs 8K
+ alignedw = ALIGN(alignedw, 128);
size = ALIGN( alignedw * alignedh, 8192);
size += ALIGN( alignedw * ALIGN(height/2, 32), 8192);
break;
+ case HAL_PIXEL_FORMAT_NV12:
+ alignedw = ALIGN(width, 16);
+ alignedh = height;
+ size = ALIGN( ALIGN(width, 128) * ALIGN(height, 32), 8192);
+ size += ALIGN( ALIGN(width, 128) * ALIGN(height/2, 32), 8192);
+ break;
case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
case HAL_PIXEL_FORMAT_YV12:
if ((format == HAL_PIXEL_FORMAT_YV12) && ((width&1) || (height&1))) {
diff --git a/msm8960/libgralloc/gralloc_priv.h b/msm8960/libgralloc/gralloc_priv.h
index 80141ae..d9f4f4f 100644
--- a/msm8960/libgralloc/gralloc_priv.h
+++ b/msm8960/libgralloc/gralloc_priv.h
@@ -92,6 +92,7 @@
/*****************************************************************************/
enum {
/* OEM specific HAL formats */
+ HAL_PIXEL_FORMAT_NV12 = 0x15, /*OMX_COLOR_FormatYUV420SemiPlanar*/
HAL_PIXEL_FORMAT_NV12_ENCODEABLE = 0x102,
HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS = 0x7FA30C04,
HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED = 0x7FA30C03,
diff --git a/msm8960/libgralloc/mapper.cpp b/msm8960/libgralloc/mapper.cpp
index 99beffd..ee16576 100644
--- a/msm8960/libgralloc/mapper.cpp
+++ b/msm8960/libgralloc/mapper.cpp
@@ -265,6 +265,17 @@
ycbcr->chroma_step = 2;
memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
break;
+ // YCbCr_420_SP
+ case HAL_PIXEL_FORMAT_NV12:
+ ystride = ALIGN(hnd->width, 16);
+ ycbcr->y = (void*)hnd->base;
+ ycbcr->cb = (void*)(hnd->base + ystride * hnd->height);
+ ycbcr->cr = (void*)(hnd->base + ystride * hnd->height + 1);
+ ycbcr->ystride = ystride;
+ ycbcr->cstride = ystride;
+ ycbcr->chroma_step = 2;
+ memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
+ break;
default:
ALOGD("%s: Invalid format passed: 0x%x", __FUNCTION__,
hnd->format);
diff --git a/msm8974/libgralloc/mapper.cpp b/msm8974/libgralloc/mapper.cpp
index 5b3a9d7..fec7301 100644
--- a/msm8974/libgralloc/mapper.cpp
+++ b/msm8974/libgralloc/mapper.cpp
@@ -251,10 +251,11 @@
{
private_handle_t* hnd = (private_handle_t*)handle;
int err = gralloc_map_and_invalidate(module, handle, usage, l, t, w, h);
- int ystride;
+ int ystride, cstride;
+
+ memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
if(!err) {
//hnd->format holds our implementation defined format
- //HAL_PIXEL_FORMAT_YCrCb_420_SP is the only one set right now.
switch (hnd->format) {
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
ystride = ALIGN(hnd->width, 16);
@@ -264,7 +265,15 @@
ycbcr->ystride = ystride;
ycbcr->cstride = ystride;
ycbcr->chroma_step = 2;
- memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+ ystride = cstride = hnd->width;
+ ycbcr->y = (void*)hnd->base;
+ ycbcr->cb = (void*)(hnd->base + ystride * hnd->height);
+ ycbcr->cr = (void*)(hnd->base + ystride * hnd->height + 1);
+ ycbcr->ystride = ystride;
+ ycbcr->cstride = cstride;
+ ycbcr->chroma_step = 2;
break;
default:
ALOGD("%s: Invalid format passed: 0x%x", __FUNCTION__,