Merge tag 'android-5.1.0_r1' into HEAD
Android 5.1.0 release 1
Conflicts:
cmds/atrace/atrace.cpp
include/media/openmax/OMX_Audio.h
services/surfaceflinger/Layer.cpp
services/surfaceflinger/Layer.h
services/surfaceflinger/SurfaceFlinger.cpp
services/surfaceflinger/SurfaceFlinger.h
Change-Id: I090bc3c6d46cb853289b449b2e5f234ff950437d
diff --git a/build/phone-xhdpi-1024-dalvik-heap.mk b/build/phone-xhdpi-1024-dalvik-heap.mk
index 221227d..20f365f 100644
--- a/build/phone-xhdpi-1024-dalvik-heap.mk
+++ b/build/phone-xhdpi-1024-dalvik-heap.mk
@@ -21,5 +21,5 @@
dalvik.vm.heapgrowthlimit=96m \
dalvik.vm.heapsize=256m \
dalvik.vm.heaptargetutilization=0.75 \
- dalvik.vm.heapminfree=512k \
+ dalvik.vm.heapminfree=2m \
dalvik.vm.heapmaxfree=8m
diff --git a/data/etc/android.hardware.sensor.ambient_temperature.xml b/data/etc/android.hardware.sensor.ambient_temperature.xml
new file mode 100644
index 0000000..ffb105d
--- /dev/null
+++ b/data/etc/android.hardware.sensor.ambient_temperature.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Copyright (c) 2014, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-->
+
+<!-- Feature for devices with an ambient temperature sensor. -->
+<permissions>
+ <feature name="android.hardware.sensor.ambient_temperature" />
+</permissions>
diff --git a/data/etc/android.hardware.sensor.relative_humidity.xml b/data/etc/android.hardware.sensor.relative_humidity.xml
new file mode 100644
index 0000000..0710079
--- /dev/null
+++ b/data/etc/android.hardware.sensor.relative_humidity.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+Copyright (c) 2014, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-->
+
+<!-- Feature for devices with relative humidity sensor. -->
+<permissions>
+ <feature name="android.hardware.sensor.relative_humidity" />
+</permissions>
diff --git a/include/gui/BufferItem.h b/include/gui/BufferItem.h
index 01b6ff4..f1896b2 100644
--- a/include/gui/BufferItem.h
+++ b/include/gui/BufferItem.h
@@ -60,6 +60,9 @@
// mCrop is the current crop rectangle for this buffer slot.
Rect mCrop;
+ // mDirtyRect is the dirty rectangle for this buffer slot.
+ Rect mDirtyRect;
+
// mTransform is the current transform flags for this buffer slot.
// refer to NATIVE_WINDOW_TRANSFORM_* in <window.h>
uint32_t mTransform;
diff --git a/include/gui/GLConsumer.h b/include/gui/GLConsumer.h
index f91fe46..bd7b973 100644
--- a/include/gui/GLConsumer.h
+++ b/include/gui/GLConsumer.h
@@ -176,6 +176,9 @@
// getCurrentCrop returns the cropping rectangle of the current buffer.
Rect getCurrentCrop() const;
+ // getDirtyRegion returns the dirty rect associated with the current buffer.
+ Rect getCurrentDirtyRect() const;
+
// getCurrentTransform returns the transform of the current buffer.
uint32_t getCurrentTransform() const;
@@ -369,6 +372,10 @@
// It gets set each time updateTexImage is called.
Rect mCurrentCrop;
+ //mCurrentDirtyRect is the dirty rectangle associated with the current
+ //buffer.
+ Rect mCurrentDirtyRect;
+
// mCurrentTransform is the transform identifier for the current texture. It
// gets set each time updateTexImage is called.
uint32_t mCurrentTransform;
diff --git a/include/gui/IGraphicBufferConsumer.h b/include/gui/IGraphicBufferConsumer.h
index 15f51fe..e083f71 100644
--- a/include/gui/IGraphicBufferConsumer.h
+++ b/include/gui/IGraphicBufferConsumer.h
@@ -67,6 +67,9 @@
// mCrop is the current crop rectangle for this buffer slot.
Rect mCrop;
+ // mDirtyRect is the dirty rectangle for this buffer slot.
+ Rect mDirtyRect;
+
// mTransform is the current transform flags for this buffer slot.
// refer to NATIVE_WINDOW_TRANSFORM_* in <window.h>
uint32_t mTransform;
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index 4e9e810..48e32cc 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -281,6 +281,14 @@
: timestamp(timestamp), isAutoTimestamp(isAutoTimestamp), crop(crop),
scalingMode(scalingMode), transform(transform), stickyTransform(sticky),
async(async), fence(fence) { }
+
+ inline QueueBufferInput(int64_t timestamp, bool isAutoTimestamp,
+ const Rect& crop, const Rect& dirtyRect, int scalingMode, uint32_t transform, bool async,
+ const sp<Fence>& fence, uint32_t sticky = 0)
+ : timestamp(timestamp), isAutoTimestamp(isAutoTimestamp), crop(crop),
+ dirtyRect(dirtyRect),scalingMode(scalingMode), transform(transform), stickyTransform(sticky),
+ async(async), fence(fence) { }
+
inline void deflate(int64_t* outTimestamp, bool* outIsAutoTimestamp,
Rect* outCrop, int* outScalingMode, uint32_t* outTransform,
bool* outAsync, sp<Fence>* outFence,
@@ -297,6 +305,24 @@
}
}
+ inline void deflate(int64_t* outTimestamp, bool* outIsAutoTimestamp,
+ Rect* outCrop, Rect* outDirtyRect, int* outScalingMode, uint32_t* outTransform,
+ bool* outAsync, sp<Fence>* outFence,
+ uint32_t* outStickyTransform = NULL) const {
+ *outTimestamp = timestamp;
+ *outIsAutoTimestamp = bool(isAutoTimestamp);
+ *outCrop = crop;
+ *outDirtyRect = dirtyRect;
+ *outScalingMode = scalingMode;
+ *outTransform = transform;
+ *outAsync = bool(async);
+ *outFence = fence;
+ if (outStickyTransform != NULL) {
+ *outStickyTransform = stickyTransform;
+ }
+ }
+
+
// Flattenable protocol
size_t getFlattenedSize() const;
size_t getFdCount() const;
@@ -307,6 +333,7 @@
int64_t timestamp;
int isAutoTimestamp;
Rect crop;
+ Rect dirtyRect;
int scalingMode;
uint32_t transform;
uint32_t stickyTransform;
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index f2cf018..31138e1 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -101,6 +101,10 @@
*/
void allocateBuffers();
+ /* sets dirty rectangle of the buffer that gets queued next for the
+ * Surface */
+ status_t setDirtyRect(const Rect* dirtyRect);
+
protected:
virtual ~Surface();
@@ -226,6 +230,10 @@
// that gets queued. It is set by calling setCrop.
Rect mCrop;
+ // mDirtyRect is the dirty rectangle set for the next buffer that gets
+ // queued. It is set by calling setDirtyRect.
+ Rect mDirtyRect;
+
// mScalingMode is the scaling mode that will be used for the next
// buffers that get queued. It is set by calling setScalingMode.
int mScalingMode;
diff --git a/include/media/openmax/OMX_Audio.h b/include/media/openmax/OMX_Audio.h
index a0cbd3b..a516df8 100644
--- a/include/media/openmax/OMX_Audio.h
+++ b/include/media/openmax/OMX_Audio.h
@@ -13,6 +13,25 @@
* express or implied.
* See the License for the specific language governing permissions
* and limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2011-2012 Dolby Laboratories, Inc.
+ *
+ * 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.
+ *
* -------------------------------------------------------------------
*/
/*
@@ -106,7 +125,10 @@
OMX_AUDIO_CodingRA, /**< Any variant of RA encoded data */
OMX_AUDIO_CodingMIDI, /**< Any variant of MIDI encoded data */
OMX_AUDIO_CodingFLAC, /**< Any variant of FLAC encoded data */
- OMX_AUDIO_CodingKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
+#ifdef DOLBY_UDC
+ OMX_AUDIO_CodingDDP, /**< Any variant of DDP encoded data */
+#endif // DOLBY_END
+ OMX_AUDIO_CodingKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
OMX_AUDIO_CodingVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
OMX_AUDIO_CodingMax = 0x7FFFFFFF
} OMX_AUDIO_CODINGTYPE;
diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h
index 2fa6ff9..6ce4cdb 100644
--- a/include/private/gui/LayerState.h
+++ b/include/private/gui/LayerState.h
@@ -39,6 +39,7 @@
enum {
eLayerHidden = 0x01, // SURFACE_HIDDEN in SurfaceControl.java
eLayerOpaque = 0x02, // SURFACE_OPAQUE
+ eLayerTransparent = 0x80, // SURFACE_TRANSPARENT
};
enum {
@@ -52,6 +53,7 @@
eLayerStackChanged = 0x00000080,
eCropChanged = 0x00000100,
eOpacityChanged = 0x00000200,
+ eTransparencyChanged = 0x80000000,
};
layer_state_t()
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index ca94aa3..fa748a2 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -46,6 +46,11 @@
libutils \
liblog
+# Executed only on QCOM BSPs
+ifeq ($(TARGET_USES_QCOM_BSP),true)
+ LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc
+ LOCAL_CFLAGS += -DQCOM_BSP
+endif
LOCAL_MODULE:= libgui
diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp
index e6fc791..797df9f 100644
--- a/libs/gui/BufferItem.cpp
+++ b/libs/gui/BufferItem.cpp
@@ -34,6 +34,7 @@
mAcquireCalled(false),
mTransformToDisplayInverse(false) {
mCrop.makeInvalid();
+ mDirtyRect.makeInvalid();
}
BufferItem::~BufferItem() {}
@@ -43,6 +44,7 @@
bufferItem.mGraphicBuffer = mGraphicBuffer;
bufferItem.mFence = mFence;
bufferItem.mCrop = mCrop;
+ bufferItem.mDirtyRect = mDirtyRect;
bufferItem.mTransform = mTransform;
bufferItem.mScalingMode = mScalingMode;
bufferItem.mTimestamp = mTimestamp;
@@ -57,6 +59,7 @@
size_t BufferItem::getPodSize() const {
size_t c = sizeof(mCrop) +
+ sizeof(mDirtyRect) +
sizeof(mTransform) +
sizeof(mScalingMode) +
sizeof(mTimestamp) +
@@ -127,6 +130,7 @@
}
FlattenableUtils::write(buffer, size, mCrop);
+ FlattenableUtils::write(buffer, size, mDirtyRect);
FlattenableUtils::write(buffer, size, mTransform);
FlattenableUtils::write(buffer, size, mScalingMode);
FlattenableUtils::write(buffer, size, mTimestamp);
@@ -169,6 +173,7 @@
}
FlattenableUtils::read(buffer, size, mCrop);
+ FlattenableUtils::read(buffer, size, mDirtyRect);
FlattenableUtils::read(buffer, size, mTransform);
FlattenableUtils::read(buffer, size, mScalingMode);
FlattenableUtils::read(buffer, size, mTimestamp);
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 36e3c06..76a826e 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -25,6 +25,7 @@
#include <gui/BufferQueueCore.h>
#include <gui/IConsumerListener.h>
#include <gui/IProducerListener.h>
+#include <cutils/properties.h>
namespace android {
@@ -89,6 +90,17 @@
// the timestamps are being auto-generated by Surface. If the app isn't
// generating timestamps explicitly, it probably doesn't want frames to
// be discarded based on them.
+#ifdef QCOM_BSP
+ char property[PROPERTY_VALUE_MAX];
+ if (property_get("hw.sf.app_buff_count", property, NULL) > 0) {
+ if (!mCore->mQueue[0].mIsAutoTimestamp && mCore->mDefaultMaxBufferCount < 3) {
+ const BufferItem& bufferItem(mCore->mQueue[0]);
+ nsecs_t desiredPresent = bufferItem.mTimestamp;
+ if ( desiredPresent < expectedPresent)
+ mCore->mDefaultMaxBufferCount = 3;
+ }
+ }
+#endif
while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) {
// If entry[1] is timely, drop entry[0] (and repeat). We apply an
// additional criterion here: we only drop the earlier buffer if our
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 16b9747..b43ee93 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -517,12 +517,14 @@
int64_t timestamp;
bool isAutoTimestamp;
Rect crop;
+ Rect dirtyRect;
int scalingMode;
uint32_t transform;
uint32_t stickyTransform;
bool async;
sp<Fence> fence;
- input.deflate(×tamp, &isAutoTimestamp, &crop, &scalingMode, &transform,
+
+ input.deflate(×tamp, &isAutoTimestamp, &crop, &dirtyRect, &scalingMode, &transform,
&async, &fence, &stickyTransform);
if (fence == NULL) {
@@ -603,6 +605,7 @@
item.mAcquireCalled = mSlots[slot].mAcquireCalled;
item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
item.mCrop = crop;
+ item.mDirtyRect = dirtyRect;
item.mTransform = transform & ~NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
item.mTransformToDisplayInverse =
bool(transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 318c087..9d5a539 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -141,6 +141,7 @@
sizeof(mCurrentTransformMatrix));
mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
+ mCurrentDirtyRect.clear();
}
GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t texTarget,
@@ -437,6 +438,7 @@
mCurrentTimestamp = item.mTimestamp;
mCurrentFence = item.mFence;
mCurrentFrameNumber = item.mFrameNumber;
+ mCurrentDirtyRect = item.mDirtyRect;
computeCurrentTransformMatrixLocked();
@@ -983,6 +985,11 @@
return NO_ERROR;
}
+Rect GLConsumer::getCurrentDirtyRect() const {
+ Mutex::Autolock lock(mMutex);
+ return mCurrentDirtyRect;
+}
+
void GLConsumer::freeBufferLocked(int slotIndex) {
ST_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
if (slotIndex == mCurrentTexture) {
diff --git a/libs/gui/IGraphicBufferAlloc.cpp b/libs/gui/IGraphicBufferAlloc.cpp
index 139f219..e090746 100644
--- a/libs/gui/IGraphicBufferAlloc.cpp
+++ b/libs/gui/IGraphicBufferAlloc.cpp
@@ -50,9 +50,13 @@
data.writeInt32(h);
data.writeInt32(format);
data.writeInt32(usage);
- remote()->transact(CREATE_GRAPHIC_BUFFER, data, &reply);
+ status_t result = remote()->transact(CREATE_GRAPHIC_BUFFER, data, &reply);
+ if(result != NO_ERROR){
+ *error = result;
+ return NULL;
+ }
sp<GraphicBuffer> graphicBuffer;
- status_t result = reply.readInt32();
+ result = reply.readInt32();
if (result == NO_ERROR) {
graphicBuffer = new GraphicBuffer();
result = reply.read(*graphicBuffer);
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 1e28f9b..649ab3b 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -433,6 +433,7 @@
return sizeof(timestamp)
+ sizeof(isAutoTimestamp)
+ sizeof(crop)
+ + sizeof(dirtyRect)
+ sizeof(scalingMode)
+ sizeof(transform)
+ sizeof(stickyTransform)
@@ -453,6 +454,7 @@
FlattenableUtils::write(buffer, size, timestamp);
FlattenableUtils::write(buffer, size, isAutoTimestamp);
FlattenableUtils::write(buffer, size, crop);
+ FlattenableUtils::write(buffer, size, dirtyRect);
FlattenableUtils::write(buffer, size, scalingMode);
FlattenableUtils::write(buffer, size, transform);
FlattenableUtils::write(buffer, size, stickyTransform);
@@ -467,6 +469,7 @@
sizeof(timestamp)
+ sizeof(isAutoTimestamp)
+ sizeof(crop)
+ + sizeof(dirtyRect)
+ sizeof(scalingMode)
+ sizeof(transform)
+ sizeof(stickyTransform)
@@ -479,6 +482,7 @@
FlattenableUtils::read(buffer, size, timestamp);
FlattenableUtils::read(buffer, size, isAutoTimestamp);
FlattenableUtils::read(buffer, size, crop);
+ FlattenableUtils::read(buffer, size, dirtyRect);
FlattenableUtils::read(buffer, size, scalingMode);
FlattenableUtils::read(buffer, size, transform);
FlattenableUtils::read(buffer, size, stickyTransform);
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 0e2baa2..7859609 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -36,6 +36,10 @@
#include <private/gui/ComposerService.h>
+#ifdef QCOM_BSP
+#include <gralloc_priv.h>
+#endif
+
namespace android {
Surface::Surface(
@@ -65,6 +69,7 @@
mReqUsage = 0;
mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
mCrop.clear();
+ mDirtyRect.clear();
mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
mTransform = 0;
mStickyTransform = 0;
@@ -126,9 +131,12 @@
int Surface::hook_dequeueBuffer_DEPRECATED(ANativeWindow* window,
ANativeWindowBuffer** buffer) {
Surface* c = getSelf(window);
- ANativeWindowBuffer* buf;
+ ANativeWindowBuffer* buf = NULL;
int fenceFd = -1;
int result = c->dequeueBuffer(&buf, &fenceFd);
+
+ if (result != NO_ERROR) return result;
+
sp<Fence> fence(new Fence(fenceFd));
int waitResult = fence->waitForever("dequeueBuffer_DEPRECATED");
if (waitResult != OK) {
@@ -172,6 +180,12 @@
return c->perform(operation, args);
}
+status_t Surface::setDirtyRect(const Rect* dirtyRect) {
+ Mutex::Autolock lock(mMutex);
+ mDirtyRect = *dirtyRect;
+ return NO_ERROR;
+}
+
int Surface::setSwapInterval(int interval) {
ATRACE_CALL();
// EGL specification states:
@@ -315,10 +329,17 @@
Rect crop;
mCrop.intersect(Rect(buffer->width, buffer->height), &crop);
+ Rect dirtyRect = mDirtyRect;
+ if(dirtyRect.isEmpty()) {
+ int drWidth = mUserWidth ? mUserWidth : mDefaultWidth;
+ int drHeight = mUserHeight ? mUserHeight : mDefaultHeight;
+ dirtyRect = Rect(drWidth, drHeight);
+ }
+
sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
IGraphicBufferProducer::QueueBufferOutput output;
IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp,
- crop, mScalingMode, mTransform ^ mStickyTransform, mSwapIntervalZero,
+ crop, dirtyRect, mScalingMode, mTransform ^ mStickyTransform, mSwapIntervalZero,
fence, mStickyTransform);
status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
if (err != OK) {
@@ -335,7 +356,7 @@
}
mConsumerRunningBehind = (numPendingBuffers >= 2);
-
+ mDirtyRect.clear();
return err;
}
@@ -385,6 +406,16 @@
}
return err;
}
+ case NATIVE_WINDOW_CONSUMER_USAGE_BITS: {
+ status_t err = NO_ERROR;
+ err = mGraphicBufferProducer->query(what, value);
+ if(err == NO_ERROR) {
+ *value |= mReqUsage;
+ return NO_ERROR;
+ } else {
+ return err;
+ }
+ }
}
}
return mGraphicBufferProducer->query(what, value);
@@ -807,7 +838,16 @@
return err;
}
// we're intending to do software rendering from this point
+ // Do not overwrite the mReqUsage flag which was set by the client
+#ifdef QCOM_BSP
+ setUsage(mReqUsage & GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY |
+ mReqUsage & GRALLOC_USAGE_PRIVATE_INTERNAL_ONLY |
+ mReqUsage & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY |
+ GRALLOC_USAGE_SW_READ_OFTEN |
+ GRALLOC_USAGE_SW_WRITE_OFTEN);
+#else
setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+#endif
}
ANativeWindowBuffer* out;
@@ -827,6 +867,7 @@
}
// figure out if we can copy the frontbuffer back
+ int backBufferSlot(getSlotFromBufferLocked(backBuffer.get()));
const sp<GraphicBuffer>& frontBuffer(mPostedBuffer);
const bool canCopyBack = (frontBuffer != 0 &&
backBuffer->width == frontBuffer->width &&
@@ -834,15 +875,23 @@
backBuffer->format == frontBuffer->format);
if (canCopyBack) {
- // copy the area that is invalid and not repainted this round
- const Region copyback(mDirtyRegion.subtract(newDirtyRegion));
+ Mutex::Autolock lock(mMutex);
+ Region oldDirtyRegion;
+ if(mSlots[backBufferSlot].dirtyRegion.isEmpty()) {
+ oldDirtyRegion.set(bounds);
+ } else {
+ for(int i = 0 ; i < NUM_BUFFER_SLOTS; i++ ) {
+ if(i != backBufferSlot && !mSlots[i].dirtyRegion.isEmpty())
+ oldDirtyRegion.orSelf(mSlots[i].dirtyRegion);
+ }
+ }
+ const Region copyback(oldDirtyRegion.subtract(newDirtyRegion));
if (!copyback.isEmpty())
copyBlt(backBuffer, frontBuffer, copyback);
} else {
// if we can't copy-back anything, modify the user's dirty
// region to make sure they redraw the whole buffer
newDirtyRegion.set(bounds);
- mDirtyRegion.clear();
Mutex::Autolock lock(mMutex);
for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) {
mSlots[i].dirtyRegion.clear();
@@ -852,15 +901,11 @@
{ // scope for the lock
Mutex::Autolock lock(mMutex);
- int backBufferSlot(getSlotFromBufferLocked(backBuffer.get()));
if (backBufferSlot >= 0) {
- Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion);
- mDirtyRegion.subtract(dirtyRegion);
- dirtyRegion = newDirtyRegion;
+ mSlots[backBufferSlot].dirtyRegion = newDirtyRegion;
}
}
- mDirtyRegion.orSelf(newDirtyRegion);
if (inOutDirtyBounds) {
*inOutDirtyBounds = newDirtyRegion.getBounds();
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 6446926..9e0704a 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -316,6 +316,9 @@
if (mask & layer_state_t::eLayerHidden) {
s->what |= layer_state_t::eVisibilityChanged;
}
+ if (mask & layer_state_t::eLayerTransparent) {
+ s->what |= layer_state_t::eTransparencyChanged;
+ }
s->flags &= ~mask;
s->flags |= (flags & mask);
s->mask |= mask;
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index 7597c99..caeccf3 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -176,7 +176,10 @@
if (control != NULL) {
bp = control->mGraphicBufferProducer;
}
- return parcel->writeStrongBinder(bp->asBinder());
+ if (bp != NULL) {
+ return parcel->writeStrongBinder(bp->asBinder());
+ }
+ return NO_INIT;
}
sp<Surface> SurfaceControl::getSurface() const
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index fa812f4..cfadbb2 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -800,7 +800,9 @@
size_t numRects = isRect() ? 1 : mStorage.size() - 1;
count[0] = numRects;
}
- sb->acquire();
+ if (sb != NULL) {
+ sb->acquire();
+ }
return sb;
}
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 6e77e45..937665b 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -162,7 +162,8 @@
(!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \
!strcmp((procname), "eglHibernateProcessIMG") || \
!strcmp((procname), "eglAwakenProcessIMG") || \
- !strcmp((procname), "eglDupNativeFenceFDANDROID"))
+ !strcmp((procname), "eglDupNativeFenceFDANDROID") || \
+ !strcmp((procname), "eglGpuPerfHintQCOM"))
@@ -452,40 +453,54 @@
#else
// by default, just pick RGBA_8888
EGLint format = HAL_PIXEL_FORMAT_RGBA_8888;
+ EGLint color_buffer = EGL_RGB_BUFFER;
- EGLint a = 0;
- cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a);
- if (a > 0) {
- // alpha-channel requested, there's really only one suitable format
- format = HAL_PIXEL_FORMAT_RGBA_8888;
- } else {
- EGLint r, g, b;
- r = g = b = 0;
- cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE, &r);
- cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g);
- cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE, &b);
- EGLint colorDepth = r + g + b;
- if (colorDepth <= 16) {
- format = HAL_PIXEL_FORMAT_RGB_565;
- } else {
- format = HAL_PIXEL_FORMAT_RGBX_8888;
- }
+ if (!cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_COLOR_BUFFER_TYPE, &color_buffer))
+ {
+ ALOGE("Could not configure a color buffer format");
+ return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
}
+ if (EGL_RGB_BUFFER != color_buffer &&
+ EGL_LUMINANCE_BUFFER != color_buffer)
+ {
+ cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_NATIVE_VISUAL_ID, &format);
+ }
+ else
+ {
+ EGLint a = 0;
+ cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a);
+ if (a > 0) {
+ // alpha-channel requested, there's really only one suitable format
+ // Format will already be RGBA8888
+ } else {
+ EGLint r, g, b;
+ r = g = b = 0;
+ cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE, &r);
+ cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g);
+ cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE, &b);
+ EGLint colorDepth = r + g + b;
+ if (colorDepth <= 16) {
+ format = HAL_PIXEL_FORMAT_RGB_565;
+ } else {
+ format = HAL_PIXEL_FORMAT_RGBX_8888;
+ }
+ }
- // now select a corresponding sRGB format if needed
- if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
- for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
- if (*attr == EGL_GL_COLORSPACE_KHR) {
- if (ENABLE_EGL_KHR_GL_COLORSPACE) {
- format = modifyFormatColorspace(format, *(attr+1));
- } else {
- // Normally we'd pass through unhandled attributes to
- // the driver. But in case the driver implements this
- // extension but we're disabling it, we want to prevent
- // it getting through -- support will be broken without
- // our help.
- ALOGE("sRGB window surfaces not supported");
- return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ // now select a corresponding sRGB format if needed
+ if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
+ for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
+ if (*attr == EGL_GL_COLORSPACE_KHR) {
+ if (ENABLE_EGL_KHR_GL_COLORSPACE) {
+ format = modifyFormatColorspace(format, *(attr+1));
+ } else {
+ // Normally we'd pass through unhandled attributes to
+ // the driver. But in case the driver implements this
+ // extension but we're disabling it, we want to prevent
+ // it getting through -- support will be broken without
+ // our help.
+ ALOGE("sRGB window surfaces not supported");
+ return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
+ }
}
}
}
@@ -1554,6 +1569,45 @@
}
// ----------------------------------------------------------------------------
+// QCOM extensions
+// ----------------------------------------------------------------------------
+#ifdef __cplusplus
+extern "C" {
+#endif
+EGLAPI EGLBoolean eglGpuPerfHintQCOM(EGLDisplay dpy, EGLContext ctx, EGLint *attrib_list);
+#ifdef __cplusplus
+}
+#endif
+
+EGLBoolean eglGpuPerfHintQCOM(EGLDisplay dpy, EGLContext ctx, EGLint *attrib_list)
+{
+ clearError();
+
+ const egl_display_ptr dp = validate_display(dpy);
+ if (!dp) return EGL_FALSE;
+
+ ContextRef _c(dp.get(), ctx);
+ if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
+ // ctx is not valid
+ return setError(EGL_BAD_CONTEXT, EGL_FALSE);
+ }
+
+ egl_context_t * c = NULL;
+ c = get_context(ctx);
+
+ EGLint result = EGL_FALSE;
+ egl_connection_t* const cnx = &gEGLImpl;
+ if (cnx->dso && cnx->egl.eglGpuPerfHintQCOM) {
+ result = cnx->egl.eglGpuPerfHintQCOM(
+ dp->disp.dpy,
+ c->context,
+ attrib_list);
+ }
+ return result;
+
+}
+
+// ----------------------------------------------------------------------------
// NVIDIA extensions
// ----------------------------------------------------------------------------
EGLuint64NV eglGetSystemTimeFrequencyNV()
diff --git a/opengl/libs/EGL/egl_entries.in b/opengl/libs/EGL/egl_entries.in
index 70d0e52..aa92ea0 100644
--- a/opengl/libs/EGL/egl_entries.in
+++ b/opengl/libs/EGL/egl_entries.in
@@ -81,6 +81,10 @@
EGL_ENTRY(EGLClientBuffer, eglGetRenderBufferANDROID, EGLDisplay, EGLSurface)
EGL_ENTRY(EGLint, eglDupNativeFenceFDANDROID, EGLDisplay, EGLSyncKHR)
+/* QCOM extensions */
+
+EGL_ENTRY(EGLBoolean, eglGpuPerfHintQCOM, EGLDisplay, EGLContext, EGLint *)
+
/* NVIDIA extensions */
EGL_ENTRY(EGLuint64NV, eglGetSystemTimeFrequencyNV, void)
diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
index b07228f..0157bfe 100644
--- a/opengl/libs/GLES2/gl2.cpp
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -180,7 +180,7 @@
const GLubyte * ret = egl_get_string_for_current_context(name);
if (ret == NULL) {
gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;
- ret = _c->glGetString(name);
+ if(_c) ret = _c->glGetString(name);
}
return ret;
}
diff --git a/services/inputflinger/EventHub.h b/services/inputflinger/EventHub.h
index 20179ae..2fbf3e1 100644
--- a/services/inputflinger/EventHub.h
+++ b/services/inputflinger/EventHub.h
@@ -57,6 +57,12 @@
#define MSC_ANDROID_TIME_SEC 0x6
#define MSC_ANDROID_TIME_USEC 0x7
+/**
+ * code for a special button that is used to show/hide a
+ * circular hovering cursor in the input framework.
+ */
+#define BTN_USF_HOVERING_CURSOR 0x230
+
namespace android {
enum {
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 8634e42..7b09b36 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -58,6 +58,9 @@
#define INDENT4 " "
#define INDENT5 " "
+// Ultrasound device name.
+#define USF_DEVICE_NAME "usf_tsc"
+
namespace android {
// --- Constants ---
@@ -2088,6 +2091,11 @@
keyCode = AKEYCODE_UNKNOWN;
flags = 0;
}
+ InputDeviceIdentifier identifier = getEventHub()->getDeviceIdentifier(rawEvent->deviceId);
+ if ((identifier.name == USF_DEVICE_NAME) && (scanCode == BTN_USF_HOVERING_CURSOR))
+ {
+ break;
+ }
processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);
}
break;
@@ -2593,6 +2601,7 @@
TouchInputMapper::TouchInputMapper(InputDevice* device) :
InputMapper(device),
mSource(0), mDeviceMode(DEVICE_MODE_DISABLED),
+ mHasExternalHoveringCursorControl(false), mExternalHoveringCursorVisible(false),
mSurfaceWidth(-1), mSurfaceHeight(-1), mSurfaceLeft(0), mSurfaceTop(0),
mSurfaceOrientation(DISPLAY_ORIENTATION_0) {
}
@@ -2864,6 +2873,8 @@
&& getDevice()->isExternal();
}
+ mHasExternalHoveringCursorControl = getDevice()->hasKey(BTN_USF_HOVERING_CURSOR);
+
// Initial downs on external touch devices should wake the device.
// Normally we don't do this for internal touch screens to prevent them from waking
// up in your pocket but you can enable it using the input device configuration.
@@ -3060,7 +3071,7 @@
}
// Create pointer controller if needed.
- if (mDeviceMode == DEVICE_MODE_POINTER ||
+ if (mDeviceMode == DEVICE_MODE_POINTER || mHasExternalHoveringCursorControl ||
(mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
if (mPointerController == NULL) {
mPointerController = getPolicy()->obtainPointerController(getDeviceId());
@@ -3730,6 +3741,20 @@
if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
sync(rawEvent->when);
}
+ if (mHasExternalHoveringCursorControl && rawEvent->type == EV_KEY) {
+ if (rawEvent->code == BTN_USF_HOVERING_CURSOR && mPointerController != NULL) {
+ if (rawEvent->value) {
+ // show a hover cursor
+ mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_STYLUS_HOVER);
+ mPointerController->unfade(android::PointerControllerInterface::TRANSITION_IMMEDIATE);
+ mExternalHoveringCursorVisible = true;
+ } else {
+ // hide the cursor
+ mPointerController->fade(android::PointerControllerInterface::TRANSITION_IMMEDIATE);
+ mExternalHoveringCursorVisible = false;
+ }
+ }
+ }
}
void TouchInputMapper::sync(nsecs_t when) {
@@ -3861,6 +3886,25 @@
mCurrentCookedPointerData.touchingIdBits);
}
+ if (mHasExternalHoveringCursorControl && mPointerController != NULL) {
+ if (mExternalHoveringCursorVisible) {
+ // find the pointer position from the first touch point (either touching or hovering)
+ uint32_t index = MAX_POINTERS;
+ if (!mCurrentRawPointerData.touchingIdBits.isEmpty()) {
+ index = mCurrentCookedPointerData.idToIndex[mCurrentRawPointerData.touchingIdBits.firstMarkedBit()];
+ } else if (!mCurrentRawPointerData.hoveringIdBits.isEmpty()) {
+ index = mCurrentCookedPointerData.idToIndex[mCurrentRawPointerData.hoveringIdBits.firstMarkedBit()];
+ }
+ if (index < MAX_POINTERS)
+ {
+ float x = mCurrentCookedPointerData.pointerCoords[index].getX();
+ float y = mCurrentCookedPointerData.pointerCoords[index].getY();
+ mPointerController->setPosition(x, y);
+ mPointerController->unfade(android::PointerControllerInterface::TRANSITION_IMMEDIATE);
+ }
+ }
+ }
+
dispatchHoverExit(when, policyFlags);
dispatchTouches(when, policyFlags);
dispatchHoverEnterAndMove(when, policyFlags);
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index c5896d4..7bb85c3 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -1369,6 +1369,11 @@
Vector<VirtualKey> mVirtualKeys;
+ // true if we support external hovering cursor control
+ bool mHasExternalHoveringCursorControl;
+ // visibility state of hovering cursor (true=visible)
+ bool mExternalHoveringCursorVisible;
+
virtual void configureParameters();
virtual void dumpParameters(String8& dump);
virtual void configureRawPointerAxes();
diff --git a/services/inputflinger/PointerControllerInterface.h b/services/inputflinger/PointerControllerInterface.h
index e94dd94..2c4015b 100644
--- a/services/inputflinger/PointerControllerInterface.h
+++ b/services/inputflinger/PointerControllerInterface.h
@@ -79,6 +79,8 @@
PRESENTATION_POINTER,
// Show spots and a spot anchor in place of the mouse pointer.
PRESENTATION_SPOT,
+ // Show a stylus hovering icon (small circle)
+ PRESENTATION_STYLUS_HOVER,
};
/* Sets the mode of the pointer controller. */
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index eade2e2..fa99131 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -51,10 +51,6 @@
LOCAL_CFLAGS += -DTARGET_DISABLE_TRIPLE_BUFFERING
endif
-ifeq ($(TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS),true)
- LOCAL_CFLAGS += -DFORCE_HWC_COPY_FOR_VIRTUAL_DISPLAYS
-endif
-
ifneq ($(NUM_FRAMEBUFFER_SURFACE_BUFFERS),)
LOCAL_CFLAGS += -DNUM_FRAMEBUFFER_SURFACE_BUFFERS=$(NUM_FRAMEBUFFER_SURFACE_BUFFERS)
endif
@@ -106,6 +102,13 @@
libgui \
libpowermanager
+ifeq ($(TARGET_USES_QCOM_BSP), true)
+ LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc
+ LOCAL_C_INCLUDES += hardware/qcom/display/libqdutils
+ LOCAL_SHARED_LIBRARIES += libqdutils
+ LOCAL_CFLAGS += -DQCOM_BSP
+endif
+
LOCAL_MODULE:= libsurfaceflinger
include $(BUILD_SHARED_LIBRARY)
diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h
index 96efc34..3531ebe 100644
--- a/services/surfaceflinger/DispSync.h
+++ b/services/surfaceflinger/DispSync.h
@@ -26,11 +26,8 @@
namespace android {
// Ignore present (retire) fences if the device doesn't have support for the
-// sync framework, or if all phase offsets are zero. The latter is useful
-// because it allows us to avoid resync bursts on devices that don't need
-// phase-offset VSYNC events.
-#if defined(RUNNING_WITHOUT_SYNC_FRAMEWORK) || \
- (VSYNC_EVENT_PHASE_OFFSET_NS == 0 && SF_VSYNC_EVENT_PHASE_OFFSET_NS == 0)
+// sync framework.
+#if defined(RUNNING_WITHOUT_SYNC_FRAMEWORK)
static const bool kIgnorePresentFences = true;
#else
static const bool kIgnorePresentFences = false;
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 564f974..526feb6 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -128,9 +128,19 @@
mDisplayName = "Virtual Screen"; // e.g. Overlay #n
break;
}
+ char property[PROPERTY_VALUE_MAX];
+ int panelOrientation = DisplayState::eOrientationDefault;
+ // Set the panel orientation from the property.
+ property_get("persist.panel.orientation", property, "0");
+ panelOrientation = atoi(property) / 90;
+
+ mPanelInverseMounted = false;
+ // Check if panel is inverse mounted (contents show up HV flipped)
+ property_get("persist.panel.inversemounted", property, "0");
+ mPanelInverseMounted = !!atoi(property);
// initialize the display orientation transform.
- setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
+ setProjection(panelOrientation, mViewport, mFrame);
}
DisplayDevice::~DisplayDevice() {
@@ -140,6 +150,13 @@
}
}
+#ifdef QCOM_BSP
+void DisplayDevice::eglSwapPreserved(bool enable) const {
+ int swapValue = enable ? EGL_BUFFER_PRESERVED : EGL_BUFFER_DESTROYED;
+ eglSurfaceAttrib(mDisplay, mSurface, EGL_SWAP_BEHAVIOR, swapValue);
+}
+#endif
+
void DisplayDevice::disconnect(HWComposer& hwc) {
if (mHwcDisplayId >= 0) {
hwc.disconnectDisplay(mHwcDisplayId);
@@ -396,6 +413,11 @@
default:
return BAD_VALUE;
}
+
+ if (DISPLAY_PRIMARY == mHwcDisplayId && isPanelInverseMounted()) {
+ flags = flags ^ Transform::ROT_180;
+ }
+
tr->set(flags, w, h);
return NO_ERROR;
}
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 8695a44..0d86154 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -126,6 +126,10 @@
int32_t getHwcDisplayId() const { return mHwcDisplayId; }
const wp<IBinder>& getDisplayToken() const { return mDisplayToken; }
+ bool isPanelInverseMounted() const {
+ return mPanelInverseMounted;
+ }
+
// We pass in mustRecompose so we can keep VirtualDisplaySurface's state
// machine happy without actually queueing a buffer if nothing has changed
status_t beginFrame(bool mustRecompose) const;
@@ -170,6 +174,12 @@
uint32_t getPageFlipCount() const;
void dump(String8& result) const;
+#ifdef QCOM_BSP
+ /* To set egl atribute, EGL_SWAP_BEHAVIOR value
+ * (EGL_BUFFER_PRESERVED/EGL_BUFFER_DESTROYED)
+ */
+ void eglSwapPreserved(bool status) const;
+#endif
private:
/*
* Constants, set during initialization
@@ -209,7 +219,7 @@
/*
* Transaction state
*/
- static status_t orientationToTransfrom(int orientation,
+ status_t orientationToTransfrom(int orientation,
int w, int h, Transform* tr);
uint32_t mLayerStack;
@@ -226,6 +236,8 @@
int mPowerMode;
// Current active config
int mActiveConfig;
+ // Panel is inverse mounted
+ int mPanelInverseMounted;
};
}; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 22d3cec..4197599 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -66,6 +66,7 @@
mConsumer->setDefaultBufferFormat(mHwc.getFormat(disp));
mConsumer->setDefaultBufferSize(mHwc.getWidth(disp), mHwc.getHeight(disp));
mConsumer->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
+ mConsumer->setMaxAcquiredBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS - 1);
}
status_t FramebufferSurface::beginFrame(bool /*mustRecompose*/) {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index edfed49..1f17b5c 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -47,6 +47,8 @@
#include "../Layer.h" // needed only for debugging
#include "../SurfaceFlinger.h"
+#define GPUTILERECT_DEBUG 0
+
namespace android {
#define MIN_HWC_HEADER_VERSION HWC_HEADER_VERSION
@@ -88,7 +90,8 @@
mFbDev(0), mHwc(0), mNumDisplays(1),
mCBContext(new cb_context),
mEventHandler(handler),
- mDebugForceFakeVSync(false)
+ mDebugForceFakeVSync(false),
+ mVDSEnabled(false)
{
for (size_t i =0 ; i<MAX_HWC_DISPLAYS ; i++) {
mLists[i] = 0;
@@ -176,6 +179,7 @@
config.height = mFbDev->height;
config.xdpi = mFbDev->xdpi;
config.ydpi = mFbDev->ydpi;
+ config.secure = true; //XXX: Assuming primary is always true
config.refresh = nsecs_t(1e9 / mFbDev->fps);
disp.configs.push_back(config);
disp.currentConfig = 0;
@@ -186,10 +190,24 @@
}
}
+ // read system property for VDS solution
+ // This property is expected to be setup once during bootup
+ if( (property_get("persist.hwc.enable_vds", value, NULL) > 0) &&
+ ((!strncmp(value, "1", strlen("1"))) ||
+ !strncasecmp(value, "true", strlen("true")))) {
+ //HAL virtual display is using VDS based implementation
+ mVDSEnabled = true;
+ }
+
if (needVSyncThread) {
// we don't have VSYNC support, we need to fake it
mVSyncThread = new VSyncThread(*this);
}
+#ifdef QCOM_BSP
+ // Threshold Area to enable GPU Tiled Rect.
+ property_get("debug.hwc.gpuTiledThreshold", value, "1.9");
+ mDynThreshold = atof(value);
+#endif
}
HWComposer::~HWComposer() {
@@ -333,6 +351,10 @@
HWC_DISPLAY_HEIGHT,
HWC_DISPLAY_DPI_X,
HWC_DISPLAY_DPI_Y,
+ //To specify if display is secure
+ //Primary is considered as secure always
+ //HDMI can be secure based on HDCP
+ HWC_DISPLAY_SECURE,
HWC_DISPLAY_NO_ATTRIBUTE,
};
#define NUM_DISPLAY_ATTRIBUTES (sizeof(DISPLAY_ATTRIBUTES) / sizeof(DISPLAY_ATTRIBUTES)[0])
@@ -355,7 +377,12 @@
return err;
}
- mDisplayData[disp].currentConfig = 0;
+ int currentConfig = getActiveConfig(disp);
+ if (currentConfig < 0 || currentConfig > (numConfigs-1)) {
+ ALOGE("%s: Invalid display config! %d", __FUNCTION__, currentConfig);
+ currentConfig = 0;
+ }
+ mDisplayData[disp].currentConfig = currentConfig;
for (size_t c = 0; c < numConfigs; ++c) {
err = mHwc->getDisplayAttributes(mHwc, disp, configs[c],
DISPLAY_ATTRIBUTES, values);
@@ -383,6 +410,9 @@
case HWC_DISPLAY_DPI_Y:
config.ydpi = values[i] / 1000.0f;
break;
+ case HWC_DISPLAY_SECURE:
+ config.secure = values[i];
+ break;
default:
ALOG_ASSERT(false, "unknown display attribute[%zu] %#x",
i, DISPLAY_ATTRIBUTES[i]);
@@ -417,6 +447,8 @@
config.width = w;
config.height = h;
config.xdpi = config.ydpi = getDefaultDensity(w, h);
+ //XXXX: No need to set secure for virtual display's as its initiated by
+ //the frameworks
return NO_ERROR;
}
@@ -492,6 +524,12 @@
return mDisplayData[disp].configs[currentConfig].ydpi;
}
+bool HWComposer::isSecure(int disp) const {
+ size_t currentConfig = mDisplayData[disp].currentConfig;
+ return mDisplayData[disp].configs[currentConfig].secure;
+}
+
+
nsecs_t HWComposer::getRefreshPeriod(int disp) const {
size_t currentConfig = mDisplayData[disp].currentConfig;
return mDisplayData[disp].configs[currentConfig].refresh;
@@ -511,42 +549,50 @@
event, disp, enabled);
return;
}
- if (event != EVENT_VSYNC) {
- ALOGW("eventControl got unexpected event %d (disp=%d en=%d)",
- event, disp, enabled);
- return;
- }
status_t err = NO_ERROR;
- if (mHwc && !mDebugForceFakeVSync) {
- // NOTE: we use our own internal lock here because we have to call
- // into the HWC with the lock held, and we want to make sure
- // that even if HWC blocks (which it shouldn't), it won't
- // affect other threads.
- Mutex::Autolock _l(mEventControlLock);
- const int32_t eventBit = 1UL << event;
- const int32_t newValue = enabled ? eventBit : 0;
- const int32_t oldValue = mDisplayData[disp].events & eventBit;
- if (newValue != oldValue) {
- ATRACE_CALL();
- err = mHwc->eventControl(mHwc, disp, event, enabled);
- if (!err) {
- int32_t& events(mDisplayData[disp].events);
- events = (events & ~eventBit) | newValue;
+ switch(event) {
+ case EVENT_VSYNC:
+ if (mHwc && !mDebugForceFakeVSync) {
+ // NOTE: we use our own internal lock here because we have to
+ // call into the HWC with the lock held, and we want to make
+ // sure that even if HWC blocks (which it shouldn't), it won't
+ // affect other threads.
+ Mutex::Autolock _l(mEventControlLock);
+ const int32_t eventBit = 1UL << event;
+ const int32_t newValue = enabled ? eventBit : 0;
+ const int32_t oldValue = mDisplayData[disp].events & eventBit;
+ if (newValue != oldValue) {
+ ATRACE_CALL();
+ err = mHwc->eventControl(mHwc, disp, event, enabled);
+ if (!err) {
+ int32_t& events(mDisplayData[disp].events);
+ events = (events & ~eventBit) | newValue;
- char tag[16];
- snprintf(tag, sizeof(tag), "HW_VSYNC_ON_%1u", disp);
- ATRACE_INT(tag, enabled);
+ char tag[16];
+ snprintf(tag, sizeof(tag), "HW_VSYNC_ON_%1u", disp);
+ ATRACE_INT(tag, enabled);
+ }
+ }
+ // error here should not happen -- not sure what we should
+ // do if it does.
+ ALOGE_IF(err, "eventControl(%d, %d) failed %s",
+ event, enabled, strerror(-err));
}
- }
- // error here should not happen -- not sure what we should
- // do if it does.
- ALOGE_IF(err, "eventControl(%d, %d) failed %s",
- event, enabled, strerror(-err));
- }
- if (err == NO_ERROR && mVSyncThread != NULL) {
- mVSyncThread->setEnabled(enabled);
+ if (err == NO_ERROR && mVSyncThread != NULL) {
+ mVSyncThread->setEnabled(enabled);
+ }
+ break;
+ case EVENT_ORIENTATION:
+ // Orientation event
+ err = mHwc->eventControl(mHwc, disp, event, enabled);
+ break;
+ default:
+ ALOGW("eventControl got unexpected event %d (disp=%d en=%d)",
+ event, disp, enabled);
+ break;
}
+ return;
}
status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
@@ -565,6 +611,8 @@
+ numLayers * sizeof(hwc_layer_1_t);
free(disp.list);
disp.list = (hwc_display_contents_1_t*)malloc(size);
+ if(disp.list == NULL)
+ return NO_MEMORY;
disp.capacity = numLayers;
}
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
@@ -632,6 +680,7 @@
}
status_t HWComposer::prepare() {
+ Mutex::Autolock _l(mDrawLock);
for (size_t i=0 ; i<mNumDisplays ; i++) {
DisplayData& disp(mDisplayData[i]);
if (disp.framebufferTarget) {
@@ -677,25 +726,50 @@
DisplayData& disp(mDisplayData[i]);
disp.hasFbComp = false;
disp.hasOvComp = false;
+#ifdef QCOM_BSP
+ disp.hasBlitComp = false;
+#endif
+
if (disp.list) {
- for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {
- hwc_layer_1_t& l = disp.list->hwLayers[i];
+#ifdef QCOM_BSP
+ //GPUTILERECT
+ prev_comp_map[i] = current_comp_map[i];
+ current_comp_map[i].reset();
+ current_comp_map[i].count = disp.list->numHwLayers-1;
+#endif
+ for (size_t j=0 ; j<disp.list->numHwLayers ; j++) {
+ hwc_layer_1_t& l = disp.list->hwLayers[j];
//ALOGD("prepare: %d, type=%d, handle=%p",
- // i, l.compositionType, l.handle);
+ // j, l.compositionType, l.handle);
- if (l.flags & HWC_SKIP_LAYER) {
+ if ((i == DisplayDevice::DISPLAY_PRIMARY) &&
+ l.flags & HWC_SKIP_LAYER) {
l.compositionType = HWC_FRAMEBUFFER;
}
if (l.compositionType == HWC_FRAMEBUFFER) {
disp.hasFbComp = true;
}
+ // If the composition type is BLIT, we set this to
+ // trigger a FLIP
+ if(l.compositionType == HWC_BLIT) {
+ disp.hasFbComp = true;
+#ifdef QCOM_BSP
+ disp.hasBlitComp = true;
+#endif
+ }
if (l.compositionType == HWC_OVERLAY) {
disp.hasOvComp = true;
}
if (l.compositionType == HWC_CURSOR_OVERLAY) {
disp.hasOvComp = true;
}
+#ifdef QCOM_BSP
+ //GPUTILERECT
+ if(l.compositionType != HWC_FRAMEBUFFER_TARGET) {
+ current_comp_map[i].compType[j] = l.compositionType;
+ }
+#endif
}
if (disp.list->numHwLayers == (disp.framebufferTarget ? 1 : 0)) {
disp.hasFbComp = true;
@@ -708,6 +782,13 @@
return (status_t)err;
}
+#ifdef QCOM_BSP
+bool HWComposer::hasBlitComposition(int32_t id) const {
+ if (!mHwc || uint32_t(id) > 31 || !mAllocatedDisplayIDs.hasBit(id))
+ return false;
+ return mDisplayData[id].hasBlitComp;
+}
+#endif
bool HWComposer::hasHwcComposition(int32_t id) const {
if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
return false;
@@ -793,15 +874,31 @@
status_t HWComposer::setActiveConfig(int disp, int mode) {
LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
DisplayData& dd(mDisplayData[disp]);
- dd.currentConfig = mode;
if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
- return (status_t)mHwc->setActiveConfig(mHwc, disp, mode);
+ status_t status = static_cast<status_t>(
+ mHwc->setActiveConfig(mHwc, disp, mode));
+ if (status == NO_ERROR) {
+ dd.currentConfig = mode;
+ } else {
+ ALOGE("%s Failed to set new config (%d) for display (%d)",
+ __FUNCTION__, mode, disp);
+ }
+ return status;
} else {
LOG_FATAL_IF(mode != 0);
}
return NO_ERROR;
}
+int HWComposer::getActiveConfig(int disp) const {
+ LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
+ if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
+ return mHwc->getActiveConfig(mHwc, disp);
+ } else {
+ return 0;
+ }
+}
+
void HWComposer::disconnectDisplay(int disp) {
LOG_ALWAYS_FATAL_IF(disp < 0 || disp == HWC_DISPLAY_PRIMARY);
DisplayData& dd(mDisplayData[disp]);
@@ -985,6 +1082,13 @@
}
}
}
+ virtual void setAnimating(bool animating) {
+ if (animating) {
+ getLayer()->flags |= HWC_SCREENSHOT_ANIMATOR_LAYER;
+ } else {
+ getLayer()->flags &= ~HWC_SCREENSHOT_ANIMATOR_LAYER;
+ }
+ }
virtual void setBlending(uint32_t blending) {
getLayer()->blending = blending;
}
@@ -1020,11 +1124,28 @@
SharedBuffer const* sb = reg.getSharedBuffer(&visibleRegion.numRects);
visibleRegion.rects = reinterpret_cast<hwc_rect_t const *>(sb->data());
}
+
virtual void setSidebandStream(const sp<NativeHandle>& stream) {
ALOG_ASSERT(stream->handle() != NULL);
getLayer()->compositionType = HWC_SIDEBAND;
getLayer()->sidebandStream = stream->handle();
}
+
+ virtual void setDirtyRect(const Rect& dirtyRect) {
+ Rect srcCrop;
+ srcCrop.left = int(ceilf(getLayer()->sourceCropf.left));
+ srcCrop.right = int(ceilf(getLayer()->sourceCropf.right));
+ srcCrop.top = int(ceilf(getLayer()->sourceCropf.top));
+ srcCrop.bottom = int(ceilf(getLayer()->sourceCropf.bottom));
+
+ /* DirtyRect is generated for the full buffer resolution. Crop the value
+ * for the hwc_layer_1_t::sourceCrop resolution before sending to HWC.
+ */
+ Rect finalDR;
+ srcCrop.intersect(dirtyRect, &finalDR);
+ getLayer()->dirtyRect = reinterpret_cast<hwc_rect_t const&>(finalDR);
+ }
+
virtual void setBuffer(const sp<GraphicBuffer>& buffer) {
if (buffer == 0 || buffer->handle == 0) {
getLayer()->compositionType = HWC_FRAMEBUFFER;
@@ -1101,6 +1222,8 @@
static String8 getFormatStr(PixelFormat format) {
switch (format) {
case PIXEL_FORMAT_RGBA_8888: return String8("RGBA_8888");
+ case PIXEL_FORMAT_RGBA_4444: return String8("RGBA_4444");
+ case PIXEL_FORMAT_RGBA_5551: return String8("RGBA_5551");
case PIXEL_FORMAT_RGBX_8888: return String8("RGBx_8888");
case PIXEL_FORMAT_RGB_888: return String8("RGB_888");
case PIXEL_FORMAT_RGB_565: return String8("RGB_565");
@@ -1117,6 +1240,7 @@
}
void HWComposer::dump(String8& result) const {
+ Mutex::Autolock _l(mDrawLock);
if (mHwc) {
result.appendFormat("Hardware Composer state (version %08x):\n", hwcApiVersion(mHwc));
result.appendFormat(" mDebugForceFakeVSync=%d\n", mDebugForceFakeVSync);
@@ -1132,20 +1256,20 @@
result.appendFormat(" Display[%zd] configurations (* current):\n", i);
for (size_t c = 0; c < disp.configs.size(); ++c) {
const DisplayConfig& config(disp.configs[c]);
- result.appendFormat(" %s%zd: %ux%u, xdpi=%f, ydpi=%f, refresh=%" PRId64 "\n",
+ result.appendFormat(" %s%zd: %ux%u, xdpi=%f, ydpi=%f, secure=%d refresh=%" PRId64 "\n",
c == disp.currentConfig ? "* " : "", c, config.width, config.height,
- config.xdpi, config.ydpi, config.refresh);
+ config.xdpi, config.ydpi, config.secure, config.refresh);
}
if (disp.list) {
result.appendFormat(
" numHwLayers=%zu, flags=%08x\n",
disp.list->numHwLayers, disp.list->flags);
-
result.append(
- " type | handle | hint | flag | tr | blnd | format | source crop (l,t,r,b) | frame | name \n"
- "-----------+----------+------+------+----+------+-------------+--------------------------------+------------------------+------\n");
- // " _________ | ________ | ____ | ____ | __ | ____ | ___________ |_____._,_____._,_____._,_____._ |_____,_____,_____,_____ | ___...
+
+ " type | handle | hint | flag | tr | blnd | format | source crop(l,t,r,b) | frame | dirtyRect | name \n"
+ "------------+----------+----------+----------+----+-------+----------+-----------------------------------+---------------------------+-------------------\n");
+ // " __________ | ________ | ________ | ________ | __ | _____ | ________ | [_____._,_____._,_____._,_____._] | [_____,_____,_____,_____] | [_____,_____,_____,_____] |
for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {
const hwc_layer_1_t&l = disp.list->hwLayers[i];
int32_t format = -1;
@@ -1174,6 +1298,7 @@
"FB TARGET",
"SIDEBAND",
"HWC_CURSOR",
+ "FB_BLIT",
"UNKNOWN"};
if (type >= NELEM(compositionTypeName))
type = NELEM(compositionTypeName) - 1;
@@ -1181,19 +1306,21 @@
String8 formatStr = getFormatStr(format);
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
result.appendFormat(
- " %9s | %08" PRIxPTR " | %04x | %04x | %02x | %04x | %-11s |%7.1f,%7.1f,%7.1f,%7.1f |%5d,%5d,%5d,%5d | %s\n",
+ " %9s | %08" PRIxPTR " | %04x | %04x | %02x | %04x | %-11s |%7.1f,%7.1f,%7.1f,%7.1f |%5d,%5d,%5d,%5d | [%5d,%5d,%5d,%5d] | %s\n",
compositionTypeName[type],
intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, formatStr.string(),
l.sourceCropf.left, l.sourceCropf.top, l.sourceCropf.right, l.sourceCropf.bottom,
l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
+ l.dirtyRect.left, l.dirtyRect.top, l.dirtyRect.right, l.dirtyRect.bottom,
name.string());
} else {
result.appendFormat(
- " %9s | %08" PRIxPTR " | %04x | %04x | %02x | %04x | %-11s |%7d,%7d,%7d,%7d |%5d,%5d,%5d,%5d | %s\n",
+ " %9s | %08" PRIxPTR " | %04x | %04x | %02x | %04x | %-11s |%7d,%7d,%7d,%7d |%5d,%5d,%5d,%5d | [%5d,%5d,%5d,%5d] | %s\n",
compositionTypeName[type],
intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, formatStr.string(),
l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom,
l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
+ l.dirtyRect.left, l.dirtyRect.top, l.dirtyRect.right, l.dirtyRect.bottom,
name.string());
}
}
@@ -1282,5 +1409,173 @@
free(list);
}
-// ---------------------------------------------------------------------------
+#ifdef QCOM_BSP
+//======================== GPU TiledRect/DR changes =====================
+bool HWComposer::areVisibleRegionsOverlapping(int32_t id ) {
+ if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+ return false;
+ const Vector< sp<Layer> >& currentLayers =
+ mFlinger->getLayerSortedByZForHwcDisplay(id);
+ size_t count = currentLayers.size();
+ Region consolidatedVisibleRegion;
+
+ for (size_t i=0; i<count; i++) {
+ //If there are any overlapping visible regions, disable GPUTileRect
+ if(!consolidatedVisibleRegion.intersect(
+ currentLayers[i]->visibleRegion).isEmpty()){
+ return true;
+ }
+ consolidatedVisibleRegion.orSelf(currentLayers[i]->visibleRegion);
+ }
+ return false;
+}
+
+bool HWComposer::canHandleOverlapArea(int32_t id, Rect unionDr) {
+ DisplayData& disp(mDisplayData[id]);
+ float layerAreaSum = 0;
+ float drArea = ((unionDr.right-unionDr.left)* (unionDr.bottom-unionDr.top));
+ hwc_layer_1_t& fbLayer = disp.list->hwLayers[disp.list->numHwLayers-1];
+ hwc_rect_t fbDisplayFrame = fbLayer.displayFrame;
+ float fbLayerArea = ((fbDisplayFrame.right - fbDisplayFrame.left)*
+ (fbDisplayFrame.bottom - fbDisplayFrame.top));
+
+ //Compute sum of the Areas of FB layers intersecting with Union Dirty Rect
+ for (size_t i=0; i<disp.list->numHwLayers-1; i++) {
+ hwc_layer_1_t& layer = disp.list->hwLayers[i];
+ if(layer.compositionType != HWC_FRAMEBUFFER)
+ continue;
+
+ hwc_rect_t displayFrame = layer.displayFrame;
+ Rect df(displayFrame.left, displayFrame.top,
+ displayFrame.right, displayFrame.bottom);
+ Rect df_dirty;
+ df_dirty.clear();
+ if(df.intersect(unionDr, &df_dirty))
+ layerAreaSum += ((df_dirty.right - df_dirty.left)*
+ (df_dirty.bottom - df_dirty.top));
+ }
+ ALOGD_IF(GPUTILERECT_DEBUG,"GPUTileRect: overlap/FB : %f",
+ (layerAreaSum/fbLayerArea));
+ // Return false, if the sum of layer Areas intersecting with union Dr is
+ // more than the threshold as we are not getting better performance.
+ return (mDynThreshold > (layerAreaSum/fbLayerArea));
+}
+
+bool HWComposer::needsScaling(int32_t id) {
+ if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+ return false;
+ DisplayData& disp(mDisplayData[id]);
+ for (size_t i=0; i<disp.list->numHwLayers-1; i++) {
+ int dst_w, dst_h, src_w, src_h;
+ hwc_layer_1_t& layer = disp.list->hwLayers[i];
+ hwc_rect_t displayFrame = layer.displayFrame;
+
+ hwc_rect_t sourceCropI = {0,0,0,0};
+ sourceCropI.left = int(ceilf(layer.sourceCropf.left));
+ sourceCropI.top = int(ceilf(layer.sourceCropf.top));
+ sourceCropI.right = int(floorf(layer.sourceCropf.right));
+ sourceCropI.bottom = int(floorf(layer.sourceCropf.bottom));
+
+ dst_w = displayFrame.right - displayFrame.left;
+ dst_h = displayFrame.bottom - displayFrame.top;
+ src_w = sourceCropI.right - sourceCropI.left;
+ src_h = sourceCropI.bottom - sourceCropI.top;
+
+ if(((src_w != dst_w) || (src_h != dst_h))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void HWComposer::computeUnionDirtyRect(int32_t id, Rect& unionDirtyRect) {
+ if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+ return;
+ const Vector< sp<Layer> >& currentLayers =
+ mFlinger->getLayerSortedByZForHwcDisplay(id);
+ size_t count = currentLayers.size();
+ Region unionDirtyRegion;
+ DisplayData& disp(mDisplayData[id]);
+
+ // Find UnionDr of all layers
+ for (size_t i=0; i<count; i++) {
+ hwc_layer_1_t& l = disp.list->hwLayers[i];
+ Rect dr;
+ dr.clear();
+ if((l.compositionType == HWC_FRAMEBUFFER) &&
+ currentLayers[i]->hasNewFrame()) {
+ dr = Rect(l.dirtyRect.left, l.dirtyRect.top, l.dirtyRect.right,
+ l.dirtyRect.bottom);
+ hwc_rect_t dst = l.displayFrame;
+
+ //Map dirtyRect to layer destination before using
+ hwc_rect_t src = {0,0,0,0};
+ src.left = int(ceilf(l.sourceCropf.left));
+ src.top = int(ceilf(l.sourceCropf.top));
+ src.right = int(floorf(l.sourceCropf.right));
+ src.bottom = int(floorf(l.sourceCropf.bottom));
+
+ int x_off = dst.left - src.left;
+ int y_off = dst.top - src.top;
+ dr = dr.offsetBy(x_off, y_off);
+ unionDirtyRegion = unionDirtyRegion.orSelf(dr);
+ }
+ }
+ unionDirtyRect = unionDirtyRegion.getBounds();
+}
+bool HWComposer::isCompositionMapChanged(int32_t id) {
+ if (prev_comp_map[id] == current_comp_map[id]) {
+ return false;
+ }
+ return true;
+}
+bool HWComposer::isGeometryChanged(int32_t id) {
+ if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+ return false;
+ DisplayData& disp(mDisplayData[id]);
+ return ( disp.list->flags & HWC_GEOMETRY_CHANGED );
+}
+/* Finds if we can enable DR optimization for GpuComp
+ * 1. return false if geometry is changed
+ * 2. if overlapping visible regions present.
+ * 3. Compute a Union Dirty Rect to operate on. */
+bool HWComposer::canUseTiledDR(int32_t id, Rect& unionDr ){
+ if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+ return false;
+
+ bool status = true;
+ if (isGeometryChanged(id)) {
+ ALOGD_IF(GPUTILERECT_DEBUG, "GPUTileRect : geometrychanged, disable");
+ status = false;
+ } else if ( hasBlitComposition(id)) {
+ ALOGD_IF(GPUTILERECT_DEBUG, "GPUTileRect: Blit comp, disable");
+ status = false;
+ } else if ( isCompositionMapChanged(id)) {
+ ALOGD_IF(GPUTILERECT_DEBUG, "GPUTileRect: comp map changed, disable");
+ status = false;
+ } else if (needsScaling(id)) {
+ /* Do Not use TiledDR optimization, if layers need scaling */
+ ALOGD_IF(GPUTILERECT_DEBUG, "GPUTileRect: Layers need scaling, disable");
+ status = false;
+ } else {
+ computeUnionDirtyRect(id, unionDr);
+ if(areVisibleRegionsOverlapping(id) &&
+ !canHandleOverlapArea(id, unionDr)){
+ /* With DR optimizaton, On certain targets we are seeing slightly
+ * lower FPS in use cases where visible regions overlap &
+ * the total dirty area of layers is greater than a threshold value.
+ * Hence this optimization has been disabled for such use cases */
+ ALOGD_IF(GPUTILERECT_DEBUG, "GPUTileRect: Visible \
+ regions overlap & Total Dirty Area > Threashold, disable");
+ status = false;
+ } else if(unionDr.isEmpty()) {
+ ALOGD_IF(GPUTILERECT_DEBUG,"GPUTileRect: UnionDr is emtpy, \
+ No need to PRESERVE");
+ status = false;
+ }
+ }
+ return status;
+}
+#endif
+
}; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index a62ac5c..44399be 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -32,6 +32,8 @@
#include <utils/Timers.h>
#include <utils/Vector.h>
+#define MAX_LAYER_COUNT 32
+
extern "C" int clock_nanosleep(clockid_t clock_id, int flags,
const struct timespec *request,
struct timespec *remain);
@@ -103,6 +105,9 @@
// set active config
status_t setActiveConfig(int disp, int mode);
+ // get active config
+ int getActiveConfig(int disp) const;
+
// reset state when an external, non-virtual display is disconnected
void disconnectDisplay(int disp);
@@ -117,10 +122,21 @@
// does this display have layers handled by GLES
bool hasGlesComposition(int32_t id) const;
+#ifdef QCOM_BSP
+ // does this display have layers handled by BLIT HW
+ bool hasBlitComposition(int32_t id) const;
+
+ //GPUTiledRect : function to find out if DR can be used in GPU Comp.
+ bool canUseTiledDR(int32_t id, Rect& dr);
+#endif
+
// get the releaseFence file descriptor for a display's framebuffer layer.
// the release fence is only valid after commit()
sp<Fence> getAndResetReleaseFence(int32_t id);
+ // is VDS solution enabled
+ inline bool isVDSEnabled() const { return mVDSEnabled; };
+
// needed forward declarations
class LayerListIterator;
@@ -163,12 +179,14 @@
virtual void setDefaultState() = 0;
virtual void setSkip(bool skip) = 0;
virtual void setIsCursorLayerHint(bool isCursor = true) = 0;
+ virtual void setAnimating(bool animating) = 0;
virtual void setBlending(uint32_t blending) = 0;
virtual void setTransform(uint32_t transform) = 0;
virtual void setFrame(const Rect& frame) = 0;
virtual void setCrop(const FloatRect& crop) = 0;
virtual void setVisibleRegionScreen(const Region& reg) = 0;
virtual void setSidebandStream(const sp<NativeHandle>& stream) = 0;
+ virtual void setDirtyRect(const Rect& dirtyRect) = 0;
virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0;
virtual void setAcquireFenceFd(int fenceFd) = 0;
virtual void setPlaneAlpha(uint8_t alpha) = 0;
@@ -245,7 +263,8 @@
// Events handling ---------------------------------------------------------
enum {
- EVENT_VSYNC = HWC_EVENT_VSYNC
+ EVENT_VSYNC = HWC_EVENT_VSYNC,
+ EVENT_ORIENTATION = HWC_EVENT_ORIENTATION
};
void eventControl(int disp, int event, int enabled);
@@ -255,6 +274,7 @@
uint32_t height;
float xdpi;
float ydpi;
+ bool secure;
nsecs_t refresh;
};
@@ -264,6 +284,7 @@
sp<Fence> getDisplayFence(int disp) const;
uint32_t getFormat(int disp) const;
bool isConnected(int disp) const;
+ bool isSecure(int disp) const;
// These return the values for the current config of a given display index.
// To get the values for all configs, use getConfigs below.
@@ -332,6 +353,9 @@
bool connected;
bool hasFbComp;
bool hasOvComp;
+#ifdef QCOM_BSP
+ bool hasBlitComp;
+#endif
size_t capacity;
hwc_display_contents_1* list;
hwc_layer_1* framebufferTarget;
@@ -361,13 +385,61 @@
sp<VSyncThread> mVSyncThread;
bool mDebugForceFakeVSync;
BitSet32 mAllocatedDisplayIDs;
-
+ bool mVDSEnabled;
// protected by mLock
mutable Mutex mLock;
+ // synchronization between Draw call and Dumpsys call
+ mutable Mutex mDrawLock;
mutable nsecs_t mLastHwVSync[HWC_NUM_PHYSICAL_DISPLAY_TYPES];
// thread-safe
mutable Mutex mEventControlLock;
+
+ //GPUTileRect : CompMap, class to track the composition type of layers
+ struct CompMap {
+ int32_t count;
+ int32_t compType[MAX_LAYER_COUNT];
+ CompMap () {
+ reset();
+ }
+ void reset () {
+ count=0;
+ for(size_t i= 0; i <MAX_LAYER_COUNT; i++) {
+ compType[i] = -1;
+ }
+ }
+ CompMap& operator=(const CompMap &rhs) {
+ if(this != &rhs) {
+ reset();
+ count = rhs.count;
+ for(int32_t i=0; i<count; i++) {
+ compType[i] = rhs.compType[i];
+ }
+ }
+ return *this;
+ }
+ bool operator== (CompMap &rhs) {
+ if( count != rhs.count)
+ return false;
+ for(int32_t i=0; i<count; i++) {
+ if(compType[i] != rhs.compType[i])
+ return false;
+ }
+ return true;
+ }
+ };
+
+#ifdef QCOM_BSP
+ //GPUTileRect Optimization Functions.
+ CompMap prev_comp_map[MAX_HWC_DISPLAYS], current_comp_map[MAX_HWC_DISPLAYS];
+ bool isCompositionMapChanged(int32_t id);
+ bool isGeometryChanged(int32_t id);
+ void computeUnionDirtyRect(int32_t id, Rect& unionDirtyRect);
+ bool areVisibleRegionsOverlapping(int32_t id );
+ bool needsScaling(int32_t id);
+ float mDynThreshold;
+ bool canHandleOverlapArea(int32_t id, Rect unionDr);
+#endif
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index c3d45ee..c6f7606 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -17,17 +17,14 @@
// #define LOG_NDEBUG 0
#include "VirtualDisplaySurface.h"
#include "HWComposer.h"
-
+#include <cutils/properties.h>
+#if QCOM_BSP
+#include <gralloc_priv.h>
+#endif
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
-#if defined(FORCE_HWC_COPY_FOR_VIRTUAL_DISPLAYS)
-static const bool sForceHwcCopy = true;
-#else
-static const bool sForceHwcCopy = false;
-#endif
-
#define VDS_LOGE(msg, ...) ALOGE("[%s] " msg, \
mDisplayName.string(), ##__VA_ARGS__)
#define VDS_LOGW_IF(cond, msg, ...) ALOGW_IF(cond, "[%s] " msg, \
@@ -45,29 +42,34 @@
}
}
-VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
+VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc,
+ int32_t &hwcDisplayId,
const sp<IGraphicBufferProducer>& sink,
const sp<IGraphicBufferProducer>& bqProducer,
const sp<IGraphicBufferConsumer>& bqConsumer,
- const String8& name)
+ const String8& name,
+ bool secure)
: ConsumerBase(bqConsumer),
mHwc(hwc),
- mDisplayId(dispId),
+ mDisplayId(NO_MEMORY),
mDisplayName(name),
mOutputUsage(GRALLOC_USAGE_HW_COMPOSER),
mProducerSlotSource(0),
mDbgState(DBG_STATE_IDLE),
mDbgLastCompositionType(COMPOSITION_UNKNOWN),
- mMustRecompose(false)
+ mMustRecompose(false),
+ mForceHwcCopy(false),
+ mSecure(false)
{
mSource[SOURCE_SINK] = sink;
mSource[SOURCE_SCRATCH] = bqProducer;
- resetPerFrameState();
-
- int sinkWidth, sinkHeight;
+ int sinkWidth, sinkHeight, sinkFormat, sinkUsage;
sink->query(NATIVE_WINDOW_WIDTH, &sinkWidth);
sink->query(NATIVE_WINDOW_HEIGHT, &sinkHeight);
+ sink->query(NATIVE_WINDOW_FORMAT, &sinkFormat);
+ sink->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &sinkUsage);
+
mSinkBufferWidth = sinkWidth;
mSinkBufferHeight = sinkHeight;
@@ -75,16 +77,46 @@
// with GLES. If the consumer needs CPU access, use the default format
// set by the consumer. Otherwise allow gralloc to decide the format based
// on usage bits.
- int sinkUsage;
- sink->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &sinkUsage);
- if (sinkUsage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
- int sinkFormat;
- sink->query(NATIVE_WINDOW_FORMAT, &sinkFormat);
- mDefaultOutputFormat = sinkFormat;
- } else {
+ mDefaultOutputFormat = sinkFormat;
+ if((sinkUsage & GRALLOC_USAGE_HW_VIDEO_ENCODER)
+#if QCOM_BSP
+ && (sinkUsage & GRALLOC_USAGE_PRIVATE_WFD)
+#endif
+ )
+ {
mDefaultOutputFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+ mForceHwcCopy = true;
+ //Set secure flag only if the session requires HW protection, currently
+ //there is no other way to distinguish different security protection levels
+ //This allows Level-3 sessions(eg.simulated displayes) to get
+ //buffers from IOMMU heap and not MM (secure) heap.
+ mSecure = secure;
}
+
+ // XXX: With this debug property we can allow screenrecord to be composed
+ // via HWC. This is useful for debugging purposes, for example when WFD
+ // is not working on a particular build.
+ char value[PROPERTY_VALUE_MAX];
+ if( (property_get("debug.hwc.screenrecord", value, NULL) > 0) &&
+ ((!strncmp(value, "1", strlen("1"))) ||
+ !strncasecmp(value, "true", strlen("true")))) {
+ mForceHwcCopy = true;
+ }
+
+ // Once the mForceHwcCopy flag is set, we can freely allocate an HWC
+ // display ID.
+ if (mForceHwcCopy && mHwc.isVDSEnabled())
+ mDisplayId = mHwc.allocateDisplayId();
+
+ hwcDisplayId = mDisplayId; //update display id for device creation in SF
+
mOutputFormat = mDefaultOutputFormat;
+ // TODO: need to add the below logs as part of dumpsys output
+ VDS_LOGV("creation: sinkFormat: 0x%x sinkUsage: 0x%x mForceHwcCopy: %d",
+ mOutputFormat, sinkUsage, mForceHwcCopy);
+
+ setOutputUsage();
+ resetPerFrameState();
ConsumerBase::mName = String8::format("VDS: %s", mDisplayName.string());
mConsumer->setConsumerName(ConsumerBase::mName);
@@ -96,6 +128,22 @@
VirtualDisplaySurface::~VirtualDisplaySurface() {
}
+// helper to update the output usage when the display is secure
+void VirtualDisplaySurface::setOutputUsage() {
+ mOutputUsage = GRALLOC_USAGE_HW_COMPOSER;
+ if (mSecure) {
+ //TODO: Currently, the framework can only say whether the display
+ //and its subsequent session are secure or not. However, there is
+ //no mechanism to distinguish the different levels of security.
+ //The current solution assumes WV L3 protection.
+ mOutputUsage |= GRALLOC_USAGE_PROTECTED;
+#ifdef QCOM_BSP
+ mOutputUsage |= GRALLOC_USAGE_PRIVATE_MM_HEAP |
+ GRALLOC_USAGE_PRIVATE_UNCACHED;
+#endif
+ }
+}
+
status_t VirtualDisplaySurface::beginFrame(bool mustRecompose) {
if (mDisplayId < 0)
return NO_ERROR;
@@ -118,7 +166,7 @@
mDbgState = DBG_STATE_PREPARED;
mCompositionType = compositionType;
- if (sForceHwcCopy && mCompositionType == COMPOSITION_GLES) {
+ if (mForceHwcCopy) {
// Some hardware can do RGB->YUV conversion more efficiently in hardware
// controlled by HWC than in hardware controlled by the video encoder.
// Forcing GLES-composed frames to go through an extra copy by the HWC
@@ -150,7 +198,7 @@
// format/usage and get a new buffer when the GLES driver calls
// dequeueBuffer().
mOutputFormat = mDefaultOutputFormat;
- mOutputUsage = GRALLOC_USAGE_HW_COMPOSER;
+ setOutputUsage();
refreshOutputBuffer();
}
@@ -165,7 +213,20 @@
if (mDisplayId < 0)
return NO_ERROR;
- if (mCompositionType == COMPOSITION_HWC) {
+ // When mForceHwcCopy is true, we override the composition type to MIXED.
+ // Therefore, we need to check whether we are in this scenario and add
+ // checks to satisfy the state machine requirements and reduce log spam.
+ // In particular, by setting mForceHwcCopy we can now expect to get an
+ // advanceFrame when composition type is MIXED and our previous state was
+ // PREPARED or GLES_DONE.
+ if (mForceHwcCopy && (mCompositionType == COMPOSITION_MIXED)) {
+ bool isValidState = (mDbgState == DBG_STATE_PREPARED) ||
+ (mDbgState == DBG_STATE_GLES_DONE);
+ VDS_LOGW_IF(!isValidState,
+ "Unexpected advanceFrame() in %s state on %s frame",
+ dbgStateStr(),
+ (mDbgState == DBG_STATE_PREPARED) ? "HWC" : "GLES/MIXED");
+ } else if (mCompositionType == COMPOSITION_HWC) {
VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED,
"Unexpected advanceFrame() in %s state on HWC frame",
dbgStateStr());
@@ -176,8 +237,7 @@
}
mDbgState = DBG_STATE_HWC;
- if (mOutputProducerSlot < 0 ||
- (mCompositionType != COMPOSITION_HWC && mFbProducerSlot < 0)) {
+ if (mOutputProducerSlot < 0) {
// Last chance bailout if something bad happened earlier. For example,
// in a GLES configuration, if the sink disappears then dequeueBuffer
// will fail, the GLES driver won't queue a buffer, but SurfaceFlinger
@@ -215,7 +275,7 @@
mDbgState = DBG_STATE_IDLE;
sp<Fence> fbFence = mHwc.getAndResetReleaseFence(mDisplayId);
- if (mCompositionType == COMPOSITION_MIXED && mFbProducerSlot >= 0) {
+ if (mFbProducerSlot >= 0) {
// release the scratch buffer back to the pool
Mutex::Autolock lock(mMutex);
int sslot = mapProducer2SourceSlot(SOURCE_SCRATCH, mFbProducerSlot);
@@ -230,7 +290,10 @@
QueueBufferOutput qbo;
sp<Fence> outFence = mHwc.getLastRetireFence(mDisplayId);
VDS_LOGV("onFrameCommitted: queue sink sslot=%d", sslot);
- if (mMustRecompose) {
+ // Allow queuing to sink buffer if mMustRecompose is true or
+ // mForceHwcCopy is true. This is required to support Miracast WFD Sink
+ // Initiatied Pause/Resume feature support
+ if (mForceHwcCopy || mMustRecompose) {
status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot,
QueueBufferInput(
systemTime(), false /* isAutoTimestamp */,
@@ -458,7 +521,7 @@
uint32_t transform;
bool async;
input.deflate(×tamp, &isAutoTimestamp, &crop, &scalingMode,
- &transform, &async, &mFbFence);
+ &transform, &async, &mFbFence);
mFbProducerSlot = pslot;
mOutputFence = mFbFence;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 363dce2..d43aa2c 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -72,11 +72,12 @@
public BnGraphicBufferProducer,
private ConsumerBase {
public:
- VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
+ VirtualDisplaySurface(HWComposer& hwc, int32_t &hwcDisplayId,
const sp<IGraphicBufferProducer>& sink,
const sp<IGraphicBufferProducer>& bqProducer,
const sp<IGraphicBufferConsumer>& bqConsumer,
- const String8& name);
+ const String8& name,
+ bool secure);
//
// DisplaySurface interface
@@ -125,6 +126,7 @@
void updateQueueBufferOutput(const QueueBufferOutput& qbo);
void resetPerFrameState();
status_t refreshOutputBuffer();
+ void setOutputUsage();
// Both the sink and scratch buffer pools have their own set of slots
// ("source slots", or "sslot"). We have to merge these into the single
@@ -139,11 +141,23 @@
// Immutable after construction
//
HWComposer& mHwc;
- const int32_t mDisplayId;
const String8 mDisplayName;
sp<IGraphicBufferProducer> mSource[2]; // indexed by SOURCE_*
uint32_t mDefaultOutputFormat;
+ // Force copy flag. Used to determine if we are forcing composition
+ // through HWC.
+ bool mForceHwcCopy;
+
+ // The display ID is now determined when VDS is initialized. This
+ // is done because VDS has all the requisite information to make
+ // a call on whether the display is to be composed/copied by HWC
+ // or not.
+ int32_t mDisplayId;
+
+ // secure flag
+ bool mSecure;
+
//
// Inter-frame state
//
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
old mode 100644
new mode 100755
index 5e3dfab..d80a358
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -47,6 +47,9 @@
#include "DisplayHardware/HWComposer.h"
#include "RenderEngine/RenderEngine.h"
+#ifdef QCOM_BSP
+#include <gralloc_priv.h>
+#endif
#define DEBUG_RESIZE 0
@@ -54,6 +57,31 @@
// ---------------------------------------------------------------------------
+/* Calculates the aspect ratio for external display based on the video w/h */
+static Rect getAspectRatio(const sp<const DisplayDevice>& hw,
+ const int& srcWidth, const int& srcHeight) {
+ Rect outRect;
+ int fbWidth = hw->getWidth();
+ int fbHeight = hw->getHeight();
+ int x , y = 0;
+ int w = fbWidth, h = fbHeight;
+ if (srcWidth * fbHeight > fbWidth * srcHeight) {
+ h = fbWidth * srcHeight / srcWidth;
+ w = fbWidth;
+ } else if (srcWidth * fbHeight < fbWidth * srcHeight) {
+ w = fbHeight * srcWidth / srcHeight;
+ h = fbHeight;
+ }
+ x = (fbWidth - w) / 2;
+ y = (fbHeight - h) / 2;
+ outRect.left = x;
+ outRect.top = y;
+ outRect.right = x + w;
+ outRect.bottom = y + h;
+
+ return outRect;
+}
+
int32_t Layer::sSequence = 1;
Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client,
@@ -81,7 +109,8 @@
mProtectedByApp(false),
mHasSurface(false),
mClientRef(client),
- mPotentialCursor(false)
+ mPotentialCursor(false),
+ mTransformHint(0)
{
mCurrentCrop.makeInvalid();
mFlinger->getRenderEngine().genTextures(1, &mTextureName);
@@ -133,6 +162,14 @@
mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2);
#else
mSurfaceFlingerConsumer->setDefaultMaxBufferCount(3);
+
+#ifdef QCOM_BSP
+ char property[PROPERTY_VALUE_MAX];
+ if (property_get("hw.sf.app_buff_count", property, NULL) > 0) {
+ mSurfaceFlingerConsumer->setDefaultMaxBufferCount(atoi(property));
+ }
+#endif
+
#endif
const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
@@ -286,7 +323,9 @@
if (CC_LIKELY(exclude.isEmpty())) {
return win;
}
- if (exclude.isRect()) {
+ Rect tmp;
+ win.intersect(exclude.getBounds(), &tmp);
+ if (exclude.isRect() && !tmp.isEmpty()) {
return win.reduce(exclude.getBounds());
}
return Region(win).subtract(exclude).getBounds();
@@ -407,26 +446,9 @@
return crop;
}
-void Layer::setGeometry(
- const sp<const DisplayDevice>& hw,
- HWComposer::HWCLayerInterface& layer)
+Transform Layer::computeBufferTransform(const sp<const DisplayDevice>& hw) const
{
- layer.setDefaultState();
-
- // enable this layer
- layer.setSkip(false);
-
- if (isSecure() && !hw->isSecure()) {
- layer.setSkip(true);
- }
-
- // this gives us only the "orientation" component of the transform
const State& s(getDrawingState());
- if (!isOpaque(s) || s.alpha != 0xFF) {
- layer.setBlending(mPremultipliedAlpha ?
- HWC_BLENDING_PREMULT :
- HWC_BLENDING_COVERAGE);
- }
// apply the layer's transform, followed by the display's global transform
// here we're guaranteed that the layer's transform preserves rects
@@ -455,10 +477,6 @@
Rect frame(s.transform.transform(computeBounds(activeTransparentRegion)));
frame.intersect(hw->getViewport(), &frame);
const Transform& tr(hw->getTransform());
- layer.setFrame(tr.transform(frame));
- layer.setCrop(computeCrop(hw));
- layer.setPlaneAlpha(s.alpha);
-
/*
* Transformations are applied in this order:
* 1) buffer orientation/flip/mirror
@@ -487,11 +505,79 @@
if (is_h_flipped != is_v_flipped) {
t_orientation ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
NATIVE_WINDOW_TRANSFORM_FLIP_H;
- }
+ }
+
}
// and apply to the current transform
transform = Transform(t_orientation) * Transform(invTransform);
}
+ return transform;
+}
+
+void Layer::setGeometry(
+ const sp<const DisplayDevice>& hw,
+ HWComposer::HWCLayerInterface& layer)
+{
+ layer.setDefaultState();
+
+ // enable this layer
+ layer.setSkip(false);
+
+ if (isSecure() && !hw->isSecure()) {
+ layer.setSkip(true);
+ }
+
+ // this gives us only the "orientation" component of the transform
+ const State& s(getDrawingState());
+ if (!isOpaque(s)) {
+ layer.setBlending(mPremultipliedAlpha ?
+ HWC_BLENDING_PREMULT :
+ HWC_BLENDING_COVERAGE);
+ }
+
+ // apply the layer's transform, followed by the display's global transform
+ // here we're guaranteed that the layer's transform preserves rects
+ Rect frame(s.transform.transform(computeBounds()));
+ frame.intersect(hw->getViewport(), &frame);
+
+ //map frame(displayFrame) to sourceCrop
+ frame = s.transform.inverse().transform(frame);
+
+ // make sure sourceCrop with in the window's bounds
+ frame.intersect(Rect(s.active.w, s.active.h), &frame);
+
+ // subtract the transparent region and snap to the bounds
+ frame = reduce(frame, s.activeTransparentRegion);
+
+ //remap frame to displayFrame
+ frame = s.transform.transform(frame);
+
+ // make sure frame(displayFrame) with in viewframe
+ frame.intersect(hw->getViewport(), &frame);
+
+ const Transform& tr(hw->getTransform());
+ layer.setFrame(tr.transform(frame));
+#ifdef QCOM_BSP
+ // set dest_rect to display width and height, if external_only flag
+ // for the layer is enabled or if its yuvLayer in extended mode.
+ uint32_t x = 0, y = 0;
+ uint32_t w = hw->getWidth();
+ uint32_t h = hw->getHeight();
+ bool extendedMode = SurfaceFlinger::isExtendedMode();
+ if(isExtOnly()) {
+ // Position: fullscreen for ext_only
+ Rect r(0, 0, w, h);
+ layer.setFrame(r);
+ } else if(hw->getDisplayType() > 0 && (extendedMode && isYuvLayer())) {
+ // Need to position the video full screen on external with aspect ratio
+ Rect r = getAspectRatio(hw, s.active.w, s.active.h);
+ layer.setFrame(r);
+ }
+#endif
+ layer.setCrop(computeCrop(hw));
+ layer.setPlaneAlpha(s.alpha);
+
+ Transform transform = computeBufferTransform(hw);
// this gives us only the "orientation" component of the transform
const uint32_t orientation = transform.getOrientation();
@@ -503,6 +589,8 @@
}
}
+
+
void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
HWComposer::HWCLayerInterface& layer) {
// we have to set the visible region on every frame because
@@ -521,6 +609,56 @@
// layer yet, or if we ran out of memory
layer.setBuffer(mActiveBuffer);
}
+
+ Rect dirtyRect = mSurfaceFlingerConsumer->getCurrentDirtyRect();
+ int bufferOrientation = computeBufferTransform(hw).getOrientation();
+ if((mActiveBuffer != NULL) && mTransformHint && !bufferOrientation &&
+ (mTransformHint != NATIVE_WINDOW_TRANSFORM_FLIP_H) &&
+ (mTransformHint != NATIVE_WINDOW_TRANSFORM_FLIP_V)) {
+ /* DirtyRect is generated by HWR without any knowledge of GPU
+ * pre-rotation. In case of pre-rotation, dirtyRect needs to be rotated
+ * accordingly.
+ *
+ * TODO: Generate and update dirtyRect from EGL and remove this code.
+ */
+
+ Rect srcRect = mActiveBuffer->getBounds();
+ Rect tempDR = dirtyRect;
+ int srcW = srcRect.getWidth();
+ int srcH = srcRect.getHeight();
+
+ if(mTransformHint & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+ swap(srcW, srcH);
+ }
+
+ int setOffsetW = -srcW/2;
+ int setOffsetH = -srcH/2;
+
+ int resetOffsetW = srcW/2;
+ int resetOffsetH = srcH/2;
+
+ if(mTransformHint & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+ swap(resetOffsetW, resetOffsetH);
+ }
+
+ /* - Move 2D space origin to srcRect origin.
+ * - Rotate
+ * - Move back the origin
+ */
+ Transform setOrigin;
+ setOrigin.set(setOffsetW, setOffsetH);
+ tempDR = setOrigin.transform(tempDR);
+ Transform rotate(mTransformHint);
+ tempDR = rotate.transform(tempDR);
+ Transform resetOrigin;
+ resetOrigin.set(resetOffsetW, resetOffsetH);
+ dirtyRect = resetOrigin.transform(tempDR);
+ }
+ layer.setDirtyRect(dirtyRect);
+
+ // NOTE: buffer can be NULL if the client never drew into this
+ // layer yet, or if we ran out of memory
+ layer.setBuffer(mActiveBuffer);
}
void Layer::setAcquireFence(const sp<const DisplayDevice>& /* hw */,
@@ -530,7 +668,8 @@
// TODO: there is a possible optimization here: we only need to set the
// acquire fence the first time a new buffer is acquired on EACH display.
- if (layer.getCompositionType() == HWC_OVERLAY || layer.getCompositionType() == HWC_CURSOR_OVERLAY) {
+ if (layer.getCompositionType() == HWC_OVERLAY || layer.getCompositionType() == HWC_CURSOR_OVERLAY ||
+ layer.getCompositionType() == HWC_BLIT) {
sp<Fence> fence = mSurfaceFlingerConsumer->getCurrentFence();
if (fence->isValid()) {
fenceFd = fence->dup();
@@ -621,11 +760,23 @@
// is probably going to have something visibly wrong.
}
+ bool canAllowGPU = false;
+#ifdef QCOM_BSP
+ if(isProtected()) {
+ char property[PROPERTY_VALUE_MAX];
+ if ((property_get("persist.gralloc.cp.level3", property, NULL) > 0) &&
+ (atoi(property) == 1)) {
+ if(hw->getDisplayType() == HWC_DISPLAY_PRIMARY)
+ canAllowGPU = true;
+ }
+ }
+#endif
+
bool blackOutLayer = isProtected() || (isSecure() && !hw->isSecure());
RenderEngine& engine(mFlinger->getRenderEngine());
- if (!blackOutLayer) {
+ if (!blackOutLayer || (canAllowGPU)) {
// TODO: we could be more subtle with isFixedSize()
const bool useFiltering = getFiltering() || needsFiltering(hw) || isFixedSize();
@@ -698,22 +849,22 @@
computeGeometry(hw, mMesh, useIdentityTransform);
- /*
- * NOTE: the way we compute the texture coordinates here produces
- * different results than when we take the HWC path -- in the later case
- * the "source crop" is rounded to texel boundaries.
- * This can produce significantly different results when the texture
- * is scaled by a large amount.
- *
- * The GL code below is more logical (imho), and the difference with
- * HWC is due to a limitation of the HWC API to integers -- a question
- * is suspend is whether we should ignore this problem or revert to
- * GL composition when a buffer scaling is applied (maybe with some
- * minimal value)? Or, we could make GL behave like HWC -- but this feel
- * like more of a hack.
- */
- const Rect win(computeBounds());
-
+ // Compute the crops exactly in the way we are doing
+ // for HWC & program texture coordinates for the clipped
+ // source after transformation.
+ Rect win(s.active.w, s.active.h);
+ if(!s.active.crop.isEmpty()) {
+ win = s.active.crop;
+ }
+#ifdef QCOM_BSP
+ win = s.transform.transform(win);
+ win.intersect(hw->getViewport(), &win);
+ win = s.transform.inverse().transform(win);
+ win.intersect(Rect(s.active.w, s.active.h), &win);
+ win = reduce(win, s.activeTransparentRegion);
+#else
+ win = reduce(win, s.activeTransparentRegion);
+#endif
float left = float(win.left) / float(s.active.w);
float top = float(win.top) / float(s.active.h);
float right = float(win.right) / float(s.active.w);
@@ -781,15 +932,37 @@
bool useIdentityTransform) const
{
const Layer::State& s(getDrawingState());
- const Transform tr(useIdentityTransform ?
+ Transform tr(useIdentityTransform ?
hw->getTransform() : hw->getTransform() * s.transform);
const uint32_t hw_h = hw->getHeight();
Rect win(s.active.w, s.active.h);
if (!s.active.crop.isEmpty()) {
win.intersect(s.active.crop, &win);
}
+
+#ifdef QCOM_BSP
+ win = s.transform.transform(win);
+ win.intersect(hw->getViewport(), &win);
+ win = s.transform.inverse().transform(win);
+ win.intersect(Rect(s.active.w, s.active.h), &win);
+ win = reduce(win, s.activeTransparentRegion);
+ Transform transform = computeBufferTransform(hw);
+ const uint32_t orientation = transform.getOrientation();
+ // If rotation or pre-rotation is there we can't match HWC 100%.
+ // Still, we can make sure input vertices to GPU is based ROI on screen
+ // after applying layer transform.
+
+ if (!(mTransformHint | mCurrentTransform | orientation)) {
+ tr = hw->getTransform();
+ if(!useIdentityTransform) {
+ win = s.transform.transform(win);
+ win.intersect(hw->getViewport(), &win);
+ }
+ }
+#else
// subtract the transparent region and snap to the bounds
win = reduce(win, s.activeTransparentRegion);
+#endif
Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
position[0] = tr.transform(win.left, win.top);
@@ -1086,7 +1259,8 @@
bool Layer::isVisible() const {
const Layer::State& s(mDrawingState);
- return !(s.flags & layer_state_t::eLayerHidden) && s.alpha
+ return !(s.flags & layer_state_t::eLayerHidden) &&
+ !(s.flags & layer_state_t::eLayerTransparent) && s.alpha
&& (mActiveBuffer != NULL || mSidebandStream != NULL);
}
@@ -1321,7 +1495,7 @@
return usage;
}
-void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const {
+void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) {
uint32_t orientation = 0;
if (!mFlinger->mDebugDisableTransformHint) {
// The transform hint is used to improve performance, but we can
@@ -1334,6 +1508,7 @@
}
}
mSurfaceFlingerConsumer->setTransformHint(orientation);
+ mTransformHint = orientation;
}
// ----------------------------------------------------------------------------
@@ -1416,6 +1591,60 @@
mFlinger->onLayerDestroyed(mLayer);
}
+#ifdef QCOM_BSP
+bool Layer::hasNewFrame() const {
+ return (mQueuedFrames > 0);
+}
+
+bool Layer::isExtOnly() const
+{
+ const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
+ if (activeBuffer != 0) {
+ uint32_t usage = activeBuffer->getUsage();
+ if(usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY)
+ return true;
+ }
+ return false;
+}
+
+bool Layer::isIntOnly() const
+{
+ const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
+ if (activeBuffer != 0) {
+ uint32_t usage = activeBuffer->getUsage();
+ if(usage & GRALLOC_USAGE_PRIVATE_INTERNAL_ONLY)
+ return true;
+ }
+ return false;
+}
+
+bool Layer::isSecureDisplay() const
+{
+ const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
+ if (activeBuffer != 0) {
+ uint32_t usage = activeBuffer->getUsage();
+ if(usage & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY)
+ return true;
+ }
+ return false;
+}
+
+// returns true, if the activeBuffer is Yuv
+bool Layer::isYuvLayer() const {
+ const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
+ if(activeBuffer != 0) {
+ ANativeWindowBuffer* buffer = activeBuffer->getNativeBuffer();
+ if(buffer) {
+ private_handle_t* hnd = static_cast<private_handle_t*>
+ (const_cast<native_handle_t*>(buffer->handle));
+ //if BUFFER_TYPE_VIDEO, its YUV
+ return (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO));
+ }
+ }
+ return false;
+}
+#endif
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 1d4eee7..ef3f437 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -276,7 +276,13 @@
// Updates the transform hint in our SurfaceFlingerConsumer to match
// the current orientation of the display device.
- void updateTransformHint(const sp<const DisplayDevice>& hw) const;
+ void updateTransformHint(const sp<const DisplayDevice>& hw);
+#ifdef QCOM_BSP
+ virtual bool isExtOnly() const;
+ virtual bool isIntOnly() const;
+ virtual bool isSecureDisplay() const;
+ virtual bool isYuvLayer() const;
+#endif
/*
* returns the rectangle that crops the content of the layer and scales it
@@ -310,6 +316,11 @@
void logFrameStats();
void getFrameStats(FrameStats* outStats) const;
+#ifdef QCOM_BSP
+ //GPUTileRect : Return true if the layer has been updated in this frame.
+ bool hasNewFrame() const;
+#endif
+
protected:
// constant
sp<SurfaceFlinger> mFlinger;
@@ -345,6 +356,7 @@
FloatRect computeCrop(const sp<const DisplayDevice>& hw) const;
bool isCropped() const;
static bool getOpacityForFormat(uint32_t format);
+ Transform computeBufferTransform(const sp<const DisplayDevice>& hw) const;
// drawing
void clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip,
@@ -411,6 +423,9 @@
// Local copy of the queued contents of the incoming BufferQueue
mutable Mutex mQueueItemLock;
Vector<BufferItem> mQueueItems;
+
+ // Transform hint assigned for the layer
+ uint32_t mTransformHint;
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 8ebafbc..c131e0b 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -183,6 +183,18 @@
glDisable(GL_BLEND);
}
+#ifdef QCOM_BSP
+void GLES20RenderEngine::startTileComposition(int x , int y, int width,
+ int height, bool preserve) {
+ glStartTilingQCOM(x, y, width, height,
+ (preserve ? GL_COLOR_BUFFER_BIT0_QCOM : GL_NONE));
+}
+
+void GLES20RenderEngine::endTileComposition(unsigned int preserveMask) {
+ glEndTilingQCOM(preserveMask);
+}
+#endif
+
void GLES20RenderEngine::bindImageAsFramebuffer(EGLImageKHR image,
uint32_t* texName, uint32_t* fbName, uint32_t* status) {
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
index 3d6243e..d85be08 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -74,6 +74,11 @@
virtual void setupFillWithColor(float r, float g, float b, float a);
virtual void disableTexturing();
virtual void disableBlending();
+#ifdef QCOM_BSP
+ virtual void startTileComposition(int x , int y, int width,
+ int height,bool preserve );
+ virtual void endTileComposition(unsigned int preserveMask);
+#endif
virtual void drawMesh(const Mesh& mesh);
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 8d7529c..00e8292 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -101,6 +101,12 @@
virtual void disableTexturing() = 0;
virtual void disableBlending() = 0;
+#ifdef QCOM_BSP
+ virtual void startTileComposition(int x, int y, int width,
+ int height, bool preserve){}
+ virtual void endTileComposition(unsigned int) {}
+#endif
+
// drawing
virtual void drawMesh(const Mesh& mesh) = 0;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 80d3cc2..db2c535 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -77,6 +77,13 @@
#include "RenderEngine/RenderEngine.h"
#include <cutils/compiler.h>
+#ifdef QCOM_BSP
+#include <gralloc_priv.h>
+#endif
+
+#ifdef QCOM_BSP
+#include <display_config.h>
+#endif
#define DISPLAY_COUNT 1
@@ -123,6 +130,10 @@
const String16 sDump("android.permission.DUMP");
// ---------------------------------------------------------------------------
+// Initialize extendedMode to false
+#ifdef QCOM_BSP
+bool SurfaceFlinger::sExtendedMode = false;
+#endif
SurfaceFlinger::SurfaceFlinger()
: BnSurfaceComposer(),
@@ -145,6 +156,7 @@
mDebugInTransaction(0),
mLastTransactionTime(0),
mBootFinished(false),
+ mGpuTileRenderEnable(false),
mPrimaryHWVsyncEnabled(false),
mHWVsyncAvailable(false),
mDaltonize(false),
@@ -169,6 +181,18 @@
mDebugDDMS = 0;
}
}
+#ifdef QCOM_BSP
+ mCanUseGpuTileRender = false;
+ property_get("debug.sf.gpu_comp_tiling", value, "0");
+ mGpuTileRenderEnable = atoi(value) ? true : false;
+ if(mGpuTileRenderEnable)
+ ALOGV("DirtyRect optimization enabled for FULL GPU Composition");
+ mUnionDirtyRect.clear();
+
+ property_get("sys.disable_ext_animation", value, "0");
+ mDisableExtAnimation = atoi(value) ? true : false;
+#endif
+
ALOGI_IF(mDebugRegion, "showupdates enabled");
ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");
}
@@ -254,13 +278,13 @@
setTransactionFlags(eDisplayTransactionNeeded);
}
-void SurfaceFlinger::createBuiltinDisplayLocked(DisplayDevice::DisplayType type) {
+void SurfaceFlinger::createBuiltinDisplayLocked(DisplayDevice::DisplayType type,
+ bool secure) {
ALOGW_IF(mBuiltinDisplays[type],
"Overwriting display token for display type %d", type);
mBuiltinDisplays[type] = new BBinder();
DisplayDeviceState info(type);
- // All non-virtual displays are currently considered secure.
- info.isSecure = true;
+ info.isSecure = secure;
mCurrentState.displays.add(mBuiltinDisplays[type], info);
}
@@ -391,6 +415,12 @@
status_t err;
Mutex::Autolock _l(mStateLock);
+ /* Set the mask bit of the sigset to block the SIGPIPE signal */
+ sigset_t sigMask;
+ sigemptyset (&sigMask);
+ sigaddset(&sigMask, SIGPIPE);
+ sigprocmask(SIG_BLOCK, &sigMask, NULL);
+
// initialize EGL for the default display
mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(mEGLDisplay, NULL, NULL);
@@ -414,9 +444,9 @@
DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
// set-up the displays that are already connected
if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
- // All non-virtual displays are currently considered secure.
- bool isSecure = true;
- createBuiltinDisplayLocked(type);
+ // query from hwc if the non-virtual display is secure.
+ bool isSecure = mHwc->isSecure(i);;
+ createBuiltinDisplayLocked(type, isSecure);
wp<IBinder> token = mBuiltinDisplays[i];
sp<IGraphicBufferProducer> producer;
@@ -480,6 +510,7 @@
void SurfaceFlinger::startBootAnim() {
// start boot animation
+ mBootFinished = false;
property_set("service.bootanim.exit", "0");
property_set("ctl.start", "bootanim");
}
@@ -503,7 +534,7 @@
status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,
Vector<DisplayInfo>* configs) {
- if (configs == NULL) {
+ if ((configs == NULL) || (display.get() == NULL)) {
return BAD_VALUE;
}
@@ -598,8 +629,8 @@
info.presentationDeadline =
hwConfig.refresh - SF_VSYNC_EVENT_PHASE_OFFSET_NS + 1000000;
- // All non-virtual displays are currently considered secure.
- info.secure = true;
+ // set secure info based on the hwcConfig
+ info.secure = hwConfig.secure;
configs->push_back(info);
}
@@ -640,8 +671,10 @@
return;
}
- hw->setActiveConfig(mode);
- getHwComposer().setActiveConfig(type, mode);
+ status_t status = getHwComposer().setActiveConfig(type, mode);
+ if (status == NO_ERROR) {
+ hw->setActiveConfig(mode);
+ }
}
status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& display, int mode) {
@@ -810,10 +843,19 @@
if (uint32_t(type) < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
Mutex::Autolock _l(mStateLock);
if (connected) {
- createBuiltinDisplayLocked((DisplayDevice::DisplayType)type);
+ // query from hwc if the connected display is secure
+ bool secure = mHwc->isSecure(type);;
+ createBuiltinDisplayLocked((DisplayDevice::DisplayType)type, secure);
} else {
mCurrentState.displays.removeItem(mBuiltinDisplays[type]);
mBuiltinDisplays[type].clear();
+#ifdef QCOM_BSP
+ // if extended_mode is set, and set mVisibleRegionsDirty
+ // as we need to rebuildLayerStack
+ if(isExtendedMode()) {
+ mVisibleRegionsDirty = true;
+ }
+#endif
}
setTransactionFlags(eDisplayTransactionNeeded);
@@ -866,11 +908,24 @@
return handlePageFlip();
}
+#ifdef QCOM_BSP
+/* Compute DirtyRegion, if DR optimization for GPU comp optimization
+ * is ON & and no external device is connected.*/
+void SurfaceFlinger::setUpTiledDr() {
+ if(mGpuTileRenderEnable && (mDisplays.size()==1)) {
+ const sp<DisplayDevice>& hw(mDisplays[HWC_DISPLAY_PRIMARY]);
+ mCanUseGpuTileRender = computeTiledDr(hw);
+ }
+}
+#endif
void SurfaceFlinger::handleMessageRefresh() {
ATRACE_CALL();
preComposition();
rebuildLayerStacks();
setUpHWComposer();
+#ifdef QCOM_BSP
+ setUpTiledDr();
+#endif
doDebugFlashRegions();
doComposition();
postComposition();
@@ -885,20 +940,45 @@
const bool repaintEverything = mRepaintEverything;
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
const sp<DisplayDevice>& hw(mDisplays[dpy]);
+
if (hw->isDisplayOn()) {
- // transform the dirty region into this screen's coordinate space
- const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
- if (!dirtyRegion.isEmpty()) {
+ const int32_t height = hw->getHeight();
+ RenderEngine& engine(getRenderEngine());
+#ifdef QCOM_BSP
+ // Use Union DR, if it is valid & GPU Tiled DR optimization is ON
+ if(mCanUseGpuTileRender && !mUnionDirtyRect.isEmpty()) {
// redraw the whole screen
doComposeSurfaces(hw, Region(hw->bounds()));
-
+ Region dirtyRegion(mUnionDirtyRect);
+ Rect dr = mUnionDirtyRect;
+ hw->eglSwapPreserved(true);
+ engine.startTileComposition(dr.left, (height-dr.bottom),
+ (dr.right-dr.left),
+ (dr.bottom-dr.top), 1);
// and draw the dirty region
- const int32_t height = hw->getHeight();
- RenderEngine& engine(getRenderEngine());
engine.fillRegionWithColor(dirtyRegion, height, 1, 0, 1, 1);
-
+ engine.endTileComposition(GL_PRESERVE);
hw->compositionComplete();
hw->swapBuffers(getHwComposer());
+ } else
+#endif
+ {
+ // transform the dirty region into this screen's coordinate
+ // space
+ const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
+ if (!dirtyRegion.isEmpty()) {
+ // redraw the whole screen
+ doComposeSurfaces(hw, Region(hw->bounds()));
+ // and draw the dirty region
+#ifdef QCOM_BSP
+ if(mGpuTileRenderEnable)
+ hw->eglSwapPreserved(false);
+#endif
+
+ engine.fillRegionWithColor(dirtyRegion, height, 1, 0, 1, 1);
+ hw->compositionComplete();
+ hw->swapBuffers(getHwComposer());
+ }
}
}
}
@@ -973,6 +1053,11 @@
}
void SurfaceFlinger::rebuildLayerStacks() {
+#ifdef QCOM_BSP
+ char prop[PROPERTY_VALUE_MAX];
+ property_get("sys.extended_mode", prop, "0");
+ sExtendedMode = atoi(prop) ? true : false;
+#endif
// rebuild the visible layer list per screen
if (CC_UNLIKELY(mVisibleRegionsDirty)) {
ATRACE_CALL();
@@ -987,21 +1072,20 @@
const sp<DisplayDevice>& hw(mDisplays[dpy]);
const Transform& tr(hw->getTransform());
const Rect bounds(hw->getBounds());
+ int dpyId = hw->getHwcDisplayId();
if (hw->isDisplayOn()) {
- SurfaceFlinger::computeVisibleRegions(layers,
+ SurfaceFlinger::computeVisibleRegions(dpyId, layers,
hw->getLayerStack(), dirtyRegion, opaqueRegion);
const size_t count = layers.size();
for (size_t i=0 ; i<count ; i++) {
const sp<Layer>& layer(layers[i]);
const Layer::State& s(layer->getDrawingState());
- if (s.layerStack == hw->getLayerStack()) {
- Region drawRegion(tr.transform(
- layer->visibleNonTransparentRegion));
- drawRegion.andSelf(bounds);
- if (!drawRegion.isEmpty()) {
- layersSortedByZ.add(layer);
- }
+ Region drawRegion(tr.transform(
+ layer->visibleNonTransparentRegion));
+ drawRegion.andSelf(bounds);
+ if (!drawRegion.isEmpty()) {
+ layersSortedByZ.add(layer);
}
}
}
@@ -1075,6 +1159,31 @@
sp<const DisplayDevice> hw(mDisplays[dpy]);
const int32_t id = hw->getHwcDisplayId();
if (id >= 0) {
+ // Get the layers in the current drawying state
+ const LayerVector& layers(mDrawingState.layersSortedByZ);
+#ifdef QCOM_BSP
+ bool freezeSurfacePresent = false;
+ const size_t layerCount = layers.size();
+ // Look for ScreenShotSurface in external layer list, only when
+ // disable external rotation animation feature is enabled
+ if(mDisableExtAnimation && (id != HWC_DISPLAY_PRIMARY)) {
+ for (size_t i = 0 ; i < layerCount ; ++i) {
+ static int screenShotLen = strlen("ScreenshotSurface");
+ const sp<Layer>& layer(layers[i]);
+ const Layer::State& s(layer->getDrawingState());
+ // check the layers associated with external display
+ if(s.layerStack == hw->getLayerStack()) {
+ if(!strncmp(layer->getName(), "ScreenshotSurface",
+ screenShotLen)) {
+ // Screenshot layer is present, and animation in
+ // progress
+ freezeSurfacePresent = true;
+ break;
+ }
+ }
+ }
+ }
+#endif
const Vector< sp<Layer> >& currentLayers(
hw->getVisibleLayersSortedByZ());
const size_t count = currentLayers.size();
@@ -1087,6 +1196,24 @@
*/
const sp<Layer>& layer(currentLayers[i]);
layer->setPerFrameData(hw, *cur);
+#ifdef QCOM_BSP
+ if(freezeSurfacePresent) {
+ // if freezeSurfacePresent, set ANIMATING flag
+ cur->setAnimating(true);
+ } else {
+ const KeyedVector<wp<IBinder>, DisplayDeviceState>&
+ draw(mDrawingState.displays);
+ size_t dc = draw.size();
+ for (size_t i=0 ; i<dc ; i++) {
+ if (draw[i].isMainDisplay()) {
+ // Pass the current orientation to HWC
+ hwc.eventControl(HWC_DISPLAY_PRIMARY,
+ SurfaceFlinger::EVENT_ORIENTATION,
+ uint32_t(draw[i].orientation));
+ }
+ }
+ }
+#endif
}
}
}
@@ -1224,6 +1351,107 @@
// here the transaction has been committed
}
+void SurfaceFlinger::setVirtualDisplayData(
+ int32_t hwcDisplayId,
+ const sp<IGraphicBufferProducer>& sink)
+{
+ sp<ANativeWindow> mNativeWindow = new Surface(sink);
+ ANativeWindow* const window = mNativeWindow.get();
+
+ int format;
+ window->query(window, NATIVE_WINDOW_FORMAT, &format);
+
+ EGLSurface surface;
+ EGLint w, h;
+ EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ surface = eglCreateWindowSurface(display, mRenderEngine->getEGLConfig(), window, NULL);
+ eglQuerySurface(display, surface, EGL_WIDTH, &w);
+ eglQuerySurface(display, surface, EGL_HEIGHT, &h);
+
+ mHwc->setVirtualDisplayProperties(hwcDisplayId, w, h, format);
+}
+
+void SurfaceFlinger::configureVirtualDisplay(int32_t &hwcDisplayId,
+ sp<DisplaySurface> &dispSurface,
+ sp<IGraphicBufferProducer> &producer,
+ const DisplayDeviceState state,
+ sp<IGraphicBufferProducer> bqProducer,
+ sp<IGraphicBufferConsumer> bqConsumer)
+{
+ bool vdsEnabled = mHwc->isVDSEnabled();
+
+ //for V4L2 based virtual display implementation
+ if(!vdsEnabled) {
+ // persist.sys.wfd.virtual will be set if WFD is launched via
+ // settings app. This is currently being done in
+ // ExtendedRemoteDisplay-WFD stack.
+ // This flag will be reset at the time of disconnection of virtual WFD
+ // display.
+ // This flag is set to zero if WFD is launched via QCOM WFD
+ // proprietary APIs which use HDMI piggyback approach.
+ char value[PROPERTY_VALUE_MAX];
+ property_get("persist.sys.wfd.virtual", value, "0");
+ int wfdVirtual = atoi(value);
+ if(!wfdVirtual) {
+ // This is for non-wfd virtual display scenarios(e.g. SSD/SR/CTS)
+ sp<VirtualDisplaySurface> vds = new VirtualDisplaySurface(*mHwc,
+ hwcDisplayId, state.surface, bqProducer, bqConsumer,
+ state.displayName, state.isSecure);
+ dispSurface = vds;
+ // There won't be any interaction with HWC for this virtual display.
+ // so the GLES driver can pass buffers directly to the sink.
+ producer = state.surface;
+ } else {
+ int sinkUsage = -1;
+ state.surface->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &sinkUsage);
+#ifdef QCOM_BSP
+ if(sinkUsage & GRALLOC_USAGE_PRIVATE_WFD)
+#endif
+ hwcDisplayId = allocateHwcDisplayId(state.type);
+
+ if (hwcDisplayId >= 0) {
+ // This is for WFD virtual display scenario.
+ // Read virtual display properties and create a
+ // rendering surface for it inorder to be handled by hwc.
+ setVirtualDisplayData(hwcDisplayId, state.surface);
+ dispSurface = new FramebufferSurface(*mHwc, state.type,
+ bqConsumer);
+ producer = bqProducer;
+ } else {
+ // in case of WFD Virtual + SSD/SR concurrency scenario,
+ // WFD virtual display instance gets valid hwcDisplayId and
+ // SSD/SR will get invalid hwcDisplayId
+ sp<VirtualDisplaySurface> vds = new VirtualDisplaySurface(*mHwc,
+ hwcDisplayId, state.surface, bqProducer, bqConsumer,
+ state.displayName, state.isSecure);
+ dispSurface = vds;
+ // There won't be any interaction with HWC for this virtual
+ // display, so the GLES driver can pass buffers directly to the
+ // sink.
+ producer = state.surface;
+ }
+ }
+ } else {
+ // VDS solution is enabled
+ // HWC is allocated for first virtual display.
+ // Subsequent virtual display sessions will be composed by GLES driver.
+ // ToDo: Modify VDS component to allocate hwcDisplayId based on
+ // mForceHwcCopy (which is based on Usage Flags)
+
+ sp<VirtualDisplaySurface> vds = new VirtualDisplaySurface(*mHwc,
+ hwcDisplayId, state.surface, bqProducer, bqConsumer,
+ state.displayName, state.isSecure);
+ dispSurface = vds;
+ if (hwcDisplayId >= 0) {
+ producer = vds;
+ } else {
+ // There won't be any interaction with HWC for this virtual display,
+ // so the GLES driver can pass buffers directly to the sink.
+ producer = state.surface;
+ }
+ }
+}
+
void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
{
const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
@@ -1312,8 +1540,40 @@
|| (state.viewport != draw[i].viewport)
|| (state.frame != draw[i].frame))
{
+#ifdef QCOM_BSP
+ int orient = state.orientation;
+ // Honor the orientation change after boot
+ // animation completes and make sure boot
+ // animation is shown in panel orientation always.
+ if(mBootFinished){
+ disp->setProjection(state.orientation,
+ state.viewport, state.frame);
+ orient = state.orientation;
+ }
+ else{
+ char property[PROPERTY_VALUE_MAX];
+ int panelOrientation =
+ DisplayState::eOrientationDefault;
+ if(property_get("persist.panel.orientation",
+ property, "0") > 0){
+ panelOrientation = atoi(property) / 90;
+ }
+ disp->setProjection(panelOrientation,
+ state.viewport, state.frame);
+ orient = panelOrientation;
+ }
+ // Set the view frame of each display only of its
+ // default orientation.
+ if(orient == DisplayState::eOrientationDefault and
+ state.frame.isValid()) {
+ qdutils::setViewFrame(disp->getHwcDisplayId(),
+ state.frame.left, state.frame.top,
+ state.frame.right, state.frame.bottom);
+ }
+#else
disp->setProjection(state.orientation,
- state.viewport, state.frame);
+ state.viewport, state.frame);
+#endif
}
if (state.width != draw[i].width || state.height != draw[i].height) {
disp->setDisplaySize(state.width, state.height);
@@ -1341,29 +1601,9 @@
// they have external state (layer stack, projection,
// etc.) but no internal state (i.e. a DisplayDevice).
if (state.surface != NULL) {
-
- int width = 0;
- int status = state.surface->query(
- NATIVE_WINDOW_WIDTH, &width);
- ALOGE_IF(status != NO_ERROR,
- "Unable to query width (%d)", status);
- int height = 0;
- status = state.surface->query(
- NATIVE_WINDOW_HEIGHT, &height);
- ALOGE_IF(status != NO_ERROR,
- "Unable to query height (%d)", status);
- if (MAX_VIRTUAL_DISPLAY_DIMENSION == 0 ||
- (width <= MAX_VIRTUAL_DISPLAY_DIMENSION &&
- height <= MAX_VIRTUAL_DISPLAY_DIMENSION)) {
- hwcDisplayId = allocateHwcDisplayId(state.type);
- }
-
- sp<VirtualDisplaySurface> vds = new VirtualDisplaySurface(
- *mHwc, hwcDisplayId, state.surface,
- bqProducer, bqConsumer, state.displayName);
-
- dispSurface = vds;
- producer = vds;
+ configureVirtualDisplay(hwcDisplayId,
+ dispSurface, producer, state, bqProducer,
+ bqConsumer);
}
} else {
ALOGE_IF(state.surface!=NULL,
@@ -1379,7 +1619,7 @@
}
const wp<IBinder>& display(curr.keyAt(i));
- if (dispSurface != NULL) {
+ if (dispSurface != NULL && producer != NULL) {
sp<DisplayDevice> hw = new DisplayDevice(this,
state.type, hwcDisplayId,
mHwc->getFormat(hwcDisplayId), state.isSecure,
@@ -1389,6 +1629,13 @@
hw->setProjection(state.orientation,
state.viewport, state.frame);
hw->setDisplayName(state.displayName);
+ // When a new display device is added update the active
+ // config by querying HWC otherwise the default config
+ // (config 0) will be used.
+ int activeConfig = mHwc->getActiveConfig(hwcDisplayId);
+ if (activeConfig >= 0) {
+ hw->setActiveConfig(activeConfig);
+ }
mDisplays.add(display, hw);
if (state.isVirtualDisplay()) {
if (hwcDisplayId >= 0) {
@@ -1547,7 +1794,7 @@
mTransactionCV.broadcast();
}
-void SurfaceFlinger::computeVisibleRegions(
+void SurfaceFlinger::computeVisibleRegions(size_t dpy,
const LayerVector& currentLayers, uint32_t layerStack,
Region& outDirtyRegion, Region& outOpaqueRegion)
{
@@ -1558,18 +1805,68 @@
Region dirty;
outDirtyRegion.clear();
-
+ bool bIgnoreLayers = false;
+ int indexLOI = -1;
size_t i = currentLayers.size();
+#ifdef QCOM_BSP
+ while (i--) {
+ const sp<Layer>& layer = currentLayers[i];
+ // iterate through the layer list to find ext_only layers and store
+ // the index
+ if (layer->isSecureDisplay()) {
+ bIgnoreLayers = true;
+ indexLOI = -1;
+ if(!dpy)
+ indexLOI = i;
+ break;
+ }
+ // iterate through the layer list to find ext_only layers or yuv
+ // layer(extended_mode) and store the index
+ if ((dpy && (layer->isExtOnly() ||
+ (isExtendedMode() && layer->isYuvLayer())))) {
+ bIgnoreLayers= true;
+ indexLOI = i;
+ }
+ }
+ i = currentLayers.size();
+#endif
while (i--) {
const sp<Layer>& layer = currentLayers[i];
// start with the whole surface at its current location
const Layer::State& s(layer->getDrawingState());
- // only consider the layers on the given layer stack
- if (s.layerStack != layerStack)
+#ifdef QCOM_BSP
+ // Only add the layer marked as "external_only" or yuvLayer
+ // (extended_mode) to external list and
+ // only remove the layer marked as "external_only" or yuvLayer in
+ // extended_mode from primary list
+ // and do not add the layer marked as "internal_only" to external list
+ // Add secure UI layers to primary and remove other layers from internal
+ //and external list
+ if(((bIgnoreLayers && indexLOI != (int)i) ||
+ (!dpy && layer->isExtOnly()) ||
+ (!dpy && isExtendedMode() && layer->isYuvLayer()))||
+ (dpy && layer->isIntOnly())) {
+ // Ignore all other layers except the layers marked as ext_only
+ // by setting visible non transparent region empty.
+ Region visibleNonTransRegion;
+ visibleNonTransRegion.set(Rect(0,0));
+ layer->setVisibleNonTransparentRegion(visibleNonTransRegion);
continue;
-
+ }
+#endif
+ // only consider the layers on the given later stack
+ // Override layers created using presentation class by the layers having
+ // ext_only flag enabled
+ if(s.layerStack != layerStack && !bIgnoreLayers) {
+ // set the visible region as empty since we have removed the
+ // layerstack check in rebuildLayerStack() function.
+ Region visibleNonTransRegion;
+ visibleNonTransRegion.set(Rect(0,0));
+ layer->setVisibleNonTransparentRegion(visibleNonTransRegion);
+ continue;
+ }
/*
* opaqueRegion: area of a surface that is fully opaque.
*/
@@ -1806,6 +2103,24 @@
hw->swapBuffers(getHwComposer());
}
+#ifdef QCOM_BSP
+bool SurfaceFlinger::computeTiledDr(const sp<const DisplayDevice>& hw) {
+ int fbWidth= hw->getWidth();
+ int fbHeight= hw->getHeight();
+ Rect fullScreenRect = Rect(0,0,fbWidth, fbHeight);
+ const int32_t id = hw->getHwcDisplayId();
+ mUnionDirtyRect.clear();
+ HWComposer& hwc(getHwComposer());
+
+ /* Compute and return the Union of Dirty Rects.
+ * Return false if the unionDR is fullscreen, as there is no benefit from
+ * preserving full screen.*/
+ return (hwc.canUseTiledDR(id, mUnionDirtyRect) &&
+ (mUnionDirtyRect != fullScreenRect));
+
+}
+#endif
+
bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty)
{
RenderEngine& engine(getRenderEngine());
@@ -1814,7 +2129,9 @@
HWComposer::LayerListIterator cur = hwc.begin(id);
const HWComposer::LayerListIterator end = hwc.end(id);
+ Region clearRegion;
bool hasGlesComposition = hwc.hasGlesComposition(id);
+ const bool hasHwcComposition = hwc.hasHwcComposition(id);
if (hasGlesComposition) {
if (!hw->makeCurrent(mEGLDisplay, mEGLContext)) {
ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
@@ -1827,14 +2144,14 @@
}
// Never touch the framebuffer if we don't have any framebuffer layers
- const bool hasHwcComposition = hwc.hasHwcComposition(id);
if (hasHwcComposition) {
// when using overlays, we assume a fully transparent framebuffer
// NOTE: we could reduce how much we need to clear, for instance
// remove where there are opaque FB layers. however, on some
// GPUs doing a "clean slate" clear might be more efficient.
// We'll revisit later if needed.
- engine.clearWithColor(0, 0, 0, 0);
+ if(!(mGpuTileRenderEnable && (mDisplays.size()==1)))
+ engine.clearWithColor(0, 0, 0, 0);
} else {
// we start with the whole screen area
const Region bounds(hw->getBounds());
@@ -1850,10 +2167,31 @@
// but limit it to the dirty region
region.andSelf(dirty);
+
// screen is already cleared here
- if (!region.isEmpty()) {
- // can happen with SurfaceView
- drawWormhole(hw, region);
+#ifdef QCOM_BSP
+ clearRegion.clear();
+ if(mGpuTileRenderEnable && (mDisplays.size()==1)) {
+ clearRegion = region;
+ if (cur == end) {
+ drawWormhole(hw, region);
+ } else if(mCanUseGpuTileRender) {
+ /* If GPUTileRect DR optimization on clear only the UnionDR
+ * (computed by computeTiledDr) which is the actual region
+ * that will be drawn on FB in this cycle.. */
+ clearRegion = clearRegion.andSelf(Region(mUnionDirtyRect));
+ }
+ } else
+#endif
+ {
+ if (!region.isEmpty()) {
+ if (cur != end) {
+ if (cur->getCompositionType() != HWC_BLIT)
+ // can happen with SurfaceView
+ drawWormhole(hw, region);
+ } else
+ drawWormhole(hw, region);
+ }
}
}
@@ -1885,6 +2223,47 @@
const Transform& tr = hw->getTransform();
if (cur != end) {
// we're using h/w composer
+#ifdef QCOM_BSP
+ int fbWidth= hw->getWidth();
+ int fbHeight= hw->getHeight();
+ /* if GPUTileRender optimization property is on & can be used
+ * i) Enable EGL_SWAP_PRESERVED flag
+ * ii) do startTile with union DirtyRect
+ * else , Disable EGL_SWAP_PRESERVED */
+ if(mGpuTileRenderEnable && (mDisplays.size()==1)) {
+ if(mCanUseGpuTileRender && !mUnionDirtyRect.isEmpty()) {
+ hw->eglSwapPreserved(true);
+ Rect dr = mUnionDirtyRect;
+ engine.startTileComposition(dr.left, (fbHeight-dr.bottom),
+ (dr.right-dr.left),
+ (dr.bottom-dr.top), 0);
+ } else {
+ // Un Set EGL_SWAP_PRESERVED flag, if no tiling required.
+ hw->eglSwapPreserved(false);
+ }
+ // DrawWormHole/Any Draw has to be within startTile & EndTile
+ if (hasGlesComposition) {
+ if (hasHwcComposition) {
+ if(mCanUseGpuTileRender && !mUnionDirtyRect.isEmpty()) {
+ const Rect& scissor(mUnionDirtyRect);
+ engine.setScissor(scissor.left,
+ hw->getHeight()- scissor.bottom,
+ scissor.getWidth(), scissor.getHeight());
+ engine.clearWithColor(0, 0, 0, 0);
+ engine.disableScissor();
+ } else {
+ engine.clearWithColor(0, 0, 0, 0);
+ }
+ } else {
+ if (cur->getCompositionType() != HWC_BLIT &&
+ !clearRegion.isEmpty()) {
+ drawWormhole(hw, clearRegion);
+ }
+ }
+ }
+ }
+#endif
+
for (size_t i=0 ; i<count && cur!=end ; ++i, ++cur) {
const sp<Layer>& layer(layers[i]);
const Region clip(dirty.intersect(tr.transform(layer->visibleRegion)));
@@ -1907,6 +2286,9 @@
layer->draw(hw, clip);
break;
}
+ case HWC_BLIT:
+ //Do nothing
+ break;
case HWC_FRAMEBUFFER_TARGET: {
// this should not happen as the iterator shouldn't
// let us get there.
@@ -1917,6 +2299,15 @@
}
layer->setAcquireFence(hw, *cur);
}
+
+#ifdef QCOM_BSP
+ // call EndTile, if starTile has been called in this cycle.
+ if(mGpuTileRenderEnable && (mDisplays.size()==1)) {
+ if(mCanUseGpuTileRender && !mUnionDirtyRect.isEmpty()) {
+ engine.endTileComposition(GL_PRESERVE);
+ }
+ }
+#endif
} else {
// we're not using h/w composer
for (size_t i=0 ; i<count ; ++i) {
@@ -1988,6 +2379,29 @@
uint32_t flags)
{
ATRACE_CALL();
+ size_t count = displays.size();
+#ifdef QCOM_BSP
+ // Delay the display projection transaction by 50ms only when the disable
+ // external rotation animation feature is enabled
+ if(mDisableExtAnimation) {
+ for (size_t i=0 ; i<count ; i++) {
+ const DisplayState& s(displays[i]);
+ if((mDisplays.indexOfKey(s.token) >= 0) && (s.token !=
+ mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY])) {
+ const uint32_t what = s.what;
+ // Invalidate and Delay the binder thread by 50 ms on
+ // eDisplayProjectionChanged to trigger a draw cycle so that
+ // it can fix one incorrect frame on the External, when we
+ // disable external animation
+ if (what & DisplayState::eDisplayProjectionChanged) {
+ invalidateHwcGeometry();
+ repaintEverything();
+ usleep(50000);
+ }
+ }
+ }
+ }
+#endif
Mutex::Autolock _l(mStateLock);
uint32_t transactionFlags = 0;
@@ -2007,7 +2421,6 @@
}
}
- size_t count = displays.size();
for (size_t i=0 ; i<count ; i++) {
const DisplayState& s(displays[i]);
transactionFlags |= setDisplayStateLocked(s);
@@ -2151,7 +2564,8 @@
flags |= eTraversalNeeded;
}
if ((what & layer_state_t::eVisibilityChanged) ||
- (what & layer_state_t::eOpacityChanged)) {
+ (what & layer_state_t::eOpacityChanged) ||
+ (what & layer_state_t::eTransparencyChanged)) {
// TODO: should we just use an eFlagsChanged for this?
if (layer->setFlags(s.flags, s.mask))
flags |= eTraversalNeeded;
@@ -3146,6 +3560,12 @@
// make sure to clear all GL error flags
engine.checkErrors();
+ if (DisplayDevice::DISPLAY_PRIMARY == hw->getDisplayType() &&
+ hw->isPanelInverseMounted()) {
+ rotation = (Transform::orientation_flags)
+ (rotation ^ Transform::ROT_180);
+ }
+
// set-up our viewport
engine.setViewportAndProjection(
reqWidth, reqHeight, sourceCrop, hw_h, yswap, rotation);
@@ -3161,9 +3581,26 @@
const Layer::State& state(layer->getDrawingState());
if (state.layerStack == hw->getLayerStack()) {
if (state.z >= minLayerZ && state.z <= maxLayerZ) {
+#ifdef QCOM_BSP
+ // dont render the secure Display Layer
+ if(layer->isSecureDisplay()) {
+ continue;
+ }
+#endif
+#ifdef QCOM_BSP
+ int dispType = hw->getDisplayType();
+ // Dont let ext_only and extended_mode to be captured
+ // If not, we would see incorrect image during rotatoin
+ // on primary
+ if (layer->isVisible() &&
+ not (!dispType && (layer->isExtOnly() ||
+ (isExtendedMode() && layer->isYuvLayer())))) {
+#else
if (layer->isVisible()) {
+#endif
if (filtering) layer->setFiltering(true);
- layer->draw(hw, useIdentityTransform);
+ if(!layer->isProtected())
+ layer->draw(hw, useIdentityTransform);
if (filtering) layer->setFiltering(false);
}
}
@@ -3221,7 +3658,6 @@
*/
result = native_window_dequeue_buffer_and_wait(window, &buffer);
if (result == NO_ERROR) {
- int syncFd = -1;
// create an EGLImage from the buffer so we can later
// turn it into a texture
EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT,
@@ -3251,31 +3687,21 @@
sync = EGL_NO_SYNC_KHR;
}
if (sync != EGL_NO_SYNC_KHR) {
- // get the sync fd
- syncFd = eglDupNativeFenceFDANDROID(mEGLDisplay, sync);
- if (syncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
- ALOGW("captureScreen: failed to dup sync khr object");
- syncFd = -1;
- }
- eglDestroySyncKHR(mEGLDisplay, sync);
- } else {
- // fallback path
- sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, NULL);
- if (sync != EGL_NO_SYNC_KHR) {
- EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync,
+ EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync,
EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 2000000000 /*2 sec*/);
- EGLint eglErr = eglGetError();
- if (result == EGL_TIMEOUT_EXPIRED_KHR) {
- ALOGW("captureScreen: fence wait timed out");
- } else {
- ALOGW_IF(eglErr != EGL_SUCCESS,
- "captureScreen: error waiting on EGL fence: %#x", eglErr);
- }
- eglDestroySyncKHR(mEGLDisplay, sync);
+ EGLint eglErr = eglGetError();
+ eglDestroySyncKHR(mEGLDisplay, sync);
+ if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+ ALOGW("captureScreen: fence wait timed out");
} else {
- ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError());
+ ALOGW_IF(eglErr != EGL_SUCCESS,
+ "captureScreen: error waiting on EGL fence: %#x", eglErr);
}
+ } else {
+ ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError());
+ // not fatal
}
+
if (DEBUG_SCREENSHOTS) {
uint32_t* pixels = new uint32_t[reqWidth*reqHeight];
getRenderEngine().readPixels(0, 0, reqWidth, reqHeight, pixels);
@@ -3293,8 +3719,7 @@
} else {
result = BAD_VALUE;
}
- // queueBuffer takes ownership of syncFd
- window->queueBuffer(window, buffer, syncFd);
+ window->queueBuffer(window, buffer, -1);
}
} else {
result = BAD_VALUE;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 4deb815..ecc189b 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -42,6 +42,7 @@
#include <gui/ISurfaceComposer.h>
#include <gui/ISurfaceComposerClient.h>
+#include <gui/BufferQueue.h>
#include <hardware/hwcomposer_defs.h>
@@ -97,7 +98,8 @@
void run() ANDROID_API;
enum {
- EVENT_VSYNC = HWC_EVENT_VSYNC
+ EVENT_VSYNC = HWC_EVENT_VSYNC,
+ EVENT_ORIENTATION = HWC_EVENT_ORIENTATION
};
// post an asynchronous message to the main thread
@@ -133,7 +135,12 @@
RenderEngine& getRenderEngine() const {
return *mRenderEngine;
}
-
+#ifdef QCOM_BSP
+ // Extended Mode - No video on primary and it will be shown full
+ // screen on External
+ static bool sExtendedMode;
+ static bool isExtendedMode() { return sExtendedMode; };
+#endif
private:
friend class Client;
friend class DisplayEventConnection;
@@ -260,6 +267,19 @@
void updateCursorAsync();
+ // Read virtual display properties
+ void setVirtualDisplayData( int32_t hwcDisplayId,
+ const sp<IGraphicBufferProducer>& sink);
+
+ // Configure Virtual Display parameters such as the display surface
+ // and the buffer queue
+ void configureVirtualDisplay(int32_t &hwcDisplayId,
+ sp<DisplaySurface> &dispSurface,
+ sp<IGraphicBufferProducer> &producer,
+ const DisplayDeviceState state,
+ sp<IGraphicBufferProducer> bqProducer,
+ sp<IGraphicBufferConsumer> bqConsumer);
+
/* handlePageFlip - latch a new buffer if available and compute the dirty
* region. Returns whether a new buffer has been latched, i.e., whether it
* is necessary to perform a refresh during this vsync.
@@ -342,7 +362,8 @@
void initializeDisplays();
// Create an IBinder for a builtin display and add it to current state
- void createBuiltinDisplayLocked(DisplayDevice::DisplayType type);
+ void createBuiltinDisplayLocked(DisplayDevice::DisplayType type,
+ bool secure);
// NOTE: can only be called from the main thread or with mStateLock held
sp<const DisplayDevice> getDisplayDevice(const wp<IBinder>& dpy) const {
@@ -371,7 +392,7 @@
* Compositing
*/
void invalidateHwcGeometry();
- static void computeVisibleRegions(
+ static void computeVisibleRegions(size_t dpy,
const LayerVector& currentLayers, uint32_t layerStack,
Region& dirtyRegion, Region& opaqueRegion);
@@ -470,6 +491,23 @@
nsecs_t mLastTransactionTime;
bool mBootFinished;
+ // Set if the Gpu Tile render DR optimization enabled
+ bool mGpuTileRenderEnable;
+ bool mCanUseGpuTileRender;
+ Rect mUnionDirtyRect;
+
+#ifdef QCOM_BSP
+ // Set up the DirtyRect/flags for GPU Comp optimization if required.
+ void setUpTiledDr();
+ // Find out if GPU composition can use Dirtyregion optimization
+ // Get the union dirty rect to operate
+ bool computeTiledDr(const sp<const DisplayDevice>& hw);
+ enum {
+ GL_PRESERVE_NONE = 0,
+ GL_PRESERVE = 1
+ };
+#endif
+
// these are thread safe
mutable MessageQueue mEventQueue;
FrameTracker mAnimFrameTracker;
@@ -493,6 +531,10 @@
mat4 mColorMatrix;
bool mHasColorMatrix;
+#ifdef QCOM_BSP
+ // Flag to disable external rotation animation feature.
+ bool mDisableExtAnimation;
+#endif
};
}; // namespace android