hwcomposer: Add support for UI mirroring
- Uevent observer as part of Hwcomposer - HPD, enabling/disabling external display from HWC Change-Id: I52b4f30c78e98c5b52c86722046389f458c2dbee
This commit is contained in:
committed by
Brian Muramatsu
parent
f48aef64b2
commit
0c8b7b5c84
@@ -43,9 +43,6 @@
|
||||
#include <cutils/properties.h>
|
||||
#include <profiler.h>
|
||||
|
||||
#include "overlay.h"
|
||||
namespace ovutils = overlay::utils;
|
||||
|
||||
#define EVEN_OUT(x) if (x & 0x0001) {x--;}
|
||||
/** min of int a, b */
|
||||
static inline int min(int a, int b) {
|
||||
@@ -101,402 +98,6 @@ static int fb_setUpdateRect(struct framebuffer_device_t* dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(HDMI_DUAL_DISPLAY)
|
||||
static int closeHDMIChannel(private_module_t* m)
|
||||
{
|
||||
// XXX - when enabling HDMI
|
||||
#if 0
|
||||
Overlay* pTemp = m->pobjOverlay;
|
||||
if(pTemp != NULL)
|
||||
pTemp->closeChannel();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
// XXX - Complete when enabling HDMI
|
||||
#if 0
|
||||
static void getSecondaryDisplayDestinationInfo(private_module_t* m, overlay_rect&
|
||||
rect, int& orientation)
|
||||
{
|
||||
Overlay* pTemp = m->pobjOverlay;
|
||||
int width = pTemp->getFBWidth();
|
||||
int height = pTemp->getFBHeight();
|
||||
int fbwidth = m->info.xres, fbheight = m->info.yres;
|
||||
rect.x = 0; rect.y = 0;
|
||||
rect.w = width; rect.h = height;
|
||||
int rot = m->orientation;
|
||||
switch(rot) {
|
||||
// ROT_0
|
||||
case 0:
|
||||
// ROT_180
|
||||
case HAL_TRANSFORM_ROT_180:
|
||||
pTemp->getAspectRatioPosition(fbwidth, fbheight,
|
||||
&rect);
|
||||
if(rot == HAL_TRANSFORM_ROT_180)
|
||||
orientation = HAL_TRANSFORM_ROT_180;
|
||||
else
|
||||
orientation = 0;
|
||||
break;
|
||||
// ROT_90
|
||||
case HAL_TRANSFORM_ROT_90:
|
||||
// ROT_270
|
||||
case HAL_TRANSFORM_ROT_270:
|
||||
//Calculate the Aspectratio for the UI
|
||||
//in the landscape mode
|
||||
//Width and height will be swapped as there
|
||||
//is rotation
|
||||
pTemp->getAspectRatioPosition(fbheight, fbwidth,
|
||||
&rect);
|
||||
|
||||
if(rot == HAL_TRANSFORM_ROT_90)
|
||||
orientation = HAL_TRANSFORM_ROT_270;
|
||||
else if(rot == HAL_TRANSFORM_ROT_270)
|
||||
orientation = HAL_TRANSFORM_ROT_90;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Determine overlay state based on whether hardware supports true UI
|
||||
mirroring and whether video is playing or not */
|
||||
static ovutils::eOverlayState getOverlayState(struct private_module_t* module)
|
||||
{
|
||||
overlay2::Overlay& ov = *(Overlay::getInstance());
|
||||
|
||||
// Default to existing state
|
||||
ovutils::eOverlayState state = ov.getState();
|
||||
|
||||
// Sanity check
|
||||
if (!module) {
|
||||
ALOGE("%s: NULL module", __FUNCTION__);
|
||||
return state;
|
||||
}
|
||||
|
||||
// Check if video is playing or not
|
||||
if (module->videoOverlay) {
|
||||
// Video is playing, check if hardware supports true UI mirroring
|
||||
if (module->trueMirrorSupport) {
|
||||
// True UI mirroring is supported by hardware
|
||||
if (ov.getState() == ovutils::OV_2D_VIDEO_ON_PANEL) {
|
||||
// Currently playing 2D video
|
||||
state = ovutils::OV_2D_TRUE_UI_MIRROR;
|
||||
} else if (ov.getState() == ovutils::OV_3D_VIDEO_ON_2D_PANEL) {
|
||||
// Currently playing M3D video
|
||||
// FIXME: Support M3D true UI mirroring
|
||||
state = ovutils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV;
|
||||
}
|
||||
} else {
|
||||
// True UI mirroring is not supported by hardware
|
||||
if (ov.getState() == ovutils::OV_2D_VIDEO_ON_PANEL) {
|
||||
// Currently playing 2D video
|
||||
state = ovutils::OV_2D_VIDEO_ON_PANEL_TV;
|
||||
} else if (ov.getState() == ovutils::OV_3D_VIDEO_ON_2D_PANEL) {
|
||||
// Currently playing M3D video
|
||||
state = ovutils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Video is not playing, true UI mirroring support is irrelevant
|
||||
state = ovutils::OV_UI_MIRROR;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
/* Set overlay state */
|
||||
static void setOverlayState(ovutils::eOverlayState state)
|
||||
{
|
||||
overlay2::Overlay& ov = *(Overlay::getInstance());
|
||||
ov.setState(state);
|
||||
}
|
||||
|
||||
static void *hdmi_ui_loop(void *ptr)
|
||||
{
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(ptr);
|
||||
while (1) {
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
while(!(m->hdmiStateChanged))
|
||||
pthread_cond_wait(&(m->overlayPost), &(m->overlayLock));
|
||||
|
||||
m->hdmiStateChanged = false;
|
||||
if (m->exitHDMIUILoop) {
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// No need to mirror UI if HDMI is not on
|
||||
if (!m->enableHDMIOutput) {
|
||||
ALOGE_IF(FB_DEBUG, "%s: hdmi not ON", __FUNCTION__);
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
continue;
|
||||
}
|
||||
|
||||
overlay2::OverlayMgr* ovMgr =
|
||||
overlay2::OverlayMgrSingleton::getOverlayMgr();
|
||||
overlay2::Overlay& ov = ovMgr->ov();
|
||||
|
||||
// Set overlay state
|
||||
ovutils::eOverlayState state = getOverlayState(m);
|
||||
setOverlayState(state);
|
||||
|
||||
// Determine the RGB pipe for UI depending on the state
|
||||
ovutils::eDest dest = ovutils::OV_PIPE_ALL;
|
||||
if (state == ovutils::OV_2D_TRUE_UI_MIRROR) {
|
||||
// True UI mirroring state: external RGB pipe is OV_PIPE2
|
||||
dest = ovutils::OV_PIPE2;
|
||||
} else if (state == ovutils::OV_UI_MIRROR) {
|
||||
// UI-only mirroring state: external RGB pipe is OV_PIPE0
|
||||
dest = ovutils::OV_PIPE0;
|
||||
} else {
|
||||
// No UI in this case
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m->hdmiMirroringState == HDMI_UI_MIRRORING) {
|
||||
int alignedW = ALIGN(m->info.xres, 32);
|
||||
|
||||
private_handle_t const* hnd =
|
||||
reinterpret_cast<private_handle_t const*>(m->framebuffer);
|
||||
unsigned int width = alignedW;
|
||||
unsigned int height = hnd->height;
|
||||
unsigned int format = hnd->format;
|
||||
unsigned int size = hnd->size/m->numBuffers;
|
||||
|
||||
ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
|
||||
// External display connected during secure video playback
|
||||
// Open secure UI session
|
||||
// NOTE: when external display is already connected and then secure
|
||||
// playback is started, we dont have to do anything
|
||||
if (m->secureVideoOverlay) {
|
||||
ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
|
||||
}
|
||||
|
||||
ovutils::Whf whf(width, height, format, size);
|
||||
ovutils::PipeArgs parg(mdpFlags,
|
||||
ovutils::OVERLAY_TRANSFORM_0,
|
||||
whf,
|
||||
ovutils::ZORDER_0,
|
||||
ovutils::IS_FG_OFF,
|
||||
ovutils::ROT_FLAG_ENABLED);
|
||||
ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
|
||||
bool ret = ov.setSource(pargs, dest);
|
||||
if (!ret) {
|
||||
ALOGE("%s setSource failed", __FUNCTION__);
|
||||
}
|
||||
|
||||
// we need to communicate m->orientation that will get some
|
||||
// modifications within setParameter func.
|
||||
// FIXME that is ugly.
|
||||
const ovutils::Params prms (ovutils::OVERLAY_TRANSFORM_UI,
|
||||
m->orientation);
|
||||
ov.setParameter(prms, dest);
|
||||
if (!ret) {
|
||||
ALOGE("%s setParameter failed transform", __FUNCTION__);
|
||||
}
|
||||
|
||||
// x,y,w,h
|
||||
ovutils::Dim dcrop(0, 0, m->info.xres, m->info.yres);
|
||||
ov.setMemoryId(m->framebuffer->fd, dest);
|
||||
ret = ov.setCrop(dcrop, dest);
|
||||
if (!ret) {
|
||||
ALOGE("%s setCrop failed", __FUNCTION__);
|
||||
}
|
||||
|
||||
ovutils::Dim pdim (m->info.xres,
|
||||
m->info.yres,
|
||||
0,
|
||||
0,
|
||||
m->orientation);
|
||||
ret = ov.setPosition(pdim, dest);
|
||||
if (!ret) {
|
||||
ALOGE("%s setPosition failed", __FUNCTION__);
|
||||
}
|
||||
|
||||
if (!ov.commit(dest)) {
|
||||
ALOGE("%s commit fails", __FUNCTION__);
|
||||
}
|
||||
|
||||
ret = ov.queueBuffer(m->currentOffset, dest);
|
||||
if (!ret) {
|
||||
ALOGE("%s queueBuffer failed", __FUNCTION__);
|
||||
}
|
||||
} else {
|
||||
setOverlayState(ovutils::OV_CLOSED);
|
||||
}
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int fb_videoOverlayStarted(struct framebuffer_device_t* dev, int started)
|
||||
{
|
||||
ALOGE_IF(FB_DEBUG, "%s started=%d", __FUNCTION__, started);
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
dev->common.module);
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
if(started != m->videoOverlay) {
|
||||
m->videoOverlay = started;
|
||||
m->hdmiStateChanged = true;
|
||||
if (!m->trueMirrorSupport) {
|
||||
if (started) {
|
||||
m->hdmiMirroringState = HDMI_NO_MIRRORING;
|
||||
ovutils::eOverlayState state = getOverlayState(m);
|
||||
setOverlayState(state);
|
||||
} else if (m->enableHDMIOutput)
|
||||
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||
} else {
|
||||
if (m->videoOverlay == VIDEO_3D_OVERLAY_STARTED) {
|
||||
ALOGE_IF(FB_DEBUG, "3D Video Started, stop mirroring!");
|
||||
m->hdmiMirroringState = HDMI_NO_MIRRORING;
|
||||
ovutils::eOverlayState state = getOverlayState(m);
|
||||
setOverlayState(state);
|
||||
}
|
||||
else if (m->enableHDMIOutput) {
|
||||
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fb_enableHDMIOutput(struct framebuffer_device_t* dev, int externaltype)
|
||||
{
|
||||
ALOGE_IF(FB_DEBUG, "%s externaltype=%d", __FUNCTION__, externaltype);
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
dev->common.module);
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
//Check if true mirroring can be supported
|
||||
m->trueMirrorSupport = ovutils::FrameBufferInfo::getInstance()->supportTrueMirroring();
|
||||
m->enableHDMIOutput = externaltype;
|
||||
if(externaltype) {
|
||||
if (m->trueMirrorSupport) {
|
||||
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||
} else {
|
||||
if(!m->videoOverlay)
|
||||
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||
}
|
||||
} else if (!externaltype) {
|
||||
// Either HDMI is disconnected or suspend occurred
|
||||
m->hdmiMirroringState = HDMI_NO_MIRRORING;
|
||||
ovutils::eOverlayState state = getOverlayState(m);
|
||||
setOverlayState(state);
|
||||
}
|
||||
m->hdmiStateChanged = true;
|
||||
pthread_cond_signal(&(m->overlayPost));
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fb_orientationChanged(struct framebuffer_device_t* dev, int orientation)
|
||||
{
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
dev->common.module);
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
neworientation = orientation;
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_open_secure_start(private_module_t* m) {
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
m->hdmiMirroringState = HDMI_NO_MIRRORING;
|
||||
m->secureVideoOverlay = true;
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_open_secure_end(private_module_t* m) {
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
if (m->enableHDMIOutput) {
|
||||
if (m->trueMirrorSupport) {
|
||||
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||
} else if(!m->videoOverlay) {
|
||||
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||
}
|
||||
m->hdmiStateChanged = true;
|
||||
pthread_cond_signal(&(m->overlayPost));
|
||||
}
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_close_secure_start(private_module_t* m) {
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
m->hdmiMirroringState = HDMI_NO_MIRRORING;
|
||||
m->secureVideoOverlay = false;
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_close_secure_end(private_module_t* m) {
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
if (m->enableHDMIOutput) {
|
||||
if (m->trueMirrorSupport) {
|
||||
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||
} else if(!m->videoOverlay) {
|
||||
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||
}
|
||||
m->hdmiStateChanged = true;
|
||||
pthread_cond_signal(&(m->overlayPost));
|
||||
}
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* fb_perform - used to add custom event and handle them in fb HAL
|
||||
* Used for external display related functions as of now
|
||||
*/
|
||||
static int fb_perform(struct framebuffer_device_t* dev, int event, int value)
|
||||
{
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
dev->common.module);
|
||||
switch(event) {
|
||||
#if defined(HDMI_DUAL_DISPLAY)
|
||||
case EVENT_EXTERNAL_DISPLAY:
|
||||
fb_enableHDMIOutput(dev, value);
|
||||
break;
|
||||
case EVENT_VIDEO_OVERLAY:
|
||||
fb_videoOverlayStarted(dev, value);
|
||||
break;
|
||||
case EVENT_ORIENTATION_CHANGE:
|
||||
fb_orientationChanged(dev, value);
|
||||
break;
|
||||
case EVENT_OVERLAY_STATE_CHANGE:
|
||||
if (value == OVERLAY_STATE_CHANGE_START) {
|
||||
// When state change starts, get a lock on overlay
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
} else if (value == OVERLAY_STATE_CHANGE_END) {
|
||||
// When state change is complete, unlock overlay
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
}
|
||||
break;
|
||||
case EVENT_OPEN_SECURE_START:
|
||||
handle_open_secure_start(m);
|
||||
break;
|
||||
case EVENT_OPEN_SECURE_END:
|
||||
handle_open_secure_end(m);
|
||||
break;
|
||||
case EVENT_CLOSE_SECURE_START:
|
||||
handle_close_secure_start(m);
|
||||
break;
|
||||
case EVENT_CLOSE_SECURE_END:
|
||||
handle_close_secure_end(m);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ALOGE("In %s: UNKNOWN Event = %d!!!", __FUNCTION__, event);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
|
||||
{
|
||||
if (private_handle_t::validate(buffer) < 0)
|
||||
@@ -510,6 +111,7 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
|
||||
private_module_t* m =
|
||||
reinterpret_cast<private_module_t*>(dev->common.module);
|
||||
|
||||
|
||||
if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
|
||||
genlock_lock_buffer(hnd, GENLOCK_READ_LOCK, GENLOCK_MAX_TIMEOUT);
|
||||
|
||||
@@ -519,6 +121,14 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
|
||||
}
|
||||
|
||||
const size_t offset = hnd->base - m->framebuffer->base;
|
||||
// frame ready to be posted, signal so that hwc can update External
|
||||
// display
|
||||
pthread_mutex_lock(&m->fbPostLock);
|
||||
m->currentOffset = offset;
|
||||
m->fbPostDone = true;
|
||||
pthread_cond_signal(&m->fbPostCond);
|
||||
pthread_mutex_unlock(&m->fbPostLock);
|
||||
|
||||
m->info.activate = FB_ACTIVATE_VBL;
|
||||
m->info.yoffset = offset / m->finfo.line_length;
|
||||
if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) {
|
||||
@@ -579,11 +189,12 @@ int mapFrameBufferLocked(struct private_module_t* module)
|
||||
info.yoffset = 0;
|
||||
info.activate = FB_ACTIVATE_NOW;
|
||||
|
||||
/* Interpretation of offset for color fields: All offsets are from the right,
|
||||
* inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you
|
||||
* can use the offset as right argument to <<). A pixel afterwards is a bit
|
||||
* stream and is written to video memory as that unmodified. This implies
|
||||
* big-endian byte order if bits_per_pixel is greater than 8.
|
||||
/* Interpretation of offset for color fields: All offsets are from the
|
||||
* right, inside a "pixel" value, which is exactly 'bits_per_pixel' wide
|
||||
* (means: you can use the offset as right argument to <<). A pixel
|
||||
* afterwards is a bit stream and is written to video memory as that
|
||||
* unmodified. This implies big-endian byte order if bits_per_pixel is
|
||||
* greater than 8.
|
||||
*/
|
||||
|
||||
if(info.bits_per_pixel == 32) {
|
||||
@@ -600,10 +211,11 @@ int mapFrameBufferLocked(struct private_module_t* module)
|
||||
info.transp.offset = 0;
|
||||
info.transp.length = 8;
|
||||
|
||||
/* Note: the GL driver does not have a r=8 g=8 b=8 a=0 config, so if we do
|
||||
* not use the MDP for composition (i.e. hw composition == 0), ask for
|
||||
* RGBA instead of RGBX. */
|
||||
if (property_get("debug.sf.hw", property, NULL) > 0 && atoi(property) == 0)
|
||||
/* Note: the GL driver does not have a r=8 g=8 b=8 a=0 config, so if we
|
||||
* do not use the MDP for composition (i.e. hw composition == 0), ask
|
||||
* for RGBA instead of RGBX. */
|
||||
if (property_get("debug.sf.hw", property, NULL) > 0 &&
|
||||
atoi(property) == 0)
|
||||
module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888;
|
||||
else if(property_get("debug.composition.type", property, NULL) > 0 &&
|
||||
(strncmp(property, "mdp", 3) == 0))
|
||||
@@ -627,7 +239,8 @@ int mapFrameBufferLocked(struct private_module_t* module)
|
||||
}
|
||||
|
||||
//adreno needs 4k aligned offsets. Max hole size is 4096-1
|
||||
int size = roundUpToPageSize(info.yres * info.xres * (info.bits_per_pixel/8));
|
||||
int size = roundUpToPageSize(info.yres * info.xres *
|
||||
(info.bits_per_pixel/8));
|
||||
|
||||
/*
|
||||
* Request NUM_BUFFERS screens (at least 2 for page flipping)
|
||||
@@ -738,9 +351,9 @@ int mapFrameBufferLocked(struct private_module_t* module)
|
||||
size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres)*
|
||||
module->numBuffers;
|
||||
module->framebuffer = new private_handle_t(fd, fbSize,
|
||||
private_handle_t::PRIV_FLAGS_USES_PMEM,
|
||||
BUFFER_TYPE_UI,
|
||||
module->fbFormat, info.xres, info.yres);
|
||||
private_handle_t::PRIV_FLAGS_USES_PMEM,
|
||||
BUFFER_TYPE_UI,
|
||||
module->fbFormat, info.xres, info.yres);
|
||||
void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (vaddr == MAP_FAILED) {
|
||||
ALOGE("Error mapping the framebuffer (%s)", strerror(errno));
|
||||
@@ -748,20 +361,10 @@ int mapFrameBufferLocked(struct private_module_t* module)
|
||||
}
|
||||
module->framebuffer->base = intptr_t(vaddr);
|
||||
memset(vaddr, 0, fbSize);
|
||||
|
||||
#if defined(HDMI_DUAL_DISPLAY)
|
||||
/* Overlay for HDMI*/
|
||||
pthread_mutex_init(&(module->overlayLock), NULL);
|
||||
pthread_cond_init(&(module->overlayPost), NULL);
|
||||
module->currentOffset = 0;
|
||||
module->exitHDMIUILoop = false;
|
||||
module->hdmiStateChanged = false;
|
||||
pthread_t hdmiUIThread;
|
||||
pthread_create(&hdmiUIThread, NULL, &hdmi_ui_loop, (void *) module);
|
||||
module->hdmiMirroringState = HDMI_NO_MIRRORING;
|
||||
module->trueMirrorSupport = false;
|
||||
#endif
|
||||
|
||||
module->fbPostDone = false;
|
||||
pthread_mutex_init(&(module->fbPostLock), NULL);
|
||||
pthread_cond_init(&(module->fbPostCond), NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -778,14 +381,6 @@ static int mapFrameBuffer(struct private_module_t* module)
|
||||
static int fb_close(struct hw_device_t *dev)
|
||||
{
|
||||
fb_context_t* ctx = (fb_context_t*)dev;
|
||||
#if defined(HDMI_DUAL_DISPLAY)
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
ctx->device.common.module);
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
m->exitHDMIUILoop = true;
|
||||
pthread_cond_signal(&(m->overlayPost));
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
#endif
|
||||
if (ctx) {
|
||||
free(ctx);
|
||||
}
|
||||
@@ -828,8 +423,10 @@ int fb_device_open(hw_module_t const* module, const char* name,
|
||||
const_cast<float&>(dev->device.xdpi) = m->xdpi;
|
||||
const_cast<float&>(dev->device.ydpi) = m->ydpi;
|
||||
const_cast<float&>(dev->device.fps) = m->fps;
|
||||
const_cast<int&>(dev->device.minSwapInterval) = PRIV_MIN_SWAP_INTERVAL;
|
||||
const_cast<int&>(dev->device.maxSwapInterval) = PRIV_MAX_SWAP_INTERVAL;
|
||||
const_cast<int&>(dev->device.minSwapInterval) =
|
||||
PRIV_MIN_SWAP_INTERVAL;
|
||||
const_cast<int&>(dev->device.maxSwapInterval) =
|
||||
PRIV_MAX_SWAP_INTERVAL;
|
||||
const_cast<int&>(dev->device.numFramebuffers) = m->numBuffers;
|
||||
if (m->finfo.reserved[0] == 0x5444 &&
|
||||
m->finfo.reserved[1] == 0x5055) {
|
||||
|
||||
Reference in New Issue
Block a user