android_hardware_qcom_display/libhwcomposer/hwc.cpp
Amara Venkata Mastan Manoj Kumar a4b0340e0f hwcomposer: Add secure intents to support Secure Playback
Add OPEN_SECURE_START, OPEN_SECURE_END, CLOSE_SECURE_START
   and CLOSE_SECURE_END secure intents for Securing/Unsecuring
   start and end notifications.

   1. On Open Secure Start and Close Secure End events, hwc_prepare
      close the current overlay state and composition will be
      done by GPU. This will teardown the exisiting Rotator session.
   2. On Open Secure End, secure configuration is enabled and
      subsequent hwc_prepare will allocate secure memory for Rotator.
   3. On Close Secure End, secure configuration is disabled and
      subsequent hwc_prepare calls will allocate non-secure memory
      for Rotator.

Change-Id: Ia81b21d19f8084f218ae16eb8e69bb62937afa26

Conflicts:
	libhwcomposer/hwc_utils.h
2012-10-14 15:47:48 -07:00

307 lines
9.4 KiB
C++

/*
* Copyright (C) 2010 The Android Open Source Project
* Copyright (C) 2012, Code Aurora Forum. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <fcntl.h>
#include <errno.h>
#include <cutils/log.h>
#include <cutils/atomic.h>
#include <EGL/egl.h>
#include <overlay.h>
#include <fb_priv.h>
#include <mdp_version.h>
#include "hwc_utils.h"
#include "hwc_qbuf.h"
#include "hwc_video.h"
#include "hwc_pip.h"
#include "hwc_uimirror.h"
#include "hwc_copybit.h"
#include "hwc_external.h"
#include "hwc_mdpcomp.h"
#include "hwc_extonly.h"
#include "qcom_ui.h"
#define VSYNC_DEBUG 0
using namespace qhwc;
static int hwc_device_open(const struct hw_module_t* module,
const char* name,
struct hw_device_t** device);
static struct hw_module_methods_t hwc_module_methods = {
open: hwc_device_open
};
hwc_module_t HAL_MODULE_INFO_SYM = {
common: {
tag: HARDWARE_MODULE_TAG,
version_major: 2,
version_minor: 0,
id: HWC_HARDWARE_MODULE_ID,
name: "Qualcomm Hardware Composer Module",
author: "CodeAurora Forum",
methods: &hwc_module_methods,
dso: 0,
reserved: {0},
}
};
/*
* Save callback functions registered to HWC
*/
static void hwc_registerProcs(struct hwc_composer_device* dev,
hwc_procs_t const* procs)
{
hwc_context_t* ctx = (hwc_context_t*)(dev);
if(!ctx) {
ALOGE("%s: Invalid context", __FUNCTION__);
return;
}
ctx->device.reserved_proc[0] = (void*)procs;
// Now that we have the functions needed, kick off
// the uevent & vsync threads
init_uevent_thread(ctx);
init_vsync_thread(ctx);
}
static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list)
{
hwc_context_t* ctx = (hwc_context_t*)(dev);
ctx->overlayInUse = false;
if(ctx->mSecureConfig == true) {
// This will tear down External Display Device.
return 0;
}
if(ctx->mExtDisplay->getExternalDisplay())
ovutils::setExtType(ctx->mExtDisplay->getExternalDisplay());
if (LIKELY(list)) {
//reset for this draw round
VideoOverlay::reset();
VideoPIP::reset();
ExtOnly::reset();
getLayerStats(ctx, list);
// Mark all layers to COPYBIT initially
CopyBit::prepare(ctx, list);
if(VideoOverlay::prepare(ctx, list)) {
ctx->overlayInUse = true;
//Nothing here
} else if(VideoPIP::prepare(ctx, list)) {
ctx->overlayInUse = true;
} else if(ExtOnly::prepare(ctx, list)) {
ctx->overlayInUse = true;
} else if(UIMirrorOverlay::prepare(ctx, list)) {
ctx->overlayInUse = true;
} else if(MDPComp::configure(dev, list)) {
ctx->overlayInUse = true;
} else if (0) {
//Other features
ctx->overlayInUse = true;
} else { // Else set this flag to false, otherwise video cases
// fail in non-overlay targets.
ctx->overlayInUse = false;
ctx->mOverlay->setState(ovutils::OV_CLOSED);
}
} else {
ctx->overlayInUse = false;
ctx->mOverlay->setState(ovutils::OV_CLOSED);
ctx->qbuf->unlockAll();
qdutils::CBUtils::checkforGPULayer(list);
}
return 0;
}
static int hwc_eventControl(struct hwc_composer_device* dev,
int event, int value)
{
int ret = 0;
static int prev_value, temp;
hwc_context_t* ctx = (hwc_context_t*)(dev);
private_module_t* m = reinterpret_cast<private_module_t*>(
ctx->mFbDev->common.module);
switch(event) {
#ifndef NO_HW_VSYNC
case HWC_EVENT_VSYNC:
if (value == prev_value){
//TODO see why HWC gets repeated events
ALOGD_IF(VSYNC_DEBUG, "%s - VSYNC is already %s",
__FUNCTION__, (value)?"ENABLED":"DISABLED");
}
temp = ctx->vstate.enable;
if(ioctl(m->framebuffer->fd, MSMFB_OVERLAY_VSYNC_CTRL, &value) < 0)
ret = -errno;
/* vsync state change logic */
if (value == 1) {
//unblock vsync thread
pthread_mutex_lock(&ctx->vstate.lock);
ctx->vstate.enable = true;
pthread_cond_signal(&ctx->vstate.cond);
pthread_mutex_unlock(&ctx->vstate.lock);
}
if (value == 0 && temp) {
//vsync thread will block
pthread_mutex_lock(&ctx->vstate.lock);
ctx->vstate.enable = false;
pthread_mutex_unlock(&ctx->vstate.lock);
}
ALOGD_IF (VSYNC_DEBUG, "VSYNC state changed from %s to %s",
(prev_value)?"ENABLED":"DISABLED", (value)?"ENABLED":"DISABLED");
prev_value = value;
/* vsync state change logic - end*/
if(ctx->mExtDisplay->isHDMIConfigured() &&
(ctx->mExtDisplay->getExternalDisplay()==EXTERN_DISPLAY_FB1)) {
// enableHDMIVsync will return -errno on error
ret = ctx->mExtDisplay->enableHDMIVsync(value);
}
break;
#endif
case HWC_EVENT_ORIENTATION:
ctx->deviceOrientation = value;
break;
default:
ret = -EINVAL;
}
return ret;
}
static int hwc_query(struct hwc_composer_device* dev,
int param, int* value)
{
hwc_context_t* ctx = (hwc_context_t*)(dev);
private_module_t* m = reinterpret_cast<private_module_t*>(
ctx->mFbDev->common.module);
switch (param) {
case HWC_BACKGROUND_LAYER_SUPPORTED:
// Not supported for now
value[0] = 0;
break;
case HWC_VSYNC_PERIOD:
value[0] = 1000000000.0 / m->fps;
ALOGI("fps: %d", value[0]);
break;
default:
return -EINVAL;
}
return 0;
}
static int hwc_set(hwc_composer_device_t *dev,
hwc_display_t dpy,
hwc_surface_t sur,
hwc_layer_list_t* list)
{
int ret = 0;
hwc_context_t* ctx = (hwc_context_t*)(dev);
if (dpy && sur) {
if (LIKELY(list)) {
VideoOverlay::draw(ctx, list);
VideoPIP::draw(ctx,list);
ExtOnly::draw(ctx, list);
CopyBit::draw(ctx, list, (EGLDisplay)dpy, (EGLSurface)sur);
MDPComp::draw(ctx, list);
}
eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur);
if (ctx->mMDP.hasOverlay) {
wait4fbPost(ctx);
//Can draw to HDMI only when fb_post is reached
UIMirrorOverlay::draw(ctx);
//HDMI commit and primary commit (PAN) happening in parallel
if(ctx->mExtDisplay->getExternalDisplay())
ctx->mExtDisplay->commit();
//Virtual barrier for threads to finish
wait4Pan(ctx);
}
} else {
ctx->mOverlay->setState(ovutils::OV_CLOSED);
ctx->qbuf->unlockAll();
}
ctx->qbuf->unlockAllPrevious();
return ret;
}
static int hwc_device_close(struct hw_device_t *dev)
{
if(!dev) {
ALOGE("%s: NULL device pointer", __FUNCTION__);
return -1;
}
closeContext((hwc_context_t*)dev);
free(dev);
return 0;
}
static int hwc_device_open(const struct hw_module_t* module, const char* name,
struct hw_device_t** device)
{
int status = -EINVAL;
if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
struct hwc_context_t *dev;
dev = (hwc_context_t*)malloc(sizeof(*dev));
memset(dev, 0, sizeof(*dev));
//Initialize hwc context
initContext(dev);
//Setup HWC methods
hwc_methods_t *methods;
methods = (hwc_methods_t *)malloc(sizeof(*methods));
memset(methods, 0, sizeof(*methods));
methods->eventControl = hwc_eventControl;
dev->device.common.tag = HARDWARE_DEVICE_TAG;
#ifndef NO_HW_VSYNC
//XXX: This disables hardware vsync on 8x55
// Fix when HW vsync is available on 8x55
if(dev->mMDP.version == 400 || (dev->mMDP.version >= 500)) {
#endif
dev->device.common.version = 0;
ALOGI("%s: Hardware VSYNC not supported", __FUNCTION__);
#ifndef NO_HW_VSYNC
} else {
dev->device.common.version = HWC_DEVICE_API_VERSION_0_3;
ALOGI("%s: Hardware VSYNC supported", __FUNCTION__);
}
#endif
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.registerProcs = hwc_registerProcs;
dev->device.query = hwc_query;
dev->device.methods = methods;
*device = &dev->device.common;
status = 0;
}
return status;
}