Merge "libexternal: prefix the property name with hw"
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index ebd7e98..20f7973 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -76,8 +76,7 @@
static bool useUncached(int usage)
{
// System heaps cannot be uncached
- if(usage & (GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP |
- GRALLOC_USAGE_PRIVATE_IOMMU_HEAP))
+ if(usage & GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP)
return false;
if (usage & GRALLOC_USAGE_PRIVATE_UNCACHED)
return true;
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index c2688b5..dfae893 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -17,13 +17,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include <fcntl.h>
#include <errno.h>
#include <cutils/log.h>
#include <cutils/atomic.h>
#include <EGL/egl.h>
+#include <utils/Trace.h>
#include <overlay.h>
#include <fb_priv.h>
@@ -124,9 +125,8 @@
hwc_display_contents_1_t *list) {
hwc_context_t* ctx = (hwc_context_t*)(dev);
const int dpy = HWC_DISPLAY_PRIMARY;
- if (LIKELY(list && list->numHwLayers > 1) &&
- ctx->dpyAttr[dpy].isActive) {
-
+ if (LIKELY(list && list->numHwLayers > 1 &&
+ list->numHwLayers <= MAX_NUM_LAYERS) && ctx->dpyAttr[dpy].isActive) {
uint32_t last = list->numHwLayers - 1;
hwc_layer_1_t *fbLayer = &list->hwLayers[last];
if(fbLayer->handle) {
@@ -136,7 +136,7 @@
if(!ret) {
// IF MDPcomp fails use this route
VideoOverlay::prepare(ctx, list, dpy);
- ctx->mFBUpdate[dpy]->prepare(ctx, fbLayer);
+ ctx->mFBUpdate[dpy]->prepare(ctx, list);
}
ctx->mLayerCache[dpy]->updateLayerCache(list);
// Use Copybit, when MDP comp fails
@@ -151,7 +151,8 @@
hwc_display_contents_1_t *list, int dpy) {
hwc_context_t* ctx = (hwc_context_t*)(dev);
- if (LIKELY(list && list->numHwLayers > 1) &&
+ if (LIKELY(list && list->numHwLayers > 1 &&
+ list->numHwLayers <= MAX_NUM_LAYERS) &&
ctx->dpyAttr[dpy].isActive &&
ctx->dpyAttr[dpy].connected) {
uint32_t last = list->numHwLayers - 1;
@@ -161,7 +162,7 @@
setListStats(ctx, list, dpy);
reset_layer_prop(ctx, dpy);
VideoOverlay::prepare(ctx, list, dpy);
- ctx->mFBUpdate[dpy]->prepare(ctx, fbLayer);
+ ctx->mFBUpdate[dpy]->prepare(ctx, list);
ctx->mLayerCache[dpy]->updateLayerCache(list);
if(ctx->mCopyBit[dpy])
ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
@@ -234,6 +235,7 @@
static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank)
{
+ ATRACE_CALL();
hwc_context_t* ctx = (hwc_context_t*)(dev);
private_module_t* m = reinterpret_cast<private_module_t*>(
ctx->mFbDev->common.module);
@@ -309,6 +311,7 @@
}
static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+ ATRACE_CALL();
int ret = 0;
const int dpy = HWC_DISPLAY_PRIMARY;
@@ -316,8 +319,9 @@
uint32_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])
- ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
+ copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
if(list->numHwLayers > 1)
hwc_sync(ctx, list, dpy, fd);
if (!VideoOverlay::draw(ctx, list, dpy)) {
@@ -331,11 +335,16 @@
//TODO We dont check for SKIP flag on this layer because we need PAN
//always. Last layer is always FB
- private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
+ private_handle_t *hnd = NULL;
+ if(copybitDone) {
+ hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
+ } else {
+ hnd = (private_handle_t *)fbLayer->handle;
+ }
if(fbLayer->compositionType == HWC_FRAMEBUFFER_TARGET && hnd) {
if(!(fbLayer->flags & HWC_SKIP_LAYER) &&
(list->numHwLayers > 1)) {
- if (!ctx->mFBUpdate[dpy]->draw(ctx, fbLayer)) {
+ if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
ret = -1;
}
@@ -352,7 +361,9 @@
}
static int hwc_set_external(hwc_context_t *ctx,
- hwc_display_contents_1_t* list, int dpy) {
+ hwc_display_contents_1_t* list, int dpy)
+{
+ ATRACE_CALL();
int ret = 0;
Locker::Autolock _l(ctx->mExtSetLock);
@@ -362,8 +373,9 @@
uint32_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])
- ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
+ copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
if(list->numHwLayers > 1)
hwc_sync(ctx, list, dpy, fd);
@@ -373,11 +385,17 @@
ret = -1;
}
- private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
+ private_handle_t *hnd = NULL;
+ if(copybitDone) {
+ hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
+ } else {
+ hnd = (private_handle_t *)fbLayer->handle;
+ }
+
if(fbLayer->compositionType == HWC_FRAMEBUFFER_TARGET &&
!(fbLayer->flags & HWC_SKIP_LAYER) && hnd &&
(list->numHwLayers > 1)) {
- if (!ctx->mFBUpdate[dpy]->draw(ctx, fbLayer)) {
+ if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
ret = -1;
}
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 8ce9f0d..4549dcf 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -23,11 +23,7 @@
#include <utils/Timers.h>
#include "hwc_copybit.h"
#include "comptype.h"
-
-//XXX: Remove HWC_BLIT
-#ifndef QCOM_BSP
-#define HWC_BLIT 4
-#endif
+#include "gr.h"
namespace qhwc {
@@ -164,27 +160,42 @@
bool useCopybitForYUV = canUseCopybitForYUV(ctx);
bool useCopybitForRGB = canUseCopybitForRGB(ctx, list, dpy);
+ LayerProp *layerProp = ctx->layerProp[dpy];
+ size_t fbLayerIndex = ctx->listStats[dpy].fbLayerIndex;
+ hwc_layer_1_t *fbLayer = &list->hwLayers[fbLayerIndex];
+ private_handle_t *fbHnd = (private_handle_t *)fbLayer->handle;
+
+
+
+ //Allocate render buffers if they're not allocated
+ if (useCopybitForYUV || useCopybitForRGB) {
+ int ret = allocRenderBuffers(fbHnd->width,
+ fbHnd->height,
+ fbHnd->format);
+ if (ret < 0) {
+ return false;
+ } else {
+ mCurRenderBufferIndex = (mCurRenderBufferIndex + 1) %
+ NUM_RENDER_BUFFERS;
+ }
+ }
+
// numAppLayers-1, as we iterate till 0th layer index
for (int i = ctx->listStats[dpy].numAppLayers-1; i >= 0 ; i--) {
private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
- if (hnd->bufferType == BUFFER_TYPE_VIDEO) {
- //YUV layer, check, if copybit can be used
- // mark the video layer to gpu when all layer is
- // going to gpu in case of dynamic composition.
- if (useCopybitForYUV) {
- list->hwLayers[i].compositionType = HWC_BLIT;
- mCopyBitDraw = true;
- }
- } else if (hnd->bufferType == BUFFER_TYPE_UI) {
- //RGB layer, check, if copybit can be used
- if (useCopybitForRGB) {
- ALOGD_IF(DEBUG_COPYBIT, "%s: Marking layer[%d] for copybit for"
- "dpy[%d] ", __FUNCTION__, i, dpy);
- list->hwLayers[i].compositionType = HWC_BLIT;
- mCopyBitDraw = true;
- }
+ if ((hnd->bufferType == BUFFER_TYPE_VIDEO && useCopybitForYUV) ||
+ (hnd->bufferType == BUFFER_TYPE_UI && useCopybitForRGB)) {
+ layerProp[i].mFlags |= HWC_COPYBIT;
+ list->hwLayers[i].compositionType = HWC_OVERLAY;
+ mCopyBitDraw = true;
+ } else {
+ // We currently cannot mix copybit layers with layers marked to
+ // be drawn on the framebuffer or that are on the layer cache.
+ mCopyBitDraw = false;
+ //There is no need to reset layer properties here as we return in
+ //draw if mCopyBitDraw is false
}
}
return true;
@@ -195,23 +206,29 @@
// draw layers marked for COPYBIT
int retVal = true;
int copybitLayerCount = 0;
+ LayerProp *layerProp = ctx->layerProp[dpy];
if(mCopyBitDraw == false) // there is no layer marked for copybit
- return true ;
+ return false ;
- size_t fbLayerIndex = ctx->listStats[dpy].fbLayerIndex;
- hwc_layer_1_t *fbLayer = &list->hwLayers[fbLayerIndex];
//render buffer
- private_handle_t *renderBuffer = (private_handle_t *)fbLayer->handle;
+ private_handle_t *renderBuffer = getCurrentRenderBuffer();
if (!renderBuffer) {
- ALOGE("%s: HWC_FRAMEBUFFER_TARGET layer handle is NULL", __FUNCTION__);
+ ALOGE("%s: Render buffer layer handle is NULL", __FUNCTION__);
return false;
}
- // numAppLayers-1, as we iterate from 0th layer index with HWC_BLIT flag
+
+ //Wait for the previous frame to complete before rendering onto it
+ if(mRelFd[0] >=0) {
+ sync_wait(mRelFd[0], 1000);
+ close(mRelFd[0]);
+ mRelFd[0] = -1;
+ }
+ // 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(!list->hwLayers[i].compositionType == HWC_BLIT) {
- ALOGD_IF(DEBUG_COPYBIT, "%s: Not Marked for C2D", __FUNCTION__);
+ if(!(layerProp[i].mFlags & HWC_COPYBIT)) {
+ ALOGD_IF(DEBUG_COPYBIT, "%s: Not Marked for copybit", __FUNCTION__);
continue;
}
int ret = -1;
@@ -372,7 +389,7 @@
}
ALOGE("%s:%d::tmp_w = %d,tmp_h = %d",__FUNCTION__,__LINE__,tmp_w,tmp_h);
- int usage = GRALLOC_USAGE_PRIVATE_MM_HEAP;
+ int usage = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
if (0 == alloc_buffer(&tmpHnd, tmp_w, tmp_h, fbHandle->format, usage)){
copybit_image_t tmp_dst;
@@ -463,12 +480,55 @@
}
+int CopyBit::allocRenderBuffers(int w, int h, int f)
+{
+ int ret = 0;
+ for (int i = 0; i < NUM_RENDER_BUFFERS; i++) {
+ if (mRenderBuffer[i] == NULL) {
+ ret = alloc_buffer(&mRenderBuffer[i],
+ w, h, f,
+ GRALLOC_USAGE_PRIVATE_IOMMU_HEAP);
+ }
+ if(ret < 0) {
+ freeRenderBuffers();
+ break;
+ }
+ }
+ return ret;
+}
+
+void CopyBit::freeRenderBuffers()
+{
+ for (int i = 0; i < NUM_RENDER_BUFFERS; i++) {
+ if(mRenderBuffer[i]) {
+ free_buffer(mRenderBuffer[i]);
+ mRenderBuffer[i] = NULL;
+ }
+ }
+}
+
+private_handle_t * CopyBit::getCurrentRenderBuffer() {
+ return mRenderBuffer[mCurRenderBufferIndex];
+}
+
+void CopyBit::setReleaseFd(int fd) {
+ if(mRelFd[0] >=0)
+ close(mRelFd[0]);
+ mRelFd[0] = mRelFd[1];
+ mRelFd[1] = dup(fd);
+}
+
struct copybit_device_t* CopyBit::getCopyBitDevice() {
return mEngine;
}
-CopyBit::CopyBit():mIsModeOn(false), mCopyBitDraw(false){
+CopyBit::CopyBit():mIsModeOn(false), mCopyBitDraw(false),
+ mCurRenderBufferIndex(0){
hw_module_t const *module;
+ for (int i = 0; i < NUM_RENDER_BUFFERS; i++)
+ mRenderBuffer[i] = NULL;
+ mRelFd[0] = -1;
+ mRelFd[1] = -1;
if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
if(copybit_open(module, &mEngine) < 0) {
ALOGE("FATAL ERROR: copybit open failed.");
@@ -480,6 +540,11 @@
CopyBit::~CopyBit()
{
+ freeRenderBuffers();
+ if(mRelFd[0] >=0)
+ close(mRelFd[0]);
+ if(mRelFd[1] >=0)
+ close(mRelFd[1]);
if(mEngine)
{
copybit_close(mEngine);
diff --git a/libhwcomposer/hwc_copybit.h b/libhwcomposer/hwc_copybit.h
index 015d85a..45d254a 100644
--- a/libhwcomposer/hwc_copybit.h
+++ b/libhwcomposer/hwc_copybit.h
@@ -21,8 +21,7 @@
#define HWC_COPYBIT_H
#include "hwc_utils.h"
-#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
-#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
+#define NUM_RENDER_BUFFERS 2
namespace qhwc {
@@ -40,6 +39,11 @@
int dpy, int* fd);
// resets the values
void reset();
+
+ private_handle_t * getCurrentRenderBuffer();
+
+ void setReleaseFd(int fd);
+
private:
// holds the copybit device
struct copybit_device_t *mEngine;
@@ -61,6 +65,19 @@
void getLayerResolution(const hwc_layer_1_t* layer,
unsigned int &width, unsigned int& height);
+
+ int allocRenderBuffers(int w, int h, int f);
+
+ void freeRenderBuffers();
+
+ private_handle_t* mRenderBuffer[NUM_RENDER_BUFFERS];
+
+ // Index of the current intermediate render buffer
+ int mCurRenderBufferIndex;
+
+ //These are the the release FDs of the T-2 and T-1 round
+ //We wait on the T-2 fence
+ int mRelFd[2];
};
}; //namespace qhwc
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index a0dbbe3..f9161a3 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -46,21 +46,24 @@
mDest = ovutils::OV_INVALID;
}
-bool FBUpdateLowRes::prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer) {
+bool FBUpdateLowRes::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list)
+{
if(!ctx->mMDP.hasOverlay) {
ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
__FUNCTION__);
return false;
}
- mModeOn = configure(ctx, fblayer);
+ mModeOn = configure(ctx, list);
ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn);
return mModeOn;
}
// Configure
-bool FBUpdateLowRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer)
+bool FBUpdateLowRes::configure(hwc_context_t *ctx,
+ hwc_display_contents_1 *list)
{
bool ret = false;
+ hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
if (LIKELY(ctx->mOverlay)) {
overlay::Overlay& ov = *(ctx->mOverlay);
private_handle_t *hnd = (private_handle_t *)layer->handle;
@@ -87,7 +90,8 @@
ovutils::ROT_FLAGS_NONE);
ov.setSource(parg, dest);
- hwc_rect_t sourceCrop = layer->sourceCrop;
+ hwc_rect_t sourceCrop;
+ getNonWormholeRegion(list, sourceCrop);
// x,y,w,h
ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
sourceCrop.right - sourceCrop.left,
@@ -99,7 +103,7 @@
static_cast<ovutils::eTransform>(transform);
ov.setTransform(orient, dest);
- hwc_rect_t displayFrame = layer->displayFrame;
+ hwc_rect_t displayFrame = sourceCrop;
ovutils::Dim dpos(displayFrame.left,
displayFrame.top,
displayFrame.right - displayFrame.left,
@@ -118,7 +122,7 @@
return ret;
}
-bool FBUpdateLowRes::draw(hwc_context_t *ctx, hwc_layer_1_t *layer)
+bool FBUpdateLowRes::draw(hwc_context_t *ctx, private_handle_t *hnd)
{
if(!mModeOn) {
return true;
@@ -126,7 +130,6 @@
bool ret = true;
overlay::Overlay& ov = *(ctx->mOverlay);
ovutils::eDest dest = mDest;
- private_handle_t *hnd = (private_handle_t *)layer->handle;
if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) {
ALOGE("%s: queueBuffer failed for FBUpdate", __FUNCTION__);
ret = false;
@@ -143,21 +146,24 @@
mDestRight = ovutils::OV_INVALID;
}
-bool FBUpdateHighRes::prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer) {
+bool FBUpdateHighRes::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list)
+{
if(!ctx->mMDP.hasOverlay) {
ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
__FUNCTION__);
return false;
}
ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn);
- mModeOn = configure(ctx, fblayer);
+ mModeOn = configure(ctx, list);
return mModeOn;
}
// Configure
-bool FBUpdateHighRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer)
+bool FBUpdateHighRes::configure(hwc_context_t *ctx,
+ hwc_display_contents_1 *list)
{
bool ret = false;
+ hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
if (LIKELY(ctx->mOverlay)) {
overlay::Overlay& ov = *(ctx->mOverlay);
private_handle_t *hnd = (private_handle_t *)layer->handle;
@@ -199,7 +205,8 @@
ovutils::ROT_FLAGS_NONE);
ov.setSource(pargR, destR);
- hwc_rect_t sourceCrop = layer->sourceCrop;
+ hwc_rect_t sourceCrop;
+ getNonWormholeRegion(list, sourceCrop);
ovutils::Dim dcropL(sourceCrop.left, sourceCrop.top,
(sourceCrop.right - sourceCrop.left) / 2,
sourceCrop.bottom - sourceCrop.top);
@@ -217,7 +224,7 @@
ov.setTransform(orient, destL);
ov.setTransform(orient, destR);
- hwc_rect_t displayFrame = layer->displayFrame;
+ hwc_rect_t displayFrame = sourceCrop;
//For FB left, top will always be 0
//That should also be the case if using 2 mixers for single display
ovutils::Dim dpos(displayFrame.left,
@@ -240,7 +247,7 @@
return ret;
}
-bool FBUpdateHighRes::draw(hwc_context_t *ctx, hwc_layer_1_t *layer)
+bool FBUpdateHighRes::draw(hwc_context_t *ctx, private_handle_t *hnd)
{
if(!mModeOn) {
return true;
@@ -249,7 +256,6 @@
overlay::Overlay& ov = *(ctx->mOverlay);
ovutils::eDest destL = mDestLeft;
ovutils::eDest destR = mDestRight;
- private_handle_t *hnd = (private_handle_t *)layer->handle;
if (!ov.queueBuffer(hnd->fd, hnd->offset, destL)) {
ALOGE("%s: queue failed for left of dpy = %d",
__FUNCTION__, mDpy);
diff --git a/libhwcomposer/hwc_fbupdate.h b/libhwcomposer/hwc_fbupdate.h
index a30a3af..5fc7708 100644
--- a/libhwcomposer/hwc_fbupdate.h
+++ b/libhwcomposer/hwc_fbupdate.h
@@ -34,9 +34,9 @@
explicit IFBUpdate(const int& dpy) : mDpy(dpy) {}
virtual ~IFBUpdate() {};
// Sets up members and prepares overlay if conditions are met
- virtual bool prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer) = 0;
+ virtual bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list) = 0;
// Draws layer
- virtual bool draw(hwc_context_t *ctx, hwc_layer_1_t *fblayer) = 0;
+ virtual bool draw(hwc_context_t *ctx, private_handle_t *hnd) = 0;
//Reset values
virtual void reset();
//Factory method that returns a low-res or high-res version
@@ -52,11 +52,12 @@
public:
explicit FBUpdateLowRes(const int& dpy);
virtual ~FBUpdateLowRes() {};
- bool prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
- bool draw(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
+ bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list);
+
+ bool draw(hwc_context_t *ctx, private_handle_t *hnd);
void reset();
private:
- bool configure(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
+ bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list);
ovutils::eDest mDest; //pipe to draw on
};
@@ -65,11 +66,11 @@
public:
explicit FBUpdateHighRes(const int& dpy);
virtual ~FBUpdateHighRes() {};
- bool prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
- bool draw(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
+ bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list);
+ bool draw(hwc_context_t *ctx, private_handle_t *hnd);
void reset();
private:
- bool configure(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
+ bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list);
ovutils::eDest mDestLeft; //left pipe to draw on
ovutils::eDest mDestRight; //right pipe to draw on
};
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index ee31e6c..c130208 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -54,7 +54,7 @@
ALOGD_IF(QCLIENT_DEBUG,"QClient Destructor invoked");
}
-void QClient::notifyCallback(uint32_t msg, uint32_t value) {
+status_t QClient::notifyCallback(uint32_t msg, uint32_t value) {
switch(msg) {
case IQService::SECURING:
securing(value);
@@ -62,9 +62,13 @@
case IQService::UNSECURING:
unsecuring(value);
break;
+ case IQService::SCREEN_REFRESH:
+ return screenRefresh();
+ break;
default:
- return;
+ return NO_ERROR;
}
+ return NO_ERROR;
}
void QClient::securing(uint32_t startEnd) {
@@ -93,4 +97,14 @@
mHwcContext->proc->invalidate(mHwcContext->proc);
}
+android::status_t QClient::screenRefresh() {
+ status_t result = NO_INIT;
+#ifdef QCOM_BSP
+ if(mHwcContext->proc) {
+ mHwcContext->proc->invalidate(mHwcContext->proc);
+ result = NO_ERROR;
+ }
+#endif
+ return result;
+}
}
diff --git a/libhwcomposer/hwc_qclient.h b/libhwcomposer/hwc_qclient.h
index 0ee6de1..9cb2680 100644
--- a/libhwcomposer/hwc_qclient.h
+++ b/libhwcomposer/hwc_qclient.h
@@ -46,7 +46,7 @@
public:
QClient(hwc_context_t *ctx);
virtual ~QClient();
- virtual void notifyCallback(uint32_t msg, uint32_t value);
+ virtual android::status_t notifyCallback(uint32_t msg, uint32_t value);
private:
//Notifies of Media Player death
@@ -59,6 +59,7 @@
void securing(uint32_t startEnd);
void unsecuring(uint32_t startEnd);
+ android::status_t screenRefresh();
hwc_context_t *mHwcContext;
const android::sp<android::IMediaDeathNotifier> mMPDeathNotifier;
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 82ab25c..5193644 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -364,6 +364,33 @@
crop_b -= crop_h * bottomCutRatio;
}
+void getNonWormholeRegion(hwc_display_contents_1_t* list,
+ hwc_rect_t& nwr)
+{
+ uint32_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;
+ nwr.top = list->hwLayers[0].displayFrame.top;
+ nwr.right = list->hwLayers[0].displayFrame.right;
+ nwr.bottom = list->hwLayers[0].displayFrame.bottom;
+
+ for (uint32_t i = 1; i < last; i++) {
+ hwc_rect_t displayFrame = list->hwLayers[i].displayFrame;
+ nwr.left = min(nwr.left, displayFrame.left);
+ nwr.top = min(nwr.top, displayFrame.top);
+ nwr.right = max(nwr.right, displayFrame.right);
+ nwr.bottom = max(nwr.bottom, displayFrame.bottom);
+ }
+
+ //Intersect with the framebuffer
+ nwr.left = max(nwr.left, fbDisplayFrame.left);
+ nwr.top = max(nwr.top, fbDisplayFrame.top);
+ nwr.right = min(nwr.right, fbDisplayFrame.right);
+ nwr.bottom = min(nwr.bottom, fbDisplayFrame.bottom);
+
+}
+
bool isExternalActive(hwc_context_t* ctx) {
return ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive;
}
@@ -452,6 +479,8 @@
fd = -1;
}
+ if (ctx->mCopyBit[dpy])
+ ctx->mCopyBit[dpy]->setReleaseFd(releaseFd);
if(UNLIKELY(swapzero)){
list->retireFenceFd = -1;
close(releaseFd);
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 671fbba..187c43a 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -56,6 +56,7 @@
class MDPComp;
class CopyBit;
+
struct MDPInfo {
int version;
char panel;
@@ -97,6 +98,7 @@
// LayerProp::flag values
enum {
HWC_MDPCOMP = 0x00000001,
+ HWC_COPYBIT = 0x00000002,
};
class LayerCache {
@@ -132,6 +134,8 @@
//Crops source buffer against destination and FB boundaries
void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,
const hwc_rect_t& scissor, int orient);
+void getNonWormholeRegion(hwc_display_contents_1_t* list,
+ hwc_rect_t& nwr);
bool isSecuring(hwc_context_t* ctx);
bool isSecureModePolicy(int mdpVersion);
bool isExternalActive(hwc_context_t* ctx);
@@ -185,6 +189,9 @@
return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_CC));
}
+template<typename T> inline T max(T a, T b) { return (a > b) ? a : b; }
+template<typename T> inline T min(T a, T b) { return (a < b) ? a : b; }
+
// Initialize uevent thread
void init_uevent_thread(hwc_context_t* ctx);
// Initialize vsync thread
diff --git a/libqservice/IQClient.cpp b/libqservice/IQClient.cpp
index 4ff67dc..30fbb64 100644
--- a/libqservice/IQClient.cpp
+++ b/libqservice/IQClient.cpp
@@ -41,12 +41,14 @@
BpQClient(const sp<IBinder>& impl)
: BpInterface<IQClient>(impl) {}
- virtual void notifyCallback(uint32_t msg, uint32_t value) {
+ virtual status_t notifyCallback(uint32_t msg, uint32_t value) {
Parcel data, reply;
data.writeInterfaceToken(IQClient::getInterfaceDescriptor());
data.writeInt32(msg);
data.writeInt32(value);
remote()->transact(NOTIFY_CALLBACK, data, &reply);
+ status_t result = reply.readInt32();
+ return result;
}
};
diff --git a/libqservice/IQClient.h b/libqservice/IQClient.h
index 68d8275..a28f826 100644
--- a/libqservice/IQClient.h
+++ b/libqservice/IQClient.h
@@ -33,7 +33,7 @@
{
public:
DECLARE_META_INTERFACE(QClient);
- virtual void notifyCallback(uint32_t msg, uint32_t value) = 0;
+ virtual android::status_t notifyCallback(uint32_t msg, uint32_t value) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/libqservice/IQService.cpp b/libqservice/IQService.cpp
index 7a88bdf..6c6f7b6 100644
--- a/libqservice/IQService.cpp
+++ b/libqservice/IQService.cpp
@@ -63,6 +63,14 @@
data.writeStrongBinder(client->asBinder());
remote()->transact(CONNECT, data, &reply);
}
+
+ virtual status_t screenRefresh() {
+ Parcel data, reply;
+ data.writeInterfaceToken(IQService::getInterfaceDescriptor());
+ remote()->transact(SCREEN_REFRESH, data, &reply);
+ status_t result = reply.readInt32();
+ return result;
+ }
};
IMPLEMENT_META_INTERFACE(QService, "android.display.IQService");
@@ -88,7 +96,8 @@
switch(code) {
case SECURING: {
if(!permission) {
- ALOGE("display.qservice SECURING access denied: pid=%d uid=%d process=%s",
+ ALOGE("display.qservice SECURING access denied: \
+ pid=%d uid=%d process=%s",
callerPid, callerUid, callingProcName);
return PERMISSION_DENIED;
}
@@ -99,7 +108,8 @@
} break;
case UNSECURING: {
if(!permission) {
- ALOGE("display.qservice UNSECURING access denied: pid=%d uid=%d process=%s",
+ ALOGE("display.qservice UNSECURING access denied: \
+ pid=%d uid=%d process=%s",
callerPid, callerUid, callingProcName);
return PERMISSION_DENIED;
}
@@ -111,7 +121,8 @@
case CONNECT: {
CHECK_INTERFACE(IQService, data, reply);
if(callerUid != AID_GRAPHICS) {
- ALOGE("display.qservice CONNECT access denied: pid=%d uid=%d process=%s",
+ ALOGE("display.qservice CONNECT access denied: \
+ pid=%d uid=%d process=%s",
callerPid, callerUid, callingProcName);
return PERMISSION_DENIED;
}
@@ -120,6 +131,16 @@
connect(client);
return NO_ERROR;
} break;
+ case SCREEN_REFRESH: {
+ CHECK_INTERFACE(IQService, data, reply);
+ if(callerUid != AID_GRAPHICS) {
+ ALOGE("display.qservice SCREEN_REFRESH access denied: \
+ pid=%d uid=%d process=%s",callerPid,
+ callerUid, callingProcName);
+ return PERMISSION_DENIED;
+ }
+ return screenRefresh();
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 70e6c64..79e831d 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -40,6 +40,7 @@
SECURING = android::IBinder::FIRST_CALL_TRANSACTION,
UNSECURING, // Hardware unsecuring start/end notification
CONNECT,
+ SCREEN_REFRESH,
};
enum {
END = 0,
@@ -48,6 +49,7 @@
virtual void securing(uint32_t startEnd) = 0;
virtual void unsecuring(uint32_t startEnd) = 0;
virtual void connect(const android::sp<qClient::IQClient>& client) = 0;
+ virtual android::status_t screenRefresh() = 0;
};
// ----------------------------------------------------------------------------
diff --git a/libqservice/QService.cpp b/libqservice/QService.cpp
index 8fc7319..54e285c 100644
--- a/libqservice/QService.cpp
+++ b/libqservice/QService.cpp
@@ -63,6 +63,14 @@
mClient = client;
}
+android::status_t QService::screenRefresh() {
+ status_t result = NO_ERROR;
+ if(mClient.get()) {
+ result = mClient->notifyCallback(SCREEN_REFRESH, 0);
+ }
+ return result;
+}
+
void QService::init()
{
if(!sQService) {
diff --git a/libqservice/QService.h b/libqservice/QService.h
index 4f7e570..268bf81 100644
--- a/libqservice/QService.h
+++ b/libqservice/QService.h
@@ -48,6 +48,7 @@
virtual void securing(uint32_t startEnd);
virtual void unsecuring(uint32_t startEnd);
virtual void connect(const android::sp<qClient::IQClient>& client);
+ virtual android::status_t screenRefresh();
static void init();
private:
QService();