author | Sky Zhou <sky.zhou@amlogic.com> | 2017-01-19 05:40:34 (GMT) |
---|---|---|
committer | Gerrit Code Review <gituser@scgit.amlogic.com> | 2017-01-19 05:40:34 (GMT) |
commit | 86947537de1d143e1759c31c1a5fb25b782e3e4a (patch) | |
tree | 6e076211da6bba113e502f429c5732c87ab9f41f | |
parent | e621a17c2cb80c9b1a48c98ec9dc6a59b14fb9fe (diff) | |
parent | 59f63517c6436cff1eecdc523d928165a8522da0 (diff) | |
download | hwcomposer-86947537de1d143e1759c31c1a5fb25b782e3e4a.zip hwcomposer-86947537de1d143e1759c31c1a5fb25b782e3e4a.tar.gz hwcomposer-86947537de1d143e1759c31c1a5fb25b782e3e4a.tar.bz2 |
Merge "PD#138457: add hwc direct & ge2d compose mode." into n-amlogic
41 files changed, 3339 insertions, 248 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 e4f6ab2..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); + } - mPriorFrameRetireFence = fb_post_with_fence_locked(mFramebufferInfo, mClientTargetHnd, mTargetAcquireFence); - mTargetAcquireFence = -1; + if (mRenderMode == DIRECT_COMPOSE_MODE) { + addReleaseFence(mDirectRenderLayerId, HwcFenceControl::dupFence(mPriorFrameRetireFence)); + } + } - // 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); + // 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); + } } - return err; -} + if (mRenderMode != GE2D_COMPOSE_MODE) { + mGE2DComposeFrameCount = 0; + } + 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; } @@ -574,10 +782,8 @@ int32_t PhysicalDevice::setClientTarget( 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 c298b5e..478b500 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> @@ -499,7 +512,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"); @@ -509,9 +522,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 fc2b085..3c0670c 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> |