summaryrefslogtreecommitdiff
authorStark Li <stark.li@amlogic.com>2017-01-12 11:04:26 (GMT)
committer Stark Li <stark.li@amlogic.com>2017-01-13 04:24:52 (GMT)
commit59f63517c6436cff1eecdc523d928165a8522da0 (patch)
tree8ddb8e64e6726f2ad841f71d86c3b42b482c61dc
parentdd2fa4ef3d91ba4e92e13e106d5d14e9f78c5443 (diff)
downloadhwcomposer-59f63517c6436cff1eecdc523d928165a8522da0.zip
hwcomposer-59f63517c6436cff1eecdc523d928165a8522da0.tar.gz
hwcomposer-59f63517c6436cff1eecdc523d928165a8522da0.tar.bz2
PD#138457: add hwc direct & ge2d compose mode.
1. For single layer or signal layer with video overlay layer and cursor layer, we will display the layer buffer to screen directlly. 2. For single layer that can not use direct mode, double layers or double layers with video overlay layer and cursor layer, Enable direct & ge2d compose mode, need: 1) set "TARGET_APP_LAYER_USE_CONTINUOUS_BUFFER := true" in product BoardConfig. 2) gralloc alloc continous buffer. see hardware/amlogic/gralloc. Debug prop "sys.sf.debug.nohwc": set this prop to true, HWC will always use opengl to compose (exclude video layer). Change-Id: I814ceb0ba8d1bf5872725474b3dd140380ef7098
Diffstat
-rw-r--r--hwc2/common/base/HwcFenceControl.cpp214
-rw-r--r--hwc2/common/base/HwcLayer.cpp107
-rw-r--r--hwc2/common/base/HwcLayer.h37
-rw-r--r--hwc2/common/base/HwcModule.cpp15
-rw-r--r--hwc2/common/base/Hwcomposer.cpp27
-rw-r--r--hwc2/common/base/SimpleThread.h15
-rw-r--r--hwc2/common/base/VsyncManager.cpp14
-rw-r--r--hwc2/common/base/VsyncManager.h14
-rw-r--r--hwc2/common/composers/Composers.cpp42
-rw-r--r--hwc2/common/composers/Composers.h45
-rw-r--r--hwc2/common/composers/GE2DComposer.cpp702
-rw-r--r--hwc2/common/composers/GE2DComposer.cpp_632
-rw-r--r--hwc2/common/composers/GE2DComposer.h169
-rw-r--r--hwc2/common/composers/GE2DComposer.h_80
-rw-r--r--hwc2/common/devices/ExternalDevice.cpp14
-rw-r--r--hwc2/common/devices/PhysicalDevice.cpp769
-rw-r--r--hwc2/common/devices/PrimaryDevice.cpp18
-rw-r--r--hwc2/common/devices/VirtualDevice.cpp21
-rw-r--r--hwc2/common/observers/SoftVsyncObserver.cpp14
-rw-r--r--hwc2/common/observers/SoftVsyncObserver.h14
-rw-r--r--hwc2/common/observers/UeventObserver.cpp14
-rw-r--r--hwc2/common/utils/Dump.cpp14
-rw-r--r--hwc2/common/utils/Dump.h15
-rw-r--r--hwc2/common/utils/HwcTrace.h19
-rw-r--r--hwc2/common/utils/Utils.cpp40
-rw-r--r--hwc2/common/utils/Utils.h38
-rw-r--r--hwc2/include/ExternalDevice.h15
-rw-r--r--hwc2/include/HwcFenceControl.h133
-rw-r--r--hwc2/include/Hwcomposer.h15
-rw-r--r--hwc2/include/IComposer.h33
-rw-r--r--hwc2/include/IComposerFactory.h25
-rw-r--r--hwc2/include/IDisplayDevice.h36
-rw-r--r--hwc2/include/IPlatFactory.h15
-rw-r--r--hwc2/include/PhysicalDevice.h100
-rw-r--r--hwc2/include/PrimaryDevice.h21
-rw-r--r--hwc2/include/UeventObserver.h14
-rw-r--r--hwc2/include/VirtualDevice.h15
-rw-r--r--hwc2/platforms/Android.mk20
-rw-r--r--hwc2/platforms/PlatFactory.cpp19
-rw-r--r--hwc2/platforms/PlatFactory.h14
-rw-r--r--hwc2/test/nv12_ved_test.cpp15
41 files changed, 3342 insertions, 251 deletions
diff --git a/hwc2/common/base/HwcFenceControl.cpp b/hwc2/common/base/HwcFenceControl.cpp
new file mode 100644
index 0000000..69cd658
--- a/dev/null
+++ b/hwc2/common/base/HwcFenceControl.cpp
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+
+// We would eliminate the non-conforming zero-length array, but we can't since
+// this is effectively included from the Linux kernel
+#include <sync/sync.h>
+#include <sw_sync.h>
+
+#include <HwcFenceControl.h>
+#include <unistd.h>
+#include <utils/Log.h>
+#include <HwcTrace.h>
+
+namespace android {
+namespace amlogic {
+
+const sp<HwcFenceControl> HwcFenceControl::NO_FENCE = sp<HwcFenceControl>(new HwcFenceControl);
+
+HwcFenceControl::HwcFenceControl() :
+ mFenceFd(-1) {
+}
+
+HwcFenceControl::HwcFenceControl(int32_t fenceFd) :
+ mFenceFd(fenceFd) {
+}
+
+HwcFenceControl::~HwcFenceControl() {
+ if (mFenceFd != -1) {
+ close(mFenceFd);
+ }
+}
+
+int32_t HwcFenceControl::createFenceTimeline() {
+ int32_t syncTimelineFd;
+
+ syncTimelineFd = sw_sync_timeline_create();
+ if (syncTimelineFd < 0) {
+ ETRACE("Stark, can't create sw_sync_timeline:");
+ return -1;
+ }
+
+ return syncTimelineFd;
+}
+
+int32_t HwcFenceControl::createFence(int32_t syncTimelineFd,
+ char* str, uint32_t val) {
+
+ int32_t fenceFd = sw_sync_fence_create(syncTimelineFd, str, val);
+ if (fenceFd < 0) {
+ ETRACE("can't create sync pt %d: %s", val, strerror(errno));
+ return -1;
+ }
+
+ return fenceFd;
+}
+
+status_t HwcFenceControl::syncTimelineInc(int32_t syncTimelineFd) {
+ status_t err;
+
+ err = sw_sync_timeline_inc(syncTimelineFd, 1);
+ if (err < 0) {
+ ETRACE("can't increment sync obj:");
+ return -1;
+ }
+ return err;
+}
+
+status_t HwcFenceControl::traceFenceInfo(int32_t fence) {
+ status_t err;
+ struct sync_fence_info_data *info;
+
+ err = sync_wait(fence, 10000);
+
+ if (err < 0) {
+ ALOGI("wait %d failed: %s\n", fence, strerror(errno));
+ } else {
+ ALOGI("wait %d done\n", fence);
+ }
+ info = sync_fence_info(fence);
+ if (info) {
+ struct sync_pt_info *pt_info = NULL;
+ ALOGI(" fence %s %d\n", info->name, info->status);
+
+ while ((pt_info = sync_pt_info(info, pt_info))) {
+ int ts_sec = pt_info->timestamp_ns / 1000000000LL;
+ int ts_usec = (pt_info->timestamp_ns % 1000000000LL) / 1000LL;
+ ALOGI(" pt %s %s %d %d.%06d", pt_info->obj_name,
+ pt_info->driver_name, pt_info->status,
+ ts_sec, ts_usec);
+ if (!strcmp(pt_info->driver_name, "sw_sync"))
+ ALOGI(" val=%d\n", *(uint32_t *)pt_info->driver_data);
+ else
+ ALOGI("\n");
+ }
+ sync_fence_info_free(info);
+ }
+
+ // closeFd( fence);
+ return err;
+}
+
+status_t HwcFenceControl::wait(int32_t fence, int32_t timeout) {
+ if (fence == -1) {
+ return NO_ERROR;
+ }
+ int32_t err = sync_wait(fence, timeout);
+ return err < 0 ? -errno : status_t(NO_ERROR);
+}
+
+status_t HwcFenceControl::waitForever(const char* logname) {
+ if (mFenceFd == -1) {
+ return NO_ERROR;
+ }
+ int32_t warningTimeout = 3000;
+ int32_t err = sync_wait(mFenceFd, warningTimeout);
+ if (err < 0 && errno == ETIME) {
+ ALOGE("%s: fence %d didn't signal in %u ms", logname, mFenceFd,
+ warningTimeout);
+ err = sync_wait(mFenceFd, TIMEOUT_NEVER);
+ }
+ return err < 0 ? -errno : status_t(NO_ERROR);
+}
+
+int32_t HwcFenceControl::merge(const String8& name, const int32_t& f1,
+ const int32_t& f2) {
+ int32_t result;
+ // Merge the two fences. In the case where one of the fences is not a
+ // valid fence (e.g. NO_FENCE) we merge the one valid fence with itself so
+ // that a new fence with the given name is created.
+ if (f1 != -1 && f2 != -1) {
+ result = sync_merge(name.string(), f1, f2);
+ } else if (f1 != -1) {
+ result = sync_merge(name.string(), f1, f1);
+ } else if (f2 != -1) {
+ result = sync_merge(name.string(), f2, f2);
+ } else {
+ return -1;
+ }
+ if (result == -1) {
+ status_t err = -errno;
+ ETRACE("merge: sync_merge(\"%s\", %d, %d) returned an error: %s (%d)",
+ name.string(), f1, f2,
+ strerror(-err), err);
+ return -1;
+ }
+ return result;
+}
+
+int32_t HwcFenceControl::dup() const {
+ return ::dup(mFenceFd);
+}
+
+int32_t HwcFenceControl::dupFence(int32_t fence) {
+ if (-1 == fence) {
+ DTRACE("acquire fence already been signaled.");
+ return -1;
+ }
+
+ int32_t dupFence = ::dup(fence);
+ if (dupFence < 0) {
+ ETRACE("acquire fence dup failed! please check it immeditely!");
+ }
+
+ return dupFence;
+}
+
+int32_t HwcFenceControl::getFenceFd() const {
+ return mFenceFd;
+}
+
+nsecs_t HwcFenceControl::getSignalTime() const {
+ if (mFenceFd == -1) {
+ return -1;
+ }
+
+ struct sync_fence_info_data* finfo = sync_fence_info(mFenceFd);
+ if (finfo == NULL) {
+ ETRACE("sync_fence_info returned NULL for fd %d", mFenceFd);
+ return -1;
+ }
+ if (finfo->status != 1) {
+ sync_fence_info_free(finfo);
+ return INT64_MAX;
+ }
+
+ struct sync_pt_info* pinfo = NULL;
+ uint64_t timestamp = 0;
+ while ((pinfo = sync_pt_info(finfo, pinfo)) != NULL) {
+ if (pinfo->timestamp_ns > timestamp) {
+ timestamp = pinfo->timestamp_ns;
+ }
+ }
+ sync_fence_info_free(finfo);
+
+ return nsecs_t(timestamp);
+}
+
+} // namespace amlogic
+} // namespace android
diff --git a/hwc2/common/base/HwcLayer.cpp b/hwc2/common/base/HwcLayer.cpp
index 78bca07..98dc63f 100644
--- a/hwc2/common/base/HwcLayer.cpp
+++ b/hwc2/common/base/HwcLayer.cpp
@@ -1,5 +1,17 @@
/*
-// Copyright(c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 <inttypes.h>
@@ -10,7 +22,6 @@
#include <cutils/properties.h>
#include <sync/sync.h>
-#include <Utils.h>
namespace android {
namespace amlogic {
@@ -24,9 +35,27 @@ HwcLayer::HwcLayer(hwc2_display_t& dpy)
mPlaneAlpha(0.0f),
mTransform(HAL_TRANSFORM_RESERVED),
mZ(0),
+ mBufferHnd(NULL),
mInitialized(false)
{
-
+ // initial layer's state.
+ mColor.r = 0;
+ mColor.g = 0;
+ mColor.b = 0;
+ mColor.a = 0;
+
+ mSourceCrop.left = 0.0f;
+ mSourceCrop.top = 0.0f;
+ mSourceCrop.right = 0.0f;
+ mSourceCrop.bottom = 0.0f;
+
+ mDisplayFrame.left = 0;
+ mDisplayFrame.top = 0;
+ mDisplayFrame.right = 0;
+ mDisplayFrame.bottom = 0;
+
+ mDamageRegion.numRects = 0;
+ mVisibleRegion.numRects = 0;
}
HwcLayer::~HwcLayer()
@@ -50,9 +79,73 @@ void HwcLayer::deinitialize() {
void HwcLayer::resetAcquireFence() {
Mutex::Autolock _l(mLock);
+ HwcFenceControl::closeFd(mAcquireFence);
mAcquireFence = -1;
}
+bool HwcLayer::isCropped() {
+ bool rtn = true;
+ private_handle_t const* buffer = reinterpret_cast<private_handle_t const*>(mBufferHnd);
+
+ if (buffer && buffer->width && buffer->height) {
+ float widthCmp = (mSourceCrop.right - mSourceCrop.left) / buffer->width;
+ float heightCmp = (mSourceCrop.bottom - mSourceCrop.top) / buffer->height;
+
+ if (widthCmp == 1.0f && heightCmp == 1.0f)
+ rtn = false;
+ }
+
+ DTRACE("chkIsCropped %d", rtn);
+ return rtn;
+}
+
+bool HwcLayer::isScaled() {
+ bool rtn = true;
+ float sourceWidth = mSourceCrop.right - mSourceCrop.left;
+ float sourceHeight = mSourceCrop.bottom - mSourceCrop.top;
+ int displayWidth = mDisplayFrame.right - mDisplayFrame.left;
+ int displayHeight = mDisplayFrame.bottom - mDisplayFrame.top;
+
+ if (displayWidth > 0 && displayHeight > 0) {
+ float widthCmp = sourceWidth / displayWidth;
+ float heightCmp = sourceHeight / displayHeight;
+
+ if (widthCmp == 1.0f && heightCmp == 1.0f)
+ rtn = false;
+ }
+
+ DTRACE("chkIsScaled %d", rtn);
+ return rtn;
+}
+
+bool HwcLayer::isOffset() {
+ bool rtn = false;
+ if (mDisplayFrame.left != 0 || mDisplayFrame.top != 0)
+ rtn = true;
+
+ DTRACE("chkIsOffset %d", rtn);
+ return rtn;
+}
+
+bool HwcLayer::isBlended() {
+ DTRACE("chkIsBlended %d", mBlendMode);
+ return mBlendMode != HWC2_BLEND_MODE_INVALID;
+}
+
+bool HwcLayer::haveColor() {
+ DTRACE("[%d, %d, %d, %d]", mColor.r, mColor.g, mColor.b, mColor.a);
+ return !(0 == mColor.r && 0 == mColor.g && 0 == mColor.b && 0 == mColor.a);
+}
+
+bool HwcLayer::havePlaneAlpha() {
+ DTRACE("mPlaneAlpha: %d", mPlaneAlpha);
+ return mPlaneAlpha > 0.0f && mPlaneAlpha < 1.0f;
+}
+
+bool HwcLayer::haveDataspace() {
+ DTRACE("mDataSpace: %d", mDataSpace);
+ return mDataSpace != HAL_DATASPACE_UNKNOWN;
+}
int32_t HwcLayer::setBuffer(buffer_handle_t buffer, int32_t acquireFence) {
Mutex::Autolock _l(mLock);
@@ -62,16 +155,10 @@ int32_t HwcLayer::setBuffer(buffer_handle_t buffer, int32_t acquireFence) {
return HWC2_ERROR_BAD_PARAMETER;
if (NULL == buffer) {
- //mBufferHnd = buffer;
- // if (-1 != acquireFence) mAcquireFence = acquireFence;
- //} else {
DTRACE("Layer buffer is null! no need to update this layer.");
}
mBufferHnd = buffer;
mAcquireFence = acquireFence;
- if (mAcquireFence > -1) {
- sync_wait(mAcquireFence, 4000);
- }
return HWC2_ERROR_NONE;
}
@@ -256,7 +343,7 @@ void HwcLayer::dump(Dump& d) {
"SIDEBAND"};
d.append(
- " %11s | %08" PRIxPTR " | %10d | %02x | %1.2f | %02x | %04x |%7.1f,%7.1f,%7.1f,%7.1f |%5d,%5d,%5d,%5d \n",
+ " %11s | %12" PRIxPTR " | %10d | %02x | %1.2f | %02x | %04x |%7.1f,%7.1f,%7.1f,%7.1f |%5d,%5d,%5d,%5d \n",
compositionTypeName[mCompositionType], intptr_t(mBufferHnd),
mZ, mDataSpace, mPlaneAlpha, mTransform, mBlendMode,
mSourceCrop.left, mSourceCrop.top, mSourceCrop.right, mSourceCrop.bottom,
diff --git a/hwc2/common/base/HwcLayer.h b/hwc2/common/base/HwcLayer.h
index 50c6d35..7af99b2 100644
--- a/hwc2/common/base/HwcLayer.h
+++ b/hwc2/common/base/HwcLayer.h
@@ -1,6 +1,19 @@
/*
-// Copyright(c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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_LAYER_H
#define HWC_LAYER_H
@@ -8,7 +21,8 @@
#include <utils/threads.h>
#include <Dump.h>
#include <utils/Vector.h>
-
+#include <Utils.h>
+#include <HwcFenceControl.h>
namespace android {
namespace amlogic {
@@ -38,9 +52,20 @@ class HwcLayer {
int32_t setCompositionType(int32_t type);
int32_t getCompositionType() const { return mCompositionType; }
+ // get HWC2 Layer state functions
buffer_handle_t getBufferHandle() const { return mBufferHnd; }
const native_handle_t* getSidebandStream() const { return mSidebandStream; }
int32_t getAcquireFence() const { return mAcquireFence; }
+ int32_t getDuppedAcquireFence() { return HwcFenceControl::dupFence(mAcquireFence); }
+ hwc_region_t getSurfaceDamage() { return mDamageRegion; };
+ int32_t getBlendMode() { return mBlendMode; };
+ hwc_color_t getColor() { return mColor; };
+ int32_t getDataspace() { return mDataSpace; };
+ hwc_rect_t getDisplayFrame() { return mDisplayFrame;};
+ float getPlaneAlpha() { return mPlaneAlpha; };
+ hwc_frect_t getSourceCrop() { return mSourceCrop; };
+ int32_t getTransform() { return mTransform; };
+ hwc_region_t getVisibleRegion() { return mVisibleRegion; };
bool initialize();
void deinitialize();
@@ -48,6 +73,14 @@ class HwcLayer {
void resetAcquireFence();
+ bool isCropped();
+ bool isScaled();
+ bool isOffset();
+ bool isBlended();
+ bool haveColor();
+ bool havePlaneAlpha();
+ bool haveDataspace();
+
#if WITH_LIBPLAYER_MODULE
void presentOverlay();
#endif
diff --git a/hwc2/common/base/HwcModule.cpp b/hwc2/common/base/HwcModule.cpp
index e48f6ee..4c7991a 100644
--- a/hwc2/common/base/HwcModule.cpp
+++ b/hwc2/common/base/HwcModule.cpp
@@ -1,6 +1,19 @@
/*
-// Copyright(c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 <hardware/hardware.h>
#include <string.h>
#include <stdio.h>
diff --git a/hwc2/common/base/Hwcomposer.cpp b/hwc2/common/base/Hwcomposer.cpp
index 65040d3..687c9f2 100644
--- a/hwc2/common/base/Hwcomposer.cpp
+++ b/hwc2/common/base/Hwcomposer.cpp
@@ -1,10 +1,24 @@
/*
-// Copyright(c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 <HwcTrace.h>
#include <Hwcomposer.h>
#include <Dump.h>
#include <UeventObserver.h>
+#include <inttypes.h>
namespace android {
namespace amlogic {
@@ -405,7 +419,8 @@ int32_t Hwcomposer::setClientTarget(
int32_t acquireFence,
int32_t /*android_dataspace_t*/ dataspace,
hwc_region_t damage) {
- DTRACE("setClientTarget disp = %d", (int32_t)display);
+ DTRACE("setClientTarget disp = %d, targetHnd = %" PRIxPTR ","
+ "acquireFence = %d, dataspace = %d", (int32_t)display, target, acquireFence, dataspace);
IDisplayDevice *device = getDisplayDevice((int32_t)display);
if (!device) {
@@ -420,7 +435,7 @@ int32_t Hwcomposer::setClientTarget(
int32_t Hwcomposer::setColorMode(
hwc2_display_t display,
int32_t /*android_color_mode_t*/ mode) {
- DTRACE("setColorMode disp = %d", (int32_t)display);
+ DTRACE("setColorMode disp = %d, mode = %d", (int32_t)display, mode);
IDisplayDevice *device = getDisplayDevice((int32_t)display);
if (!device) {
@@ -435,7 +450,7 @@ int32_t Hwcomposer::setColorTransform(
hwc2_display_t display,
const float* matrix,
int32_t /*android_color_transform_t*/ hint) {
- DTRACE("setColorTransform disp = %d", (int32_t)display);
+ DTRACE("setColorTransform disp = %d, hint = %d", (int32_t)display, hint);
IDisplayDevice *device = getDisplayDevice((int32_t)display);
if (!device) {
@@ -450,7 +465,7 @@ int32_t Hwcomposer::setOutputBuffer(
hwc2_display_t display,
buffer_handle_t buffer,
int32_t releaseFence) {
- DTRACE("setOutputBuffer disp = %d", (int32_t)display);
+ DTRACE("setOutputBuffer disp = %d, releaseFence = %d", (int32_t)display, releaseFence);
if (display != HWC_DISPLAY_VIRTUAL) {
ETRACE("Should be a virtual display: %d", (int32_t)display);
return HWC2_ERROR_UNSUPPORTED;
@@ -468,7 +483,7 @@ int32_t Hwcomposer::setOutputBuffer(
int32_t Hwcomposer::setPowerMode(
hwc2_display_t display,
int32_t /*hwc2_power_mode_t*/ mode) {
- DTRACE("setPowerMode disp = %d", (int32_t)display);
+ DTRACE("setPowerMode disp = %d, mode = %d", (int32_t)display, mode);
IDisplayDevice *device = getDisplayDevice((int32_t)display);
if (!device) {
diff --git a/hwc2/common/base/SimpleThread.h b/hwc2/common/base/SimpleThread.h
index 8842c21..7cf51cf 100644
--- a/hwc2/common/base/SimpleThread.h
+++ b/hwc2/common/base/SimpleThread.h
@@ -1,6 +1,19 @@
/*
-// Copyright(c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 SIMPLE_THREAD_H
#define SIMPLE_THREAD_H
diff --git a/hwc2/common/base/VsyncManager.cpp b/hwc2/common/base/VsyncManager.cpp
index 22e896b..13b705e 100644
--- a/hwc2/common/base/VsyncManager.cpp
+++ b/hwc2/common/base/VsyncManager.cpp
@@ -1,5 +1,17 @@
/*
-// Copyright(c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 <HwcTrace.h>
diff --git a/hwc2/common/base/VsyncManager.h b/hwc2/common/base/VsyncManager.h
index 6c5dfe1..3ad81c6 100644
--- a/hwc2/common/base/VsyncManager.h
+++ b/hwc2/common/base/VsyncManager.h
@@ -1,5 +1,17 @@
/*
-// Copyright(c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 VSYNC_MANAGER_H
diff --git a/hwc2/common/composers/Composers.cpp b/hwc2/common/composers/Composers.cpp
new file mode 100644
index 0000000..093386c
--- a/dev/null
+++ b/hwc2/common/composers/Composers.cpp
@@ -0,0 +1,42 @@
+/*
+// Copyright(c) 2016 Amlogic Corporation
+*/
+
+#include <HwcTrace.h>
+#include <Composers.h>
+#include <IDisplayDevice.h>
+
+
+namespace android {
+namespace amlogic {
+
+Composers::Composers(IDisplayDevice& disp)
+ : mDisplayDevice(disp),
+ mInitialized(false)
+{
+}
+
+Composers::~Composers()
+{
+ WARN_IF_NOT_DEINIT();
+}
+
+bool Composers::initialize(framebuffer_info_t* fbInfo)
+{
+ if (mInitialized) {
+ WTRACE("object has been initialized");
+ return true;
+ }
+
+ mInitialized = true;
+ return true;
+}
+
+void Composers::deinitialize()
+{
+ mInitialized = false;
+}
+
+} // namespace amlogic
+} // namesapce android
+
diff --git a/hwc2/common/composers/Composers.h b/hwc2/common/composers/Composers.h
new file mode 100644
index 0000000..ae48eee
--- a/dev/null
+++ b/hwc2/common/composers/Composers.h
@@ -0,0 +1,45 @@
+/*
+// Copyright(c) 2016 Amlogic Corporation
+*/
+
+#ifndef COMPOSERS_H
+#define COMPOSERS_H
+
+#include <IComposer.h>
+
+namespace android {
+namespace amlogic {
+
+// class IComposer;
+class IDisplayDevice;
+
+class Composers :public IComposer {
+public:
+ Composers(IDisplayDevice& disp);
+ virtual ~Composers();
+
+public:
+
+ virtual bool initialize(framebuffer_info_t* fbInfo);
+ virtual void deinitialize();
+ virtual int32_t startCompose(Vector< hwc2_layer_t > hwcLayers, int32_t *offset = 0, int32_t frameCount = 0) = 0;
+ virtual const char* getName() const = 0;
+ // virtual void setCurGlesFbSlot(uint32_t slot) = 0;
+ virtual const buffer_handle_t getBufHnd() = 0;
+ virtual void mergeRetireFence(int32_t slot, int32_t retireFence) = 0;
+ virtual void removeRetireFence(int32_t slot) = 0;
+ virtual void setVideoOverlayLayerId(hwc2_layer_t layerId) = 0;
+ virtual void fillRectangle(hwc_rect_t clipRect, uint32_t color, uint32_t addr) = 0;
+
+private:
+ IDisplayDevice& mDisplayDevice;
+
+ bool mInitialized;
+};
+
+} // namespace amlogic
+} // namespace android
+
+
+#endif /* COMPOSERS_H */
+
diff --git a/hwc2/common/composers/GE2DComposer.cpp b/hwc2/common/composers/GE2DComposer.cpp
new file mode 100644
index 0000000..9611989
--- a/dev/null
+++ b/hwc2/common/composers/GE2DComposer.cpp
@@ -0,0 +1,702 @@
+/*
+// Copyright(c) 2016 Amlogic Corporation
+*/
+#include <HwcTrace.h>
+#include <HwcFenceControl.h>
+#include <GE2DComposer.h>
+#include <inttypes.h>
+#include <linux/ion.h>
+#include <ion/ion.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+
+namespace android {
+namespace amlogic {
+
+GE2DComposer::GE2DComposer(IDisplayDevice& disp)
+ : Composers(disp),
+ mDisplayDevice(disp),
+ mLock(),
+ mSyncTimelineFd(-1),
+ mCondition(),
+ mQueueItems(),
+ mQueuedFrames(0),
+ mBufferMask(0),
+ mNumBuffers(1),
+ mFbSlot(0),
+ mCurGlesFbSlot(-1),
+ mSingleFbSize(0),
+ mGe2dBufHnd(NULL),
+ mBasePhyAddr(0),
+ mGe2dFd(-1),
+ mVideoLayerId(0),
+ mSrcBufferInfo(NULL),
+ mDebug(false),
+ mExitThread(false),
+ mInitialized(false)
+{
+ mName = "GE2D";
+
+ mQueueItems.setCapacity(8);
+ mQueueItems.clear();
+}
+
+GE2DComposer::~GE2DComposer()
+{
+ WARN_IF_NOT_DEINIT();
+}
+
+int32_t GE2DComposer::allocBuffer(private_module_t* module, size_t size, int32_t usage, buffer_handle_t* pHandle)
+{
+ ion_user_handle_t ion_hnd;
+ unsigned char *cpu_ptr = NULL;
+ int32_t shared_fd;
+ int32_t ret;
+ int32_t ion_flags = 0;
+ int32_t lock_state = 0;
+
+ if (usage & GRALLOC_USAGE_AML_DMA_BUFFER)
+ {
+ ret = ion_alloc(module->ion_client, size, 0, ION_HEAP_CARVEOUT_MASK,
+ ion_flags, &ion_hnd);
+ }
+
+ if ( ret != 0)
+ {
+ ETRACE("Failed to ion_alloc from ion_client:%d", module->ion_client);
+ return -1;
+ }
+
+ ret = ion_share( module->ion_client, ion_hnd, &shared_fd );
+ if ( ret != 0 )
+ {
+ ETRACE( "ion_share( %d ) failed", module->ion_client );
+ if ( 0 != ion_free( module->ion_client, ion_hnd ) )
+ ETRACE( "ion_free( %d ) failed", module->ion_client );
+ return -1;
+ }
+
+ if (!(usage & GRALLOC_USAGE_PROTECTED))
+ {
+ cpu_ptr = (unsigned char*)mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shared_fd, 0 );
+
+ if ( MAP_FAILED == cpu_ptr )
+ {
+ ETRACE( "ion_map( %d ) failed", module->ion_client );
+ if ( 0 != ion_free( module->ion_client, ion_hnd ) )
+ ETRACE( "ion_free( %d ) failed", module->ion_client );
+ close( shared_fd );
+ return -1;
+ }
+ lock_state = private_handle_t::LOCK_STATE_MAPPED;
+ }
+
+ private_handle_t *hnd = new private_handle_t( private_handle_t::PRIV_FLAGS_USES_ION /*TODO ion extend*| priv_heap_flag*/,
+ usage, size, cpu_ptr, lock_state );
+
+ if ( NULL != hnd )
+ {
+ hnd->share_fd = shared_fd;
+ hnd->ion_hnd = ion_hnd;
+ /*TODO ion extend hnd->min_pgsz = min_pgsz; */
+ *pHandle = hnd;
+ return 0;
+ }
+ else
+ {
+ ETRACE( "Gralloc out of mem for ion_client:%d", module->ion_client );
+ }
+
+ close( shared_fd );
+
+ if (!(usage & GRALLOC_USAGE_PROTECTED))
+ {
+ ret = munmap( cpu_ptr, size );
+ if ( 0 != ret )
+ ETRACE( "munmap failed for base:%p size: %zd", cpu_ptr, size );
+ }
+
+ ret = ion_free( module->ion_client, ion_hnd );
+ if ( 0 != ret )
+ ETRACE( "ion_free( %d ) failed", module->ion_client );
+ return -1;
+}
+
+void GE2DComposer::freeBuffer(private_handle_t const* hnd, private_module_t* m)
+{
+ if ( hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION )
+ {
+ /* Buffer might be unregistered already so we need to assure we have a valid handle*/
+ if ( 0 != hnd->base )
+ {
+ if ( 0 != munmap( (void*)hnd->base, hnd->size ) ) ETRACE( "Failed to munmap handle %p", hnd );
+ }
+ close( hnd->share_fd );
+ if ( 0 != ion_free( m->ion_client, hnd->ion_hnd ) ) ETRACE( "Failed to ion_free( ion_client: %d ion_hnd: %p )", m->ion_client, hnd->ion_hnd );
+ memset( (void*)hnd, 0, sizeof( *hnd ) );
+ }
+}
+
+bool GE2DComposer::initialize(framebuffer_info_t* fbInfo)
+{
+ Mutex::Autolock _l(mLock);
+
+ if (mInitialized) {
+ WTRACE("object has been initialized");
+ return true;
+ }
+
+ // create a release fence timeline.
+ mSyncTimelineFd = HwcFenceControl::createFenceTimeline();
+ if (mSyncTimelineFd == -1) {
+ DEINIT_AND_RETURN_FALSE("sync timeline create failed!");
+ }
+ mCurrentSyncTime = 1;
+
+ // create ge2d composer thread.
+ mExitThread = false;
+ mThread = new GE2DRenderThread(this);
+ if (!mThread.get()) {
+ DEINIT_AND_RETURN_FALSE("failed to create ge2d composer thread.");
+ }
+ mThread->run("GE2DComposer", PRIORITY_URGENT_DISPLAY);
+
+ // framebuffer stuff.
+ mFbInfo = fbInfo;
+ mSingleFbSize = fbInfo->finfo.line_length * fbInfo->info.yres;
+ mNumBuffers = fbInfo->fbSize / mSingleFbSize;
+
+ if (!mGe2dBufHnd) {
+ int32_t usage = GRALLOC_USAGE_AML_DMA_BUFFER;
+ int32_t ret = allocBuffer(mFbInfo->grallocModule, mFbInfo->fbSize, usage, &mGe2dBufHnd);
+ if (ret < 0) {
+ ETRACE("allocBuffer failed!");
+ return false;
+ }
+ mBasePhyAddr = getIonPhyAddr(mFbInfo, mGe2dBufHnd);
+ } else {
+ DTRACE("Buffer alloced already.");
+ }
+
+ // ge2d info.
+ mSrcBufferInfo = new aml_ge2d_info_t();
+
+ // ge2d init.
+ mGe2dFd = ge2d_open();
+ mInitialized = true;
+ return true;
+}
+
+void GE2DComposer::deinitialize()
+{
+ mExitThread = true;
+ mCondition.signal();
+
+ if (mThread.get()) {
+ mThread->requestExitAndWait();
+ mThread = NULL;
+ }
+
+ if (mSrcBufferInfo) {
+ delete mSrcBufferInfo;
+ mSrcBufferInfo = NULL;
+ }
+
+ private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(mGe2dBufHnd);
+ if (NULL != hnd) {
+ freeBuffer(hnd, mFbInfo->grallocModule);
+ mGe2dBufHnd = NULL;
+ }
+
+ // ge2d exit.
+ ge2d_close(mGe2dFd);
+ mInitialized = false;
+}
+
+const char* GE2DComposer::getName() const
+{
+ return mName;
+}
+
+const buffer_handle_t GE2DComposer::getBufHnd()
+{
+ Mutex::Autolock _l(mLock);
+
+ return mGe2dBufHnd;
+}
+
+/* void GE2DComposer::setCurGlesFbSlot(uint32_t slot)
+{
+ Mutex::Autolock _l(mLock);
+
+ mCurGlesFbSlot = slot;
+}*/
+
+void GE2DComposer::mergeRetireFence(int32_t slot, int32_t retireFence)
+{
+ Mutex::Autolock _l(mLock);
+ DTRACE("slot:%d, retireFence: %d", slot, retireFence);
+
+ int32_t index = slot / mFbInfo->info.yres;
+ mSlots[index].mSlot = slot;
+ int32_t tempFence = HwcFenceControl::merge(String8("retire_fences"), mSlots[index].mFence, retireFence);
+ HwcFenceControl::closeFd(retireFence);
+ HwcFenceControl::closeFd(mSlots[index].mFence);
+ mSlots[index].mFence = tempFence;
+}
+
+void GE2DComposer::removeRetireFence(int32_t slot)
+{
+ Mutex::Autolock _l(mLock);
+ DTRACE("slot:%d", slot);
+
+ int32_t index = slot / mFbInfo->info.yres;
+ // mSlots[index].mSlot = 0;
+ HwcFenceControl::closeFd(mSlots[index].mFence);
+ mSlots[index].mFence = -1;
+}
+
+void GE2DComposer::setVideoOverlayLayerId(hwc2_layer_t layerId)
+{
+ Mutex::Autolock _l(mLock);
+ DTRACE("layerId:%d", layerId);
+
+ mVideoLayerId = layerId;
+}
+
+uint32_t GE2DComposer::findFreeFbSlot()
+{
+ int32_t fbSlot = 0;
+
+ if (mNumBuffers == 1) {
+ // If we have only one buffer, we never use page-flipping.
+ return 0;
+ }
+
+ if (mBufferMask >= ((1LU<<mNumBuffers)-1)) {
+ // We ran out of buffers. reinit to 0;
+ mBufferMask = 0x1;
+ return 0;
+ }
+
+ // find a free slot
+ for (uint32_t i=0 ; i<mNumBuffers ; i++) {
+ if ((mBufferMask & (1LU<<i)) == 0) {
+ mBufferMask |= (1LU<<i);
+ break;
+ }
+
+ fbSlot += mFbInfo->info.yres;
+ }
+
+ return fbSlot;
+}
+
+int32_t GE2DComposer::startCompose(
+ Vector< hwc2_layer_t > hwcLayers,
+ int32_t *offset, int32_t frameCount)
+{
+ Mutex::Autolock _l(mLock);
+
+ // find a free slot of fb.
+ *offset = mFbSlot = findFreeFbSlot();
+
+ { // clear display region.
+ hwc_rect_t clipRect;
+
+ HwcLayer* videoLayer = mDisplayDevice.getLayerById(mVideoLayerId);
+ uint32_t addr = mBasePhyAddr + mFbSlot * mFbInfo->finfo.line_length;
+ if (videoLayer) {
+ clipRect = videoLayer->getDisplayFrame();
+ fillRectangle(clipRect, 0, addr);
+ mVideoLayerId = 0;
+ }
+
+ if (frameCount < 3) {
+ clipRect.left = 0;
+ clipRect.top = 0;
+ clipRect.right = mFbInfo->info.xres;
+ clipRect.bottom = mFbInfo->info.yres;
+ fillRectangle(clipRect, 0, addr);
+ }
+ }
+
+ // add hwcLayers to work queue.
+ int32_t index = mFbSlot / mFbInfo->info.yres;
+ mSlots[index].mSlot = mFbSlot;
+ mSlots[index].mLayersState.clear();
+ for (uint32_t i=0; i<hwcLayers.size(); i++) {
+ hwc2_layer_t layerId = hwcLayers.itemAt(i);
+ HwcLayer* hwcLayer = mDisplayDevice.getLayerById(layerId);
+ if (NULL != hwcLayer) {
+ // Merge layers's fences and prior retire fence.
+ int32_t fence = hwcLayer->getDuppedAcquireFence();
+ int32_t tempFence = HwcFenceControl::merge(String8("layers"), fence, mSlots[index].mFence);
+ HwcFenceControl::closeFd(mSlots[index].mFence);
+ HwcFenceControl::closeFd(fence);
+ mSlots[index].mFence = tempFence;
+
+ // push layers state to mQueueItems.
+ LayerState* layerState = new LayerState();
+ layerState->setLayerState(hwcLayer);
+ mSlots[index].mLayersState.push_back(layerState);
+ }
+ }
+ // mSlots[index].mLayersState = layersState;
+ android_atomic_inc(&mQueuedFrames);
+ mQueueItems.push_back(mSlots[index]);
+ mSlots[index].mFence = -1;
+
+ int32_t ge2dFence = HwcFenceControl::createFence(mSyncTimelineFd, "ge2d_flag_fence", mCurrentSyncTime++);
+
+ mCondition.signal();
+ return ge2dFence;
+}
+
+void GE2DComposer::fillRectangle(hwc_rect_t clipRect, uint32_t color, uint32_t addr)
+{
+ mSrcBufferInfo->src_info[0].paddr = addr;
+ mSrcBufferInfo->src_info[0].format = HAL_PIXEL_FORMAT_RGBA_8888;
+ mSrcBufferInfo->src_info[0].rect.x = clipRect.left;
+ mSrcBufferInfo->src_info[0].rect.y = clipRect.top;
+ mSrcBufferInfo->src_info[0].rect.w = clipRect.right - clipRect.left;
+ mSrcBufferInfo->src_info[0].rect.h = clipRect.bottom - clipRect.top;
+ mSrcBufferInfo->src_info[0].canvas_w = clipRect.right - clipRect.left;
+ mSrcBufferInfo->src_info[0].canvas_h = clipRect.bottom - clipRect.top;
+ mSrcBufferInfo->src_info[0].memtype = CANVAS_ALLOC;
+
+ mSrcBufferInfo->dst_info.paddr = addr;
+ mSrcBufferInfo->dst_info.format = HAL_PIXEL_FORMAT_RGBA_8888;
+ mSrcBufferInfo->color = color;
+ mSrcBufferInfo->offset = 0;
+ mSrcBufferInfo->dst_info.rect.x = clipRect.left;
+ mSrcBufferInfo->dst_info.rect.y = clipRect.top;
+ mSrcBufferInfo->dst_info.rect.w = clipRect.right - clipRect.left;
+ mSrcBufferInfo->dst_info.rect.h = clipRect.bottom - clipRect.top;
+ mSrcBufferInfo->dst_info.canvas_w = clipRect.right - clipRect.left;
+ mSrcBufferInfo->dst_info.canvas_h = clipRect.bottom - clipRect.top;
+ mSrcBufferInfo->dst_info.memtype = CANVAS_ALLOC;
+ mSrcBufferInfo->ge2d_op = AML_GE2D_FILLRECTANGLE;
+ ge2d_process(mGe2dFd, mSrcBufferInfo);
+}
+
+bool GE2DComposer::isFullScreen(
+ hwc_rect_t displayFrame)
+{
+ if (displayFrame.left == 0
+ && displayFrame.top == 0
+ && displayFrame.right == mFbInfo->info.xres
+ && displayFrame.bottom == mFbInfo->info.yres) {
+ return true;
+ }
+
+ return false;
+}
+
+void GE2DComposer::tracer()
+{
+ static char const* ge2dOp[] = {
+ "AML_GE2D_FILLRECTANGLE",
+ "AML_GE2D_BLEND",
+ "AML_GE2D_STRETCHBLIT",
+ "AML_GE2D_BLIT",
+ "AML_GE2D_NONE"};
+
+ static char const* memType[] = {
+ "CANVAS_OSD0",
+ "CANVAS_OSD1",
+ "CANVAS_ALLOC",
+ "CANVAS_INVALID"};
+ ALOGE(" OP: %22s", ge2dOp[mSrcBufferInfo->ge2d_op]);
+ ALOGE(
+ " addr | memtype | canvas size | fmt | tr | blnd |"
+ " source crop (x,y,w,h) |\n"
+ " --------------+-----------------+-------------+-----+----+------|"
+ "--------------------------------+\n");
+ ALOGE(
+ " SRC0:\n"
+ " %12x | %15s | %5dx%5d | %03x | %02s | %04s |%5d,%5d,%5d,%5d \n",
+ mSrcBufferInfo->src_info[0].paddr, memType[mSrcBufferInfo->src_info[0].memtype],
+ mSrcBufferInfo->src_info[0].canvas_w, mSrcBufferInfo->src_info[0].canvas_h, mSrcBufferInfo->src_info[0].format,
+ "no", " no", mSrcBufferInfo->src_info[0].rect.x, mSrcBufferInfo->src_info[0].rect.y,
+ mSrcBufferInfo->src_info[0].rect.w, mSrcBufferInfo->src_info[0].rect.h);
+ ALOGE(
+ " SRC1:\n"
+ " %12x | %15s | %5dx%5d | %03x | %02s | %04s |%5d,%5d,%5d,%5d \n",
+ mSrcBufferInfo->src_info[1].paddr, memType[mSrcBufferInfo->src_info[1].memtype],
+ mSrcBufferInfo->src_info[1].canvas_w, mSrcBufferInfo->src_info[1].canvas_h, mSrcBufferInfo->src_info[1].format,
+ "no", " no", mSrcBufferInfo->src_info[1].rect.x, mSrcBufferInfo->src_info[1].rect.y,
+ mSrcBufferInfo->src_info[1].rect.w, mSrcBufferInfo->src_info[1].rect.h);
+ ALOGE(
+ " DST:\n"
+ " %12x | %15s | %5dx%5d | %03x | %02x | %04x |%5d,%5d,%5d,%5d \n",
+ mSrcBufferInfo->dst_info.paddr, memType[mSrcBufferInfo->dst_info.memtype],
+ mSrcBufferInfo->dst_info.canvas_w, mSrcBufferInfo->dst_info.canvas_h, mSrcBufferInfo->dst_info.format,
+ mSrcBufferInfo->dst_info.rotation, mSrcBufferInfo->blend_mode,
+ mSrcBufferInfo->dst_info.rect.x, mSrcBufferInfo->dst_info.rect.y,
+ mSrcBufferInfo->dst_info.rect.w, mSrcBufferInfo->dst_info.rect.h);
+ ALOGE(
+ " --------------+-----------------+-------------+-----+----+------|"
+ "--------------------------------+\n\n");
+}
+
+void GE2DComposer::dumpLayers(
+ private_handle_t const* hnd)
+{
+ void *layerBuffer = NULL;
+
+ layerBuffer = mmap(NULL, hnd->size, PROT_READ|PROT_WRITE, MAP_SHARED, hnd->share_fd, 0);
+ if (layerBuffer != MAP_FAILED) {
+#if 1
+ int32_t base = 4 * (hnd->stride * (hnd->height / 2) + 10);
+ char* tmp = (char*)layerBuffer + base;
+ ALOGD("[0x%x, 0x%x, 0x%x, 0x%x]\n"
+ "[0x%x, 0x%x, 0x%x, 0x%x]\n"
+ "[0x%x, 0x%x, 0x%x, 0x%x]\n"
+ "[0x%x, 0x%x, 0x%x, 0x%x]\n",
+ tmp[0], tmp[1], tmp[2], tmp[3],
+ tmp[4], tmp[5], tmp[6], tmp[7],
+ tmp[8], tmp[9], tmp[10], tmp[11],
+ tmp[12], tmp[13], tmp[14], tmp[15]);
+#else
+ int fd;
+ char path[128];
+
+ sprintf(path, "/data/local/tmp/layer_%" PRId64 ".bin", systemTime(SYSTEM_TIME_MONOTONIC));
+ fd = open(path, O_RDWR | O_CREAT);
+ if (-1 == fd) {
+ ALOGE("Stark, open file failed!");
+ return;
+ }
+ write(fd, layerBuffer, hnd->size);
+ sync();
+ close(fd);
+#endif
+ munmap(layerBuffer, hnd->size);
+ ALOGD("dumpLayer ok");
+ } else {
+ ALOGE("layerBuffer mmap fail");
+ }
+}
+
+void GE2DComposer::runGE2DProcess(int32_t slot, Vector< LayerState* > &hwcLayersState)
+{
+ bool sameSize = false;
+ hwc_frect_t sourceCrop[GE2D_COMPOSE_MAX_LAYERS];
+ const LayerState* layer[GE2D_COMPOSE_MAX_LAYERS] = { NULL, NULL, NULL };
+ private_handle_t const* hnd[GE2D_COMPOSE_MAX_LAYERS] = { NULL, NULL, NULL };
+ uint32_t layerNum = hwcLayersState.size();
+ hwc_rect_t displayFrame[GE2D_COMPOSE_MAX_LAYERS];
+
+ for (int32_t i=0; i<layerNum; i++) {
+ layer[i] = hwcLayersState.itemAt(i);
+ sourceCrop[i] = layer[i]->mSourceCrop;
+ displayFrame[i] = layer[i]->mDisplayFrame;
+ hnd[i] = reinterpret_cast<private_handle_t const*>(layer[i]->mBufferHnd);
+ ALOGD("layer[%d] zorder: %d, blend: %d, PlaneAlpha: %f, "
+ "mColor: [%d, %d, %d, %d], mDataSpace: %d, format hnd[%d]: %x",
+ i, layer[i]->mZ, layer[i]->mBlendMode, layer[i]->mPlaneAlpha,
+ layer[i]->mColor.r, layer[i]->mColor.g, layer[i]->mColor.b,
+ layer[i]->mColor.a, layer[i]->mDataSpace, i, hnd[i]->format);
+ }
+
+#if 1 // TODO:2 same size layers case.
+ if (layerNum > GE2D_COMPOSE_ONE_LAYER) {
+ if (Utils::compareRect(sourceCrop[0], sourceCrop[1])
+ && Utils::compareRect(sourceCrop[0], displayFrame[0])
+ && Utils::compareRect(sourceCrop[1], displayFrame[1])) {
+ sameSize = true;
+ // swap layers and hnds.
+ Utils::swap(layer[0], layer[1]);
+ Utils::swap(hnd[0], hnd[1]);
+ }
+ }
+#endif
+
+ if ((layerNum == GE2D_COMPOSE_TWO_LAYERS && !hnd[1])
+ || (layerNum == GE2D_COMPOSE_MAX_LAYERS && (!hnd[1] || !hnd[2]))) {
+ ETRACE("%d layers compose, hnd should not be null", layerNum);
+ return;
+ }
+
+ mSrcBufferInfo->offset = 0;
+ if (sameSize) {
+ for (int32_t i=0; i<GE2D_COMPOSE_TWO_LAYERS; i++) {
+ mSrcBufferInfo->src_info[i].paddr = getIonPhyAddr(mFbInfo, hnd[i]);
+ mSrcBufferInfo->src_info[i].format = hnd[i]->format;
+ mSrcBufferInfo->src_info[i].rect.x = (int32_t)sourceCrop[i].left;
+ mSrcBufferInfo->src_info[i].rect.y = (int32_t)sourceCrop[i].top;
+ mSrcBufferInfo->src_info[i].rect.w = (int32_t)(sourceCrop[i].right - sourceCrop[i].left);
+ mSrcBufferInfo->src_info[i].rect.h = (int32_t)(sourceCrop[i].bottom- sourceCrop[i].top);
+ mSrcBufferInfo->src_info[i].canvas_w = hnd[i]->stride;
+ mSrcBufferInfo->src_info[i].canvas_h = hnd[i]->height;
+ mSrcBufferInfo->src_info[i].memtype = CANVAS_ALLOC;
+ }
+
+ mSrcBufferInfo->blend_mode = layer[0]->mBlendMode;
+
+ mSrcBufferInfo->dst_info.paddr = mBasePhyAddr + slot * mFbInfo->finfo.line_length;
+ mSrcBufferInfo->dst_info.format = HAL_PIXEL_FORMAT_RGBA_8888;
+ mSrcBufferInfo->dst_info.rect.x = displayFrame[0].left;
+ mSrcBufferInfo->dst_info.rect.y = displayFrame[0].top;
+ mSrcBufferInfo->dst_info.rect.w = displayFrame[0].right - displayFrame[0].left;
+ mSrcBufferInfo->dst_info.rect.h = displayFrame[0].bottom - displayFrame[0].top;
+ mSrcBufferInfo->dst_info.canvas_w = mFbInfo->info.xres;
+ mSrcBufferInfo->dst_info.canvas_h = mFbInfo->info.yres;
+ mSrcBufferInfo->dst_info.memtype = CANVAS_ALLOC;
+ mSrcBufferInfo->dst_info.rotation = layer[0]->mTransform;
+
+ // ge2d processing.
+ mSrcBufferInfo->ge2d_op = AML_GE2D_BLEND;
+ ge2d_process(mGe2dFd, mSrcBufferInfo);
+
+ if (mDebug) {
+ // ALOGE("hnd[0]->format: 0x%x, hnd[1]->format: 0x%x", hnd[0]->format, hnd[1]->format);
+ // dumpLayers(hnd[0]);
+
+ ALOGE(" same crop");
+ tracer();
+ }
+
+ if (sameSize && layerNum == GE2D_COMPOSE_TWO_LAYERS) return;
+ }
+
+ int32_t beginWith = 0;
+ if (sameSize) {
+ if (layerNum == GE2D_COMPOSE_THREE_LAYERS) {
+ beginWith = GE2D_COMPOSE_THREE_LAYERS -1;
+ }
+ }
+
+ bool canBlend = false;
+ for (int32_t i=beginWith; i<layerNum; i++) {
+ mSrcBufferInfo->blend_mode = layer[i]->mBlendMode;
+ canBlend = Utils::compareSize(sourceCrop[i], displayFrame[i]);
+
+ if (0 == i && !isFullScreen(displayFrame[i])) {
+ hwc_rect_t clipRect;
+ clipRect.left = 0;
+ clipRect.top = 0;
+ clipRect.right = mFbInfo->info.xres;
+ clipRect.bottom = mFbInfo->info.yres;
+ fillRectangle(clipRect, 0, mBasePhyAddr + slot * mFbInfo->finfo.line_length);
+ }
+
+ mSrcBufferInfo->src_info[0].paddr = getIonPhyAddr(mFbInfo, hnd[i]);
+ mSrcBufferInfo->src_info[0].format = hnd[i]->format;
+ mSrcBufferInfo->src_info[0].rect.x = (int32_t)sourceCrop[i].left;
+ mSrcBufferInfo->src_info[0].rect.y = (int32_t)sourceCrop[i].top;
+ if (!canBlend
+ && (hnd[i]->format == HAL_PIXEL_FORMAT_YCrCb_420_SP
+ || hnd[i]->format == HAL_PIXEL_FORMAT_YV12)) {
+ mSrcBufferInfo->src_info[0].rect.w = (int32_t)(sourceCrop[i].right - sourceCrop[i].left);
+ mSrcBufferInfo->src_info[0].rect.h = (int32_t)(sourceCrop[i].bottom- sourceCrop[i].top);
+ } else {
+ mSrcBufferInfo->src_info[0].rect.w = (int32_t)(sourceCrop[i].right - sourceCrop[i].left);
+ mSrcBufferInfo->src_info[0].rect.h = (int32_t)(sourceCrop[i].bottom- sourceCrop[i].top);
+ }
+ mSrcBufferInfo->src_info[0].canvas_w = hnd[i]->stride;
+ mSrcBufferInfo->src_info[0].canvas_h = hnd[i]->height;
+ mSrcBufferInfo->src_info[0].memtype = CANVAS_ALLOC;
+
+ // SRC1 equals DST.
+ mSrcBufferInfo->src_info[1].paddr = mBasePhyAddr + slot * mFbInfo->finfo.line_length;
+ mSrcBufferInfo->src_info[1].format = HAL_PIXEL_FORMAT_RGBA_8888;
+ mSrcBufferInfo->src_info[1].rect.x = displayFrame[i].left;
+ mSrcBufferInfo->src_info[1].rect.y = displayFrame[i].top;
+ mSrcBufferInfo->src_info[1].rect.w = displayFrame[i].right - displayFrame[i].left;
+ mSrcBufferInfo->src_info[1].rect.h = displayFrame[i].bottom - displayFrame[i].top;
+ mSrcBufferInfo->src_info[1].canvas_w = mFbInfo->info.xres;
+ mSrcBufferInfo->src_info[1].canvas_h = mFbInfo->info.yres;
+ mSrcBufferInfo->src_info[1].memtype = CANVAS_ALLOC;
+
+ mSrcBufferInfo->dst_info.paddr = mBasePhyAddr + slot * mFbInfo->finfo.line_length;
+ mSrcBufferInfo->dst_info.format = HAL_PIXEL_FORMAT_RGBA_8888;
+ mSrcBufferInfo->dst_info.rect.x = displayFrame[i].left;
+ mSrcBufferInfo->dst_info.rect.y = displayFrame[i].top;
+ /*mSrcBufferInfo->dst_info.rect.w = displayFrame.right - displayFrame.left;
+ mSrcBufferInfo->dst_info.rect.h = displayFrame.bottom - displayFrame.top;*/
+ mSrcBufferInfo->dst_info.canvas_w = mFbInfo->info.xres;
+ mSrcBufferInfo->dst_info.canvas_h = mFbInfo->info.yres;
+ mSrcBufferInfo->dst_info.memtype = CANVAS_ALLOC;
+
+ mSrcBufferInfo->dst_info.rotation = layer[i]->mTransform;
+
+ // ge2d processing.
+ if (0 == i || !canBlend || BLEND_MODE_INVALID == mSrcBufferInfo->blend_mode) {
+ mSrcBufferInfo->dst_info.rect.w = displayFrame[i].right - displayFrame[i].left;
+ mSrcBufferInfo->dst_info.rect.h = displayFrame[i].bottom - displayFrame[i].top;
+ mSrcBufferInfo->ge2d_op = AML_GE2D_STRETCHBLIT;
+ } else {
+ mSrcBufferInfo->dst_info.rect.w = Utils::min(mSrcBufferInfo->src_info[0].rect.w, mSrcBufferInfo->src_info[1].rect.w);
+ mSrcBufferInfo->dst_info.rect.h = Utils::min(mSrcBufferInfo->src_info[0].rect.h, mSrcBufferInfo->src_info[1].rect.h);
+ mSrcBufferInfo->ge2d_op = AML_GE2D_BLEND;
+ if (mDebug) dumpLayers(hnd[i]);
+ }
+
+ ge2d_process(mGe2dFd, mSrcBufferInfo);
+ if (mDebug) {
+ ALOGE(" layers sameSize is %d", sameSize);
+ tracer();
+ }
+ }
+}
+
+// #define GE2D_PORCESS_TIMESTAMP
+bool GE2DComposer::threadLoop()
+{
+ Mutex::Autolock _l(mLock);
+ mCondition.wait(mLock);
+ if (mExitThread) {
+ ITRACE("exiting thread loop");
+ return false;
+ }
+
+ Fifo::iterator front(mQueueItems.begin());
+ // do ge2d compose.
+ while (mQueuedFrames > 0 && mQueueItems.size() > 0) {
+#ifdef GE2D_PORCESS_TIMESTAMP
+ nsecs_t beforeTimeStamp = systemTime(SYSTEM_TIME_MONOTONIC);
+#endif
+ // wait all layers fence here.
+ int32_t slot = front->mSlot;
+ int32_t mergedFence = front->mFence;
+ Vector< LayerState* > layersState = front->mLayersState;
+
+ // wait all fence to be signaled here.
+ HwcFenceControl::waitAndCloseFd(mergedFence, 2800);
+
+ // run ge2d process here.
+ runGE2DProcess(slot, layersState);
+
+ // ge2d finished process, make sure fd close here.
+ for (int32_t i=0; i<layersState.size(); i++) {
+ LayerState* layer = layersState.itemAt(i);
+ // ALOGE("close->layer:[%12" PRIxPTR ", %d]", layer->mBufferHnd, layer->mBufferFd);
+ if (layer != NULL) {
+ Utils::closeFd(layer->mBufferFd);
+ layer->mBufferFd = -1;
+ delete layer;
+ }
+ }
+
+#ifdef GE2D_PORCESS_TIMESTAMP
+ nsecs_t afterTimeStamp = systemTime(SYSTEM_TIME_MONOTONIC);
+ ALOGE("Ge2d process Period: %" PRId64 "", afterTimeStamp - beforeTimeStamp);
+#endif
+ // usleep(1000*100);
+ // signal ge2d's release fence.
+ HwcFenceControl::syncTimelineInc(mSyncTimelineFd);
+
+ mQueueItems.erase(front);
+ front = mQueueItems.begin();
+ android_atomic_dec(&mQueuedFrames);
+ }
+
+ return true;
+}
+
+} // namespace amlogic
+} // namesapce android
+
diff --git a/hwc2/common/composers/GE2DComposer.cpp_ b/hwc2/common/composers/GE2DComposer.cpp_
new file mode 100644
index 0000000..376fd04
--- a/dev/null
+++ b/hwc2/common/composers/GE2DComposer.cpp_
@@ -0,0 +1,632 @@
+/*
+// Copyright(c) 2016 Amlogic Corporation
+*/
+#include <HwcTrace.h>
+#include <HwcFenceControl.h>
+#include <GE2DComposer.h>
+#include <IDisplayDevice.h>
+#include <inttypes.h>
+
+#define GE2D_PORCESS_DEBUG
+
+namespace android {
+namespace amlogic {
+
+GE2DComposer::GE2DComposer(IDisplayDevice& disp)
+ : Composers(disp),
+ mDisplayDevice(disp),
+ mLock(),
+ mCondition(),
+ mSyncTimelineFd(-1),
+ mBufferMask(0),
+ mNumBuffers(1),
+ mFbSlot(0),
+ mCurGlesFbSlot(-1),
+ mSingleFbSize(0),
+ mGe2dBufHnd(NULL),
+ mSrcBufferInfo(NULL),
+ mExitThread(false),
+ mInitialized(false)
+{
+ mName = "GE2D";
+
+ mQueue.setCapacity(8);
+ mQueue.clear();
+}
+
+GE2DComposer::~GE2DComposer()
+{
+ WARN_IF_NOT_DEINIT();
+}
+
+int32_t GE2DComposer::allocBuffer(private_module_t* module, size_t size, int32_t usage, buffer_handle_t* pHandle)
+{
+ ion_user_handle_t ion_hnd;
+ unsigned char *cpu_ptr = NULL;
+ int32_t shared_fd;
+ int32_t ret;
+ int32_t ion_flags = 0;
+ int32_t lock_state = 0;
+
+#if 1 // no need cache.
+ if ( (usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN )
+ {
+ ion_flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC;
+ }
+#endif
+
+ if (usage & GRALLOC_USAGE_AML_DMA_BUFFER)
+ {
+ ret = ion_alloc(module->ion_client, size, 0, ION_HEAP_CARVEOUT_MASK,
+ ion_flags, &ion_hnd);
+ }
+
+ if ( ret != 0)
+ {
+ ETRACE("Failed to ion_alloc from ion_client:%d", module->ion_client);
+ return -1;
+ }
+
+ ret = ion_share( module->ion_client, ion_hnd, &shared_fd );
+ if ( ret != 0 )
+ {
+ ETRACE( "ion_share( %d ) failed", module->ion_client );
+ if ( 0 != ion_free( module->ion_client, ion_hnd ) )
+ ETRACE( "ion_free( %d ) failed", module->ion_client );
+ return -1;
+ }
+
+ if (!(usage & GRALLOC_USAGE_PROTECTED))
+ {
+ cpu_ptr = (unsigned char*)mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shared_fd, 0 );
+
+ if ( MAP_FAILED == cpu_ptr )
+ {
+ ETRACE( "ion_map( %d ) failed", module->ion_client );
+ if ( 0 != ion_free( module->ion_client, ion_hnd ) )
+ ETRACE( "ion_free( %d ) failed", module->ion_client );
+ close( shared_fd );
+ return -1;
+ }
+ lock_state = private_handle_t::LOCK_STATE_MAPPED;
+ }
+
+ private_handle_t *hnd = new private_handle_t( private_handle_t::PRIV_FLAGS_USES_ION /*TODO ion extend*| priv_heap_flag*/, usage, size, cpu_ptr,
+ lock_state );
+
+ if ( NULL != hnd )
+ {
+ hnd->share_fd = shared_fd;
+ hnd->ion_hnd = ion_hnd;
+ /*TODO ion extend hnd->min_pgsz = min_pgsz; */
+ *pHandle = hnd;
+ return 0;
+ }
+ else
+ {
+ ETRACE( "Gralloc out of mem for ion_client:%d", module->ion_client );
+ }
+
+ close( shared_fd );
+
+ if (!(usage & GRALLOC_USAGE_PROTECTED))
+ {
+ ret = munmap( cpu_ptr, size );
+ if ( 0 != ret )
+ ETRACE( "munmap failed for base:%p size: %zd", cpu_ptr, size );
+ }
+
+ ret = ion_free( module->ion_client, ion_hnd );
+ if ( 0 != ret )
+ ETRACE( "ion_free( %d ) failed", module->ion_client );
+ return -1;
+}
+
+void GE2DComposer::freeBuffer(private_handle_t const* hnd, private_module_t* m)
+{
+ if ( hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION )
+ {
+ /* Buffer might be unregistered already so we need to assure we have a valid handle*/
+ if ( 0 != hnd->base )
+ {
+ if ( 0 != munmap( (void*)hnd->base, hnd->size ) ) ETRACE( "Failed to munmap handle %p", hnd );
+ }
+ close( hnd->share_fd );
+ if ( 0 != ion_free( m->ion_client, hnd->ion_hnd ) ) ETRACE( "Failed to ion_free( ion_client: %d ion_hnd: %p )", m->ion_client, hnd->ion_hnd );
+ memset( (void*)hnd, 0, sizeof( *hnd ) );
+ }
+}
+
+bool GE2DComposer::initialize(framebuffer_info_t* fbInfo)
+{
+ Mutex::Autolock _l(mLock);
+
+ if (mInitialized) {
+ WTRACE("object has been initialized");
+ return true;
+ }
+
+ // create a release fence timeline.
+ mSyncTimelineFd = HwcFenceControl::createFenceTimeline();
+ if (mSyncTimelineFd == -1) {
+ DEINIT_AND_RETURN_FALSE("sync timeline create failed!");
+ }
+ mCurrentSyncTime = 1;
+
+ // create ge2d composer thread.
+ mExitThread = false;
+ mThread = new GE2DRenderThread(this);
+ if (!mThread.get()) {
+ DEINIT_AND_RETURN_FALSE("failed to create ge2d composer thread.");
+ }
+ mThread->run("GE2DComposer", PRIORITY_URGENT_DISPLAY);
+
+ // framebuffer stuff.
+ mFbInfo = fbInfo;
+ mSingleFbSize = fbInfo->finfo.line_length
+ * fbInfo->info.yres;
+ mNumBuffers = fbInfo->fbSize / mSingleFbSize;
+
+ mSrcBufferInfo = new aml_ge2d_info_t();
+
+ // ge2d init.
+ ge2d_init();
+ mInitialized = true;
+ return true;
+}
+
+void GE2DComposer::deinitialize()
+{
+ mExitThread = true;
+ mCondition.signal();
+
+ if (mThread.get()) {
+ mThread->requestExitAndWait();
+ mThread = NULL;
+ }
+
+ if (mSrcBufferInfo != NULL) {
+ delete mSrcBufferInfo;
+ mSrcBufferInfo = NULL;
+ }
+
+ // ge2d exit.
+ ge2d_exit();
+ mInitialized = false;
+}
+
+const char* GE2DComposer::getName() const
+{
+ return mName;
+}
+
+const uint32_t GE2DComposer::getFbSlot()
+{
+ Mutex::Autolock _l(mLock);
+
+ return mFbSlot;
+}
+
+void GE2DComposer::setCurGlesFbSlot(uint32_t slot) {
+ Mutex::Autolock _l(mLock);
+
+ mCurGlesFbSlot = slot;
+}
+
+uint32_t GE2DComposer::findFreeFbSlot()
+{
+ int32_t fbSlot = 0;
+
+ if (mNumBuffers == 1) {
+ // If we have only one buffer, we never use page-flipping.
+ return 0;
+ }
+
+ if (-1 != mCurGlesFbSlot) {
+ // mBufferMask = 0x0;
+ // If gles composer just before come here, we should avoid this buffer and prior buffer.
+ fbSlot = mCurGlesFbSlot + 2 * mFbInfo->info.yres;
+ if (fbSlot % (3*mFbInfo->info.yres) == 0) {
+ mBufferMask = 0x1;
+ } else if (fbSlot % (3*mFbInfo->info.yres) == 1) {
+ mBufferMask = 0x7;
+ } else if (fbSlot % (3*mFbInfo->info.yres) == 2) {
+ mBufferMask = 0x3;
+ }
+
+ /*for (uint32_t i= 0; i<(fbSlot % (3*mFbInfo->info.yres)) / mFbInfo->info.yres + 1; i++) {
+ mBufferMask |= (1LU<<i);
+ }*/
+ mCurGlesFbSlot = -1;
+ ETRACE("Stark, mNumBuffers: %d, mBufferMask: 0x%x", mNumBuffers, mBufferMask);
+ } else {
+ if (mBufferMask >= ((1LU<<mNumBuffers)-1)) {
+ // We ran out of buffers. reinit to 0;
+ mBufferMask = 0x1;
+ return 0;
+ }
+
+ // find a free slot
+ for (uint32_t i=0 ; i<mNumBuffers ; i++) {
+ if ((mBufferMask & (1LU<<i)) == 0) {
+ mBufferMask |= (1LU<<i);
+ break;
+ }
+
+ fbSlot += 2 * mFbInfo->info.yres;
+ }
+ }
+
+ return fbSlot % (3*mFbInfo->info.yres);
+}
+
+int32_t GE2DComposer::startCompose(Vector< hwc2_layer_t > hwcLayers, int32_t *offset)
+{
+ Mutex::Autolock _l(mLock);
+ if (NULL != mGe2dBuffer) {
+ int32_t usage = GRALLOC_USAGE_AML_DMA_BUFFER;
+ int32_t ret = allocBuffer(mFbInfo->grallocModule, mFbInfo->fbSize, usage, &mGe2dBufHnd);
+ if (ret < 0) {
+ ETRACE("allocBuffer failed!");
+ return ALLOC_BUFFER_FAILED;
+ }
+ } else {
+ DTRACE("Buffer alloced already.");
+ }
+
+ // find a free slot of fb.
+ mFbSlot = findFreeFbSlot();
+ *offset = mFbSlot;
+
+ // add hwcLayers to work queue.
+ mQueue.push_back(hwcLayers);
+
+ int32_t ge2dFence = HwcFenceControl::createFence(mSyncTimelineFd, "ge2d_flag", mCurrentSyncTime++);
+ int32_t layersMergedFence = -1;
+ int32_t ge2dMergedFence = -1;
+
+ // wait all layers fence here.
+ for (uint32_t i=0; i<hwcLayers.size(); i++) {
+ hwc2_layer_t layerId = hwcLayers.itemAt(i);
+ HwcLayer* hwcLayer = mDisplayDevice.getLayerById(layerId);
+ if (hwcLayer != NULL) {
+ int32_t duppedFence = hwcLayer->getDuppedAcquireFence();
+ int32_t tempFence = -1;
+
+ tempFence = HwcFenceControl::merge(String8("layers_merged"), duppedFence, layersMergedFence);
+ HwcFenceControl::closeFd(layersMergedFence);
+ layersMergedFence = tempFence;
+
+ // wait layers to be drawed here.
+ HwcFenceControl::waitAndCloseFd(duppedFence, 5000);
+ // HwcFenceControl::closeFd(duppedFence);
+ }
+ }
+ mCondition.signal();
+
+ // merge layer's fences and ge2d fence.
+ ge2dMergedFence = HwcFenceControl::merge(String8("ge2d_flag"), layersMergedFence, ge2dFence);
+ DTRACE("ge2d merged fence: %d", ge2dMergedFence);
+
+ HwcFenceControl::closeFd(ge2dFence);
+ HwcFenceControl::closeFd(layersMergedFence);
+
+ return ge2dMergedFence;
+}
+
+// test.
+void GE2DComposer::directMemcpy(Fifo::iterator front)
+{
+ uintptr_t buffer = (uintptr_t)mFbInfo->grallocModule->fb_primary.framebuffer->base;
+
+ // ge2d work here.
+ for (uint32_t i=0; i<front->size(); i++) {
+ // do ge2d compose.
+ hwc2_layer_t layerId = front->itemAt(i);
+ HwcLayer* hwcLayer = mDisplayDevice.getLayerById(layerId);
+ ETRACE("thread loop to do ge2d work here.");
+
+ if (hwcLayer != NULL) {
+ // video overlay.
+ private_handle_t const* hnd =
+ reinterpret_cast<private_handle_t const*>(hwcLayer->getBufferHandle());
+ if (hnd != NULL) {
+ // common memcpy mode.
+ if (private_handle_t::validate(hnd) < 0) {
+ ETRACE("invalid layer handle.");
+ continue;
+ }
+ void* fBuffer = (void*)(buffer + mSingleFbSize * (mFbSlot/mFbInfo->info.yres));
+ ETRACE("hnd->stride is %d, hnd->height is %d, hnd->size: %d, hnd->base: 0x%llx, mSingleFbSize: %d, Slot: %d, buffer: 0x%llx",
+ hnd->stride, hnd->height, hnd->size, (uintptr_t)hnd->base, mSingleFbSize, mFbSlot/mFbInfo->info.yres, (uintptr_t)fBuffer);
+ if (fBuffer != MAP_FAILED) {
+ memset(fBuffer, 0, mSingleFbSize);
+ memcpy(fBuffer, hnd->base, hnd->size);
+ ETRACE("copy ok");
+ } else {
+ ETRACE("buffer mmap fail");
+ }
+ }
+ }
+ }
+}
+
+#if 0
+void GE2DComposer::runGE2DProcess(HwcLayer* hwcLayer)
+{
+ // ge2d work here.
+ DTRACE("thread loop to do ge2d work here.");
+ hwc_frect_t sourceCrop;
+ hwc_rect_t displayFrame;
+ private_handle_t const* hnd =
+ reinterpret_cast<private_handle_t const*>(hwcLayer->getBufferHandle());
+ if (hnd != NULL) {
+ sourceCrop = hwcLayer->getSourceCrop();
+ displayFrame = hwcLayer->getDisplayFrame();
+
+ mSrcBufferInfo->src_info[0].paddr = getIonPhyAddr(mFbInfo, hnd);
+ mSrcBufferInfo->src_info[0].format = hnd->format;
+ // mSrcBufferInfo->src_info[0].rotation = hwcLayer->getTransform();
+
+ mSrcBufferInfo->src_info[0].rect.x = (int)sourceCrop.left;
+ mSrcBufferInfo->src_info[0].rect.y = (int)sourceCrop.top;
+ mSrcBufferInfo->src_info[0].rect.w = (int)(sourceCrop.right - displayFrame.left);
+ mSrcBufferInfo->src_info[0].rect.h = (int)(sourceCrop.bottom- displayFrame.top);
+ mSrcBufferInfo->src_info[0].canvas_w = hnd->stride;
+ mSrcBufferInfo->src_info[0].canvas_h = hnd->height;
+
+ mSrcBufferInfo->src_info[0].memtype = CANVAS_ALLOC;
+
+ // src1 equals dst.
+ mSrcBufferInfo->src_info[1].rect.x = 0;
+ mSrcBufferInfo->src_info[1].rect.y = 0;
+ mSrcBufferInfo->src_info[1].rect.w = mFbInfo->info.xres;
+ mSrcBufferInfo->src_info[1].rect.h = mFbInfo->info.yres;
+ mSrcBufferInfo->src_info[1].memtype = CANVAS_OSD0;
+
+ mSrcBufferInfo->blend_mode = hwcLayer->getBlendMode();
+
+ mSrcBufferInfo->dst_info.rect.x = displayFrame.left;
+ mSrcBufferInfo->dst_info.rect.y = displayFrame.top;
+ mSrcBufferInfo->dst_info.rect.w = displayFrame.right - displayFrame.left;
+ mSrcBufferInfo->dst_info.rect.h = displayFrame.bottom - displayFrame.top;
+ mSrcBufferInfo->dst_info.memtype = CANVAS_OSD0;
+ mSrcBufferInfo->dst_info.rotation = hwcLayer->getTransform();
+ }
+
+ // ge2d processing.
+ if (0 == mSrcBufferInfo->blend_mode)
+ mSrcBufferInfo->ge2d_op = AML_GE2D_STRETCHBLIT;
+ else
+ mSrcBufferInfo->ge2d_op = AML_GE2D_BLEND;
+
+#ifdef GE2D_PORCESS_DEBUG
+ nsecs_t beforeTimeStamp = systemTime(SYSTEM_TIME_MONOTONIC);
+#endif
+ ge2d_process(mSrcBufferInfo);
+#ifdef GE2D_PORCESS_DEBUG
+ nsecs_t afterTimeStamp = systemTime(SYSTEM_TIME_MONOTONIC);
+ ETRACE("ge2d process Period: %" PRId64 "", afterTimeStamp - beforeTimeStamp);
+ ETRACE("Src1 stride is %d, height is %d, Slot: %d, format: %d, blendMode: %d, "
+ "srcCrop: [%d, %d, %d, %d], displayFrame:[%d, %d, %d, %d]",
+ mSrcBufferInfo->src_info[0].canvas_w, mSrcBufferInfo->src_info[0].canvas_h,
+ mSrcBufferInfo->offset, mSrcBufferInfo->src_info[0].format, mSrcBufferInfo->blend_mode,
+ mSrcBufferInfo->src_info[0].rect.x, mSrcBufferInfo->src_info[0].rect.y,mSrcBufferInfo->src_info[0].rect.w,mSrcBufferInfo->src_info[0].rect.h,
+ mSrcBufferInfo->dst_info.rect.x, mSrcBufferInfo->dst_info.rect.y, mSrcBufferInfo->dst_info.rect.w, mSrcBufferInfo->dst_info.rect.h);
+ ETRACE("Src2 stride is %d, height is %d, Slot: %d, format: %d, blendMode: %d, "
+ "srcCrop: [%d, %d, %d, %d], displayFrame:[%d, %d, %d, %d]",
+ mSrcBufferInfo->src_info[1].canvas_w, mSrcBufferInfo->src_info[1].canvas_h,
+ mSrcBufferInfo->offset, mSrcBufferInfo->src_info[1].format, mSrcBufferInfo->blend_mode,
+ mSrcBufferInfo->src_info[1].rect.x, mSrcBufferInfo->src_info[1].rect.y,mSrcBufferInfo->src_info[1].rect.w,mSrcBufferInfo->src_info[1].rect.h,
+ mSrcBufferInfo->dst_info.rect.x, mSrcBufferInfo->dst_info.rect.y, mSrcBufferInfo->dst_info.rect.w, mSrcBufferInfo->dst_info.rect.h);
+#endif
+}
+
+#else
+void GE2DComposer::runGE2DProcess(HwcLayer* hwcLayer1, HwcLayer* hwcLayer2)
+{
+ bool sameSourceCrop = false;
+ bool swapLayers = false;
+ hwc_frect_t sourceCrop[2];
+ HwcLayer* layer[2];
+ private_handle_t const* hnd[2];
+ nsecs_t beforeTimeStamp = 0, afterTimeStamp = 0;
+ hwc_rect_t displayFrame;
+ uint32_t layerNum = GE2D_COMPOSE_ONE_LAYER;
+
+ layer[0] = hwcLayer1;
+ layer[1] = hwcLayer2;
+
+ if (layer[1] != NULL) {
+ layerNum = GE2D_COMPOSE_TWO_LAYERS;
+ sourceCrop[0] = layer[0]->getSourceCrop();
+ sourceCrop[1] = layer[1]->getSourceCrop();
+ if ((int32_t)sourceCrop[0].left == (int32_t)sourceCrop[1].left
+ && (int32_t)sourceCrop[0].top == (int32_t)sourceCrop[1].top
+ && (int32_t)sourceCrop[0].right == (int32_t)sourceCrop[1].right
+ && (int32_t)sourceCrop[0].bottom == (int32_t)sourceCrop[1].bottom) {
+ sameSourceCrop = true;
+ }
+
+ if (sameSourceCrop && 0 != layer[1]->getBlendMode() && 0 == layer[0]->getBlendMode()) {
+ layer[0] = hwcLayer2;
+ layer[1] = hwcLayer1;
+ swapLayers = true;
+ }
+ }
+
+ for (int32_t i=0; i<layerNum; i++) {
+ hnd[i] = reinterpret_cast<private_handle_t const*>(layer[i]->getBufferHandle());
+ }
+
+ if (sameSourceCrop && swapLayers) {
+ if (hnd[0] != NULL && hnd[1] != NULL) {
+ for (int32_t i=0; i<layerNum; i++) {
+ ETRACE("hnds: %p, %p", hnd[0], hnd[1]);
+ mSrcBufferInfo->src_info[i].paddr = getIonPhyAddr(mFbInfo, hnd[i]);
+ mSrcBufferInfo->src_info[i].format = hnd[i]->format;
+ mSrcBufferInfo->src_info[i].rect.x = (int32_t)sourceCrop[i].left;
+ mSrcBufferInfo->src_info[i].rect.y = (int32_t)sourceCrop[i].top;
+ mSrcBufferInfo->src_info[i].rect.w = (int32_t)(sourceCrop[i].right - sourceCrop[i].left);
+ mSrcBufferInfo->src_info[i].rect.h = (int32_t)(sourceCrop[i].bottom- sourceCrop[i].top);
+ mSrcBufferInfo->src_info[i].canvas_w = hnd[i]->stride;
+ mSrcBufferInfo->src_info[i].canvas_h = hnd[i]->height;
+ mSrcBufferInfo->src_info[i].memtype = CANVAS_ALLOC;
+ }
+ mSrcBufferInfo->blend_mode = layer[0]->getBlendMode();
+ displayFrame = layer[0]->getDisplayFrame();
+
+ mSrcBufferInfo->dst_info.rect.x = displayFrame.left;
+ mSrcBufferInfo->dst_info.rect.y = displayFrame.top;
+ mSrcBufferInfo->dst_info.rect.w = displayFrame.right - displayFrame.left;
+ mSrcBufferInfo->dst_info.rect.h = displayFrame.bottom - displayFrame.top;
+ mSrcBufferInfo->dst_info.memtype = CANVAS_OSD0;
+ }
+ mSrcBufferInfo->dst_info.rotation = layer[0]->getTransform();
+
+ // ge2d processing.
+ mSrcBufferInfo->ge2d_op = AML_GE2D_BLEND;
+#ifdef GE2D_PORCESS_DEBUG
+ nsecs_t beforeTimeStamp = systemTime(SYSTEM_TIME_MONOTONIC);
+#endif
+ ge2d_process(mSrcBufferInfo);
+#ifdef GE2D_PORCESS_DEBUG
+ nsecs_t afterTimeStamp = systemTime(SYSTEM_TIME_MONOTONIC);
+ ETRACE("Same SourceCrop ge2d process Period: %" PRId64 "", afterTimeStamp - beforeTimeStamp);
+
+ ETRACE("Same SourceCrop Src1 stride is %d, height is %d, Slot: %d, format: %d, blendMode: %d, "
+ "srcCrop: [%d, %d, %d, %d], displayFrame:[%d, %d, %d, %d]",
+ mSrcBufferInfo->src_info[0].canvas_w, mSrcBufferInfo->src_info[0].canvas_h,
+ mSrcBufferInfo->offset, mSrcBufferInfo->src_info[0].format, mSrcBufferInfo->blend_mode,
+ mSrcBufferInfo->src_info[0].rect.x, mSrcBufferInfo->src_info[0].rect.y,mSrcBufferInfo->src_info[0].rect.w,mSrcBufferInfo->src_info[0].rect.h,
+ mSrcBufferInfo->dst_info.rect.x, mSrcBufferInfo->dst_info.rect.y, mSrcBufferInfo->dst_info.rect.w, mSrcBufferInfo->dst_info.rect.h);
+ ETRACE("Same SourceCrop Src2 stride is %d, height is %d, Slot: %d, format: %d, blendMode: %d, "
+ "srcCrop: [%d, %d, %d, %d], displayFrame:[%d, %d, %d, %d]",
+ mSrcBufferInfo->src_info[1].canvas_w, mSrcBufferInfo->src_info[1].canvas_h,
+ mSrcBufferInfo->offset, mSrcBufferInfo->src_info[1].format, mSrcBufferInfo->blend_mode,
+ mSrcBufferInfo->src_info[1].rect.x, mSrcBufferInfo->src_info[1].rect.y,mSrcBufferInfo->src_info[1].rect.w,mSrcBufferInfo->src_info[1].rect.h,
+ mSrcBufferInfo->dst_info.rect.x, mSrcBufferInfo->dst_info.rect.y, mSrcBufferInfo->dst_info.rect.w, mSrcBufferInfo->dst_info.rect.h);
+#endif
+ } else {
+ if (layerNum == GE2D_COMPOSE_TWO_LAYERS && hnd[1] == NULL) {
+ ETRACE("two layers compose, hnd should not be null");
+ return;
+ }
+ for (int32_t i=0; i<layerNum; i++) {
+ mSrcBufferInfo->src_info[0].paddr = getIonPhyAddr(mFbInfo, hnd[i]);
+ mSrcBufferInfo->src_info[0].format = hnd[i]->format;
+ mSrcBufferInfo->src_info[0].rect.x = (int32_t)sourceCrop[i].left;
+ mSrcBufferInfo->src_info[0].rect.y = (int32_t)sourceCrop[i].top;
+ mSrcBufferInfo->src_info[0].rect.w = (int32_t)(sourceCrop[i].right - sourceCrop[i].left);
+ mSrcBufferInfo->src_info[0].rect.h = (int32_t)(sourceCrop[i].bottom- sourceCrop[i].top);
+ mSrcBufferInfo->src_info[0].canvas_w = hnd[i]->stride;
+ mSrcBufferInfo->src_info[0].canvas_h = hnd[i]->height;
+ mSrcBufferInfo->src_info[0].memtype = CANVAS_ALLOC;
+
+ // src1 equals dst.
+ mSrcBufferInfo->src_info[1].rect.x = 0;
+ mSrcBufferInfo->src_info[1].rect.y = 0;
+ mSrcBufferInfo->src_info[1].rect.w = mFbInfo->info.xres;
+ mSrcBufferInfo->src_info[1].rect.h = mFbInfo->info.yres;
+ mSrcBufferInfo->src_info[1].memtype = CANVAS_OSD0;
+ mSrcBufferInfo->blend_mode = layer[i]->getBlendMode();
+
+ displayFrame = layer[i]->getDisplayFrame();
+ mSrcBufferInfo->dst_info.rect.x = displayFrame.left;
+ mSrcBufferInfo->dst_info.rect.y = displayFrame.top;
+ mSrcBufferInfo->dst_info.rect.w = displayFrame.right - displayFrame.left;
+ mSrcBufferInfo->dst_info.rect.h = displayFrame.bottom - displayFrame.top;
+ mSrcBufferInfo->dst_info.memtype = CANVAS_OSD0;
+ mSrcBufferInfo->dst_info.rotation = layer[i]->getTransform();
+
+ // ge2d processing.
+ if (0 == mSrcBufferInfo->blend_mode)
+ mSrcBufferInfo->ge2d_op = AML_GE2D_STRETCHBLIT;
+ else
+ mSrcBufferInfo->ge2d_op = AML_GE2D_BLEND;
+#ifdef GE2D_PORCESS_DEBUG
+ nsecs_t beforeTimeStamp = systemTime(SYSTEM_TIME_MONOTONIC);
+#endif
+ ge2d_process(mSrcBufferInfo);
+#ifdef GE2D_PORCESS_DEBUG
+ nsecs_t afterTimeStamp = systemTime(SYSTEM_TIME_MONOTONIC);
+ ETRACE("Ge2d process Period: %" PRId64 "", afterTimeStamp - beforeTimeStamp);
+ ETRACE("Src1 stride is %d, height is %d, Slot: %d, format: %d, blendMode: %d, "
+ "srcCrop: [%d, %d, %d, %d], displayFrame:[%d, %d, %d, %d]",
+ mSrcBufferInfo->src_info[0].canvas_w, mSrcBufferInfo->src_info[0].canvas_h,
+ mSrcBufferInfo->offset, mSrcBufferInfo->src_info[0].format, mSrcBufferInfo->blend_mode,
+ mSrcBufferInfo->src_info[0].rect.x, mSrcBufferInfo->src_info[0].rect.y,mSrcBufferInfo->src_info[0].rect.w,mSrcBufferInfo->src_info[0].rect.h,
+ mSrcBufferInfo->dst_info.rect.x, mSrcBufferInfo->dst_info.rect.y, mSrcBufferInfo->dst_info.rect.w, mSrcBufferInfo->dst_info.rect.h);
+ ETRACE("Src2 stride is %d, height is %d, Slot: %d, format: %d, blendMode: %d, "
+ "srcCrop: [%d, %d, %d, %d], displayFrame:[%d, %d, %d, %d]",
+ mSrcBufferInfo->src_info[1].canvas_w, mSrcBufferInfo->src_info[1].canvas_h,
+ mSrcBufferInfo->offset, mSrcBufferInfo->src_info[1].format, mSrcBufferInfo->blend_mode,
+ mSrcBufferInfo->src_info[1].rect.x, mSrcBufferInfo->src_info[1].rect.y,mSrcBufferInfo->src_info[1].rect.w,mSrcBufferInfo->src_info[1].rect.h,
+ mSrcBufferInfo->dst_info.rect.x, mSrcBufferInfo->dst_info.rect.y, mSrcBufferInfo->dst_info.rect.w, mSrcBufferInfo->dst_info.rect.h);
+#endif
+ }
+ }
+}
+#endif
+
+bool GE2DComposer::threadLoop()
+{
+ Mutex::Autolock _l(mLock);
+ mCondition.wait(mLock);
+ if (mExitThread) {
+ ITRACE("exiting thread loop");
+ return false;
+ }
+
+ DTRACE("Stark, sync timeline fd : %d", mSyncTimelineFd);
+ Fifo::iterator front(mQueue.begin());
+ while (mQueue.size() > 0) {
+ // direct memcpy mode test.
+ // directMemcpy(front);
+
+ // do ge2d compose.
+ // ETRACE("thread loop to do ge2d work here.");
+ hwc2_layer_t layerId = front->itemAt(0);
+ HwcLayer* hwcLayer = mDisplayDevice.getLayerById(layerId);
+ switch (front->size()) {
+ case GE2D_COMPOSE_ONE_LAYER:
+ {
+ // run one layer ge2d process.
+ if (hwcLayer != NULL) {
+ mSrcBufferInfo->offset = mFbSlot;
+ runGE2DProcess(hwcLayer, NULL);
+ }
+ }
+ break;
+ case GE2D_COMPOSE_TWO_LAYERS:
+ {
+ // run 2 layers ge2d process.
+ hwc2_layer_t layerId2 = front->itemAt(1);
+ HwcLayer* hwcLayer2 = mDisplayDevice.getLayerById(layerId2);
+
+ // run two layers ge2d process.
+ if (hwcLayer != NULL && hwcLayer2 != NULL) {
+ mSrcBufferInfo->offset = mFbSlot;
+ runGE2DProcess(hwcLayer, hwcLayer2);
+ }
+ }
+ break;
+ case GE2D_COMPOSE_THREE_LAYERS:
+ default:
+ ETRACE("More than 2 layers exists, ge2d can't do that process!");
+ break;
+ }
+
+ // signal ge2d's release fence.
+ HwcFenceControl::syncTimelineInc(mSyncTimelineFd);
+
+ mQueue.erase(front);
+ front = mQueue.begin();
+ }
+
+ return true;
+}
+
+} // namespace amlogic
+} // namesapce android
+
diff --git a/hwc2/common/composers/GE2DComposer.h b/hwc2/common/composers/GE2DComposer.h
new file mode 100644
index 0000000..509252f
--- a/dev/null
+++ b/hwc2/common/composers/GE2DComposer.h
@@ -0,0 +1,169 @@
+/*
+// Copyright(c) 2016 Amlogic Corporation
+*/
+
+#ifndef GE2D_COMPOSER_H
+#define GE2D_COMPOSER_H
+
+#include <utils/KeyedVector.h>
+#include <SimpleThread.h>
+#include <Composers.h>
+#include <IDisplayDevice.h>
+#include <inttypes.h>
+
+#include <ge2d_port.h>
+#include <../kernel-headers/linux/ge2d.h>
+
+namespace android {
+namespace amlogic {
+
+class LayerState {
+public:
+ LayerState()
+ : mBufferHnd(NULL),
+ mBlendMode(0),
+ mTransform(HAL_TRANSFORM_RESERVED),
+ mBufferFd(-1) {
+ }
+
+ ~LayerState() {
+ }
+
+ //void setLayerState(HwcLayer* hwcLayer);
+ void setLayerState(HwcLayer* hwcLayer) {
+ mBlendMode = hwcLayer->getBlendMode();
+ mColor = hwcLayer->getColor();
+ mCompositionType = hwcLayer->getCompositionType();
+ mAcquireFence = hwcLayer->getAcquireFence();
+ mDataSpace = hwcLayer->getDataspace();
+ mPlaneAlpha = hwcLayer->getPlaneAlpha();
+ mTransform = hwcLayer->getTransform();
+ mZ = hwcLayer->getZ();
+ mSourceCrop = hwcLayer->getSourceCrop();
+ mDisplayFrame = hwcLayer->getDisplayFrame();
+ mBufferHnd = hwcLayer->getBufferHandle();
+
+ private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(mBufferHnd);
+ mBufferFd = Utils::checkAndDupFd(hnd->ion_hnd);
+ }
+
+ int32_t mBlendMode;
+ hwc_color_t mColor;
+ int32_t mCompositionType;
+ int32_t mAcquireFence;
+ int32_t mDataSpace;
+ float mPlaneAlpha;
+ int32_t mTransform;
+ uint32_t mZ;
+ hwc_frect_t mSourceCrop;
+ hwc_rect_t mDisplayFrame;
+ // hwc_region_t mDamageRegion;
+ hwc_region_t mVisibleRegion;
+
+ buffer_handle_t mBufferHnd;
+
+ // hold this until ge2d finish process.
+ int32_t mBufferFd;
+};
+
+class SlotInfo {
+public:
+ SlotInfo()
+ : mSlot(-1),
+ mFence(-1),
+ mLayersState() {
+ mLayersState.setCapacity(GE2D_COMPOSE_MAX_LAYERS);
+ mLayersState.clear();
+ }
+
+ ~SlotInfo() {
+ }
+
+ const int32_t getSlot() const { return mSlot; };
+ const int32_t getMergedFence() const { return mFence; };
+ const Vector< LayerState* > getLayersState() const { return mLayersState; };
+
+ int32_t mSlot;
+ int32_t mFence;
+ Vector< LayerState* > mLayersState;
+};
+
+enum { NUM_GE2D_BUFFER_SLOTS = 3 };
+
+class IDisplayDevice;
+
+class GE2DComposer : public Composers {
+
+public:
+ GE2DComposer(IDisplayDevice& disp);
+ virtual ~GE2DComposer();
+
+public:
+ typedef Vector< SlotInfo > Fifo;
+
+ virtual bool initialize(framebuffer_info_t* fbInfo);
+ virtual void deinitialize();
+ virtual const char* getName() const;
+ virtual int32_t startCompose(Vector< hwc2_layer_t > hwcLayers, int32_t *offset = 0, int32_t frameCount = 0);
+ // virtual void setCurGlesFbSlot(uint32_t slot);
+ virtual const buffer_handle_t getBufHnd();
+ virtual void mergeRetireFence(int32_t slot, int32_t retireFence);
+ virtual void removeRetireFence(int32_t slot);
+ virtual void setVideoOverlayLayerId(hwc2_layer_t layerId);
+ virtual void fillRectangle(hwc_rect_t clipRect, uint32_t color, uint32_t addr);
+private:
+ uint32_t findFreeFbSlot();
+ void runGE2DProcess(int32_t slot, Vector< LayerState* > &hwcLayersState);
+ void directMemcpy(Fifo::iterator front); // test.
+ int32_t allocBuffer(private_module_t* module, size_t size, int32_t usage, buffer_handle_t* pHandle);
+ void freeBuffer(private_handle_t const* hnd, private_module_t* m);
+ bool isFullScreen(hwc_rect_t displayFrame);
+ void tracer();
+ void dumpLayers(private_handle_t const* hnd);
+
+
+ IDisplayDevice& mDisplayDevice;
+ const char* mName;
+
+ // Thread safe, mQueueItems is a FIFO of queued work used in synchronous mode.
+ volatile int32_t mQueuedFrames;
+ Fifo mQueueItems;
+
+ // Fence.
+ int32_t mSyncTimelineFd;
+ uint32_t mCurrentSyncTime;
+
+ int32_t mBufferMask;
+ int32_t mNumBuffers;
+ SlotInfo mSlots[NUM_GE2D_BUFFER_SLOTS];
+ hwc2_layer_t mVideoLayerId;
+ // LayerState mVideoLayerState;
+ int32_t mFbSlot;
+ int32_t mCurGlesFbSlot;
+ framebuffer_info_t* mFbInfo;
+ int32_t mSingleFbSize;
+
+ buffer_handle_t mGe2dBufHnd;
+ uint32_t mBasePhyAddr;
+ int32_t mGe2dFd;
+
+ aml_ge2d_info_t *mSrcBufferInfo;
+ bool mDebug;
+
+ int32_t mDevice;
+ mutable Mutex mLock;
+ Condition mCondition;
+ bool mExitThread;
+ bool mInitialized;
+
+private:
+ DECLARE_THREAD(GE2DRenderThread, GE2DComposer);
+};
+
+} // namespace amlogic
+} // namespace android
+
+
+
+#endif /* GE2D_COMPOSITOR_H */
+
diff --git a/hwc2/common/composers/GE2DComposer.h_ b/hwc2/common/composers/GE2DComposer.h_
new file mode 100644
index 0000000..707e8bb
--- a/dev/null
+++ b/hwc2/common/composers/GE2DComposer.h_
@@ -0,0 +1,80 @@
+/*
+// Copyright(c) 2016 Amlogic Corporation
+*/
+
+#ifndef GE2D_COMPOSER_H
+#define GE2D_COMPOSER_H
+
+#include <utils/KeyedVector.h>
+#include <SimpleThread.h>
+#include <Composers.h>
+
+#include <ge2d/include_aml/ge2d_port.h>
+#include <ge2d/include_aml/ge2d.h>
+// #include <ge2d/aml_ge2d.h>
+
+namespace android {
+namespace amlogic {
+
+class IDisplayDevice;
+
+class GE2DComposer : public Composers {
+public:
+ GE2DComposer(IDisplayDevice& disp);
+ virtual ~GE2DComposer();
+
+public:
+ typedef Vector< Vector< hwc2_layer_t > > Fifo;
+
+ virtual bool initialize(framebuffer_info_t* fbInfo);
+ virtual void deinitialize();
+ virtual const char* getName() const;
+ virtual int32_t startCompose(Vector< hwc2_layer_t > hwcLayers, int32_t *offset = 0);
+ virtual void setCurGlesFbSlot(uint32_t slot);
+ virtual const uint32_t getFbSlot();
+
+private:
+ uint32_t findFreeFbSlot();
+ void runGE2DProcess(HwcLayer* hwcLayer1, HwcLayer* hwcLayer2);
+ void directMemcpy(Fifo::iterator front); // test.
+
+ IDisplayDevice& mDisplayDevice;
+ const char* mName;
+
+ // mQueue is a FIFO of queued work used in synchronous mode.
+ Fifo mQueue;
+
+ // Fence.
+ int32_t mSyncTimelineFd;
+ uint32_t mCurrentSyncTime;
+
+ int32_t mBufferMask;
+ int32_t mNumBuffers;
+ int32_t mFbSlot;
+ int32_t mCurGlesFbSlot;
+ framebuffer_info_t* mFbInfo;
+ int32_t mSingleFbSize;
+ buffer_handle_t mGe2dBufHnd;
+
+ // ge2d target buffer info.
+ // buffer_info_t *mTargetBufferInfo;
+ // ge2d src buffer info.
+ aml_ge2d_info_t *mSrcBufferInfo;
+
+ int32_t mDevice;
+ mutable Mutex mLock;
+ Condition mCondition;
+ bool mExitThread;
+ bool mInitialized;
+
+private:
+ DECLARE_THREAD(GE2DRenderThread, GE2DComposer);
+};
+
+} // namespace amlogic
+} // namespace android
+
+
+
+#endif /* GE2D_COMPOSITOR_H */
+
diff --git a/hwc2/common/devices/ExternalDevice.cpp b/hwc2/common/devices/ExternalDevice.cpp
index b56f60a..c01e9f9 100644
--- a/hwc2/common/devices/ExternalDevice.cpp
+++ b/hwc2/common/devices/ExternalDevice.cpp
@@ -1,5 +1,17 @@
/*
-// Copyright(c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 <HwcTrace.h>
diff --git a/hwc2/common/devices/PhysicalDevice.cpp b/hwc2/common/devices/PhysicalDevice.cpp
index dad6c44..e9d61bd 100644
--- a/hwc2/common/devices/PhysicalDevice.cpp
+++ b/hwc2/common/devices/PhysicalDevice.cpp
@@ -1,14 +1,29 @@
/*
-// Copyright(c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
*/
+
#include <fcntl.h>
+#include <inttypes.h>
#include <HwcTrace.h>
#include <PhysicalDevice.h>
#include <Hwcomposer.h>
#include <sys/ioctl.h>
#include <sync/sync.h>
#include <Utils.h>
-
+#include <HwcFenceControl.h>
+#include <cutils/properties.h>
#include <tvp/OmxUtil.h>
static int Amvideo_Handle = 0;
@@ -16,17 +31,26 @@ static int Amvideo_Handle = 0;
namespace android {
namespace amlogic {
-PhysicalDevice::PhysicalDevice(hwc2_display_t id, Hwcomposer& hwc)
+PhysicalDevice::PhysicalDevice(hwc2_display_t id, Hwcomposer& hwc, DeviceControlFactory* controlFactory)
: mId(id),
mHwc(hwc),
+ mControlFactory(controlFactory),
mActiveDisplayConfig(-1),
mVsyncObserver(NULL),
mIsConnected(false),
mFramebufferHnd(NULL),
- mFramebufferInfo(NULL),
+ mFbSlot(0),
+ mComposer(NULL),
mPriorFrameRetireFence(-1),
+ mClientTargetHnd(NULL),
mTargetAcquireFence(-1),
+ mRenderMode(GLES_COMPOSE_MODE),
mIsValidated(false),
+ mDirectRenderLayerId(0),
+ mVideoOverlayLayerId(0),
+ mGE2DClearVideoRegionCount(0),
+ mOSD0Blank(false),
+ mGE2DComposeFrameCount(0),
mInitialized(false)
{
CTRACE();
@@ -53,11 +77,18 @@ PhysicalDevice::PhysicalDevice(hwc2_display_t id, Hwcomposer& hwc)
// set capacity of mDisplayConfigs
mDisplayConfigs.setCapacity(DEVICE_COUNT);
+
+ mGE2DRenderSortedLayerIds.setCapacity(GE2D_COMPOSE_MAX_LAYERS);
+ mGE2DRenderSortedLayerIds.clear();
+
+ mHwcCurReleaseFences = mHwcPriorReleaseFences = NULL;
}
PhysicalDevice::~PhysicalDevice()
{
WARN_IF_NOT_DEINIT();
+ clearFenceList(mHwcCurReleaseFences);
+ clearFenceList(mHwcPriorReleaseFences);
}
bool PhysicalDevice::initialize() {
@@ -82,16 +113,32 @@ void PhysicalDevice::deinitialize() {
Mutex::Autolock _l(mLock);
DEINIT_AND_DELETE_OBJ(mVsyncObserver);
+ DEINIT_AND_DELETE_OBJ(mComposer);
+
+ if (mFramebufferContext != NULL) {
+ delete mFramebufferContext;
+ mFramebufferContext = NULL;
+ }
+
+ if (mCursorContext != NULL) {
+ delete mCursorContext;
+ mCursorContext = NULL;
+ }
mInitialized = false;
}
HwcLayer* PhysicalDevice::getLayerById(hwc2_layer_t layerId) {
HwcLayer* layer = NULL;
+ ssize_t index = mHwcLayers.indexOfKey(layerId);
- layer = mHwcLayers.valueFor(layerId);
- if (!layer) ETRACE("getLayerById %lld error!", layerId);
+ if (index >= 0) {
+ layer = mHwcLayers.valueFor(layerId);
+ }
+ if (!layer) {
+ DTRACE("getLayerById %lld error!", layerId);
+ }
return layer;
}
@@ -103,14 +150,14 @@ int32_t PhysicalDevice::acceptDisplayChanges() {
layer = mHwcLayersChangeType.valueAt(i);
if (layer) {
if (layer->getCompositionType() == HWC2_COMPOSITION_DEVICE
- || layer->getCompositionType() == HWC2_COMPOSITION_SOLID_COLOR) {
+ || layer->getCompositionType() == HWC2_COMPOSITION_SOLID_COLOR) {
layer->setCompositionType(HWC2_COMPOSITION_CLIENT);
} else if (layer->getCompositionType() == HWC2_COMPOSITION_SIDEBAND) {
layer->setCompositionType(HWC2_COMPOSITION_DEVICE);
}
}
}
- // reset layer changed or requested to zero.
+ // reset layer changed or requested size to zero.
mHwcLayersChangeType.clear();
mHwcLayersChangeRequest.clear();
@@ -128,6 +175,7 @@ bool PhysicalDevice::createLayer(hwc2_layer_t* outLayer) {
hwc2_layer_t layerId = reinterpret_cast<hwc2_layer_t>(layer);
mHwcLayers.add(layerId, layer);
*outLayer = layerId;
+ ETRACE("layerId %lld.\n", layerId);
return true;
}
@@ -140,6 +188,15 @@ bool PhysicalDevice::destroyLayer(hwc2_layer_t layerId) {
return false;
}
+ for (int i = 0; i < 2; i++) {
+ ssize_t idx = mLayerReleaseFences[i].indexOfKey(layerId);
+ if (idx >= 0) {
+ HwcFenceControl::closeFd(mLayerReleaseFences[i].valueAt(idx));
+ mLayerReleaseFences[i].removeItemsAt(idx);
+ DTRACE("destroyLayer remove layer %lld from cur release list %p\n", layerId, &(mLayerReleaseFences[i]));
+ }
+ }
+
mHwcLayers.removeItem(layerId);
DEINIT_AND_DELETE_OBJ(layer);
return true;
@@ -201,9 +258,10 @@ int32_t PhysicalDevice::getClientTargetSupport(
uint32_t height,
int32_t /*android_pixel_format_t*/ format,
int32_t /*android_dataspace_t*/ dataspace) {
+ framebuffer_info_t* fbInfo = mFramebufferContext->getInfo();
- if (width == mFramebufferInfo->info.xres
- && height == mFramebufferInfo->info.yres
+ if (width == fbInfo->info.xres
+ && height == fbInfo->info.yres
&& format == HAL_PIXEL_FORMAT_RGBA_8888
&& dataspace == HAL_DATASPACE_UNKNOWN) {
return HWC2_ERROR_NONE;
@@ -211,8 +269,8 @@ int32_t PhysicalDevice::getClientTargetSupport(
DTRACE("fbinfo: [%d x %d], client: [%d x %d]"
"format: %d, dataspace: %d",
- mFramebufferInfo->info.xres,
- mFramebufferInfo->info.yres,
+ fbInfo->info.xres,
+ fbInfo->info.yres,
width, height, format, dataspace);
// TODO: ?
@@ -242,6 +300,7 @@ int32_t PhysicalDevice::getDisplayAttribute(
ETRACE("display %d is not connected.", mId);
}
+ // framebuffer_info_t* fbInfo = mFramebufferContext->getInfo();
DisplayConfig *configChosen = mDisplayConfigs.itemAt(config);
if (!configChosen) {
ETRACE("failed to get display config: %ld", config);
@@ -262,19 +321,19 @@ int32_t PhysicalDevice::getDisplayAttribute(
ETRACE("refresh period: %d", *outValue);
break;
case HWC2_ATTRIBUTE_WIDTH:
- //*outValue = mFramebufferInfo->info.xres;
+ //*outValue = fbInfo->info.xres;
*outValue = configChosen->getWidth();
break;
case HWC2_ATTRIBUTE_HEIGHT:
- //*outValue = mFramebufferInfo->info.yres;
+ //*outValue = fbInfo->info.yres;
*outValue = configChosen->getHeight();
break;
case HWC2_ATTRIBUTE_DPI_X:
- //*outValue = mFramebufferInfo->xdpi*1000;
+ //*outValue = fbInfo->xdpi*1000;
*outValue = configChosen->getDpiX() * 1000.0f;
break;
case HWC2_ATTRIBUTE_DPI_Y:
- //*outValue = mFramebufferInfo->ydpi*1000;
+ //*outValue = fbInfo->ydpi*1000;
*outValue = configChosen->getDpiY() * 1000.0f;
break;
default:
@@ -330,7 +389,11 @@ int32_t PhysicalDevice::getDisplayRequests(
HwcLayer *layer = mHwcLayersChangeRequest.valueAt(i);
if (layer->getCompositionType() == HWC2_COMPOSITION_DEVICE) {
// video overlay.
- if (layer->getBufferHandle()) {
+ if (layerId == mVideoOverlayLayerId) {
+ outLayers[i] = layerId;
+ outLayerRequests[i] = HWC2_LAYER_REQUEST_CLEAR_CLIENT_TARGET;
+ }
+ /* if (layer->getBufferHandle()) {
private_handle_t const* hnd =
reinterpret_cast<private_handle_t const*>(layer->getBufferHandle());
if (hnd->flags & private_handle_t::PRIV_FLAGS_VIDEO_OVERLAY) {
@@ -338,7 +401,7 @@ int32_t PhysicalDevice::getDisplayRequests(
outLayerRequests[i] = HWC2_LAYER_REQUEST_CLEAR_CLIENT_TARGET;
continue;
}
- }
+ } */
}
// sideband stream.
@@ -412,72 +475,163 @@ int32_t PhysicalDevice::getHdrCapabilities(
return HWC2_ERROR_NONE;
}
+void PhysicalDevice::swapReleaseFence() {
+ //dumpFenceList(mHwcCurReleaseFences);
+
+ if (mHwcCurReleaseFences == NULL || mHwcPriorReleaseFences == NULL) {
+ if (mHwcCurReleaseFences) {
+ clearFenceList(mHwcPriorReleaseFences);
+ }
+
+ if (mHwcPriorReleaseFences) {
+ clearFenceList(mHwcPriorReleaseFences);
+ }
+
+ mHwcCurReleaseFences = &(mLayerReleaseFences[0]);
+ mHwcPriorReleaseFences = &(mLayerReleaseFences[1]);
+ } else {
+ KeyedVector<hwc2_layer_t, int32_t> * tmp = mHwcCurReleaseFences;
+ clearFenceList(mHwcPriorReleaseFences);
+ mHwcCurReleaseFences = mHwcPriorReleaseFences;
+ mHwcPriorReleaseFences = tmp;
+ }
+}
+
+
+void PhysicalDevice::addReleaseFence(hwc2_layer_t layerId, int32_t fenceFd) {
+ ssize_t idx = mHwcCurReleaseFences->indexOfKey(layerId);
+ if (idx >= 0 && idx < mHwcCurReleaseFences->size()) {
+ int32_t oldFence = mHwcCurReleaseFences->valueAt(idx);
+ String8 mergeName("hwc-release");
+ int32_t newFence = HwcFenceControl::merge(mergeName, oldFence, fenceFd);
+ mHwcCurReleaseFences->replaceValueAt(idx, newFence);
+ HwcFenceControl::closeFd(oldFence);
+ HwcFenceControl::closeFd(fenceFd);
+ ETRACE("addReleaseFence:(%d, %d) + %d -> (%d,%d)\n", idx, oldFence, fenceFd, idx, newFence);
+ dumpFenceList(mHwcCurReleaseFences);
+ } else {
+ mHwcCurReleaseFences->add(layerId, fenceFd);
+ }
+}
+
+void PhysicalDevice::clearFenceList(KeyedVector<hwc2_layer_t, int32_t> * fenceList) {
+ if (!fenceList || !fenceList->size())
+ return;
+
+ for (int i = 0; i < fenceList->size(); i++) {
+ int32_t fenceFd = fenceList->valueAt(i);
+ HwcFenceControl::closeFd(fenceFd);
+ DTRACE("clearFenceList close fd %d\n", fenceFd);
+ fenceList->replaceValueAt(i, -1);
+ }
+ fenceList->clear();
+}
+
+void PhysicalDevice::dumpFenceList(KeyedVector<hwc2_layer_t, int32_t> * fenceList) {
+ if (!fenceList || fenceList->isEmpty())
+ return;
+
+ String8 resultStr("dumpFenceList: ");
+ for (int i = 0; i < fenceList->size(); i++) {
+ hwc2_layer_t layerId = fenceList->keyAt(i);
+ int32_t fenceFd = fenceList->valueAt(i);
+ resultStr.appendFormat("(%lld, %d), ", layerId, fenceFd);
+ }
+
+ ETRACE("%s", resultStr.string());
+}
+
int32_t PhysicalDevice::getReleaseFences(
uint32_t* outNumElements,
hwc2_layer_t* outLayers,
int32_t* outFences) {
- HwcLayer* layer = NULL;
- uint32_t num_layer = 0;
+ *outNumElements = mHwcPriorReleaseFences->size();
- if (NULL == outLayers || NULL == outFences) {
- for (uint32_t i=0; i<mHwcLayers.size(); i++) {
- hwc2_layer_t layerId = mHwcLayers.keyAt(i);
- layer = mHwcLayers.valueAt(i);
- if (layer) num_layer++;
+ if (outLayers && outFences) {
+ for (uint32_t i=0; i<mHwcPriorReleaseFences->size(); i++) {
+ outLayers[i] = mHwcPriorReleaseFences->keyAt(i);
+ outFences[i] = HwcFenceControl::dupFence(mHwcPriorReleaseFences->valueAt(i));
}
- } else {
- for (uint32_t i=0; i<mHwcLayers.size(); i++) {
- hwc2_layer_t layerId = mHwcLayers.keyAt(i);
- layer = mHwcLayers.valueAt(i);
- if (layer) {
- DTRACE("outFences: %d", layer->getAcquireFence());
- /*if (layer->getAcquireFence() > -1) {
- close(layer->getAcquireFence());
- }*/
- if (layer->getAcquireFence() > -1) {
- outFences[num_layer] = layer->getAcquireFence();
- } else {
- outFences[num_layer] = -1;
- }
- outLayers[num_layer++] = layerId;
- layer->resetAcquireFence();
- // TODO: ?
- }
+ }
+
+ return HWC2_ERROR_NONE;
+}
+
+void PhysicalDevice::directCompose(framebuffer_info_t * fbInfo) {
+ HwcLayer* layer = NULL;
+ ssize_t idx = mHwcLayers.indexOfKey(mDirectRenderLayerId);
+ if (idx >= 0) {
+ layer = mHwcLayers.valueAt(idx);
+ if (mTargetAcquireFence > -1) {
+ ETRACE("ERROR:directCompose with mTargetAcquireFence %d\n", mTargetAcquireFence);
+ HwcFenceControl::closeFd(mTargetAcquireFence);
}
+
+ mTargetAcquireFence = layer->getDuppedAcquireFence();
+ mClientTargetHnd = layer->getBufferHandle();
+ DTRACE("Hit only one non video overlay layer, handle: %08" PRIxPTR ", fence: %d",
+ intptr_t(mClientTargetHnd), mTargetAcquireFence);
+
+ hwc_rect_t displayframe = layer->getDisplayFrame();
+ fbInfo->info.xoffset = displayframe.left;
+ fbInfo->info.yoffset = displayframe.top;
+ return;
}
- if (num_layer > 0) {
- DTRACE("There are %d layer requests.", num_layer);
- *outNumElements = num_layer;
- } else {
- DTRACE("No layer have set buffer yet.");
+ ETRACE("Didn't find direct compose layer!");
+}
+
+void PhysicalDevice::ge2dCompose(framebuffer_info_t * fbInfo, bool hasVideoOverlay) {
+ if (mGE2DRenderSortedLayerIds.size() > 0) {
+ DTRACE("GE2D compose mFbSlot: %d", mFbSlot);
+ if (hasVideoOverlay) {
+ if (mGE2DClearVideoRegionCount < 3) {
+ mComposer->setVideoOverlayLayerId(mVideoOverlayLayerId);
+ }
+ }
+ if (mTargetAcquireFence > -1) {
+ ETRACE("ERROR:GE2D compose with mTargetAcquireFence %d\n", mTargetAcquireFence);
+ HwcFenceControl::closeFd(mTargetAcquireFence);
+ }
+ mTargetAcquireFence = mComposer->startCompose(mGE2DRenderSortedLayerIds, &mFbSlot, mGE2DComposeFrameCount);
+ for (uint32_t i=0; i<mGE2DRenderSortedLayerIds.size(); i++) {
+ addReleaseFence(mGE2DRenderSortedLayerIds.itemAt(i), HwcFenceControl::dupFence(mTargetAcquireFence));
+ }
+ // HwcFenceControl::traceFenceInfo(mTargetAcquireFence);
+ // dumpLayers(mGE2DRenderSortedLayerIds);
+ if (mGE2DComposeFrameCount < 3) {
+ mGE2DComposeFrameCount++;
+ }
+ mClientTargetHnd = mComposer->getBufHnd();
+ fbInfo->yOffset = mFbSlot;
+ return;
}
- return HWC2_ERROR_NONE;
+ ETRACE("Didn't find ge2d compose layers!");
}
-int32_t PhysicalDevice::postFramebuffer(int32_t* outRetireFence) {
+int32_t PhysicalDevice::postFramebuffer(int32_t* outRetireFence, bool hasVideoOverlay) {
HwcLayer* layer = NULL;
- int32_t err = 0;
void *cbuffer;
// deal physical display's client target layer
- framebuffer_info_t* cbinfo = mCursorContext->getCursorInfo();
+ framebuffer_info_t fbInfo = *(mFramebufferContext->getInfo());
+ framebuffer_info_t* cbInfo = mCursorContext->getInfo();
bool cursorShow = false;
for (uint32_t i=0; i<mHwcLayers.size(); i++) {
hwc2_layer_t layerId = mHwcLayers.keyAt(i);
layer = mHwcLayers.valueAt(i);
if (layer && layer->getCompositionType()== HWC2_COMPOSITION_CURSOR) {
- if (private_handle_t::validate(layer->getBufferHandle()) < 0) {
+ private_handle_t *hnd = (private_handle_t *)(layer->getBufferHandle());
+ if (private_handle_t::validate(hnd) < 0) {
ETRACE("invalid cursor layer handle.");
break;
}
- private_handle_t *hnd = (private_handle_t *)(layer->getBufferHandle());
DTRACE("This is a Sprite, hnd->stride is %d, hnd->height is %d", hnd->stride, hnd->height);
- if (cbinfo->info.xres != (uint32_t)hnd->stride || cbinfo->info.yres != (uint32_t)hnd->height) {
+ if (cbInfo->info.xres != (uint32_t)hnd->stride || cbInfo->info.yres != (uint32_t)hnd->height) {
ETRACE("disp: %d cursor need to redrew", mId);
- update_cursor_buffer_locked(cbinfo, hnd->stride, hnd->height);
- cbuffer = mmap(NULL, hnd->size, PROT_READ|PROT_WRITE, MAP_SHARED, cbinfo->fd, 0);
+ update_cursor_buffer_locked(cbInfo, hnd->stride, hnd->height);
+ cbuffer = mmap(NULL, hnd->size, PROT_READ|PROT_WRITE, MAP_SHARED, cbInfo->fd, 0);
if (cbuffer != MAP_FAILED) {
memcpy(cbuffer, hnd->base, hnd->size);
munmap(cbuffer, hnd->size);
@@ -491,68 +645,122 @@ int32_t PhysicalDevice::postFramebuffer(int32_t* outRetireFence) {
}
}
+ if (mRenderMode == GLES_COMPOSE_MODE) {
+ /*private_handle_t const* buffer = reinterpret_cast<private_handle_t const*>(mClientTargetHnd);
+ if (buffer && private_handle_t::validate(buffer) == 0) {
+ uint32_t slot = buffer->offset / fbInfo.finfo.line_length;
+ mComposer->setCurGlesFbSlot(slot);
+ DTRACE("GLES compose Slot: %d", slot);
+ }*/
+ } else if (mRenderMode == DIRECT_COMPOSE_MODE) { // if only one layer exists, let hwc do her work.
+ directCompose(&fbInfo);
+ /* if (mGE2DComposeFrameCount != 0) {
+ addReleaseFence(mDirectRenderLayerId, HwcFenceControl::dupFence(mPriorFrameRetireFence));
+ }*/
+ } else if (mRenderMode == GE2D_COMPOSE_MODE) {
+ ge2dCompose(&fbInfo, hasVideoOverlay);
+ }
+ fbInfo.renderMode = mRenderMode;
+
+ if (hasVideoOverlay && mHwcLayers.size() == 1) {
+ fbInfo.op |= 0x00000001;
+ } else {
+ fbInfo.op &= ~0x00000001;
+ }
+
if (!mClientTargetHnd || private_handle_t::validate(mClientTargetHnd) < 0 || mPowerMode == HWC2_POWER_MODE_OFF) {
DTRACE("mClientTargetHnd is null or Enter suspend state, mTargetAcquireFence: %d", mTargetAcquireFence);
- if (mTargetAcquireFence > -1) {
- sync_wait(mTargetAcquireFence, 5000);
- close(mTargetAcquireFence);
- mTargetAcquireFence = -1;
- }
- *outRetireFence = -1;
+ *outRetireFence = HwcFenceControl::merge(String8("Layer"), mPriorFrameRetireFence, mTargetAcquireFence);
+ HwcFenceControl::closeFd(mTargetAcquireFence);
+ mTargetAcquireFence = -1;
+ HwcFenceControl::closeFd(mPriorFrameRetireFence);
+ mPriorFrameRetireFence = -1;
if (private_handle_t::validate(mClientTargetHnd) < 0) {
ETRACE("mClientTargetHnd is not validate!");
- return HWC2_ERROR_NONE;
}
- }
+ } else {
+ *outRetireFence = HwcFenceControl::dupFence(mPriorFrameRetireFence);
+ if (*outRetireFence >= 0) {
+ DTRACE("Get prior frame's retire fence %d", *outRetireFence);
+ } else {
+ ETRACE("No valid prior frame's retire returned. %d ", *outRetireFence);
+ // -1 means no fence, less than -1 is some error
+ *outRetireFence = -1;
+ }
+ HwcFenceControl::closeFd(mPriorFrameRetireFence);
+ mPriorFrameRetireFence = -1;
- *outRetireFence = mPriorFrameRetireFence;
+ // real post framebuffer here.
+ DTRACE("fbInfo->renderMode: %d", fbInfo.renderMode);
+ mPriorFrameRetireFence = fb_post_with_fence_locked(&fbInfo, mClientTargetHnd, mTargetAcquireFence);
+ mTargetAcquireFence = -1;
- if (*outRetireFence >= 0) {
- DTRACE("Get prior frame's retire fence %d", *outRetireFence);
- } else {
- ETRACE("No valid prior frame's retire returned. %d ", *outRetireFence);
- // -1 means no fence, less than -1 is some error
- *outRetireFence = -1;
- }
+ if (mRenderMode == GE2D_COMPOSE_MODE) {
+ mComposer->mergeRetireFence(mFbSlot, HwcFenceControl::dupFence(mPriorFrameRetireFence));
+ } else {
+ if (mGE2DComposeFrameCount != 0) {
+ mComposer->removeRetireFence(mFbSlot);
+ }
+
+ if (mRenderMode == DIRECT_COMPOSE_MODE) {
+ addReleaseFence(mDirectRenderLayerId, HwcFenceControl::dupFence(mPriorFrameRetireFence));
+ }
+ }
- mPriorFrameRetireFence = fb_post_with_fence_locked(mFramebufferInfo, mClientTargetHnd, mTargetAcquireFence);
- mTargetAcquireFence = -1;
+ // finally we need to update cursor's blank status.
+ if (cbInfo->fd > 0 && cursorShow != mCursorContext->getStatus()) {
+ mCursorContext->setStatus(cursorShow);
+ DTRACE("UPDATE FB1 status to %d", !cursorShow);
+ ioctl(cbInfo->fd, FBIOBLANK, !cursorShow);
+ }
+ }
- // finally we need to update cursor's blank status
- if (cbinfo->fd > 0 && cursorShow != mCursorContext->getCursorStatus()) {
- mCursorContext->setCursorStatus(cursorShow);
- DTRACE("UPDATE FB1 status to %d", !cursorShow);
- ioctl(cbinfo->fd, FBIOBLANK, !cursorShow);
+ if (mRenderMode != GE2D_COMPOSE_MODE) {
+ mGE2DComposeFrameCount = 0;
}
- return err;
+ return HWC2_ERROR_NONE;
}
-
int32_t PhysicalDevice::presentDisplay(
int32_t* outRetireFence) {
int32_t err = HWC2_ERROR_NONE;
HwcLayer* layer = NULL;
+ bool hasVideoOverlay = false;
if (mIsValidated) {
// TODO: need improve the way to set video axis.
#if WITH_LIBPLAYER_MODULE
- for (uint32_t i=0; i<mHwcLayers.size(); i++) {
- hwc2_layer_t layerId = mHwcLayers.keyAt(i);
- layer = mHwcLayers.valueAt(i);
-
- if (layer && layer->getCompositionType()== HWC2_COMPOSITION_DEVICE) {
+ ssize_t index = mHwcLayers.indexOfKey(mVideoOverlayLayerId);
+ if (index >= 0) {
+ layer = mHwcLayers.valueFor(mVideoOverlayLayerId);
+ if (layer != NULL) {
layer->presentOverlay();
- break;
+ hasVideoOverlay = true;
+ if (mGE2DClearVideoRegionCount < 3) {
+ mGE2DClearVideoRegionCount++;
+ }
}
+ } else {
+ mGE2DClearVideoRegionCount = 0;
}
#endif
- err = postFramebuffer(outRetireFence);
+ err = postFramebuffer(outRetireFence, hasVideoOverlay);
+
mIsValidated = false;
} else { // display not validate yet.
err = HWC2_ERROR_NOT_VALIDATED;
}
+ // reset layers' acquire fence.
+ for (uint32_t i=0; i<mHwcLayers.size(); i++) {
+ hwc2_layer_t layerId = mHwcLayers.keyAt(i);
+ layer = mHwcLayers.valueAt(i);
+ if (layer != NULL) {
+ layer->resetAcquireFence();
+ }
+ }
+
return err;
}
@@ -567,17 +775,15 @@ int32_t PhysicalDevice::setClientTarget(
int32_t /*android_dataspace_t*/ dataspace,
hwc_region_t damage) {
- if (target && private_handle_t::validate(target) < 0) {
- return HWC2_ERROR_BAD_PARAMETER;
- }
+ if (target && private_handle_t::validate(target) < 0) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
if (NULL != target) {
mClientTargetHnd = target;
mClientTargetDamageRegion = damage;
- if (-1 != acquireFence) {
- mTargetAcquireFence = acquireFence;
- //sync_wait(mTargetAcquireFence, 3000);
- }
+ mTargetAcquireFence = acquireFence;
+ ETRACE("setClientTarget %p, %d", target, acquireFence);
// TODO: HWC2_ERROR_BAD_PARAMETER && dataspace && damage.
} else {
DTRACE("client target is null!, no need to update this frame.");
@@ -611,48 +817,272 @@ bool PhysicalDevice::vsyncControl(bool enabled) {
return mVsyncObserver->control(enabled);
}
+void PhysicalDevice::dumpLayers(Vector < hwc2_layer_t > layerIds) {
+ for (uint32_t x=0; x<layerIds.size(); x++) {
+ HwcLayer* layer = getLayerById(layerIds.itemAt(x));
+ static char const* compositionTypeName[] = {
+ "UNKNOWN",
+ "GLES",
+ "HWC",
+ "SOLID",
+ "HWC_CURSOR",
+ "SIDEBAND"};
+ ALOGE(" %11s | %12" PRIxPTR " | %10d | %02x | %1.2f | %02x | %04x |%7.1f,%7.1f,%7.1f,%7.1f |%5d,%5d,%5d,%5d \n",
+ compositionTypeName[layer->getCompositionType()],
+ intptr_t(layer->getBufferHandle()), layer->getZ(), layer->getDataspace(),
+ layer->getPlaneAlpha(), layer->getTransform(), layer->getBlendMode(),
+ layer->getSourceCrop().left, layer->getSourceCrop().top, layer->getSourceCrop().right, layer->getSourceCrop().bottom,
+ layer->getDisplayFrame().left, layer->getDisplayFrame().top, layer->getDisplayFrame().right, layer->getDisplayFrame().bottom);
+ }
+}
+
+void PhysicalDevice::dumpLayers(KeyedVector<hwc2_layer_t, HwcLayer*> layers) {
+ for (uint32_t x=0; x<layers.size(); x++) {
+ HwcLayer* layer = layers.valueAt(x);
+ static char const* compositionTypeName[] = {
+ "UNKNOWN",
+ "GLES",
+ "HWC",
+ "SOLID",
+ "HWC_CURSOR",
+ "SIDEBAND"};
+ ALOGE(" %11s | %12" PRIxPTR " | %10d | %02x | %1.2f | %02x | %04x |%7.1f,%7.1f,%7.1f,%7.1f |%5d,%5d,%5d,%5d \n",
+ compositionTypeName[layer->getCompositionType()],
+ intptr_t(layer->getBufferHandle()), layer->getZ(), layer->getDataspace(),
+ layer->getPlaneAlpha(), layer->getTransform(), layer->getBlendMode(),
+ layer->getSourceCrop().left, layer->getSourceCrop().top, layer->getSourceCrop().right, layer->getSourceCrop().bottom,
+ layer->getDisplayFrame().left, layer->getDisplayFrame().top, layer->getDisplayFrame().right, layer->getDisplayFrame().bottom);
+ }
+}
+
+bool PhysicalDevice::layersStateCheck(int32_t renderMode,
+ KeyedVector<hwc2_layer_t, HwcLayer*> & composeLayers) {
+ bool ret = false;
+ uint32_t layerNum = composeLayers.size();
+ hwc_frect_t sourceCrop[GE2D_COMPOSE_MAX_LAYERS];
+ HwcLayer* layer[GE2D_COMPOSE_MAX_LAYERS] = { NULL, NULL, NULL };
+ private_handle_t const* hnd[GE2D_COMPOSE_MAX_LAYERS] = { NULL, NULL, NULL };
+ hwc_rect_t displayFrame[GE2D_COMPOSE_MAX_LAYERS];
+
+ for (int32_t i=0; i<layerNum; i++) {
+ layer[i] = composeLayers.valueAt(i);
+ sourceCrop[i] = layer[i]->getSourceCrop();
+ displayFrame[i] = layer[i]->getDisplayFrame();
+ hnd[i] = reinterpret_cast<private_handle_t const*>(layer[i]->getBufferHandle());
+ ALOGD("layer[%d] zorder: %d, blend: %d, PlaneAlpha: %f, "
+ "mColor: [%d, %d, %d, %d], mDataSpace: %d, format hnd[%d]: %x",
+ i, layer[i]->getZ(), layer[i]->getBlendMode(), layer[i]->getPlaneAlpha(),
+ layer[i]->getColor().r, layer[i]->getColor().g, layer[i]->getColor().b,
+ layer[i]->getColor().a, layer[i]->getDataspace(), i, hnd[i]->format);
+ }
+
+ if (renderMode == DIRECT_COMPOSE_MODE) {
+ switch (hnd[0]->format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_RGB_888:
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ ALOGD("Layer format match direct composer.");
+ ret = true;
+ break;
+ default:
+ ALOGD("Layer format not support by direct compose");
+ return false;
+ break;
+ }
+ if (layer[0]->isCropped()
+ || layer[0]->isScaled()
+ || layer[0]->isOffset()) {
+ ALOGD("direct compose can not process!");
+ return false;
+ }
+ }else if (renderMode == GE2D_COMPOSE_MODE) {
+ bool yuv420Sp = false;
+ for (int32_t i=0; i<layerNum; i++) {
+ switch (hnd[i]->format) {
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ yuv420Sp = true;
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_RGB_888:
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_Y8:
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ case HAL_PIXEL_FORMAT_YCbCr_422_I:
+ ALOGD("Layer format match ge2d composer.");
+ ret = true;
+ break;
+ default:
+ ALOGD("Layer format not support by ge2d");
+ return false;
+ break;
+ }
+ if (layer[i]->havePlaneAlpha()
+ || layer[i]->haveColor()
+ || layer[i]->haveDataspace()
+ || (layer[i]->isBlended()
+ && layer[i]->isScaled())) {
+ ALOGD("ge2d compose can not process!");
+ return false;
+ }
+ }
+
+ if (yuv420Sp && GE2D_COMPOSE_TWO_LAYERS == layerNum) {
+ if (Utils::compareRect(sourceCrop[0], sourceCrop[1])
+ && Utils::compareRect(sourceCrop[0], displayFrame[0])
+ && Utils::compareRect(sourceCrop[1], displayFrame[1])) {
+ ALOGD("2 layers is same size and have yuv420sp format ge2d compose can not process!");
+ return false;
+ }
+
+ }
+ }
+
+ return ret;
+}
+
+/*************************************************************
+ * For direct framebuffer composer:
+ * 1) only support one layer.
+ * 2) layer format: rgba, rgbx,rgb565,bgra;
+ * 3) layer no need scale to display;
+ * 4) layer has no offset to display; (will support later.)
+
+ * For ge2d composer:
+ * 1) support layer format that direct composer can't support.
+ * 2) support 2 layers blending.
+ * 3) support scale and rotation etc.
+**************************************************************/
+int32_t PhysicalDevice::composersFilter(
+ KeyedVector<hwc2_layer_t, HwcLayer*> & composeLayers) {
+
+ // direct Composer.
+ if (composeLayers.size() == GE2D_COMPOSE_ONE_LAYER) {
+ // if only one layer exists, do direct framebuffer composer.
+ bool directCompose = layersStateCheck(DIRECT_COMPOSE_MODE, composeLayers);
+ if (directCompose) {
+ hwc2_layer_t layerGlesLayerId = composeLayers.keyAt(0);
+ composeLayers.clear();
+ mDirectRenderLayerId = layerGlesLayerId;
+ return DIRECT_COMPOSE_MODE;
+ }
+ }
+
+ // if direct composer can't work, try this.
+ if (composeLayers.size() > GE2D_COMPOSE_NO_LAYER
+ && composeLayers.size() < GE2D_COMPOSE_MAX_LAYERS) {
+ bool ge2dCompose = layersStateCheck(GE2D_COMPOSE_MODE, composeLayers);
+ if (!ge2dCompose) return GLES_COMPOSE_MODE;
+ mGE2DRenderSortedLayerIds.clear();
+ for (uint32_t i=0; i<composeLayers.size(); i++) {
+ hwc2_layer_t layerGlesLayerId = composeLayers.keyAt(i);
+ HwcLayer* layer = getLayerById(layerGlesLayerId);
+ if (0 == i) {
+ mGE2DRenderSortedLayerIds.push_front(layerGlesLayerId);
+ continue;
+ }
+ for (uint32_t j=0; j<i; j++) {
+ HwcLayer* layer1 = getLayerById(mGE2DRenderSortedLayerIds.itemAt(j));
+ HwcLayer* layer2 = getLayerById(layerGlesLayerId);
+ if (layer1 != NULL && layer2 != NULL) {
+ uint32_t z1 = layer1->getZ();
+ uint32_t z2 = layer2->getZ();
+ if (layer1->getZ() > layer2->getZ()) {
+ mGE2DRenderSortedLayerIds.insertAt(layerGlesLayerId, j, 1);
+ break;
+ }
+ if (j == i-1) mGE2DRenderSortedLayerIds.push_back(layerGlesLayerId);
+ } else {
+ ETRACE("Layer1 or Layer2 is NULL!!!");
+ }
+ }
+ }
+
+ // Vector < hwc2_layer_t > layerIds;
+ if (!mComposer) {
+ // create ge2d composer...
+ mComposer = mControlFactory->createComposer(*this);
+ if (!mComposer || !mComposer->initialize(mFramebufferContext->getInfo())) {
+ DEINIT_AND_DELETE_OBJ(mComposer);
+ return GLES_COMPOSE_MODE;
+ }
+ }
+ composeLayers.clear();
+ return GE2D_COMPOSE_MODE;
+ }
+
+ return GLES_COMPOSE_MODE;
+}
+
+void PhysicalDevice::clearFramebuffer() {
+ hwc_rect_t clipRect;
+ framebuffer_info_t* fbInfo = mFramebufferContext->getInfo();
+ uint32_t addr = getIonPhyAddr(fbInfo, mFramebufferHnd);
+ clipRect.left = 0;
+ clipRect.top = 0;
+ clipRect.right = fbInfo->info.xres;
+ clipRect.bottom = fbInfo->info.yres_virtual;
+ mComposer->fillRectangle(clipRect, 0, addr);
+
+ DTRACE("Composer mode: %d, %d layers", mRenderMode, mHwcLayers.size());
+}
+
int32_t PhysicalDevice::validateDisplay(uint32_t* outNumTypes,
uint32_t* outNumRequests) {
HwcLayer* layer = NULL;
bool istvp = false;
+ bool glesCompose = false;
+ bool isContinuousBuf = true;
+
+ mRenderMode = GLES_COMPOSE_MODE;
+ mVideoOverlayLayerId = 0;
+ swapReleaseFence();
for (uint32_t i=0; i<mHwcLayers.size(); i++) {
hwc2_layer_t layerId = mHwcLayers.keyAt(i);
layer = mHwcLayers.valueAt(i);
- if (layer) {
+ if (layer != NULL) {
// Physical Display.
- if (layer->getCompositionType() == HWC2_COMPOSITION_DEVICE) {
- // video overlay.
- if (layer->getBufferHandle()) {
- private_handle_t const* hnd =
- reinterpret_cast<private_handle_t const*>(layer->getBufferHandle());
+ private_handle_t const* hnd =
+ reinterpret_cast<private_handle_t const*>(layer->getBufferHandle());
+ if (hnd) {
+ if (!(hnd->flags & private_handle_t::PRIV_FLAGS_CONTINUOUS_BUF)) {
+ ALOGE("continous buffer flag is not set!");
+ isContinuousBuf = false;
+ }
+ if (hnd && layer->getCompositionType() == HWC2_COMPOSITION_DEVICE) {
+ // video overlay.
if (hnd->flags & private_handle_t::PRIV_FLAGS_VIDEO_OMX) {
set_omx_pts((char*)hnd->base, &Amvideo_Handle);
istvp = true;
}
if (hnd->flags & private_handle_t::PRIV_FLAGS_VIDEO_OVERLAY) {
+ ETRACE("PRIV_FLAGS_VIDEO_OVERLAY!!!!");
+ mVideoOverlayLayerId = layerId;
mHwcLayersChangeRequest.add(layerId, layer);
continue;
}
- }
- // change all other device type to client.
- mHwcLayersChangeType.add(layerId, layer);
- continue;
+ mHwcGlesLayers.add(layerId, layer);
+ continue;
+ }
}
// cursor layer.
if (layer->getCompositionType() == HWC2_COMPOSITION_CURSOR) {
- DTRACE("This is a Cursor layer!");
+ ETRACE("This is a Cursor layer!");
mHwcLayersChangeRequest.add(layerId, layer);
continue;
}
// sideband stream.
if (layer->getCompositionType() == HWC2_COMPOSITION_SIDEBAND
- && layer->getSidebandStream()) {
+ && layer->getSidebandStream()) {
// TODO: we just transact SIDEBAND to OVERLAY for now;
- DTRACE("get HWC_SIDEBAND layer, just change to overlay");
+ ETRACE("get HWC_SIDEBAND layer, just change to overlay");
mHwcLayersChangeRequest.add(layerId, layer);
mHwcLayersChangeType.add(layerId, layer);
continue;
@@ -660,28 +1090,57 @@ int32_t PhysicalDevice::validateDisplay(uint32_t* outNumTypes,
// TODO: solid color.
if (layer->getCompositionType() == HWC2_COMPOSITION_SOLID_COLOR) {
- DTRACE("This is a Solid Color layer!");
- //mHwcLayersChangeRequest.add(layerId, layer);
- mHwcLayersChangeType.add(layerId, layer);
+ ETRACE("This is a Solid Color layer!");
+ // mHwcLayersChangeRequest.add(layerId, layer);
+ // mHwcLayersChangeType.add(layerId, layer);
+ mHwcGlesLayers.add(layerId, layer);
continue;
}
+
+ if (layer->getCompositionType() == HWC2_COMPOSITION_CLIENT) {
+ ETRACE("Meet a client layer!");
+ glesCompose = true;
+ }
}
}
+ bool noDevComp = Utils::checkBoolProp("sys.sf.debug.nohwc");
+#ifndef USE_CONTINOUS_BUFFER_COMPOSER
+ ALOGE("No continous buffer composer!");
+ noDevComp = true;
+#endif
+
+ // dumpLayers(mHwcLayers);
+ if (isContinuousBuf && !glesCompose && !noDevComp) {
+ mRenderMode = composersFilter(mHwcGlesLayers);
+ }
+
+ if (mHwcLayers.size() == 0 && mComposer) {
+ clearFramebuffer();
+ }
+
+ if (mHwcGlesLayers.size() > 0) {
+ for (int i=0;i<mHwcGlesLayers.size(); i++) {
+ mHwcLayersChangeType.add(mHwcGlesLayers.keyAt(i), mHwcGlesLayers.valueAt(i));
+ }
+ mHwcGlesLayers.clear();
+ }
+
if (istvp == false && Amvideo_Handle!=0) {
closeamvideo();
Amvideo_Handle = 0;
}
if (mHwcLayersChangeRequest.size() > 0) {
- DTRACE("There are %d layer requests.", mHwcLayersChangeRequest.size());
+ ETRACE("There are %d layer requests.", mHwcLayersChangeRequest.size());
*outNumRequests = mHwcLayersChangeRequest.size();
}
// mark the validate function is called.(???)
mIsValidated = true;
+
if (mHwcLayersChangeType.size() > 0) {
- DTRACE("there are %d layer types has changed.", mHwcLayersChangeType.size());
+ ETRACE("there are %d layer types has changed.", mHwcLayersChangeType.size());
*outNumTypes = mHwcLayersChangeType.size();
return HWC2_ERROR_HAS_CHANGES;
}
@@ -692,15 +1151,15 @@ int32_t PhysicalDevice::validateDisplay(uint32_t* outNumTypes,
int32_t PhysicalDevice::setCursorPosition(hwc2_layer_t layerId, int32_t x, int32_t y) {
HwcLayer* layer = getLayerById(layerId);
if (layer && HWC2_COMPOSITION_CURSOR == layer->getCompositionType()) {
- framebuffer_info_t* cbinfo = mCursorContext->getCursorInfo();
+ framebuffer_info_t* cbInfo = mCursorContext->getInfo();
fb_cursor cinfo;
- if (cbinfo->fd < 0) {
- ETRACE("setCursorPosition fd=%d", cbinfo->fd );
+ if (cbInfo->fd < 0) {
+ ETRACE("setCursorPosition fd=%d", cbInfo->fd );
}else {
cinfo.hot.x = x;
cinfo.hot.y = y;
DTRACE("setCursorPosition x_pos=%d, y_pos=%d", cinfo.hot.x, cinfo.hot.y);
- ioctl(cbinfo->fd, FBIO_CURSOR, &cinfo);
+ ioctl(cbInfo->fd, FBIO_CURSOR, &cinfo);
}
} else {
ETRACE("setCursorPosition bad layer.");
@@ -720,62 +1179,65 @@ int32_t PhysicalDevice::initDisplay() {
Mutex::Autolock _l(mLock);
if (!mFramebufferHnd) {
- mFramebufferInfo = new framebuffer_info_t();
- //init information from osd.
- mFramebufferInfo->displayType = mId;
- mFramebufferInfo->fbIdx = getOsdIdx(mId);
- int32_t err = init_frame_buffer_locked(mFramebufferInfo);
- int32_t bufferSize = mFramebufferInfo->finfo.line_length
- * mFramebufferInfo->info.yres;
+ // init framebuffer context.
+ mFramebufferContext = new FBContext();
+ framebuffer_info_t* fbInfo = mFramebufferContext->getInfo();
+ // init information from osd.
+ fbInfo->displayType = mId;
+ fbInfo->fbIdx = getOsdIdx(mId);
+ int32_t err = init_frame_buffer_locked(fbInfo);
+ int32_t bufferSize = fbInfo->finfo.line_length
+ * fbInfo->info.yres;
DTRACE("init_frame_buffer get fbinfo->fbIdx (%d) "
"fbinfo->info.xres (%d) fbinfo->info.yres (%d)",
- mFramebufferInfo->fbIdx, mFramebufferInfo->info.xres,
- mFramebufferInfo->info.yres);
+ fbInfo->fbIdx, fbInfo->info.xres,
+ fbInfo->info.yres);
int32_t usage = 0;
private_module_t *grallocModule = Hwcomposer::getInstance().getGrallocModule();
if (mId == HWC_DISPLAY_PRIMARY) {
- grallocModule->fb_primary.fb_info = *(mFramebufferInfo);
+ grallocModule->fb_primary.fb_info = *(fbInfo);
} else if (mId == HWC_DISPLAY_EXTERNAL) {
- grallocModule->fb_external.fb_info = *(mFramebufferInfo);
+ grallocModule->fb_external.fb_info = *(fbInfo);
usage |= GRALLOC_USAGE_EXTERNAL_DISP;
}
+ fbInfo->grallocModule = grallocModule;
//Register the framebuffer to gralloc module
mFramebufferHnd = new private_handle_t(
private_handle_t::PRIV_FLAGS_FRAMEBUFFER,
- usage, mFramebufferInfo->fbSize, 0,
- 0, mFramebufferInfo->fd, bufferSize, 0);
+ usage, fbInfo->fbSize, 0,
+ 0, fbInfo->fd, bufferSize, 0);
grallocModule->base.registerBuffer(&(grallocModule->base), mFramebufferHnd);
DTRACE("init_frame_buffer get frame size %d usage %d",
- bufferSize,usage);
+ bufferSize, usage);
}
mIsConnected = true;
// init cursor framebuffer
- mCursorContext = new CursorContext();
- framebuffer_info_t* cbinfo = mCursorContext->getCursorInfo();
- cbinfo->fd = -1;
+ mCursorContext = new FBContext();
+ framebuffer_info_t* cbInfo = mCursorContext->getInfo();
+ cbInfo->fd = -1;
//init information from cursor framebuffer.
- cbinfo->fbIdx = mId*2+1;
- if (1 != cbinfo->fbIdx && 3 != cbinfo->fbIdx) {
+ cbInfo->fbIdx = mId*2+1;
+ if (1 != cbInfo->fbIdx && 3 != cbInfo->fbIdx) {
ETRACE("invalid fb index: %d, need to check!",
- cbinfo->fbIdx);
+ cbInfo->fbIdx);
return 0;
}
- int32_t err = init_cursor_buffer_locked(cbinfo);
+ int32_t err = init_cursor_buffer_locked(cbInfo);
if (err != 0) {
ETRACE("init_cursor_buffer_locked failed, need to check!");
return 0;
}
ITRACE("init_cursor_buffer get cbinfo->fbIdx (%d) "
"cbinfo->info.xres (%d) cbinfo->info.yres (%d)",
- cbinfo->fbIdx,
- cbinfo->info.xres,
- cbinfo->info.yres);
+ cbInfo->fbIdx,
+ cbInfo->info.xres,
+ cbInfo->info.yres);
- if ( cbinfo->fd >= 0) {
+ if ( cbInfo->fd >= 0) {
DTRACE("init_cursor_buffer success!");
}else{
DTRACE("init_cursor_buffer fail!");
@@ -813,7 +1275,8 @@ bool PhysicalDevice::updateDisplayConfigs()
}
ETRACE("output mode refresh rate: %d", rate);
- ret |= Utils::checkVinfo(mFramebufferInfo);
+ framebuffer_info_t* fbinfo = mFramebufferContext->getInfo();
+ ret |= Utils::checkVinfo(fbinfo);
if (ret) {
// reset display configs
@@ -823,10 +1286,10 @@ bool PhysicalDevice::updateDisplayConfigs()
// use active fb dimension as config width/height
DisplayConfig *config = new DisplayConfig(rate,
- mFramebufferInfo->info.xres,
- mFramebufferInfo->info.yres,
- mFramebufferInfo->xdpi,
- mFramebufferInfo->ydpi);
+ fbinfo->info.xres,
+ fbinfo->info.yres,
+ fbinfo->xdpi,
+ fbinfo->ydpi);
// add it to the front of other configs
mDisplayConfigs.push_front(config);
@@ -980,7 +1443,7 @@ exit:
void PhysicalDevice::dump(Dump& d) {
Mutex::Autolock _l(mLock);
d.append("-------------------------------------------------------------"
- "------------------------------------------------------------\n");
+ "----------------------------------------------------------------\n");
d.append("Device Name: %s (%s)\n", mName,
mIsConnected ? "connected" : "disconnected");
d.append(" CONFIG | VSYNC_PERIOD | WIDTH | HEIGHT |"
@@ -1005,14 +1468,14 @@ void PhysicalDevice::dump(Dump& d) {
// dump layer list
d.append(" Layers state:\n");
d.append(" numLayers=%zu\n", mHwcLayers.size());
- d.append(" numChangedTypeLayers=%zu\n", mHwcLayersChangeType.size());
- d.append(" numChangedRequestLayers=%zu\n", mHwcLayersChangeRequest.size());
+ // d.append(" numChangedTypeLayers=%zu\n", mHwcLayersChangeType.size());
+ // d.append(" numChangedRequestLayers=%zu\n", mHwcLayersChangeRequest.size());
if (mHwcLayers.size() > 0) {
d.append(
- " type | handle | zorder | ds | alpa | tr | blnd |"
+ " type | handle | zorder | ds | alpa | tr | blnd |"
" source crop (l,t,r,b) | frame \n"
- " -------------+----------+------------+----+------+----+------+"
+ " -------------+--------------+------------+----+------+----+------+"
"--------------------------------+------------------------\n");
for (uint32_t i=0; i<mHwcLayers.size(); i++) {
hwc2_layer_t layerId = mHwcLayers.keyAt(i);
diff --git a/hwc2/common/devices/PrimaryDevice.cpp b/hwc2/common/devices/PrimaryDevice.cpp
index 8f5b434..f49ebae 100644
--- a/hwc2/common/devices/PrimaryDevice.cpp
+++ b/hwc2/common/devices/PrimaryDevice.cpp
@@ -1,5 +1,17 @@
/*
-// Copyright(c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 <HwcTrace.h>
@@ -10,8 +22,8 @@
namespace android {
namespace amlogic {
-PrimaryDevice::PrimaryDevice(Hwcomposer& hwc)
- : PhysicalDevice(DEVICE_PRIMARY, hwc)
+PrimaryDevice::PrimaryDevice(Hwcomposer& hwc, DeviceControlFactory* controlFactory)
+ : PhysicalDevice(DEVICE_PRIMARY, hwc, controlFactory)
{
CTRACE();
}
diff --git a/hwc2/common/devices/VirtualDevice.cpp b/hwc2/common/devices/VirtualDevice.cpp
index a141582..dd64ded 100644
--- a/hwc2/common/devices/VirtualDevice.cpp
+++ b/hwc2/common/devices/VirtualDevice.cpp
@@ -1,6 +1,19 @@
/*
-// Copyright(c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 <HwcTrace.h>
#include <Hwcomposer.h>
#include <VirtualDevice.h>
@@ -465,7 +478,7 @@ int32_t VirtualDevice::setOutputBuffer(
void VirtualDevice::dump(Dump& d) {
Mutex::Autolock _l(mLock);
d.append("----------------------------------------------------------"
- "---------------------------------------------------------------\n");
+ "-------------------------------------------------------------------\n");
d.append("Device Name: %s (%s)\n", mName,
mIsConnected ? "connected" : "disconnected");
@@ -475,9 +488,9 @@ void VirtualDevice::dump(Dump& d) {
d.append(" numChangedTypeLayers=%zu\n", mHwcLayersChangeType.size());
if (mHwcLayers.size() > 0) {
d.append(
- " type | handle | zorder | ds | alpa | tr | blnd |"
+ " type | handle | zorder | ds | alpa | tr | blnd |"
" source crop (l,t,r,b) | frame \n"
- " -------------+----------+------------+----+------+----+------+"
+ " -------------+--------------+------------+----+------+----+------+"
"--------------------------------+------------------------\n");
for (uint32_t i=0; i<mHwcLayers.size(); i++) {
hwc2_layer_t layerId = mHwcLayers.keyAt(i);
diff --git a/hwc2/common/observers/SoftVsyncObserver.cpp b/hwc2/common/observers/SoftVsyncObserver.cpp
index 44cda76..7fc3ecb 100644
--- a/hwc2/common/observers/SoftVsyncObserver.cpp
+++ b/hwc2/common/observers/SoftVsyncObserver.cpp
@@ -1,5 +1,17 @@
/*
-// Copyright(c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 <HwcTrace.h>
diff --git a/hwc2/common/observers/SoftVsyncObserver.h b/hwc2/common/observers/SoftVsyncObserver.h
index 027e8e3..6cf1c2b 100644
--- a/hwc2/common/observers/SoftVsyncObserver.h
+++ b/hwc2/common/observers/SoftVsyncObserver.h
@@ -1,5 +1,17 @@
/*
-// Copyright(c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 SOFT_VSYNC_OBSERVER_H
diff --git a/hwc2/common/observers/UeventObserver.cpp b/hwc2/common/observers/UeventObserver.cpp
index ea64c86..7d9d3c5 100644
--- a/hwc2/common/observers/UeventObserver.cpp
+++ b/hwc2/common/observers/UeventObserver.cpp
@@ -1,5 +1,17 @@
/*
-// Copyright(c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 <poll.h>
diff --git a/hwc2/common/utils/Dump.cpp b/hwc2/common/utils/Dump.cpp
index e9809bd..da06f38 100644
--- a/hwc2/common/utils/Dump.cpp
+++ b/hwc2/common/utils/Dump.cpp
@@ -1,5 +1,17 @@
/*
-// Copyright (c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 <stdarg.h>
diff --git a/hwc2/common/utils/Dump.h b/hwc2/common/utils/Dump.h
index 7f97317..ea4fce5 100644
--- a/hwc2/common/utils/Dump.h
+++ b/hwc2/common/utils/Dump.h
@@ -1,6 +1,19 @@
/*
-// Copyright (c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 DUMP_H_
#define DUMP_H_
diff --git a/hwc2/common/utils/HwcTrace.h b/hwc2/common/utils/HwcTrace.h
index 6041cf2..7b913cb 100644
--- a/hwc2/common/utils/HwcTrace.h
+++ b/hwc2/common/utils/HwcTrace.h
@@ -1,6 +1,19 @@
/*
-// Copyright(c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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_TRACE_H
#define HWC_TRACE_H
@@ -13,8 +26,8 @@
extern "C" {
#endif
-//#define DEBUG
-#ifdef DEBUG
+// #define HWC_DEBUG
+#ifdef HWC_DEBUG
// Helper to automatically preappend classname::functionname to the log message
#define VTRACE(fmt,...) ALOGV("%s: " fmt, __func__, ##__VA_ARGS__)
#define DTRACE(fmt,...) ALOGD("%s: " fmt, __func__, ##__VA_ARGS__)
diff --git a/hwc2/common/utils/Utils.cpp b/hwc2/common/utils/Utils.cpp
index 9af81fc..9104e17 100644
--- a/hwc2/common/utils/Utils.cpp
+++ b/hwc2/common/utils/Utils.cpp
@@ -49,18 +49,18 @@ int32_t Utils::checkIntProp(const char* prop) {
return 0;
}
-int32_t Utils::checkAndDupFence(int32_t fence) {
- if (fence < 0) {
- ETRACE("not a vliad fence %d",fence);
+int32_t Utils::checkAndDupFd(int32_t fd) {
+ if (fd < 0) {
+ ETRACE("not a vliad fd %d", fd);
return -1;
}
- int32_t dup_fence = dup(fence);
- if (dup_fence < 0) {
- ETRACE("fence dup failed: %s", strerror(errno));
+ int32_t dup_fd = ::dup(fd);
+ if (dup_fd < 0) {
+ ETRACE("fd dup failed: %s", strerror(errno));
}
- return dup_fence;
+ return dup_fd;
}
#if WITH_LIBPLAYER_MODULE
@@ -117,32 +117,32 @@ bool Utils::checkOutputMode(char* curmode, int32_t* rate) {
return true;
}
-bool Utils::checkVinfo(framebuffer_info_t *fbinfo) {
- if (fbinfo != NULL && fbinfo->fd >= 0) {
+bool Utils::checkVinfo(framebuffer_info_t *fbInfo) {
+ if (fbInfo != NULL && fbInfo->fd >= 0) {
struct fb_var_screeninfo vinfo;
- if (ioctl(fbinfo->fd, FBIOGET_VSCREENINFO, &vinfo) == -1)
+ if (ioctl(fbInfo->fd, FBIOGET_VSCREENINFO, &vinfo) == -1)
{
ALOGE("FBIOGET_VSCREENINFO error!!!");
return -errno;
}
- if (vinfo.xres != fbinfo->info.xres
- || vinfo.yres != fbinfo->info.yres
- || vinfo.width != fbinfo->info.width
- || vinfo.height != fbinfo->info.height) {
+ if (vinfo.xres != fbInfo->info.xres
+ || vinfo.yres != fbInfo->info.yres
+ || vinfo.width != fbInfo->info.width
+ || vinfo.height != fbInfo->info.height) {
if (int32_t(vinfo.width) <= 16 || int32_t(vinfo.height) <= 9) {
// the driver doesn't return that information
// default to 160 dpi
vinfo.width = ((vinfo.xres * 25.4f)/160.0f + 0.5f);
vinfo.height = ((vinfo.yres * 25.4f)/160.0f + 0.5f);
}
- fbinfo->xdpi = (vinfo.xres * 25.4f) / vinfo.width;
- fbinfo->ydpi = (vinfo.yres * 25.4f) / vinfo.height;
+ fbInfo->xdpi = (vinfo.xres * 25.4f) / vinfo.width;
+ fbInfo->ydpi = (vinfo.yres * 25.4f) / vinfo.height;
- fbinfo->info.xres = vinfo.xres;
- fbinfo->info.yres = vinfo.yres;
- fbinfo->info.width = vinfo.width;
- fbinfo->info.height = vinfo.height;
+ fbInfo->info.xres = vinfo.xres;
+ fbInfo->info.yres = vinfo.yres;
+ fbInfo->info.width = vinfo.width;
+ fbInfo->info.height = vinfo.height;
return true;
}
diff --git a/hwc2/common/utils/Utils.h b/hwc2/common/utils/Utils.h
index a6783a6..351fb22 100644
--- a/hwc2/common/utils/Utils.h
+++ b/hwc2/common/utils/Utils.h
@@ -27,7 +27,10 @@ public:
~Utils();
static bool checkBoolProp(const char* prop);
static int32_t checkIntProp(const char* prop);
- static int32_t checkAndDupFence(int32_t fence);
+ static int32_t checkAndDupFd(int32_t fd);
+ static inline void closeFd(int32_t fd) {
+ if (fd > -1) close(fd);
+ }
#if WITH_LIBPLAYER_MODULE
static bool checkSysfsStatus(const char* sysfstr, char* lastr, int32_t size);
#endif
@@ -39,6 +42,39 @@ public:
static const char* getHotplugInString();
static const char* getHotplugOutString();
+ template <typename T, typename S>
+ static inline bool compareRect(T a, S b) {
+ if ((int32_t)a.left == (int32_t)b.left
+ && (int32_t)a.top == (int32_t)b.top
+ && (int32_t)a.right == (int32_t)b.right
+ && (int32_t)a.bottom == (int32_t)b.bottom) {
+ return true;
+ }
+ return false;
+ }
+ template <typename T, typename S>
+ static inline bool compareSize(T a, S b) {
+ if ((int32_t)(a.right-a.left) == (int32_t)(b.right-b.left)
+ && (int32_t)(a.bottom-a.top) == (int32_t)(b.bottom-b.top)) {
+ return true;
+ }
+ return false;
+ }
+ template <typename T>
+ static inline T min(T a, T b) {
+ return a<b ? a : b;
+ }
+ template <typename T>
+ static inline T max(T a, T b) {
+ return a>b ? a : b;
+ }
+ template <typename T>
+ static inline void swap(T& a, T& b) {
+ T t = a;
+ a = b;
+ b = t;
+ }
+
};
} // namespace amlogic
diff --git a/hwc2/include/ExternalDevice.h b/hwc2/include/ExternalDevice.h
index 346005b..f743690 100644
--- a/hwc2/include/ExternalDevice.h
+++ b/hwc2/include/ExternalDevice.h
@@ -1,6 +1,19 @@
/*
-// Copyright (c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 EXTERNAL_DEVICE_H
#define EXTERNAL_DEVICE_H
diff --git a/hwc2/include/HwcFenceControl.h b/hwc2/include/HwcFenceControl.h
new file mode 100644
index 0000000..ed0e380
--- a/dev/null
+++ b/hwc2/include/HwcFenceControl.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * 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_FENCE_H
+#define HWC_FENCE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/String8.h>
+#include <utils/Timers.h>
+#include <utils/StrongPointer.h>
+#include <utils/RefBase.h>
+
+
+namespace android {
+namespace amlogic {
+
+
+// ===========================================================================
+// HwcFenceControl
+// ===========================================================================
+
+class HwcFenceControl
+ : public LightRefBase<HwcFenceControl>
+{
+public:
+ static const sp<HwcFenceControl> NO_FENCE;
+
+ // TIMEOUT_NEVER may be passed to the wait method to indicate that it
+ // should wait indefinitely for the fence to signal.
+ enum { TIMEOUT_NEVER = -1 };
+
+ // Construct a new Fence object with an invalid file descriptor. This
+ // should be done when the Fence object will be set up by unflattening
+ // serialized data.
+ HwcFenceControl();
+
+ // Construct a new Fence object to manage a given fence file descriptor.
+ // When the new Fence object is destructed the file descriptor will be
+ // closed.
+ HwcFenceControl(int32_t fenceFd);
+
+ // Check whether the Fence has an open fence file descriptor. Most Fence
+ // methods treat an invalid file descriptor just like a valid fence that
+ // is already signalled, so using this is usually not necessary.
+ bool isValid() const { return mFenceFd != -1; }
+
+ // wait waits for up to timeout milliseconds for the fence to signal. If
+ // the fence signals then NO_ERROR is returned. If the timeout expires
+ // before the fence signals then -ETIME is returned. A timeout of
+ // TIMEOUT_NEVER may be used to indicate that the call should wait
+ // indefinitely for the fence to signal.
+ static status_t wait(int32_t fence, int32_t timeout);
+
+ // waitForever is a convenience function for waiting forever for a fence to
+ // signal (just like wait(TIMEOUT_NEVER)), but issuing an error to the
+ // system log and fence state to the kernel log if the wait lasts longer
+ // than a warning timeout.
+ // The logname argument should be a string identifying
+ // the caller and will be included in the log message.
+ status_t waitForever(const char* logname);
+
+ // fence.
+ static int32_t createFenceTimeline();
+ static int32_t createFence(int32_t syncTimelineFd,char* str, uint32_t val);
+ static status_t syncTimelineInc(int32_t syncTimelineFd);
+ static status_t traceFenceInfo(int32_t fence);
+
+ static inline void closeFd(int32_t fence) {
+ if (fence > -1) {
+ close(fence);
+ }
+ }
+ static inline void waitAndCloseFd(int32_t fence, int32_t timeout) {
+ if (fence > -1) {
+ wait(fence, timeout);
+ close(fence);
+ }
+ }
+
+ // merge combines two Fence objects, creating a new Fence object that
+ // becomes signaled when both f1 and f2 are signaled (even if f1 or f2 is
+ // destroyed before it becomes signaled). The name argument specifies the
+ // human-readable name to associated with the new Fence object.
+ static int32_t merge(const String8& name, const int32_t& f1,
+ const int32_t& f2);
+
+ // Return a duplicate of the fence file descriptor. The caller is
+ // responsible for closing the returned file descriptor. On error, -1 will
+ // be returned and errno will indicate the problem.
+ int32_t dup() const;
+ static int32_t dupFence(int32_t fence);
+
+ int32_t getFenceFd() const;
+
+ // getSignalTime returns the system monotonic clock time at which the
+ // fence transitioned to the signaled state. If the fence is not signaled
+ // then INT64_MAX is returned. If the fence is invalid or if an error
+ // occurs then -1 is returned.
+ nsecs_t getSignalTime() const;
+
+private:
+ // Only allow instantiation using ref counting.
+ friend class LightRefBase<HwcFenceControl>;
+ ~HwcFenceControl();
+
+ // Disallow copying
+ HwcFenceControl(const HwcFenceControl& rhs);
+ HwcFenceControl& operator = (const HwcFenceControl& rhs);
+ const HwcFenceControl& operator = (const HwcFenceControl& rhs) const;
+
+ int32_t mFenceFd;
+};
+
+}; // namespace amlogic
+}; // namespace android
+
+
+#endif // ANDROID_FENCE_H
diff --git a/hwc2/include/Hwcomposer.h b/hwc2/include/Hwcomposer.h
index cec6e74..02bd6a5 100644
--- a/hwc2/include/Hwcomposer.h
+++ b/hwc2/include/Hwcomposer.h
@@ -1,6 +1,19 @@
/*
-// Copyright(c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 HWCOMPOSER_H
#define HWCOMPOSER_H
diff --git a/hwc2/include/IComposer.h b/hwc2/include/IComposer.h
new file mode 100644
index 0000000..f3b6fbe
--- a/dev/null
+++ b/hwc2/include/IComposer.h
@@ -0,0 +1,33 @@
+/*
+// Copyright(c) 2016 Amlogic Corporation
+*/
+#ifndef ICOMPOSER_H
+#define ICOMPOSER_H
+
+#include <HwcLayer.h>
+
+namespace android {
+namespace amlogic {
+
+// aml composer interface
+class IComposer {
+public:
+ IComposer() {}
+ virtual ~IComposer() {}
+public:
+ virtual bool initialize(framebuffer_info_t* fbInfo) = 0;
+ virtual void deinitialize() = 0;
+ virtual int32_t startCompose(Vector< hwc2_layer_t > hwcLayers, int32_t *offset = 0, int32_t frameCount = 0) = 0;
+ virtual const char* getName() const = 0;
+ // virtual void setCurGlesFbSlot(uint32_t slot) = 0;
+ virtual const buffer_handle_t getBufHnd() = 0;
+ virtual void mergeRetireFence(int32_t slot, int32_t retireFence) = 0;
+ virtual void removeRetireFence(int32_t slot) = 0;
+ virtual void setVideoOverlayLayerId(hwc2_layer_t layerId) = 0;
+ virtual void fillRectangle(hwc_rect_t clipRect, uint32_t color, uint32_t addr) = 0;
+};
+
+}
+}
+
+#endif /* IDISPLAY_DEVICE_H */
diff --git a/hwc2/include/IComposerFactory.h b/hwc2/include/IComposerFactory.h
new file mode 100644
index 0000000..856e44c
--- a/dev/null
+++ b/hwc2/include/IComposerFactory.h
@@ -0,0 +1,25 @@
+/*
+// Copyright(c) 2016 Amlogic Corporation
+*/
+#ifndef ICOMPOSER_FACTORY_H_
+#define ICOMPOSER_FACTORY_H_
+
+
+#include <IComposer.h>
+
+namespace android {
+namespace amlogic {
+
+
+class IComposerFactory {
+
+public:
+ virtual ~IComposerFactory() {};
+
+public:
+ virtual IComposer* createComposer(String8 key) = 0;
+};
+} // namespace amlogic
+} // namespace android
+
+#endif /* ICOMPOSER_FACTORY_H_ */
diff --git a/hwc2/include/IDisplayDevice.h b/hwc2/include/IDisplayDevice.h
index fa297f4..7c4df71 100644
--- a/hwc2/include/IDisplayDevice.h
+++ b/hwc2/include/IDisplayDevice.h
@@ -1,9 +1,23 @@
/*
-// Copyright(c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 IDISPLAY_DEVICE_H
#define IDISPLAY_DEVICE_H
+#include <utils/KeyedVector.h>
#include <Dump.h>
#include <hardware/hwcomposer2.h>
#include <Hwcomposer.h>
@@ -12,6 +26,26 @@
namespace android {
namespace amlogic {
+enum {
+ LAYER_MAX_NUM_CHANGE_REQUEST = 8,
+ LAYER_MAX_NUM_CHANGE_TYPE = 16,
+ LAYER_MAX_NUM_SUPPORT = LAYER_MAX_NUM_CHANGE_TYPE,
+};
+
+enum {
+ GLES_COMPOSE_MODE = 0,
+ DIRECT_COMPOSE_MODE = 1,
+ GE2D_COMPOSE_MODE = 2,
+};
+
+enum {
+ GE2D_COMPOSE_NO_LAYER = 0,
+ GE2D_COMPOSE_ONE_LAYER = 1,
+ GE2D_COMPOSE_TWO_LAYERS = 2,
+ GE2D_COMPOSE_THREE_LAYERS = 3,
+ GE2D_COMPOSE_MAX_LAYERS = GE2D_COMPOSE_THREE_LAYERS,
+};
+
// display config
class DisplayConfig {
public:
diff --git a/hwc2/include/IPlatFactory.h b/hwc2/include/IPlatFactory.h
index 89ccf42..3122cf8 100644
--- a/hwc2/include/IPlatFactory.h
+++ b/hwc2/include/IPlatFactory.h
@@ -1,6 +1,19 @@
/*
-// Copyright(c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 IPLATFORM_FACTORY_H_
#define IPLATFORM_FACTORY_H_
diff --git a/hwc2/include/PhysicalDevice.h b/hwc2/include/PhysicalDevice.h
index 85419f6..8efbd75 100644
--- a/hwc2/include/PhysicalDevice.h
+++ b/hwc2/include/PhysicalDevice.h
@@ -1,6 +1,19 @@
/*
-// Copyright(c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 PHYSICAL_DEVICE_H
#define PHYSICAL_DEVICE_H
@@ -8,11 +21,12 @@
#include <SoftVsyncObserver.h>
#include <IDisplayDevice.h>
#include <HwcLayer.h>
+#include <IComposer.h>
namespace android {
namespace amlogic {
-class IHdcpControl;
+// class IHdcpControl;
typedef struct hdr_capabilities {
bool init;
@@ -27,23 +41,24 @@ class DeviceControlFactory {
public:
virtual ~DeviceControlFactory(){}
public:
- virtual IHdcpControl* createHdcpControl() = 0;
+ // virtual IHdcpControl* createHdcpControl() = 0;
+ virtual IComposer* createComposer(IDisplayDevice& disp) = 0;
};
-class CursorContext {
+class FBContext {
public:
- CursorContext()
+ FBContext()
: mStatus(false)
{
- mCursorInfo = new framebuffer_info_t();
+ mFBInfo = new framebuffer_info_t();
}
- virtual ~CursorContext(){}
+ virtual ~FBContext(){}
- virtual framebuffer_info_t* getCursorInfo() { return mCursorInfo; }
- virtual bool getCursorStatus() { return mStatus; }
- virtual void setCursorStatus(bool status) { mStatus = status; }
+ virtual framebuffer_info_t* getInfo() { return mFBInfo; }
+ virtual bool getStatus() { return mStatus; }
+ virtual void setStatus(bool status) { mStatus = status; }
private:
- framebuffer_info_t *mCursorInfo;
+ framebuffer_info_t *mFBInfo;
bool mStatus;
};
@@ -51,13 +66,8 @@ class Hwcomposer;
class SoftVsyncObserver;
class PhysicalDevice : public IDisplayDevice {
- enum {
- LAYER_MAX_NUM_CHANGE_REQUEST = 8,
- LAYER_MAX_NUM_CHANGE_TYPE = 16,
- LAYER_MAX_NUM_SUPPORT = LAYER_MAX_NUM_CHANGE_TYPE,
- };
public:
- PhysicalDevice(hwc2_display_t id, Hwcomposer& hwc);
+ PhysicalDevice(hwc2_display_t id, Hwcomposer& hwc, DeviceControlFactory* controlFactory);
~PhysicalDevice();
friend class Hwcomposer;
@@ -101,9 +111,9 @@ public:
virtual int32_t validateDisplay(uint32_t* outNumTypes, uint32_t* outNumRequests);
virtual int32_t setCursorPosition(hwc2_layer_t layerId, int32_t x, int32_t y);
- virtual int32_t createVirtualDisplay(uint32_t width, uint32_t height, int32_t* format, hwc2_display_t* outDisplay);
- virtual int32_t destroyVirtualDisplay(hwc2_display_t display);
- virtual int32_t setOutputBuffer(buffer_handle_t buffer, int32_t releaseFence);
+ virtual int32_t createVirtualDisplay(uint32_t width, uint32_t height, int32_t* format, hwc2_display_t* outDisplay) = 0;
+ virtual int32_t destroyVirtualDisplay(hwc2_display_t display) = 0;
+ virtual int32_t setOutputBuffer(buffer_handle_t buffer, int32_t releaseFence) = 0;
// Other Display methods
virtual Hwcomposer& getDevice() const { return mHwc; }
@@ -130,28 +140,58 @@ public:
private:
// For use by Device
int32_t initDisplay();
- int32_t postFramebuffer(int32_t* outRetireFence);
+ int32_t postFramebuffer(int32_t* outRetireFence, bool hasVideoOverlay);
int32_t getLineValue(const char *lineStr, const char *magicStr);
+
int32_t parseHdrCapabilities();
+ void directCompose(framebuffer_info_t * fbInfo);
+ void ge2dCompose(framebuffer_info_t * fbInfo, bool hasVideoOverlay);
+ int32_t setOSD0Blank(bool blank);
+ bool layersStateCheck(int32_t renderMode, KeyedVector<hwc2_layer_t, HwcLayer*> & composeLayers);
+ int32_t composersFilter(KeyedVector<hwc2_layer_t, HwcLayer*>& composeLayers);
+
+ //swap the mHwcCurReleaseFence and mHwcPriorReleaseFence;
+ void swapReleaseFence();
+ //this function will take contorl of fencefd, if you need use it also, please dup it before call.
+ void addReleaseFence(hwc2_layer_t layerId, int32_t fenceFd);
+ void clearFenceList(KeyedVector<hwc2_layer_t, int32_t> * fenceList);
+ void dumpFenceList(KeyedVector<hwc2_layer_t, int32_t> * fenceList);
+ void dumpLayers(Vector < hwc2_layer_t > layerIds);
+ void dumpLayers(KeyedVector<hwc2_layer_t, HwcLayer*> layers);
+ void clearFramebuffer();
+
+ template <typename T, typename S>
+ static inline bool compareSize(T a, S b) {
+ if ((int32_t)(a.right - a.left) == (int32_t)(b.right - b.left)
+ && (int32_t)(a.bottom - a.top) == (int32_t)(b.bottom - b.top)) {
+ return true;
+ }
+ return false;
+ }
// Member variables
hwc2_display_t mId;
const char *mName;
bool mIsConnected;
Hwcomposer& mHwc;
+ DeviceControlFactory *mControlFactory;
char mDisplayMode[32];
+ bool mOSD0Blank;
// display configs
Vector<DisplayConfig*> mDisplayConfigs;
int mActiveDisplayConfig;
SoftVsyncObserver *mVsyncObserver;
+ IComposer *mComposer;
// DeviceControlFactory *mControlFactory;
- framebuffer_info_t *mFramebufferInfo;
+ // framebuffer_info_t *mFramebufferInfo;
private_handle_t *mFramebufferHnd;
- CursorContext *mCursorContext;
+ FBContext *mCursorContext;
+ FBContext *mFramebufferContext;
+ int32_t mFbSlot;
int32_t /*android_color_mode_t*/ mColorMode;
@@ -161,7 +201,9 @@ private:
buffer_handle_t mClientTargetHnd;
hwc_region_t mClientTargetDamageRegion;
int32_t mTargetAcquireFence;
+ int32_t mGE2DComposeFrameCount;
int32_t mPriorFrameRetireFence;
+ int32_t mRenderMode;
bool mIsValidated;
// num of composition type changed layer.
@@ -169,13 +211,23 @@ private:
uint32_t mNumLayerChangerequest;
// layer
+ hwc2_layer_t mDirectRenderLayerId;
+ hwc2_layer_t mVideoOverlayLayerId;
+ int32_t mGE2DClearVideoRegionCount;
+ Vector< hwc2_layer_t > mGE2DRenderSortedLayerIds;
KeyedVector<hwc2_layer_t, HwcLayer*> mHwcLayersChangeType;
KeyedVector<hwc2_layer_t, HwcLayer*> mHwcLayersChangeRequest;
+ KeyedVector<hwc2_layer_t, HwcLayer*> mHwcGlesLayers;
KeyedVector<hwc2_layer_t, HwcLayer*> mHwcLayers;
- //HDR Capabilities
+ // HDR Capabilities
hdr_capabilities_t mHdrCapabilities;
+ // record the release fence of layer.
+ KeyedVector<hwc2_layer_t, int32_t> mLayerReleaseFences[2];
+ KeyedVector<hwc2_layer_t, int32_t> * mHwcCurReleaseFences;
+ KeyedVector<hwc2_layer_t, int32_t> * mHwcPriorReleaseFences;
+
// lock
Mutex mLock;
bool mInitialized;
diff --git a/hwc2/include/PrimaryDevice.h b/hwc2/include/PrimaryDevice.h
index 136f6e6..777c305 100644
--- a/hwc2/include/PrimaryDevice.h
+++ b/hwc2/include/PrimaryDevice.h
@@ -1,11 +1,25 @@
/*
-// Copyright(c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 PRIMARY_DEVICE_H
#define PRIMARY_DEVICE_H
+#include <utils/KeyedVector.h>
#include <PhysicalDevice.h>
+#include <IComposerFactory.h>
namespace android {
namespace amlogic {
@@ -13,11 +27,14 @@ namespace amlogic {
class PrimaryDevice : public PhysicalDevice {
public:
- PrimaryDevice(Hwcomposer& hwc);
+ PrimaryDevice(Hwcomposer& hwc, DeviceControlFactory *composer);
virtual ~PrimaryDevice();
public:
virtual bool initialize();
virtual void deinitialize();
+ virtual int32_t createVirtualDisplay(uint32_t width, uint32_t height, int32_t* format, hwc2_display_t* outDisplay){ return HWC2_ERROR_NONE; }
+ virtual int32_t destroyVirtualDisplay(hwc2_display_t display) { return HWC2_ERROR_NONE; }
+ virtual int32_t setOutputBuffer(buffer_handle_t buffer, int32_t releaseFence) { return HWC2_ERROR_NONE; }
private:
static void hotplugInEventListener(void *data);
diff --git a/hwc2/include/UeventObserver.h b/hwc2/include/UeventObserver.h
index 48680bc..f5bcd55 100644
--- a/hwc2/include/UeventObserver.h
+++ b/hwc2/include/UeventObserver.h
@@ -1,5 +1,17 @@
/*
-// Copyright(c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 UEVENT_OBSERVER_H
diff --git a/hwc2/include/VirtualDevice.h b/hwc2/include/VirtualDevice.h
index 6bae7ad..918ac72 100644
--- a/hwc2/include/VirtualDevice.h
+++ b/hwc2/include/VirtualDevice.h
@@ -1,6 +1,19 @@
/*
-// Copyright(c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 VIRTUAL_DEVICE_H
#define VIRTUAL_DEVICE_H
diff --git a/hwc2/platforms/Android.mk b/hwc2/platforms/Android.mk
index b8d50da..5c2df1c 100644
--- a/hwc2/platforms/Android.mk
+++ b/hwc2/platforms/Android.mk
@@ -12,6 +12,7 @@ LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_SRC_FILES := \
../common/base/HwcLayer.cpp \
+ ../common/base/HwcFenceControl.cpp \
../common/base/Hwcomposer.cpp \
../common/base/HwcModule.cpp \
../common/base/VsyncManager.cpp \
@@ -20,6 +21,8 @@ LOCAL_SRC_FILES := \
../common/devices/VirtualDevice.cpp \
../common/observers/SoftVsyncObserver.cpp \
../common/observers/UeventObserver.cpp \
+ ../common/composers/Composers.cpp \
+ ../common/composers/GE2DComposer.cpp \
../common/utils/Utils.cpp \
../common/utils/Dump.cpp
@@ -34,13 +37,19 @@ LOCAL_SHARED_LIBRARIES := \
libhardware \
libutils \
libsync \
- libfbcnf
+ libion \
+ libfbcnf \
+ libge2d
-LOCAL_STATIC_LIBRARIES := libomxutil
+LOCAL_STATIC_LIBRARIES := \
+ libomxutil
LOCAL_C_INCLUDES := \
system/core \
- system/core/libsync/include
+ system/core/libsync \
+ system/core/libsync/include \
+ system/core/include \
+ vendor/amlogic/system/libge2d/inlcude
LOCAL_C_INCLUDES += $(LOCAL_PATH) \
$(LOCAL_PATH)/../include \
@@ -50,6 +59,7 @@ LOCAL_C_INCLUDES += $(LOCAL_PATH) \
$(LOCAL_PATH)/../common/observers \
$(LOCAL_PATH)/../common/planes \
$(LOCAL_PATH)/../common/utils \
+ $(LOCAL_PATH)/../common/composers \
$(LOCAL_PATH)/../.. \
$(LOCAL_PATH)/
@@ -73,6 +83,10 @@ LOCAL_C_INCLUDES += $(MESON_GRALLOC_DIR)
LOCAL_C_INCLUDES += system/core/libion/include/ \
system/core/libion/kernel-headers
+ifeq ($(TARGET_APP_LAYER_USE_CONTINUOUS_BUFFER),true)
+LOCAL_CFLAGS += -DUSE_CONTINOUS_BUFFER_COMPOSER
+endif
+
# WITH_LIBPLAYER_MODULE := true
ifneq ($(WITH_LIBPLAYER_MODULE),false)
LOCAL_SHARED_LIBRARIES += libamavutils_alsa
diff --git a/hwc2/platforms/PlatFactory.cpp b/hwc2/platforms/PlatFactory.cpp
index f5dda2f..921d29b 100644
--- a/hwc2/platforms/PlatFactory.cpp
+++ b/hwc2/platforms/PlatFactory.cpp
@@ -1,12 +1,26 @@
/*
-// Copyright(c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 <HwcTrace.h>
#include <PrimaryDevice.h>
//#include <ExternalDevice.h>
#include <VirtualDevice.h>
#include <Hwcomposer.h>
#include <PlatFactory.h>
+#include <GE2DComposer.h>
namespace android {
namespace amlogic {
@@ -29,11 +43,12 @@ IDisplayDevice* PlatFactory::createDisplayDevice(int disp)
class PlatDeviceControlFactory: public DeviceControlFactory {
public:
+ virtual IComposer* createComposer(IDisplayDevice& disp) {return new GE2DComposer(disp);}
};
switch (disp) {
case IDisplayDevice::DEVICE_PRIMARY:
- return new PrimaryDevice(hwc);
+ return new PrimaryDevice(hwc, new PlatDeviceControlFactory());
case IDisplayDevice::DEVICE_VIRTUAL:
return new VirtualDevice(hwc);
case IDisplayDevice::DEVICE_EXTERNAL:
diff --git a/hwc2/platforms/PlatFactory.h b/hwc2/platforms/PlatFactory.h
index 75cd622..9f84c60 100644
--- a/hwc2/platforms/PlatFactory.h
+++ b/hwc2/platforms/PlatFactory.h
@@ -1,5 +1,17 @@
/*
-// Copyright(c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 MOOFPLATFORMFACTORY_H_
diff --git a/hwc2/test/nv12_ved_test.cpp b/hwc2/test/nv12_ved_test.cpp
index 253c924..98e6a07 100644
--- a/hwc2/test/nv12_ved_test.cpp
+++ b/hwc2/test/nv12_ved_test.cpp
@@ -1,7 +1,20 @@
/*
-// Copyright (c) 2016 Amlogic Corporation
+// Copyright (c) 2014 Intel Corporation
+//
+// 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 <gtest/gtest.h>
#include <binder/IMemory.h>