display : Add support for copybit composition
This change add support for copybit composition in display HAL
for MDP3 targets.
Change-Id: I9bc8e40f624b0760f4faa223cb03a13695611bb3
Acked-by: Sravan Kumar D.V.N <sravank1@codeaurora.org>
diff --git a/common.mk b/common.mk
index 99dfbdf..ecf5d66 100644
--- a/common.mk
+++ b/common.mk
@@ -2,6 +2,7 @@
common_includes := hardware/qcom/display/libgralloc
common_includes += hardware/qcom/display/libgenlock
common_includes += hardware/qcom/display/liboverlay
+common_includes += hardware/qcom/display/libcopybit
common_includes += hardware/qcom/display/libqdutils
ifeq ($(TARGET_USES_POST_PROCESSING),true)
diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp
index 977a3ab..f79c33b 100644
--- a/libcopybit/copybit.cpp
+++ b/libcopybit/copybit.cpp
@@ -60,6 +60,7 @@
int mFD;
uint8_t mAlpha;
int mFlags;
+ bool mBlitToFB;
};
/**
@@ -212,6 +213,10 @@
req->alpha = dev->mAlpha;
req->transp_mask = MDP_TRANSP_NOP;
req->flags = dev->mFlags | flags;
+ // check if we are blitting to f/b
+ if (COPYBIT_ENABLE == dev->mBlitToFB) {
+ req->flags |= MDP_MEMORY_ID_TYPE_FB;
+ }
#if defined(COPYBIT_QSD8K)
req->flags |= MDP_BLEND_FG_PREMULT;
#endif
@@ -322,6 +327,16 @@
ctx->mFlags &= ~0x7;
ctx->mFlags |= value & 0x7;
break;
+ case COPYBIT_BLIT_TO_FRAMEBUFFER:
+ if (COPYBIT_ENABLE == value) {
+ ctx->mBlitToFB = value;
+ } else if (COPYBIT_DISABLE == value) {
+ ctx->mBlitToFB = value;
+ } else {
+ ALOGE ("%s:Invalid input for COPYBIT_BLIT_TO_FRAMEBUFFER : %d",
+ __FUNCTION__, value);
+ }
+ break;
default:
status = -EINVAL;
break;
diff --git a/libcopybit/copybit.h b/libcopybit/copybit.h
index 6384dfe..c14af74 100644
--- a/libcopybit/copybit.h
+++ b/libcopybit/copybit.h
@@ -52,6 +52,10 @@
/* name for copybit_set_parameter */
enum {
+ /* Default blit destination is offline buffer */
+ /* clients to set this to '1', if blitting to framebuffer */
+ /* and reset to '0', after calling blit/stretch */
+ COPYBIT_BLIT_TO_FRAMEBUFFER = 0,
/* rotation of the source image in degrees (0 to 359) */
COPYBIT_ROTATION_DEG = 1,
/* plane alpha value */
diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk
index 8e04606..5067a2a 100644
--- a/libhwcomposer/Android.mk
+++ b/libhwcomposer/Android.mk
@@ -6,9 +6,10 @@
LOCAL_MODULE_TAGS := optional
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
LOCAL_SHARED_LIBRARIES := $(common_libs) libEGL liboverlay libgenlock \
- libqdutils libhardware_legacy
+ libqdutils libhardware_legacy libdl libmemalloc
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"hwcomposer\"
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
LOCAL_SRC_FILES := hwc.cpp hwc_video.cpp hwc_utils.cpp \
- hwc_uimirror.cpp hwc_ext_observer.cpp
+ hwc_uimirror.cpp hwc_ext_observer.cpp \
+ hwc_copybit.cpp
include $(BUILD_SHARED_LIBRARY)
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 1b1aa86..7826a5f 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -20,11 +20,11 @@
#include <cutils/log.h>
#include <cutils/atomic.h>
-#include <EGL/egl.h>
#include "hwc_utils.h"
#include "hwc_video.h"
#include "hwc_uimirror.h"
+#include "hwc_copybit.h"
using namespace qhwc;
@@ -83,7 +83,11 @@
} 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;
}
+ CopyBit::prepare(ctx, list);
}
return 0;
@@ -98,6 +102,7 @@
hwc_context_t* ctx = (hwc_context_t*)(dev);
if (LIKELY(list)) {
VideoOverlay::draw(ctx, list);
+ CopyBit::draw(ctx, list, (EGLDisplay)dpy, (EGLSurface)sur);
EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur);
UIMirrorOverlay::draw(ctx);
} else {
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
new file mode 100644
index 0000000..adcd4dc
--- /dev/null
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -0,0 +1,453 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012, Code Aurora Forum. 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
+ *
+ * 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 "hwc_copybit.h"
+#include "hwc_copybitEngine.h"
+
+namespace qhwc {
+
+
+struct range {
+ int current;
+ int end;
+};
+struct region_iterator : public copybit_region_t {
+
+ region_iterator(hwc_region_t region) {
+ mRegion = region;
+ r.end = region.numRects;
+ r.current = 0;
+ this->next = iterate;
+ }
+
+private:
+ static int iterate(copybit_region_t const * self, copybit_rect_t* rect){
+ if (!self || !rect) {
+ ALOGE("iterate invalid parameters");
+ return 0;
+ }
+
+ region_iterator const* me =
+ static_cast<region_iterator const*>(self);
+ if (me->r.current != me->r.end) {
+ rect->l = me->mRegion.rects[me->r.current].left;
+ rect->t = me->mRegion.rects[me->r.current].top;
+ rect->r = me->mRegion.rects[me->r.current].right;
+ rect->b = me->mRegion.rects[me->r.current].bottom;
+ me->r.current++;
+ return 1;
+ }
+ return 0;
+ }
+
+ hwc_region_t mRegion;
+ 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::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;
+ }
+}
+
+bool CopyBit::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) {
+ for (int i=list->numHwLayers-1; i >= 0 ; i--) {
+ private_handle_t *hnd =
+ (private_handle_t *)list->hwLayers[i].handle;
+ if (isSkipLayer(&list->hwLayers[i])) {
+ break;
+ } else if(canUseCopybit(ctx, list, getYuvCount())
+ && !ctx->overlayInUse){
+ list->hwLayers[i].compositionType = HWC_USE_COPYBIT;
+ } else {
+ list->hwLayers[i].compositionType = HWC_FRAMEBUFFER;
+ }
+ }
+ return true;
+}
+bool CopyBit::draw(hwc_context_t *ctx, hwc_layer_list_t *list, EGLDisplay dpy,
+ EGLSurface sur){
+ for (size_t i=0; i<list->numHwLayers; i++) {
+ if (list->hwLayers[i].flags & HWC_SKIP_LAYER) {
+ continue;
+ } else if (list->hwLayers[i].compositionType == HWC_USE_COPYBIT) {
+ drawLayerUsingCopybit(ctx, &(list->hwLayers[i]),
+ (EGLDisplay)dpy,
+ (EGLSurface)sur,
+ LINK_eglGetRenderBufferANDROID,
+ LINK_eglGetCurrentSurface);
+ }
+ }
+ return true;
+}
+
+int CopyBit::drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_t *layer,
+ EGLDisplay dpy,
+ EGLSurface surface,
+ functype_eglGetRenderBufferANDROID& LINK_eglGetRenderBufferANDROID,
+ functype_eglGetCurrentSurface LINK_eglGetCurrentSurface)
+{
+ 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;
+ }
+
+ // 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;
+ if(!fbHandle) {
+ ALOGE("%s: Framebuffer handle is NULL", __FUNCTION__);
+ genlock_unlock_buffer(hnd);
+ return -1;
+ }
+
+ // Set the copybit source:
+ copybit_image_t src;
+ src.w = hnd->width;
+ src.h = hnd->height;
+ src.format = hnd->format;
+ src.base = (void *)hnd->base;
+ src.handle = (native_handle_t *)layer->handle;
+ src.horiz_padding = src.w - hnd->width;
+ // Initialize vertical padding to zero for now,
+ // 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;
+ copybit_rect_t srcRect = {sourceCrop.left, sourceCrop.top,
+ sourceCrop.right,
+ sourceCrop.bottom};
+
+ // Copybit destination rect
+ hwc_rect_t displayFrame = layer->displayFrame;
+ copybit_rect_t dstRect = {displayFrame.left, displayFrame.top,
+ displayFrame.right,
+ displayFrame.bottom};
+
+ // Copybit dst
+ copybit_image_t dst;
+ dst.w = ALIGN(fbHandle->width,32);
+ dst.h = fbHandle->height;
+ dst.format = fbHandle->format;
+ dst.base = (void *)fbHandle->base;
+ dst.handle = (native_handle_t *)renderBuffer->handle;
+
+ copybit_device_t *copybit = ctx->mCopybitEngine->getEngine();
+
+ int32_t screen_w = displayFrame.right - displayFrame.left;
+ int32_t screen_h = displayFrame.bottom - displayFrame.top;
+ int32_t src_crop_width = sourceCrop.right - sourceCrop.left;
+ int32_t src_crop_height = sourceCrop.bottom -sourceCrop.top;
+
+ // Copybit dst
+ float copybitsMaxScale =
+ (float)copybit->get(copybit,COPYBIT_MAGNIFICATION_LIMIT);
+ float copybitsMinScale =
+ (float)copybit->get(copybit,COPYBIT_MINIFICATION_LIMIT);
+
+ if((layer->transform == HWC_TRANSFORM_ROT_90) ||
+ (layer->transform == HWC_TRANSFORM_ROT_270)) {
+ //swap screen width and height
+ int tmp = screen_w;
+ screen_w = screen_h;
+ screen_h = tmp;
+ }
+ private_handle_t *tmpHnd = NULL;
+
+ if(screen_w <=0 || screen_h<=0 ||src_crop_width<=0 || src_crop_height<=0 ) {
+ 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;
+ }
+
+ float dsdx = (float)screen_w/src_crop_width;
+ float dtdy = (float)screen_h/src_crop_height;
+
+ float scaleLimitMax = copybitsMaxScale * copybitsMaxScale;
+ float scaleLimitMin = copybitsMinScale * copybitsMinScale;
+ if(dsdx > scaleLimitMax ||
+ dtdy > scaleLimitMax ||
+ dsdx < 1/scaleLimitMin ||
+ dtdy < 1/scaleLimitMin) {
+ 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 ||
+ dtdy > copybitsMaxScale ||
+ dsdx < 1/copybitsMinScale ||
+ dtdy < 1/copybitsMinScale){
+ // The requested scale is out of the range the hardware
+ // can support.
+ ALOGE("%s:%d::Need to scale twice dsdx=%f, dtdy=%f,copybitsMaxScale=%f,\
+ copybitsMinScale=%f,screen_w=%d,screen_h=%d \
+ src_crop_width=%d src_crop_height=%d",__FUNCTION__,__LINE__,
+ dsdx,dtdy,copybitsMaxScale,1/copybitsMinScale,screen_w,screen_h,
+ src_crop_width,src_crop_height);
+
+ //Driver makes width and height as even
+ //that may cause wrong calculation of the ratio
+ //in display and crop.Hence we make
+ //crop width and height as even.
+ src_crop_width = (src_crop_width/2)*2;
+ src_crop_height = (src_crop_height/2)*2;
+
+ int tmp_w = src_crop_width;
+ int tmp_h = src_crop_height;
+
+ if (dsdx > copybitsMaxScale || dtdy > copybitsMaxScale ){
+ tmp_w = src_crop_width*copybitsMaxScale;
+ tmp_h = src_crop_height*copybitsMaxScale;
+ }else if (dsdx < 1/copybitsMinScale ||dtdy < 1/copybitsMinScale ){
+ tmp_w = src_crop_width/copybitsMinScale;
+ tmp_h = src_crop_height/copybitsMinScale;
+ tmp_w = (tmp_w/2)*2;
+ tmp_h = (tmp_h/2)*2;
+ }
+ ALOGE("%s:%d::tmp_w = %d,tmp_h = %d",__FUNCTION__,__LINE__,tmp_w,tmp_h);
+
+ int usage = GRALLOC_USAGE_PRIVATE_MM_HEAP;
+
+ if (0 == alloc_buffer(&tmpHnd, tmp_w, tmp_h, fbHandle->format, usage)){
+ copybit_image_t tmp_dst;
+ copybit_rect_t tmp_rect;
+ tmp_dst.w = tmp_w;
+ tmp_dst.h = tmp_h;
+ tmp_dst.format = tmpHnd->format;
+ tmp_dst.handle = tmpHnd;
+ tmp_dst.horiz_padding = src.horiz_padding;
+ tmp_dst.vert_padding = src.vert_padding;
+ tmp_rect.l = 0;
+ tmp_rect.t = 0;
+ tmp_rect.r = tmp_dst.w;
+ tmp_rect.b = tmp_dst.h;
+ //create one clip region
+ hwc_rect tmp_hwc_rect = {0,0,tmp_rect.r,tmp_rect.b};
+ hwc_region_t tmp_hwc_reg = {1,(hwc_rect_t const*)&tmp_hwc_rect};
+ region_iterator tmp_it(tmp_hwc_reg);
+ copybit->set_parameter(copybit,COPYBIT_TRANSFORM,0);
+ // TODO : alpha not defined , fix this
+ // copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA,
+ // (layer->blending == HWC_BLENDING_NONE) ? -1 : layer->alpha);
+ err = copybit->stretch(copybit,&tmp_dst, &src, &tmp_rect,
+ &srcRect, &tmp_it);
+ if(err < 0){
+ ALOGE("%s:%d::tmp copybit stretch failed",__FUNCTION__,
+ __LINE__);
+ if(tmpHnd)
+ free_buffer(tmpHnd);
+ genlock_unlock_buffer(hnd);
+ return err;
+ }
+ // copy new src and src rect crop
+ src = tmp_dst;
+ srcRect = tmp_rect;
+ }
+ }
+ // Copybit region
+ hwc_region_t region = layer->visibleRegionScreen;
+ region_iterator copybitRegion(region);
+
+ 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);
+ // TODO : alpha not defined , fix this
+ // copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA,
+ // (layer->blending == HWC_BLENDING_NONE) ? -1 : layer->alpha);
+ copybit->set_parameter(copybit, COPYBIT_PREMULTIPLIED_ALPHA,
+ (layer->blending == HWC_BLENDING_PREMULT)?
+ COPYBIT_ENABLE : COPYBIT_DISABLE);
+ copybit->set_parameter(copybit, COPYBIT_DITHER,
+ (dst.format == HAL_PIXEL_FORMAT_RGB_565)?
+ COPYBIT_ENABLE : COPYBIT_DISABLE);
+ copybit->set_parameter(copybit, COPYBIT_BLIT_TO_FRAMEBUFFER,
+ COPYBIT_ENABLE);
+ err = copybit->stretch(copybit, &dst, &src, &dstRect, &srcRect,
+ ©bitRegion);
+ copybit->set_parameter(copybit, COPYBIT_BLIT_TO_FRAMEBUFFER,
+ COPYBIT_DISABLE);
+
+ if(tmpHnd)
+ free_buffer(tmpHnd);
+
+ 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;
+}
+
+void CopyBit::getLayerResolution(const hwc_layer_t* layer, int& width,
+ int& height)
+{
+ hwc_rect_t displayFrame = layer->displayFrame;
+
+ width = displayFrame.right - displayFrame.left;
+ height = displayFrame.bottom - displayFrame.top;
+}
+
+bool CopyBit::canUseCopybit(hwc_context_t *ctx, const hwc_layer_list_t* list,
+ const int numYUVBuffers)
+{
+ // XXX : TODO , currently returning false for MDP4 targets,
+ // This has to be modified after adding C2D support.
+ if(ctx->hasOverlay)
+ return false;
+
+ framebuffer_device_t* fbDev = ctx->mFbDevice->getFb();
+ if(!fbDev) {
+ ALOGE("ERROR: canUseCopybit : fb device is invalid");
+ return false;
+ }
+
+ if (!list)
+ return false;
+
+ // If , couldnt link to adreno library return false.
+ if(LINK_eglGetRenderBufferANDROID == NULL ||
+ LINK_eglGetCurrentSurface == NULL )
+ return false;
+
+ if(!ctx->hasOverlay) {
+ if (numYUVBuffers)
+ return true;
+ }
+
+ int fb_w = fbDev->width;
+ int fb_h = fbDev->height;
+
+ /*
+ * Use copybit only when we need to blit
+ * max 2 full screen sized regions
+ */
+
+ unsigned int renderArea = 0;
+
+ for(unsigned int i = 0; i < list->numHwLayers; i++ ) {
+ int w, h;
+ getLayerResolution(&list->hwLayers[i], w, h);
+ renderArea += w*h;
+ }
+
+ return (renderArea <= (2 * fb_w * fb_h));
+}
+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);
+}
+
+
+
+//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;
+}
+
+CopybitEngine::CopybitEngine(){
+ hw_module_t const *module;
+ if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
+ copybit_open(module, &sEngine);
+ } else {
+ ALOGE("FATAL ERROR: copybit open failed.");
+ }
+}
+CopybitEngine::~CopybitEngine()
+{
+ if(sEngine)
+ {
+ copybit_close(sEngine);
+ sEngine = NULL;
+ }
+}
+
+}; //namespace qhwc
diff --git a/libhwcomposer/hwc_copybit.h b/libhwcomposer/hwc_copybit.h
new file mode 100644
index 0000000..adf088b
--- /dev/null
+++ b/libhwcomposer/hwc_copybit.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012, Code Aurora Forum. 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
+ *
+ * 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.
+ */
+#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.
+class CopyBit {
+public:
+ //Sets up members and prepares copybit if conditions are met
+ static bool prepare(hwc_context_t *ctx, hwc_layer_list_t *list);
+ //Draws layer if the layer is set for copybit in prepare
+ static bool draw(hwc_context_t *ctx, hwc_layer_list_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_t *layer,
+ EGLDisplay dpy, EGLSurface surface,
+ functype_eglGetRenderBufferANDROID& LINK_eglGetRenderBufferANDROID,
+ functype_eglGetCurrentSurface LINK_eglGetCurrentSurface);
+ static bool canUseCopybit(hwc_context_t* ctx, const hwc_layer_list_t* list,
+ const int numYUVBuffers);
+ static void closeEglLib();
+ static void openEglLibAndGethandle();
+private:
+ //Marks layer flags if this feature is used
+ static void markFlags(hwc_layer_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;
+ //Flags if this feature is on.
+ static bool sIsModeOn;
+ //handle for adreno lib
+ static void* egl_lib;
+
+ static functype_eglGetRenderBufferANDROID LINK_eglGetRenderBufferANDROID;
+ static functype_eglGetCurrentSurface LINK_eglGetCurrentSurface;
+
+ static void getLayerResolution(const hwc_layer_t* layer, int& width,
+ int& height);
+
+};
+
+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_copybitEngine.h b/libhwcomposer/hwc_copybitEngine.h
new file mode 100644
index 0000000..d627e44
--- /dev/null
+++ b/libhwcomposer/hwc_copybitEngine.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012, Code Aurora Forum. 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
+ *
+ * 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.
+ */
+#ifndef HWC_COPYBIT_ENGINE_H
+#define HWC_COPYBIT_ENGINE_H
+
+namespace qhwc {
+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
+};
+
+}; //namespace qhwc
+
+#endif //HWC_COPYBIT_ENGINE_H
diff --git a/libhwcomposer/hwc_uimirror.cpp b/libhwcomposer/hwc_uimirror.cpp
index f5cf3e6..4540be8 100644
--- a/libhwcomposer/hwc_uimirror.cpp
+++ b/libhwcomposer/hwc_uimirror.cpp
@@ -73,11 +73,11 @@
overlay::Overlay& ov = *(ctx->mOverlay);
// Set overlay state
ov.setState(sState);
- framebuffer_device_t *fbDev = ctx->fbDev;
+ framebuffer_device_t *fbDev = ctx->mFbDevice->getFb();
if(fbDev) {
private_module_t* m = reinterpret_cast<private_module_t*>(
fbDev->common.module);
- int alignedW = ALIGN(m->info.xres, 32);
+ int alignedW = ALIGN_TO(m->info.xres, 32);
private_handle_t const* hnd =
reinterpret_cast<private_handle_t const*>(m->framebuffer);
@@ -143,7 +143,7 @@
overlay::Overlay& ov = *(ctx->mOverlay);
ovutils::eOverlayState state = ov.getState();
ovutils::eDest dest = ovutils::OV_PIPE_ALL;
- framebuffer_device_t *fbDev = ctx->fbDev;
+ framebuffer_device_t *fbDev = ctx->mFbDevice->getFb();
if(fbDev) {
private_module_t* m = reinterpret_cast<private_module_t*>(
fbDev->common.module);
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index ea2fe66..ae5c526 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -19,11 +19,11 @@
#include "mdp_version.h"
#include "hwc_video.h"
#include "hwc_ext_observer.h"
+#include "hwc_copybit.h"
namespace qhwc {
void initContext(hwc_context_t *ctx)
{
//XXX: target specific initializations here
- openFramebufferDevice(ctx);
ctx->mOverlay = overlay::Overlay::getInstance();
ctx->qbuf = new QueuedBufferStore();
ctx->mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
@@ -32,6 +32,9 @@
ctx->mExtDisplayObserver = ExtDisplayObserver::getInstance();
ctx->mExtDisplayObserver->setHwcContext(ctx);
+ ctx->mFbDevice = FbDevice::getInstance();
+ ctx->mCopybitEngine = CopybitEngine::getInstance();
+ CopyBit::openEglLibAndGethandle();
}
void closeContext(hwc_context_t *ctx)
@@ -41,23 +44,19 @@
ctx->mOverlay = NULL;
}
- if(ctx->fbDev) {
- framebuffer_close(ctx->fbDev);
- ctx->fbDev = NULL;
+ if(ctx->mCopybitEngine) {
+ delete ctx->mCopybitEngine;
+ ctx->mCopybitEngine = NULL;
}
-
+ if(ctx->mFbDevice) {
+ delete ctx->mFbDevice;
+ ctx->mFbDevice = NULL;
+ }
if(ctx->qbuf) {
delete ctx->qbuf;
ctx->qbuf = NULL;
}
-}
-
-// Opens Framebuffer device
-void openFramebufferDevice(hwc_context_t *ctx) {
- hw_module_t const *module;
- if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
- framebuffer_open(module, &(ctx->fbDev));
- }
+ CopyBit::closeEglLib();
}
void dumpLayer(hwc_layer_t const* l)
@@ -102,6 +101,7 @@
}
VideoOverlay::setStats(yuvCount, yuvLayerIndex, isYuvLayerSkip);
+ CopyBit::setStats(yuvCount, yuvLayerIndex, isYuvLayerSkip);
ctx->numHwLayers = list->numHwLayers;
return;
@@ -163,4 +163,33 @@
}
}
+//FbDevice class functions
+FbDevice* FbDevice::sInstance = 0;;
+struct framebuffer_device_t* FbDevice::getFb() {
+ return sFb;
+}
+
+FbDevice* FbDevice::getInstance() {
+ if(sInstance == NULL)
+ sInstance = new FbDevice();
+ return sInstance;
+}
+
+FbDevice::FbDevice(){
+ hw_module_t const *module;
+ if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
+ framebuffer_open(module, &sFb);
+ } else {
+ ALOGE("FATAL ERROR: framebuffer open failed.");
+ }
+}
+FbDevice::~FbDevice()
+{
+ if(sFb)
+ {
+ framebuffer_close(sFb);
+ sFb = NULL;
+ }
+}
+
};//namespace
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 2ee7188..0bf30c9 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -26,16 +26,33 @@
#include <string.h>
#include <fb_priv.h>
#include <overlay.h>
+#include <copybit.h>
+#include <hwc_copybitEngine.h>
#include <genlock.h>
#include "hwc_qbuf.h"
+#include <EGL/egl.h>
-#define ALIGN(x, align) (((x) + ((align)-1)) & ~((align)-1))
+#define ALIGN_TO(x, align) (((x) + ((align)-1)) & ~((align)-1))
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
+#define FINAL_TRANSFORM_MASK 0x000F
struct hwc_context_t;
namespace qhwc {
+enum external_display_type {
+ EXT_TYPE_NONE,
+ EXT_TYPE_HDMI,
+ EXT_TYPE_WIFI
+};
+enum HWCCompositionType {
+ HWC_USE_GPU = HWC_FRAMEBUFFER, // This layer is to be handled by
+ // Surfaceflinger
+ HWC_USE_OVERLAY = HWC_OVERLAY, // This layer is to be handled by the overlay
+ HWC_USE_COPYBIT // This layer is to be handled by copybit
+};
+
+
class ExtDisplayObserver;
// -----------------------------------------------------------------------------
// Utility functions - implemented in hwc_utils.cpp
@@ -43,7 +60,6 @@
void getLayerStats(hwc_context_t *ctx, const hwc_layer_list_t *list);
void initContext(hwc_context_t *ctx);
void closeContext(hwc_context_t *ctx);
-void openFramebufferDevice(hwc_context_t *ctx);
//Crops source buffer against destination and FB boundaries
void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,
const int fbWidth, const int fbHeight);
@@ -62,6 +78,28 @@
static inline bool isBufferLocked(const private_handle_t* hnd) {
return (hnd && (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags));
}
+// -----------------------------------------------------------------------------
+// Copybit specific - inline or implemented in hwc_copybit.cpp
+typedef EGLClientBuffer (*functype_eglGetRenderBufferANDROID) (
+ EGLDisplay dpy,
+ EGLSurface draw);
+typedef EGLSurface (*functype_eglGetCurrentSurface)(EGLint readdraw);
+
+// -----------------------------------------------------------------------------
+// Singleton for Framebuffer device
+class FbDevice{
+public:
+ ~FbDevice();
+ // API to get Fb device(non static)
+ struct framebuffer_device_t *getFb();
+ // API to get singleton
+ static FbDevice* getInstance();
+
+private:
+ FbDevice();
+ struct framebuffer_device_t *sFb;
+ static FbDevice* sInstance; // singleton
+};
}; //qhwc namespace
@@ -77,7 +115,10 @@
int overlayInUse;
//Framebuffer device
- framebuffer_device_t *fbDev;
+ qhwc::FbDevice* mFbDevice;
+
+ //Copybit Engine
+ qhwc::CopybitEngine* mCopybitEngine;
//Overlay object - NULL for non overlay devices
overlay::Overlay *mOverlay;
diff --git a/libhwcomposer/hwc_video.cpp b/libhwcomposer/hwc_video.cpp
index 525d662..180ab86 100644
--- a/libhwcomposer/hwc_video.cpp
+++ b/libhwcomposer/hwc_video.cpp
@@ -33,6 +33,10 @@
//Cache stats, figure out the state, config overlay
bool VideoOverlay::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) {
sIsModeOn = false;
+ if(!ctx->hasOverlay) {
+ ALOGD_IF(VIDEO_DEBUG,"%s, this hw doesnt support overlay", __FUNCTION__);
+ return false;
+ }
chooseState(ctx);
//if the state chosen above is CLOSED, skip this block.
if(sState != ovutils::OV_CLOSED) {