hwc: Add support for copybit(C2D) composition
- Add CopybitEngine to hwc_context
- draw the layer on the HWC_FRAMEBUFFER_TARGET using
copybit(c2d) if it qualifies for C2D composition.
- use fence returned from the copybit during c2d
composition
Change-Id: I052da015cd031f7abd6411d83d7944c335caeff7
diff --git a/libgralloc/Android.mk b/libgralloc/Android.mk
index 159a252..f4e3834 100644
--- a/libgralloc/Android.mk
+++ b/libgralloc/Android.mk
@@ -35,7 +35,7 @@
LOCAL_MODULE := libmemalloc
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
-LOCAL_SHARED_LIBRARIES := $(common_libs) libgenlock
+LOCAL_SHARED_LIBRARIES := $(common_libs) libgenlock libqdutils
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdmemalloc\"
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
LOCAL_SRC_FILES := ionalloc.cpp alloc_controller.cpp
diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk
index 543efd9..a9ada35 100644
--- a/libhwcomposer/Android.mk
+++ b/libhwcomposer/Android.mk
@@ -8,7 +8,7 @@
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
LOCAL_SHARED_LIBRARIES := $(common_libs) libEGL liboverlay libgenlock \
libexternal libqdutils libhardware_legacy \
- libdl libmemalloc libqservice
+ libdl libmemalloc libqservice libsync
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdhwcomposer\"
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
LOCAL_SRC_FILES := hwc.cpp \
@@ -17,6 +17,7 @@
hwc_uevents.cpp \
hwc_vsync.cpp \
hwc_fbupdate.cpp \
- hwc_mdpcomp.cpp
+ hwc_mdpcomp.cpp \
+ hwc_copybit.cpp
include $(BUILD_SHARED_LIBRARY)
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index ac1be19..ba84580 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -2,6 +2,9 @@
* Copyright (C) 2010 The Android Open Source Project
* Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
*
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
* 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
@@ -30,6 +33,7 @@
#include "hwc_fbupdate.h"
#include "hwc_mdpcomp.h"
#include "external.h"
+#include "hwc_copybit.h"
using namespace qhwc;
#define VSYNC_DEBUG 0
@@ -96,6 +100,9 @@
if(ctx->mFBUpdate[i])
ctx->mFBUpdate[i]->reset();
+
+ if(ctx->mCopyBit[i])
+ ctx->mCopyBit[i]->reset();
}
VideoOverlay::reset();
}
@@ -127,11 +134,16 @@
if(fbLayer->handle) {
setListStats(ctx, list, dpy);
reset_layer_prop(ctx, dpy);
- if(!ctx->mMDPComp->prepare(ctx, list)) {
+ int ret = ctx->mMDPComp->prepare(ctx, list);
+ if(!ret) {
+ // IF MDPcomp fails use this route
VideoOverlay::prepare(ctx, list, dpy);
ctx->mFBUpdate[dpy]->prepare(ctx, fbLayer);
}
ctx->mLayerCache[dpy]->updateLayerCache(list);
+ // Use Copybit, when MDP comp fails
+ if(!ret && ctx->mCopyBit[dpy])
+ ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
}
}
return 0;
@@ -154,6 +166,8 @@
VideoOverlay::prepare(ctx, list, dpy);
ctx->mFBUpdate[dpy]->prepare(ctx, fbLayer);
ctx->mLayerCache[dpy]->updateLayerCache(list);
+ if(ctx->mCopyBit[dpy])
+ ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
ctx->mExtDispConfiguring = false;
}
}
@@ -296,8 +310,10 @@
ctx->dpyAttr[dpy].isActive) {
uint32_t last = list->numHwLayers - 1;
hwc_layer_1_t *fbLayer = &list->hwLayers[last];
-
- hwc_sync(ctx, list, dpy);
+ int fd = -1; //FenceFD from the Copybit(valid in async mode)
+ if(ctx->mCopyBit[dpy])
+ ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
+ hwc_sync(ctx, list, dpy, fd);
if (!VideoOverlay::draw(ctx, list, dpy)) {
ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__);
ret = -1;
@@ -338,8 +354,11 @@
ctx->dpyAttr[dpy].connected) {
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)
+ if(ctx->mCopyBit[dpy])
+ ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
- hwc_sync(ctx, list, dpy);
+ hwc_sync(ctx, list, dpy, fd);
if (!VideoOverlay::draw(ctx, list, dpy)) {
ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__);
@@ -369,7 +388,6 @@
int ret = 0;
hwc_context_t* ctx = (hwc_context_t*)(dev);
Locker::Autolock _l(ctx->mBlankLock);
-
for (uint32_t i = 0; i < numDisplays; i++) {
hwc_display_contents_1_t* list = displays[i];
switch(i) {
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 1249e84..e764c69 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
*
* Not a Contribution, Apache license notifications and license are retained
* for attribution purposes only.
@@ -20,14 +20,12 @@
#define DEBUG_COPYBIT 0
#include <copybit.h>
-#include <genlock.h>
-#include "hwc_copybit.h"
+#include <utils/Timers.h>
#include "hwc_copybit.h"
#include "comptype.h"
namespace qhwc {
-
struct range {
int current;
int end;
@@ -65,44 +63,9 @@
mutable range r;
};
-// Initialize CopyBit Class Static Mmembers.
-functype_eglGetRenderBufferANDROID CopyBit::LINK_eglGetRenderBufferANDROID
- = NULL;
-functype_eglGetCurrentSurface CopyBit::LINK_eglGetCurrentSurface = NULL;
-int CopyBit::sYuvCount = 0;
-int CopyBit::sYuvLayerIndex = -1;
-bool CopyBit::sIsModeOn = false;
-bool CopyBit::sIsLayerSkip = false;
-void* CopyBit::egl_lib = NULL;
-
-void CopyBit::openEglLibAndGethandle()
-{
- egl_lib = ::dlopen("libEGL_adreno200.so", RTLD_GLOBAL | RTLD_LAZY);
- if (!egl_lib) {
- return;
- }
- updateEglHandles(egl_lib);
-}
-void CopyBit::closeEglLib()
-{
- if(egl_lib)
- ::dlclose(egl_lib);
-
- egl_lib = NULL;
- updateEglHandles(NULL);
-}
-
-void CopyBit::updateEglHandles(void* egl_lib)
-{
- if(egl_lib != NULL) {
- *(void **)&CopyBit::LINK_eglGetRenderBufferANDROID =
- ::dlsym(egl_lib, "eglGetRenderBufferANDROID");
- *(void **)&CopyBit::LINK_eglGetCurrentSurface =
- ::dlsym(egl_lib, "eglGetCurrentSurface");
- }else {
- LINK_eglGetCurrentSurface = NULL;
- LINK_eglGetCurrentSurface = NULL;
- }
+void CopyBit::reset() {
+ mIsModeOn = false;
+ mCopyBitDraw = false;
}
bool CopyBit::canUseCopybitForYUV(hwc_context_t *ctx) {
@@ -113,15 +76,16 @@
return true;
}
-bool CopyBit::canUseCopybitForRGB(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
- int compositionType =
- qdutils::QCCompositionType::getInstance().getCompositionType();
+bool CopyBit::canUseCopybitForRGB(hwc_context_t *ctx,
+ hwc_display_contents_1_t *list,
+ int dpy) {
+ int compositionType = qdutils::QCCompositionType::
+ getInstance().getCompositionType();
if ((compositionType & qdutils::COMPOSITION_TYPE_C2D) ||
(compositionType & qdutils::COMPOSITION_TYPE_DYN)) {
- if (sYuvCount) {
+ if(ctx->listStats[dpy].yuvCount) {
//Overlay up & running. Dont use COPYBIT for RGB layers.
- // TODO need to implement blending with C2D
return false;
}
}
@@ -131,17 +95,13 @@
// use copybit, if (TotalRGBRenderArea < 2 * FB Area)
// this is done based on perf inputs in ICS
// TODO: Above condition needs to be re-evaluated in JB
-
- framebuffer_device_t *fbDev = ctx->mFbDev;
- if (!fbDev) {
- ALOGE("%s:Invalid FB device", __FUNCTION__);
- return false;
- }
- unsigned int fbArea = (fbDev->width * fbDev->height);
+ int fbWidth = ctx->dpyAttr[dpy].xres;
+ int fbHeight = ctx->dpyAttr[dpy].yres;
+ unsigned int fbArea = (fbWidth * fbHeight);
unsigned int renderArea = getRGBRenderingArea(list);
ALOGD_IF (DEBUG_COPYBIT, "%s:renderArea %u, fbArea %u",
__FUNCTION__, renderArea, fbArea);
- if (renderArea < (2 * fbArea)) {
+ if (renderArea <= (2 * fbArea)) {
return true;
}
} else if ((compositionType & qdutils::COMPOSITION_TYPE_MDP)) {
@@ -154,7 +114,8 @@
return false;
}
-unsigned int CopyBit::getRGBRenderingArea(const hwc_display_contents_1_t *list) {
+unsigned int CopyBit::getRGBRenderingArea
+ (const hwc_display_contents_1_t *list) {
//Calculates total rendering area for RGB layers
unsigned int renderArea = 0;
unsigned int w=0, h=0;
@@ -170,71 +131,116 @@
return renderArea;
}
-bool CopyBit::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
+bool CopyBit::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+ int dpy) {
- int compositionType =
- qdutils::QCCompositionType::getInstance().getCompositionType();
+ if(mEngine == NULL) {
+ // No copybit device found - cannot use copybit
+ return false;
+ }
+ int compositionType = qdutils::QCCompositionType::
+ getInstance().getCompositionType();
- if ((compositionType & qdutils::COMPOSITION_TYPE_GPU) ||
- (compositionType & qdutils::COMPOSITION_TYPE_CPU)) {
+ if ((compositionType == qdutils::COMPOSITION_TYPE_GPU) ||
+ (compositionType == qdutils::COMPOSITION_TYPE_CPU)) {
//GPU/CPU composition, don't change layer composition type
return true;
}
- bool useCopybitForYUV = canUseCopybitForYUV(ctx);
- bool useCopybitForRGB = canUseCopybitForRGB(ctx, list);
-
if(!(validateParams(ctx, list))) {
- ALOGE("%s:Invalid Params", __FUNCTION__);
- return false;
+ ALOGE("%s:Invalid Params", __FUNCTION__);
+ return false;
}
- for (int i=list->numHwLayers-1; i >= 0 ; i--) {
+ if(ctx->listStats[dpy].skipCount) {
+ //GPU will be anyways used
+ return false;
+ }
+
+ bool useCopybitForYUV = canUseCopybitForYUV(ctx);
+ bool useCopybitForRGB = canUseCopybitForRGB(ctx, list, dpy);
+
+ // 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 (isSkipLayer(&list->hwLayers[i])) {
- return true;
- } else if (hnd->bufferType == BUFFER_TYPE_VIDEO) {
- //YUV layer, check, if copybit can be used
- if (useCopybitForYUV) {
- list->hwLayers[i].compositionType = HWC_USE_COPYBIT;
- }
- } else if (hnd->bufferType == BUFFER_TYPE_UI) {
- //RGB layer, check, if copybit can be used
- if (useCopybitForRGB) {
- list->hwLayers[i].compositionType = HWC_USE_COPYBIT;
- }
- }
- }
- return true;
-}
-
-bool CopyBit::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list, EGLDisplay dpy,
- EGLSurface sur){
- // draw layers marked for COPYBIT
- int retVal = true;
- for (size_t i=0; i<list->numHwLayers; i++) {
- if (list->hwLayers[i].compositionType == HWC_USE_COPYBIT) {
- retVal = drawLayerUsingCopybit(ctx, &(list->hwLayers[i]),
- (EGLDisplay)dpy,
- (EGLSurface)sur,
- LINK_eglGetRenderBufferANDROID,
- LINK_eglGetCurrentSurface);
- if(retVal<0) {
- ALOGE("%s : drawLayerUsingCopybit failed", __FUNCTION__);
- }
+ 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;
+ }
}
}
return true;
}
+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;
+
+ if(mCopyBitDraw == false) // there is no layer marked for copybit
+ return true ;
+
+ 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;
+ if (!renderBuffer) {
+ ALOGE("%s: HWC_FRAMEBUFFER_TARGET layer handle is NULL", __FUNCTION__);
+ return false;
+ }
+ // numAppLayers-1, as we iterate from 0th layer index with HWC_BLIT 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__);
+ continue;
+ }
+ int ret = -1;
+ if (list->hwLayers[i].acquireFenceFd != -1 ) {
+ // Wait for acquire Fence on the App buffers.
+ ret = sync_wait(list->hwLayers[i].acquireFenceFd, 1000);
+ if(ret < 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;
+ }
+ retVal = drawLayerUsingCopybit(ctx, &(list->hwLayers[i]),
+ renderBuffer, dpy);
+ copybitLayerCount++;
+ if(retVal < 0) {
+ ALOGE("%s : drawLayerUsingCopybit failed", __FUNCTION__);
+ }
+ }
+
+ if (copybitLayerCount) {
+ copybit_device_t *copybit = getCopyBitDevice();
+ // Async mode
+ copybit->flush_get_fence(copybit, fd);
+ }
+ return true;
+}
+
int CopyBit::drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
- EGLDisplay dpy,
- EGLSurface surface,
- functype_eglGetRenderBufferANDROID& LINK_eglGetRenderBufferANDROID,
- functype_eglGetCurrentSurface LINK_eglGetCurrentSurface)
+ private_handle_t *renderBuffer, int dpy)
{
hwc_context_t* ctx = (hwc_context_t*)(dev);
+ int err = 0;
if(!ctx) {
ALOGE("%s: null context ", __FUNCTION__);
return -1;
@@ -246,26 +252,9 @@
return -1;
}
- // Lock this buffer for read.
- genlock_lock_type lockType = GENLOCK_READ_LOCK;
- int err = genlock_lock_buffer(hnd, lockType, GENLOCK_MAX_TIMEOUT);
- if (GENLOCK_FAILURE == err) {
- ALOGE("%s: genlock_lock_buffer(READ) failed", __FUNCTION__);
- return -1;
- }
- //render buffer
- EGLSurface eglSurface = LINK_eglGetCurrentSurface(EGL_DRAW);
- android_native_buffer_t *renderBuffer =
- (android_native_buffer_t *)LINK_eglGetRenderBufferANDROID(dpy, eglSurface);
- if (!renderBuffer) {
- ALOGE("%s: eglGetRenderBuffer returned NULL buffer", __FUNCTION__);
- genlock_unlock_buffer(hnd);
- return -1;
- }
- private_handle_t *fbHandle = (private_handle_t *)renderBuffer->handle;
+ private_handle_t *fbHandle = (private_handle_t *)renderBuffer;
if(!fbHandle) {
ALOGE("%s: Framebuffer handle is NULL", __FUNCTION__);
- genlock_unlock_buffer(hnd);
return -1;
}
@@ -281,8 +270,6 @@
// this needs to change to accomodate vertical stride
// if needed in the future
src.vert_padding = 0;
- // Remove the srcBufferTransform if any
- layer->transform = (layer->transform & FINAL_TRANSFORM_MASK);
// Copybit source rect
hwc_rect_t sourceCrop = layer->sourceCrop;
@@ -302,9 +289,9 @@
dst.h = fbHandle->height;
dst.format = fbHandle->format;
dst.base = (void *)fbHandle->base;
- dst.handle = (native_handle_t *)renderBuffer->handle;
+ dst.handle = (native_handle_t *)fbHandle;
- copybit_device_t *copybit = ctx->mCopybitEngine->getEngine();
+ copybit_device_t *copybit = mEngine;
int32_t screen_w = displayFrame.right - displayFrame.left;
int32_t screen_h = displayFrame.bottom - displayFrame.top;
@@ -330,7 +317,6 @@
ALOGE("%s: wrong params for display screen_w=%d src_crop_width=%d \
screen_w=%d src_crop_width=%d", __FUNCTION__, screen_w,
src_crop_width,screen_w,src_crop_width);
- genlock_unlock_buffer(hnd);
return -1;
}
@@ -346,7 +332,6 @@
ALOGE("%s: greater than max supported size dsdx=%f dtdy=%f \
scaleLimitMax=%f scaleLimitMin=%f", __FUNCTION__,dsdx,dtdy,
scaleLimitMax,1/scaleLimitMin);
- genlock_unlock_buffer(hnd);
return -1;
}
if(dsdx > copybitsMaxScale ||
@@ -411,7 +396,6 @@
__LINE__);
if(tmpHnd)
free_buffer(tmpHnd);
- genlock_unlock_buffer(hnd);
return err;
}
// copy new src and src rect crop
@@ -431,9 +415,8 @@
layer->transform);
//TODO: once, we are able to read layer alpha, update this
copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 255);
- copybit->set_parameter(copybit, COPYBIT_PREMULTIPLIED_ALPHA,
- (layer->blending == HWC_BLENDING_PREMULT)?
- COPYBIT_ENABLE : COPYBIT_DISABLE);
+ 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);
@@ -449,13 +432,6 @@
if(err < 0)
ALOGE("%s: copybit stretch failed",__FUNCTION__);
-
- // Unlock this buffer since copybit is done with it.
- err = genlock_unlock_buffer(hnd);
- if (GENLOCK_FAILURE == err) {
- ALOGE("%s: genlock_unlock_buffer failed", __FUNCTION__);
- }
-
return err;
}
@@ -468,62 +444,41 @@
height = displayFrame.bottom - displayFrame.top;
}
-bool CopyBit::validateParams(hwc_context_t *ctx, const hwc_display_contents_1_t *list) {
- //Validate parameters
- if (!ctx) {
- ALOGE("%s:Invalid HWC context", __FUNCTION__);
- return false;
- } else if (!list) {
- ALOGE("%s:Invalid HWC layer list", __FUNCTION__);
- return false;
- }
-
- framebuffer_device_t *fbDev = ctx->mFbDev;
-
- if (!fbDev) {
- ALOGE("%s:Invalid FB device", __FUNCTION__);
- return false;
- }
-
- if (LINK_eglGetRenderBufferANDROID == NULL ||
- LINK_eglGetCurrentSurface == NULL) {
- ALOGE("%s:Not able to link to ADRENO", __FUNCTION__);
- return false;
- }
-
- return true;
+bool CopyBit::validateParams(hwc_context_t *ctx,
+ const hwc_display_contents_1_t *list) {
+ //Validate parameters
+ if (!ctx) {
+ ALOGE("%s:Invalid HWC context", __FUNCTION__);
+ return false;
+ } else if (!list) {
+ ALOGE("%s:Invalid HWC layer list", __FUNCTION__);
+ return false;
+ }
+ return true;
}
-//CopybitEngine Class functions
-CopybitEngine* CopybitEngine::sInstance = 0;
-struct copybit_device_t* CopybitEngine::getEngine() {
- return sEngine;
-}
-CopybitEngine* CopybitEngine::getInstance() {
- if(sInstance == NULL)
- sInstance = new CopybitEngine();
- return sInstance;
+struct copybit_device_t* CopyBit::getCopyBitDevice() {
+ return mEngine;
}
-CopybitEngine::CopybitEngine(){
+CopyBit::CopyBit():mIsModeOn(false), mCopyBitDraw(false){
hw_module_t const *module;
if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
- copybit_open(module, &sEngine);
- CopyBit::openEglLibAndGethandle();
+ if(copybit_open(module, &mEngine) < 0) {
+ ALOGE("FATAL ERROR: copybit open failed.");
+ }
} else {
- ALOGE("FATAL ERROR: copybit open failed.");
+ ALOGE("FATAL ERROR: copybit hw module not found");
}
}
-CopybitEngine::~CopybitEngine()
+CopyBit::~CopyBit()
{
- if(sEngine)
+ if(mEngine)
{
- CopyBit::closeEglLib();
- copybit_close(sEngine);
- sEngine = NULL;
+ copybit_close(mEngine);
+ mEngine = NULL;
}
}
-
}; //namespace qhwc
diff --git a/libhwcomposer/hwc_copybit.h b/libhwcomposer/hwc_copybit.h
index ae82b6c..015d85a 100644
--- a/libhwcomposer/hwc_copybit.h
+++ b/libhwcomposer/hwc_copybit.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
*
* Not a Contribution, Apache license notifications and license are retained
* for attribution purposes only.
@@ -20,94 +20,49 @@
#ifndef HWC_COPYBIT_H
#define HWC_COPYBIT_H
#include "hwc_utils.h"
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <gralloc_priv.h>
-#include <gr.h>
-#include <dlfcn.h>
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
namespace qhwc {
-//Feature for using Copybit to display RGB layers.
-typedef EGLClientBuffer (*functype_eglGetRenderBufferANDROID) (
- EGLDisplay dpy,
- EGLSurface draw);
-typedef EGLSurface (*functype_eglGetCurrentSurface)(EGLint readdraw);
class CopyBit {
public:
+ CopyBit();
+ ~CopyBit();
+ // API to get copybit engine(non static)
+ struct copybit_device_t *getCopyBitDevice();
//Sets up members and prepares copybit if conditions are met
- static bool prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list);
+ bool prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+ int dpy);
//Draws layer if the layer is set for copybit in prepare
- static bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list, EGLDisplay dpy,
- EGLSurface sur);
- //Receives data from hwc
- static void setStats(int yuvCount, int yuvLayerIndex, bool isYuvLayerSkip);
-
- static void updateEglHandles(void*);
- static int drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
- EGLDisplay dpy, EGLSurface surface,
- functype_eglGetRenderBufferANDROID& LINK_eglGetRenderBufferANDROID,
- functype_eglGetCurrentSurface LINK_eglGetCurrentSurface);
- static bool canUseCopybitForYUV (hwc_context_t *ctx);
- static bool canUseCopybitForRGB (hwc_context_t *ctx,
- hwc_display_contents_1_t *list);
- static bool validateParams (hwc_context_t *ctx,
- const hwc_display_contents_1_t *list);
- static void closeEglLib();
- static void openEglLibAndGethandle();
+ bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+ int dpy, int* fd);
+ // resets the values
+ void reset();
private:
- //Marks layer flags if this feature is used
- static void markFlags(hwc_layer_1_t *layer);
- //returns yuv count
- static int getYuvCount();
-
- //Number of yuv layers in this drawing round
- static int sYuvCount;
- //Index of YUV layer, relevant only if count is 1
- static int sYuvLayerIndex;
- //Flags if a yuv layer is animating or below something that is animating
- static bool sIsLayerSkip;
+ // holds the copybit device
+ struct copybit_device_t *mEngine;
+ // Helper functions for copybit composition
+ int drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
+ private_handle_t *renderBuffer, int dpy);
+ bool canUseCopybitForYUV (hwc_context_t *ctx);
+ bool canUseCopybitForRGB (hwc_context_t *ctx,
+ hwc_display_contents_1_t *list, int dpy);
+ bool validateParams (hwc_context_t *ctx,
+ const hwc_display_contents_1_t *list);
//Flags if this feature is on.
- static bool sIsModeOn;
- //handle for adreno lib
- static void* egl_lib;
+ bool mIsModeOn;
+ // flag that indicates whether CopyBit composition is enabled for this cycle
+ bool mCopyBitDraw;
- static functype_eglGetRenderBufferANDROID LINK_eglGetRenderBufferANDROID;
- static functype_eglGetCurrentSurface LINK_eglGetCurrentSurface;
+ unsigned int getRGBRenderingArea
+ (const hwc_display_contents_1_t *list);
- static unsigned int getRGBRenderingArea (const hwc_display_contents_1_t *list);
-
- static void getLayerResolution(const hwc_layer_1_t* layer,
+ void getLayerResolution(const hwc_layer_1_t* layer,
unsigned int &width, unsigned int& height);
};
-class CopybitEngine {
-public:
- ~CopybitEngine();
- // API to get copybit engine(non static)
- struct copybit_device_t *getEngine();
- // API to get singleton
- static CopybitEngine* getInstance();
-private:
- CopybitEngine();
- struct copybit_device_t *sEngine;
- static CopybitEngine* sInstance; // singleton
-};
-
-
-inline void CopyBit::setStats(int yuvCount, int yuvLayerIndex,
- bool isYuvLayerSkip) {
- sYuvCount = yuvCount;
- sYuvLayerIndex = yuvLayerIndex;
- sIsLayerSkip = isYuvLayerSkip;
-}
-
-inline int CopyBit::getYuvCount() { return sYuvCount; }
-
-
}; //namespace qhwc
#endif //HWC_COPYBIT_H
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index 334df26..6b8f4e3 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -27,6 +27,8 @@
#include <stdlib.h>
#include "hwc_utils.h"
#include "hwc_fbupdate.h"
+#include "hwc_copybit.h"
+#include "comptype.h"
#include "external.h"
namespace qhwc {
@@ -38,6 +40,16 @@
int vsync = 0;
int64_t timestamp = 0;
const char *str = udata;
+ bool usecopybit = false;
+ int compositionType =
+ qdutils::QCCompositionType::getInstance().getCompositionType();
+
+ if (compositionType & (qdutils::COMPOSITION_TYPE_DYN |
+ qdutils::COMPOSITION_TYPE_MDP |
+ qdutils::COMPOSITION_TYPE_C2D)) {
+ usecopybit = true;
+
+ }
if(!strcasestr("change@/devices/virtual/switch/hdmi", str) &&
!strcasestr("change@/devices/virtual/switch/wfd", str)) {
@@ -72,6 +84,8 @@
ctx->mFBUpdate[HWC_DISPLAY_EXTERNAL] =
IFBUpdate::getObject(ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].xres,
HWC_DISPLAY_EXTERNAL);
+ if(usecopybit)
+ ctx->mCopyBit[HWC_DISPLAY_EXTERNAL] = new CopyBit();
} else {
ctx->mExtDisplay->processUEventOffline(udata);
if(ctx->mFBUpdate[HWC_DISPLAY_EXTERNAL]) {
@@ -79,6 +93,11 @@
delete ctx->mFBUpdate[HWC_DISPLAY_EXTERNAL];
ctx->mFBUpdate[HWC_DISPLAY_EXTERNAL] = NULL;
}
+ if(ctx->mCopyBit[HWC_DISPLAY_EXTERNAL]){
+ Locker::Autolock _l(ctx->mExtSetLock);
+ delete ctx->mCopyBit[HWC_DISPLAY_EXTERNAL];
+ ctx->mCopyBit[HWC_DISPLAY_EXTERNAL] = NULL;
+ }
}
ALOGD("%s sending hotplug: connected = %d", __FUNCTION__, connected);
Locker::Autolock _l(ctx->mExtSetLock); //hwc comp could be on
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 76635d5..9cc5c24 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -1,6 +1,9 @@
/*
* Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012, The Linux Foundation All rights reserved.
+ * Copyright (C) 2012-2013, The Linux Foundation All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +17,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
+#define HWC_UTILS_DEBUG 0
#include <sys/ioctl.h>
#include <EGL/egl.h>
#include <cutils/properties.h>
@@ -25,9 +28,10 @@
#include "hwc_mdpcomp.h"
#include "hwc_fbupdate.h"
#include "mdp_version.h"
+#include "hwc_copybit.h"
#include "external.h"
#include "QService.h"
-
+#include "comptype.h"
namespace qhwc {
// Opens Framebuffer device
@@ -66,6 +70,19 @@
ctx->mFBUpdate[HWC_DISPLAY_PRIMARY] =
IFBUpdate::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres,
HWC_DISPLAY_PRIMARY);
+
+ char value[PROPERTY_VALUE_MAX];
+ // Check if the target supports copybit compostion (dyn/mdp/c2d) to
+ // decide if we need to open the copybit module.
+ int compositionType =
+ qdutils::QCCompositionType::getInstance().getCompositionType();
+
+ if (compositionType & (qdutils::COMPOSITION_TYPE_DYN |
+ qdutils::COMPOSITION_TYPE_MDP |
+ qdutils::COMPOSITION_TYPE_C2D)) {
+ ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit();
+ }
+
ctx->mExtDisplay = new ExternalDisplay(ctx);
for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++)
ctx->mLayerCache[i] = new LayerCache();
@@ -87,6 +104,13 @@
ctx->mOverlay = NULL;
}
+ for(int i = 0; i< HWC_NUM_DISPLAY_TYPES; i++) {
+ if(ctx->mCopyBit[i]) {
+ delete ctx->mCopyBit[i];
+ ctx->mCopyBit[i] = NULL;
+ }
+ }
+
if(ctx->mFbDev) {
framebuffer_close(ctx->mFbDev);
ctx->mFbDev = NULL;
@@ -251,13 +275,15 @@
return ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive;
}
-int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy) {
+int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
+ int fd) {
int ret = 0;
struct mdp_buf_sync data;
int acquireFd[MAX_NUM_LAYERS];
int count = 0;
int releaseFd = -1;
int fbFd = -1;
+ memset(&data, 0, sizeof(data));
bool swapzero = false;
data.flags = MDP_BUF_SYNC_FLAG_WAIT;
data.acq_fen_fd = acquireFd;
@@ -270,35 +296,52 @@
//Accumulate acquireFenceFds
for(uint32_t i = 0; i < list->numHwLayers; i++) {
- if((list->hwLayers[i].compositionType == HWC_OVERLAY ||
- list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) &&
- list->hwLayers[i].acquireFenceFd != -1 ){
+ if(list->hwLayers[i].compositionType == HWC_OVERLAY &&
+ list->hwLayers[i].acquireFenceFd != -1) {
if(UNLIKELY(swapzero))
acquireFd[count++] = -1;
else
acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
}
+ if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
+ if(UNLIKELY(swapzero))
+ acquireFd[count++] = -1;
+ else if(fd != -1) {
+ //set the acquireFD from fd - which is coming from c2d
+ acquireFd[count++] = fd;
+ // Buffer sync IOCTL should be async when using c2d fence is
+ // used
+ data.flags &= ~MDP_BUF_SYNC_FLAG_WAIT;
+ } else if(list->hwLayers[i].acquireFenceFd != -1)
+ acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
+ }
}
data.acq_fen_fd_cnt = count;
fbFd = ctx->dpyAttr[dpy].fd;
-
//Waits for acquire fences, returns a release fence
- if(LIKELY(!swapzero))
+ 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("ioctl MSMFB_BUFFER_SYNC failed, err=%s",
strerror(errno));
}
-
for(uint32_t i = 0; i < list->numHwLayers; i++) {
- if((list->hwLayers[i].compositionType == HWC_OVERLAY ||
- list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET)) {
+ if(list->hwLayers[i].compositionType == HWC_OVERLAY ||
+ list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
//Close the acquireFenceFds
if(list->hwLayers[i].acquireFenceFd > 0) {
close(list->hwLayers[i].acquireFenceFd);
list->hwLayers[i].acquireFenceFd = -1;
}
+ if(fd > 0) {
+ close(fd);
+ fd = -1;
+ }
//Populate releaseFenceFds.
if(UNLIKELY(swapzero))
list->hwLayers[i].releaseFenceFd = -1;
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 9541404..0005582 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -1,6 +1,9 @@
/*
* Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -51,6 +54,7 @@
class ExternalDisplay;
class IFBUpdate;
class MDPComp;
+class CopyBit;
struct MDPInfo {
int version;
@@ -82,7 +86,6 @@
bool needsAlphaScale;
};
-
struct LayerProp {
uint32_t mFlags; //qcom specific layer flags
LayerProp():mFlags(0) {};
@@ -133,7 +136,8 @@
void dumpsys_log(android::String8& buf, const char* fmt, ...);
//Sync point impl.
-int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy);
+int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
+ int fd);
// Inline utility functions
static inline bool isSkipLayer(const hwc_layer_1_t* l) {
@@ -214,6 +218,10 @@
const hwc_procs_t* proc;
//Framebuffer device
framebuffer_device_t *mFbDev;
+
+ //CopyBit objects
+ qhwc::CopyBit *mCopyBit[HWC_NUM_DISPLAY_TYPES];
+
//Overlay object - NULL for non overlay devices
overlay::Overlay *mOverlay;
//QService object
diff --git a/libqdutils/Android.mk b/libqdutils/Android.mk
index ecae273..eb04afb 100644
--- a/libqdutils/Android.mk
+++ b/libqdutils/Android.mk
@@ -9,8 +9,8 @@
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdutils\"
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
LOCAL_SRC_FILES := profiler.cpp mdp_version.cpp \
- idle_invalidator.cpp
-
+ idle_invalidator.cpp \
+ comptype.cpp
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
diff --git a/libqdutils/comptype.cpp b/libqdutils/comptype.cpp
new file mode 100644
index 0000000..a29158a
--- /dev/null
+++ b/libqdutils/comptype.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2013, 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 or 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<comptype.h>
+
+//Instanticate the QCCompositionType Singleton
+ANDROID_SINGLETON_STATIC_INSTANCE(qdutils::QCCompositionType);
diff --git a/libqdutils/comptype.h b/libqdutils/comptype.h
index a90f957..63c99d3 100644
--- a/libqdutils/comptype.h
+++ b/libqdutils/comptype.h
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
-
+ * Copyright (C) 2012-2013, 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:
@@ -10,7 +10,7 @@
* 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 Code Aurora Forum, Inc. nor the names of its
+ * * Neither the name of The Linux Foundation or the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -89,5 +89,4 @@
}
}; //namespace qdutils
-ANDROID_SINGLETON_STATIC_INSTANCE(qdutils::QCCompositionType);
#endif //INCLUDE_LIBQCOM_COMPTYPES