summaryrefslogtreecommitdiff
path: root/libs/gui
diff options
context:
space:
mode:
Diffstat (limited to 'libs/gui')
-rw-r--r--libs/gui/Android.bp32
-rw-r--r--libs/gui/BufferHubConsumer.cpp161
-rw-r--r--libs/gui/BufferHubProducer.cpp717
-rw-r--r--libs/gui/BufferItem.cpp31
-rw-r--r--libs/gui/BufferItemConsumer.cpp17
-rw-r--r--libs/gui/BufferQueue.cpp53
-rw-r--r--libs/gui/BufferQueueConsumer.cpp34
-rw-r--r--libs/gui/BufferQueueProducer.cpp68
-rw-r--r--libs/gui/ConsumerBase.cpp66
-rw-r--r--libs/gui/CpuConsumer.cpp241
-rw-r--r--libs/gui/DisplayEventReceiver.cpp12
-rw-r--r--libs/gui/FrameTimestamps.cpp1
-rw-r--r--libs/gui/GLConsumer.cpp307
-rw-r--r--libs/gui/HdrMetadata.cpp97
-rw-r--r--libs/gui/IGraphicBufferProducer.cpp111
-rw-r--r--libs/gui/ISurfaceComposer.cpp115
-rw-r--r--libs/gui/ISurfaceComposerClient.cpp4
-rw-r--r--libs/gui/LayerDebugInfo.cpp20
-rw-r--r--libs/gui/LayerState.cpp109
-rw-r--r--libs/gui/StreamSplitter.cpp6
-rw-r--r--libs/gui/Surface.cpp137
-rw-r--r--libs/gui/SurfaceComposerClient.cpp935
-rw-r--r--libs/gui/SurfaceControl.cpp155
-rw-r--r--libs/gui/SyncFeatures.cpp2
-rw-r--r--libs/gui/include/gui/BufferHubConsumer.h112
-rw-r--r--libs/gui/include/gui/BufferHubProducer.h219
-rw-r--r--libs/gui/include/gui/BufferItem.h8
-rw-r--r--libs/gui/include/gui/BufferItemConsumer.h4
-rw-r--r--libs/gui/include/gui/BufferQueue.h6
-rw-r--r--libs/gui/include/gui/ConsumerBase.h14
-rw-r--r--libs/gui/include/gui/CpuConsumer.h30
-rw-r--r--libs/gui/include/gui/GLConsumer.h23
-rw-r--r--libs/gui/include/gui/HdrMetadata.h45
-rw-r--r--libs/gui/include/gui/IGraphicBufferProducer.h31
-rw-r--r--libs/gui/include/gui/ISurfaceComposer.h31
-rw-r--r--libs/gui/include/gui/ISurfaceComposerClient.h6
-rw-r--r--libs/gui/include/gui/LayerDebugInfo.h3
-rw-r--r--libs/gui/include/gui/LayerState.h (renamed from libs/gui/include/private/gui/LayerState.h)26
-rw-r--r--libs/gui/include/gui/Surface.h22
-rw-r--r--libs/gui/include/gui/SurfaceComposerClient.h291
-rw-r--r--libs/gui/include/gui/SurfaceControl.h91
-rw-r--r--libs/gui/tests/Android.bp32
-rw-r--r--libs/gui/tests/CpuConsumer_test.cpp65
-rw-r--r--libs/gui/tests/GLTest.cpp10
-rw-r--r--libs/gui/tests/IGraphicBufferProducer_test.cpp150
-rw-r--r--libs/gui/tests/SurfaceParcelable_test.cpp168
-rw-r--r--libs/gui/tests/Surface_test.cpp114
-rw-r--r--libs/gui/view/Surface.cpp16
48 files changed, 3365 insertions, 1583 deletions
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 02d29a3e69..b29c1d5157 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -19,7 +19,7 @@ cc_library_headers {
cc_library_shared {
name: "libgui",
- vendor_available: true,
+ vendor_available: false,
vndk: {
enabled: true,
},
@@ -63,6 +63,12 @@ cc_library_shared {
// Allow documentation warnings
"-Wno-documentation",
+ // Allow implicit instantiation for templated class function
+ "-Wno-undefined-func-template",
+
+ // Allow explicitly marking struct as packed even when unnecessary
+ "-Wno-packed",
+
"-DDEBUG_ONLY_CODE=0",
],
@@ -77,6 +83,8 @@ cc_library_shared {
srcs: [
"BitTube.cpp",
+ "BufferHubConsumer.cpp",
+ "BufferHubProducer.cpp",
"BufferItem.cpp",
"BufferItemConsumer.cpp",
"BufferQueue.cpp",
@@ -90,6 +98,7 @@ cc_library_shared {
"FrameTimestamps.cpp",
"GLConsumer.cpp",
"GuiConfig.cpp",
+ "HdrMetadata.cpp",
"IDisplayEventConnection.cpp",
"IConsumerListener.cpp",
"IGraphicBufferConsumer.cpp",
@@ -111,8 +120,11 @@ cc_library_shared {
],
shared_libs: [
+ "android.hardware.graphics.common@1.1",
"libsync",
"libbinder",
+ "libbufferhubqueue", // TODO(b/70046255): Remove this once BufferHub is integrated into libgui.
+ "libpdx_default_transport",
"libcutils",
"libEGL",
"libGLESv2",
@@ -128,9 +140,26 @@ cc_library_shared {
"android.hardware.configstore-utils",
],
+ // bufferhub is not used when building libgui for vendors
+ target: {
+ vendor: {
+ cflags: ["-DNO_BUFFERHUB"],
+ exclude_srcs: [
+ "BufferHubConsumer.cpp",
+ "BufferHubProducer.cpp",
+ ],
+ exclude_shared_libs: [
+ "libbufferhubqueue",
+ "libpdx_default_transport",
+ ],
+ },
+ },
+
header_libs: [
+ "libdvr_headers",
"libnativebase_headers",
"libgui_headers",
+ "libpdx_headers",
],
export_shared_lib_headers: [
@@ -140,6 +169,7 @@ cc_library_shared {
"libui",
"android.hidl.token@1.0-utils",
"android.hardware.graphics.bufferqueue@1.0",
+ "android.hardware.graphics.common@1.1",
],
export_header_lib_headers: [
diff --git a/libs/gui/BufferHubConsumer.cpp b/libs/gui/BufferHubConsumer.cpp
new file mode 100644
index 0000000000..b5cdeb280a
--- /dev/null
+++ b/libs/gui/BufferHubConsumer.cpp
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gui/BufferHubConsumer.h>
+
+namespace android {
+
+using namespace dvr;
+
+/* static */
+sp<BufferHubConsumer> BufferHubConsumer::Create(const std::shared_ptr<ConsumerQueue>& queue) {
+ sp<BufferHubConsumer> consumer = new BufferHubConsumer;
+ consumer->mQueue = queue;
+ return consumer;
+}
+
+/* static */ sp<BufferHubConsumer> BufferHubConsumer::Create(ConsumerQueueParcelable parcelable) {
+ if (!parcelable.IsValid()) {
+ ALOGE("BufferHubConsumer::Create: Invalid consumer parcelable.");
+ return nullptr;
+ }
+
+ sp<BufferHubConsumer> consumer = new BufferHubConsumer;
+ consumer->mQueue = ConsumerQueue::Import(parcelable.TakeChannelHandle());
+ return consumer;
+}
+
+status_t BufferHubConsumer::acquireBuffer(BufferItem* /*buffer*/, nsecs_t /*presentWhen*/,
+ uint64_t /*maxFrameNumber*/) {
+ ALOGE("BufferHubConsumer::acquireBuffer: not implemented.");
+ return INVALID_OPERATION;
+}
+
+status_t BufferHubConsumer::detachBuffer(int /*slot*/) {
+ ALOGE("BufferHubConsumer::detachBuffer: not implemented.");
+ return INVALID_OPERATION;
+}
+
+status_t BufferHubConsumer::attachBuffer(int* /*outSlot*/, const sp<GraphicBuffer>& /*buffer*/) {
+ ALOGE("BufferHubConsumer::attachBuffer: not implemented.");
+ return INVALID_OPERATION;
+}
+
+status_t BufferHubConsumer::releaseBuffer(int /*buf*/, uint64_t /*frameNumber*/,
+ EGLDisplay /*display*/, EGLSyncKHR /*fence*/,
+ const sp<Fence>& /*releaseFence*/) {
+ ALOGE("BufferHubConsumer::releaseBuffer: not implemented.");
+ return INVALID_OPERATION;
+}
+
+status_t BufferHubConsumer::consumerConnect(const sp<IConsumerListener>& /*consumer*/,
+ bool /*controlledByApp*/) {
+ ALOGE("BufferHubConsumer::consumerConnect: not implemented.");
+
+ // TODO(b/73267953): Make BufferHub honor producer and consumer connection. Returns NO_ERROR to
+ // make IGraphicBufferConsumer_test happy.
+ return NO_ERROR;
+}
+
+status_t BufferHubConsumer::consumerDisconnect() {
+ ALOGE("BufferHubConsumer::consumerDisconnect: not implemented.");
+
+ // TODO(b/73267953): Make BufferHub honor producer and consumer connection. Returns NO_ERROR to
+ // make IGraphicBufferConsumer_test happy.
+ return NO_ERROR;
+}
+
+status_t BufferHubConsumer::getReleasedBuffers(uint64_t* /*slotMask*/) {
+ ALOGE("BufferHubConsumer::getReleasedBuffers: not implemented.");
+ return INVALID_OPERATION;
+}
+
+status_t BufferHubConsumer::setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) {
+ ALOGE("BufferHubConsumer::setDefaultBufferSize: not implemented.");
+ return INVALID_OPERATION;
+}
+
+status_t BufferHubConsumer::setMaxBufferCount(int /*bufferCount*/) {
+ ALOGE("BufferHubConsumer::setMaxBufferCount: not implemented.");
+ return INVALID_OPERATION;
+}
+
+status_t BufferHubConsumer::setMaxAcquiredBufferCount(int /*maxAcquiredBuffers*/) {
+ ALOGE("BufferHubConsumer::setMaxAcquiredBufferCount: not implemented.");
+
+ // TODO(b/73267953): Make BufferHub honor producer and consumer connection. Returns NO_ERROR to
+ // make IGraphicBufferConsumer_test happy.
+ return NO_ERROR;
+}
+
+status_t BufferHubConsumer::setConsumerName(const String8& /*name*/) {
+ ALOGE("BufferHubConsumer::setConsumerName: not implemented.");
+ return INVALID_OPERATION;
+}
+
+status_t BufferHubConsumer::setDefaultBufferFormat(PixelFormat /*defaultFormat*/) {
+ ALOGE("BufferHubConsumer::setDefaultBufferFormat: not implemented.");
+ return INVALID_OPERATION;
+}
+
+status_t BufferHubConsumer::setDefaultBufferDataSpace(android_dataspace /*defaultDataSpace*/) {
+ ALOGE("BufferHubConsumer::setDefaultBufferDataSpace: not implemented.");
+ return INVALID_OPERATION;
+}
+
+status_t BufferHubConsumer::setConsumerUsageBits(uint64_t /*usage*/) {
+ ALOGE("BufferHubConsumer::setConsumerUsageBits: not implemented.");
+ return INVALID_OPERATION;
+}
+
+status_t BufferHubConsumer::setConsumerIsProtected(bool /*isProtected*/) {
+ ALOGE("BufferHubConsumer::setConsumerIsProtected: not implemented.");
+ return INVALID_OPERATION;
+}
+
+status_t BufferHubConsumer::setTransformHint(uint32_t /*hint*/) {
+ ALOGE("BufferHubConsumer::setTransformHint: not implemented.");
+ return INVALID_OPERATION;
+}
+
+status_t BufferHubConsumer::getSidebandStream(sp<NativeHandle>* /*outStream*/) const {
+ ALOGE("BufferHubConsumer::getSidebandStream: not implemented.");
+ return INVALID_OPERATION;
+}
+
+status_t BufferHubConsumer::getOccupancyHistory(
+ bool /*forceFlush*/, std::vector<OccupancyTracker::Segment>* /*outHistory*/) {
+ ALOGE("BufferHubConsumer::getOccupancyHistory: not implemented.");
+ return INVALID_OPERATION;
+}
+
+status_t BufferHubConsumer::discardFreeBuffers() {
+ ALOGE("BufferHubConsumer::discardFreeBuffers: not implemented.");
+ return INVALID_OPERATION;
+}
+
+status_t BufferHubConsumer::dumpState(const String8& /*prefix*/, String8* /*outResult*/) const {
+ ALOGE("BufferHubConsumer::dumpState: not implemented.");
+ return INVALID_OPERATION;
+}
+
+IBinder* BufferHubConsumer::onAsBinder() {
+ ALOGE("BufferHubConsumer::onAsBinder: BufferHubConsumer should never be used as an Binder "
+ "object.");
+ return nullptr;
+}
+
+} // namespace android
diff --git a/libs/gui/BufferHubProducer.cpp b/libs/gui/BufferHubProducer.cpp
new file mode 100644
index 0000000000..ae5cca2d20
--- /dev/null
+++ b/libs/gui/BufferHubProducer.cpp
@@ -0,0 +1,717 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dvr/dvr_api.h>
+#include <gui/BufferHubProducer.h>
+#include <inttypes.h>
+#include <log/log.h>
+#include <system/window.h>
+
+namespace android {
+
+using namespace dvr;
+
+/* static */
+sp<BufferHubProducer> BufferHubProducer::Create(const std::shared_ptr<ProducerQueue>& queue) {
+ sp<BufferHubProducer> producer = new BufferHubProducer;
+ producer->queue_ = queue;
+ return producer;
+}
+
+/* static */
+sp<BufferHubProducer> BufferHubProducer::Create(ProducerQueueParcelable parcelable) {
+ if (!parcelable.IsValid()) {
+ ALOGE("BufferHubProducer::Create: Invalid producer parcelable.");
+ return nullptr;
+ }
+
+ sp<BufferHubProducer> producer = new BufferHubProducer;
+ producer->queue_ = ProducerQueue::Import(parcelable.TakeChannelHandle());
+ return producer;
+}
+
+status_t BufferHubProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
+ ALOGV("requestBuffer: slot=%d", slot);
+
+ std::unique_lock<std::mutex> lock(mutex_);
+
+ if (connected_api_ == kNoConnectedApi) {
+ ALOGE("requestBuffer: BufferHubProducer has no connected producer");
+ return NO_INIT;
+ }
+
+ if (slot < 0 || slot >= max_buffer_count_) {
+ ALOGE("requestBuffer: slot index %d out of range [0, %d)", slot, max_buffer_count_);
+ return BAD_VALUE;
+ } else if (!buffers_[slot].mBufferState.isDequeued()) {
+ ALOGE("requestBuffer: slot %d is not owned by the producer (state = %s)", slot,
+ buffers_[slot].mBufferState.string());
+ return BAD_VALUE;
+ } else if (buffers_[slot].mGraphicBuffer != nullptr) {
+ ALOGE("requestBuffer: slot %d is not empty.", slot);
+ return BAD_VALUE;
+ } else if (buffers_[slot].mBufferProducer == nullptr) {
+ ALOGE("requestBuffer: slot %d is not dequeued.", slot);
+ return BAD_VALUE;
+ }
+
+ const auto& buffer_producer = buffers_[slot].mBufferProducer;
+ sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
+
+ buffers_[slot].mGraphicBuffer = graphic_buffer;
+ buffers_[slot].mRequestBufferCalled = true;
+
+ *buf = graphic_buffer;
+ return NO_ERROR;
+}
+
+status_t BufferHubProducer::setMaxDequeuedBufferCount(int max_dequeued_buffers) {
+ ALOGV("setMaxDequeuedBufferCount: max_dequeued_buffers=%d", max_dequeued_buffers);
+
+ std::unique_lock<std::mutex> lock(mutex_);
+
+ if (max_dequeued_buffers <= 0 ||
+ max_dequeued_buffers >
+ int(BufferHubQueue::kMaxQueueCapacity - kDefaultUndequeuedBuffers)) {
+ ALOGE("setMaxDequeuedBufferCount: %d out of range (0, %zu]", max_dequeued_buffers,
+ BufferHubQueue::kMaxQueueCapacity);
+ return BAD_VALUE;
+ }
+
+ // The new dequeued_buffers count should not be violated by the number
+ // of currently dequeued buffers.
+ int dequeued_count = 0;
+ for (const auto& buf : buffers_) {
+ if (buf.mBufferState.isDequeued()) {
+ dequeued_count++;
+ }
+ }
+ if (dequeued_count > max_dequeued_buffers) {
+ ALOGE("setMaxDequeuedBufferCount: the requested dequeued_buffers"
+ "count (%d) exceeds the current dequeued buffer count (%d)",
+ max_dequeued_buffers, dequeued_count);
+ return BAD_VALUE;
+ }
+
+ max_dequeued_buffer_count_ = max_dequeued_buffers;
+ return NO_ERROR;
+}
+
+status_t BufferHubProducer::setAsyncMode(bool async) {
+ if (async) {
+ // TODO(b/36724099) BufferHubQueue's consumer end always acquires the buffer
+ // automatically and behaves differently from IGraphicBufferConsumer. Thus,
+ // android::BufferQueue's async mode (a.k.a. allocating an additional buffer
+ // to prevent dequeueBuffer from being blocking) technically does not apply
+ // here.
+ //
+ // In Daydream, non-blocking producer side dequeue is guaranteed by careful
+ // buffer consumer implementations. In another word, BufferHubQueue based
+ // dequeueBuffer should never block whether setAsyncMode(true) is set or
+ // not.
+ //
+ // See: IGraphicBufferProducer::setAsyncMode and
+ // BufferQueueProducer::setAsyncMode for more about original implementation.
+ ALOGW("BufferHubProducer::setAsyncMode: BufferHubQueue should always be "
+ "asynchronous. This call makes no effact.");
+ return NO_ERROR;
+ }
+ return NO_ERROR;
+}
+
+status_t BufferHubProducer::dequeueBuffer(int* out_slot, sp<Fence>* out_fence, uint32_t width,
+ uint32_t height, PixelFormat format, uint64_t usage,
+ uint64_t* /*outBufferAge*/,
+ FrameEventHistoryDelta* /* out_timestamps */) {
+ ALOGV("dequeueBuffer: w=%u, h=%u, format=%d, usage=%" PRIu64, width, height, format, usage);
+
+ status_t ret;
+ std::unique_lock<std::mutex> lock(mutex_);
+
+ if (connected_api_ == kNoConnectedApi) {
+ ALOGE("dequeueBuffer: BufferQueue has no connected producer");
+ return NO_INIT;
+ }
+
+ const uint32_t kLayerCount = 1;
+ if (int32_t(queue_->capacity()) < max_dequeued_buffer_count_ + kDefaultUndequeuedBuffers) {
+ // Lazy allocation. When the capacity of |queue_| has not reached
+ // |max_dequeued_buffer_count_|, allocate new buffer.
+ // TODO(jwcai) To save memory, the really reasonable thing to do is to go
+ // over existing slots and find first existing one to dequeue.
+ ret = AllocateBuffer(width, height, kLayerCount, format, usage);
+ if (ret < 0) return ret;
+ }
+
+ size_t slot = 0;
+ std::shared_ptr<BufferProducer> buffer_producer;
+
+ for (size_t retry = 0; retry < BufferHubQueue::kMaxQueueCapacity; retry++) {
+ LocalHandle fence;
+ auto buffer_status = queue_->Dequeue(dequeue_timeout_ms_, &slot, &fence);
+ if (!buffer_status) return NO_MEMORY;
+
+ buffer_producer = buffer_status.take();
+ if (!buffer_producer) return NO_MEMORY;
+
+ if (width == buffer_producer->width() && height == buffer_producer->height() &&
+ uint32_t(format) == buffer_producer->format()) {
+ // The producer queue returns a buffer producer matches the request.
+ break;
+ }
+
+ // Needs reallocation.
+ // TODO(jwcai) Consider use VLOG instead if we find this log is not useful.
+ ALOGI("dequeueBuffer: requested buffer (w=%u, h=%u, format=%u) is different "
+ "from the buffer returned at slot: %zu (w=%u, h=%u, format=%u). Need "
+ "re-allocattion.",
+ width, height, format, slot, buffer_producer->width(), buffer_producer->height(),
+ buffer_producer->format());
+ // Mark the slot as reallocating, so that later we can set
+ // BUFFER_NEEDS_REALLOCATION when the buffer actually get dequeued.
+ buffers_[slot].mIsReallocating = true;
+
+ // Remove the old buffer once the allocation before allocating its
+ // replacement.
+ RemoveBuffer(slot);
+
+ // Allocate a new producer buffer with new buffer configs. Note that if
+ // there are already multiple buffers in the queue, the next one returned
+ // from |queue_->Dequeue| may not be the new buffer we just reallocated.
+ // Retry up to BufferHubQueue::kMaxQueueCapacity times.
+ ret = AllocateBuffer(width, height, kLayerCount, format, usage);
+ if (ret < 0) return ret;
+ }
+
+ // With the BufferHub backed solution. Buffer slot returned from
+ // |queue_->Dequeue| is guaranteed to avaiable for producer's use.
+ // It's either in free state (if the buffer has never been used before) or
+ // in queued state (if the buffer has been dequeued and queued back to
+ // BufferHubQueue).
+ LOG_ALWAYS_FATAL_IF((!buffers_[slot].mBufferState.isFree() &&
+ !buffers_[slot].mBufferState.isQueued()),
+ "dequeueBuffer: slot %zu is not free or queued, actual state: %s.", slot,
+ buffers_[slot].mBufferState.string());
+
+ buffers_[slot].mBufferState.freeQueued();
+ buffers_[slot].mBufferState.dequeue();
+ ALOGV("dequeueBuffer: slot=%zu", slot);
+
+ // TODO(jwcai) Handle fence properly. |BufferHub| has full fence support, we
+ // just need to exopose that through |BufferHubQueue| once we need fence.
+ *out_fence = Fence::NO_FENCE;
+ *out_slot = int(slot);
+ ret = NO_ERROR;
+
+ if (buffers_[slot].mIsReallocating) {
+ ret |= BUFFER_NEEDS_REALLOCATION;
+ buffers_[slot].mIsReallocating = false;
+ }
+
+ return ret;
+}
+
+status_t BufferHubProducer::detachBuffer(int /* slot */) {
+ ALOGE("BufferHubProducer::detachBuffer not implemented.");
+ return INVALID_OPERATION;
+}
+
+status_t BufferHubProducer::detachNextBuffer(sp<GraphicBuffer>* /* out_buffer */,
+ sp<Fence>* /* out_fence */) {
+ ALOGE("BufferHubProducer::detachNextBuffer not implemented.");
+ return INVALID_OPERATION;
+}
+
+status_t BufferHubProducer::attachBuffer(int* /* out_slot */,
+ const sp<GraphicBuffer>& /* buffer */) {
+ // With this BufferHub backed implementation, we assume (for now) all buffers
+ // are allocated and owned by the BufferHub. Thus the attempt of transfering
+ // ownership of a buffer to the buffer queue is intentionally unsupported.
+ LOG_ALWAYS_FATAL("BufferHubProducer::attachBuffer not supported.");
+ return INVALID_OPERATION;
+}
+
+status_t BufferHubProducer::queueBuffer(int slot, const QueueBufferInput& input,
+ QueueBufferOutput* output) {
+ ALOGV("queueBuffer: slot %d", slot);
+
+ if (output == nullptr) {
+ return BAD_VALUE;
+ }
+
+ int64_t timestamp;
+ bool is_auto_timestamp;
+ android_dataspace dataspace;
+ Rect crop(Rect::EMPTY_RECT);
+ int scaling_mode;
+ uint32_t transform;
+ sp<Fence> fence;
+
+ input.deflate(&timestamp, &is_auto_timestamp, &dataspace, &crop, &scaling_mode, &transform,
+ &fence);
+
+ // Check input scaling mode is valid.
+ switch (scaling_mode) {
+ case NATIVE_WINDOW_SCALING_MODE_FREEZE:
+ case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
+ case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
+ case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
+ break;
+ default:
+ ALOGE("queueBuffer: unknown scaling mode %d", scaling_mode);
+ return BAD_VALUE;
+ }
+
+ // Check input fence is valid.
+ if (fence == nullptr) {
+ ALOGE("queueBuffer: fence is NULL");
+ return BAD_VALUE;
+ }
+
+ std::unique_lock<std::mutex> lock(mutex_);
+
+ if (connected_api_ == kNoConnectedApi) {
+ ALOGE("queueBuffer: BufferQueue has no connected producer");
+ return NO_INIT;
+ }
+
+ if (slot < 0 || slot >= max_buffer_count_) {
+ ALOGE("queueBuffer: slot index %d out of range [0, %d)", slot, max_buffer_count_);
+ return BAD_VALUE;
+ } else if (!buffers_[slot].mBufferState.isDequeued()) {
+ ALOGE("queueBuffer: slot %d is not owned by the producer (state = %s)", slot,
+ buffers_[slot].mBufferState.string());
+ return BAD_VALUE;
+ } else if ((!buffers_[slot].mRequestBufferCalled || buffers_[slot].mGraphicBuffer == nullptr)) {
+ ALOGE("queueBuffer: slot %d is not requested (mRequestBufferCalled=%d, "
+ "mGraphicBuffer=%p)",
+ slot, buffers_[slot].mRequestBufferCalled, buffers_[slot].mGraphicBuffer.get());
+ return BAD_VALUE;
+ }
+
+ // Post the buffer producer with timestamp in the metadata.
+ const auto& buffer_producer = buffers_[slot].mBufferProducer;
+
+ // Check input crop is not out of boundary of current buffer.
+ Rect buffer_rect(buffer_producer->width(), buffer_producer->height());
+ Rect cropped_rect(Rect::EMPTY_RECT);
+ crop.intersect(buffer_rect, &cropped_rect);
+ if (cropped_rect != crop) {
+ ALOGE("queueBuffer: slot %d has out-of-boundary crop.", slot);
+ return BAD_VALUE;
+ }
+
+ LocalHandle fence_fd(fence->isValid() ? fence->dup() : -1);
+
+ DvrNativeBufferMetadata meta_data;
+ meta_data.timestamp = timestamp;
+ meta_data.is_auto_timestamp = int32_t(is_auto_timestamp);
+ meta_data.dataspace = int32_t(dataspace);
+ meta_data.crop_left = crop.left;
+ meta_data.crop_top = crop.top;
+ meta_data.crop_right = crop.right;
+ meta_data.crop_bottom = crop.bottom;
+ meta_data.scaling_mode = int32_t(scaling_mode);
+ meta_data.transform = int32_t(transform);
+
+ buffer_producer->PostAsync(&meta_data, fence_fd);
+ buffers_[slot].mBufferState.queue();
+
+ output->width = buffer_producer->width();
+ output->height = buffer_producer->height();
+ output->transformHint = 0; // default value, we don't use it yet.
+
+ // |numPendingBuffers| counts of the number of buffers that has been enqueued
+ // by the producer but not yet acquired by the consumer. Due to the nature
+ // of BufferHubQueue design, this is hard to trace from the producer's client
+ // side, but it's safe to assume it's zero.
+ output->numPendingBuffers = 0;
+
+ // Note that we are not setting nextFrameNumber here as it seems to be only
+ // used by surface flinger. See more at b/22802885, ag/791760.
+ output->nextFrameNumber = 0;
+
+ return NO_ERROR;
+}
+
+status_t BufferHubProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
+ ALOGV(__FUNCTION__);
+
+ std::unique_lock<std::mutex> lock(mutex_);
+
+ if (connected_api_ == kNoConnectedApi) {
+ ALOGE("cancelBuffer: BufferQueue has no connected producer");
+ return NO_INIT;
+ }
+
+ if (slot < 0 || slot >= max_buffer_count_) {
+ ALOGE("cancelBuffer: slot index %d out of range [0, %d)", slot, max_buffer_count_);
+ return BAD_VALUE;
+ } else if (!buffers_[slot].mBufferState.isDequeued()) {
+ ALOGE("cancelBuffer: slot %d is not owned by the producer (state = %s)", slot,
+ buffers_[slot].mBufferState.string());
+ return BAD_VALUE;
+ } else if (fence == nullptr) {
+ ALOGE("cancelBuffer: fence is NULL");
+ return BAD_VALUE;
+ }
+
+ auto buffer_producer = buffers_[slot].mBufferProducer;
+ queue_->Enqueue(buffer_producer, size_t(slot), 0ULL);
+ buffers_[slot].mBufferState.cancel();
+ buffers_[slot].mFence = fence;
+ ALOGV("cancelBuffer: slot %d", slot);
+
+ return NO_ERROR;
+}
+
+status_t BufferHubProducer::query(int what, int* out_value) {
+ ALOGV(__FUNCTION__);
+
+ std::unique_lock<std::mutex> lock(mutex_);
+
+ if (out_value == nullptr) {
+ ALOGE("query: out_value was NULL");
+ return BAD_VALUE;
+ }
+
+ int value = 0;
+ switch (what) {
+ case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
+ // TODO(b/36187402) This should be the maximum number of buffers that this
+ // producer queue's consumer can acquire. Set to be at least one. Need to
+ // find a way to set from the consumer side.
+ value = kDefaultUndequeuedBuffers;
+ break;
+ case NATIVE_WINDOW_BUFFER_AGE:
+ value = 0;
+ break;
+ case NATIVE_WINDOW_WIDTH:
+ value = int32_t(queue_->default_width());
+ break;
+ case NATIVE_WINDOW_HEIGHT:
+ value = int32_t(queue_->default_height());
+ break;
+ case NATIVE_WINDOW_FORMAT:
+ value = int32_t(queue_->default_format());
+ break;
+ case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
+ // BufferHubQueue is always operating in async mode, thus semantically
+ // consumer can never be running behind. See BufferQueueCore.cpp core
+ // for more information about the original meaning of this flag.
+ value = 0;
+ break;
+ case NATIVE_WINDOW_CONSUMER_USAGE_BITS:
+ // TODO(jwcai) This is currently not implement as we don't need
+ // IGraphicBufferConsumer parity.
+ value = 0;
+ break;
+ case NATIVE_WINDOW_DEFAULT_DATASPACE:
+ // TODO(jwcai) Return the default value android::BufferQueue is using as
+ // there is no way dvr::ConsumerQueue can set it.
+ value = 0; // HAL_DATASPACE_UNKNOWN
+ break;
+ case NATIVE_WINDOW_STICKY_TRANSFORM:
+ // TODO(jwcai) Return the default value android::BufferQueue is using as
+ // there is no way dvr::ConsumerQueue can set it.
+ value = 0;
+ break;
+ case NATIVE_WINDOW_CONSUMER_IS_PROTECTED:
+ // In Daydream's implementation, the consumer end (i.e. VR Compostior)
+ // knows how to handle protected buffers.
+ value = 1;
+ break;
+ default:
+ return BAD_VALUE;
+ }
+
+ ALOGV("query: key=%d, v=%d", what, value);
+ *out_value = value;
+ return NO_ERROR;
+}
+
+status_t BufferHubProducer::connect(const sp<IProducerListener>& /* listener */, int api,
+ bool /* producer_controlled_by_app */,
+ QueueBufferOutput* output) {
+ // Consumer interaction are actually handled by buffer hub, and we need
+ // to maintain consumer operations here. We only need to perform basic input
+ // parameter checks here.
+ ALOGV(__FUNCTION__);
+
+ if (output == nullptr) {
+ return BAD_VALUE;
+ }
+
+ std::unique_lock<std::mutex> lock(mutex_);
+
+ if (connected_api_ != kNoConnectedApi) {
+ return BAD_VALUE;
+ }
+
+ if (!queue_->is_connected()) {
+ ALOGE("BufferHubProducer::connect: This BufferHubProducer is not "
+ "connected to bufferhud. Has it been taken out as a parcelable?");
+ return BAD_VALUE;
+ }
+
+ switch (api) {
+ case NATIVE_WINDOW_API_EGL:
+ case NATIVE_WINDOW_API_CPU:
+ case NATIVE_WINDOW_API_MEDIA:
+ case NATIVE_WINDOW_API_CAMERA:
+ connected_api_ = api;
+
+ output->width = queue_->default_width();
+ output->height = queue_->default_height();
+
+ // default values, we don't use them yet.
+ output->transformHint = 0;
+ output->numPendingBuffers = 0;
+ output->nextFrameNumber = 0;
+ output->bufferReplaced = false;
+
+ break;
+ default:
+ ALOGE("BufferHubProducer::connect: unknow API %d", api);
+ return BAD_VALUE;
+ }
+
+ return NO_ERROR;
+}
+
+status_t BufferHubProducer::disconnect(int api, DisconnectMode /*mode*/) {
+ // Consumer interaction are actually handled by buffer hub, and we need
+ // to maintain consumer operations here. We only need to perform basic input
+ // parameter checks here.
+ ALOGV(__FUNCTION__);
+
+ std::unique_lock<std::mutex> lock(mutex_);
+
+ if (kNoConnectedApi == connected_api_) {
+ return NO_INIT;
+ } else if (api != connected_api_) {
+ return BAD_VALUE;
+ }
+
+ FreeAllBuffers();
+ connected_api_ = kNoConnectedApi;
+ return NO_ERROR;
+}
+
+status_t BufferHubProducer::setSidebandStream(const sp<NativeHandle>& stream) {
+ if (stream != nullptr) {
+ // TODO(jwcai) Investigate how is is used, maybe use BufferHubBuffer's
+ // metadata.
+ ALOGE("SidebandStream is not currently supported.");
+ return INVALID_OPERATION;
+ }
+ return NO_ERROR;
+}
+
+void BufferHubProducer::allocateBuffers(uint32_t /* width */, uint32_t /* height */,
+ PixelFormat /* format */, uint64_t /* usage */) {
+ // TODO(jwcai) |allocateBuffers| aims to preallocate up to the maximum number
+ // of buffers permitted by the current BufferQueue configuration (aka
+ // |max_buffer_count_|).
+ ALOGE("BufferHubProducer::allocateBuffers not implemented.");
+}
+
+status_t BufferHubProducer::allowAllocation(bool /* allow */) {
+ ALOGE("BufferHubProducer::allowAllocation not implemented.");
+ return INVALID_OPERATION;
+}
+
+status_t BufferHubProducer::setGenerationNumber(uint32_t generation_number) {
+ ALOGV(__FUNCTION__);
+
+ std::unique_lock<std::mutex> lock(mutex_);
+ generation_number_ = generation_number;
+ return NO_ERROR;
+}
+
+String8 BufferHubProducer::getConsumerName() const {
+ // BufferHub based implementation could have one to many producer/consumer
+ // relationship, thus |getConsumerName| from the producer side does not
+ // make any sense.
+ ALOGE("BufferHubProducer::getConsumerName not supported.");
+ return String8("BufferHubQueue::DummyConsumer");
+}
+
+status_t BufferHubProducer::setSharedBufferMode(bool shared_buffer_mode) {
+ if (shared_buffer_mode) {
+ ALOGE("BufferHubProducer::setSharedBufferMode(true) is not supported.");
+ // TODO(b/36373181) Front buffer mode for buffer hub queue as ANativeWindow.
+ return INVALID_OPERATION;
+ }
+ // Setting to default should just work as a no-op.
+ return NO_ERROR;
+}
+
+status_t BufferHubProducer::setAutoRefresh(bool auto_refresh) {
+ if (auto_refresh) {
+ ALOGE("BufferHubProducer::setAutoRefresh(true) is not supported.");
+ return INVALID_OPERATION;
+ }
+ // Setting to default should just work as a no-op.
+ return NO_ERROR;
+}
+
+status_t BufferHubProducer::setDequeueTimeout(nsecs_t timeout) {
+ ALOGV(__FUNCTION__);
+
+ std::unique_lock<std::mutex> lock(mutex_);
+ dequeue_timeout_ms_ = static_cast<int>(timeout / (1000 * 1000));
+ return NO_ERROR;
+}
+
+status_t BufferHubProducer::getLastQueuedBuffer(sp<GraphicBuffer>* /* out_buffer */,
+ sp<Fence>* /* out_fence */,
+ float /*out_transform_matrix*/[16]) {
+ ALOGE("BufferHubProducer::getLastQueuedBuffer not implemented.");
+ return INVALID_OPERATION;
+}
+
+void BufferHubProducer::getFrameTimestamps(FrameEventHistoryDelta* /*outDelta*/) {
+ ALOGE("BufferHubProducer::getFrameTimestamps not implemented.");
+}
+
+status_t BufferHubProducer::getUniqueId(uint64_t* out_id) const {
+ ALOGV(__FUNCTION__);
+
+ *out_id = unique_id_;
+ return NO_ERROR;
+}
+
+status_t BufferHubProducer::getConsumerUsage(uint64_t* out_usage) const {
+ ALOGV(__FUNCTION__);
+
+ // same value as returned by querying NATIVE_WINDOW_CONSUMER_USAGE_BITS
+ *out_usage = 0;
+ return NO_ERROR;
+}
+
+status_t BufferHubProducer::TakeAsParcelable(ProducerQueueParcelable* out_parcelable) {
+ if (!out_parcelable || out_parcelable->IsValid()) return BAD_VALUE;
+
+ if (connected_api_ != kNoConnectedApi) {
+ ALOGE("BufferHubProducer::TakeAsParcelable: BufferHubProducer has "
+ "connected client. Must disconnect first.");
+ return BAD_VALUE;
+ }
+
+ if (!queue_->is_connected()) {
+ ALOGE("BufferHubProducer::TakeAsParcelable: This BufferHubProducer "
+ "is not connected to bufferhud. Has it been taken out as a "
+ "parcelable?");
+ return BAD_VALUE;
+ }
+
+ auto status = queue_->TakeAsParcelable();
+ if (!status) {
+ ALOGE("BufferHubProducer::TakeAsParcelable: Failed to take out "
+ "ProducuerQueueParcelable from the producer queue, error: %s.",
+ status.GetErrorMessage().c_str());
+ return BAD_VALUE;
+ }
+
+ *out_parcelable = status.take();
+ return NO_ERROR;
+}
+
+status_t BufferHubProducer::AllocateBuffer(uint32_t width, uint32_t height, uint32_t layer_count,
+ PixelFormat format, uint64_t usage) {
+ auto status = queue_->AllocateBuffer(width, height, layer_count, uint32_t(format), usage);
+ if (!status) {
+ ALOGE("BufferHubProducer::AllocateBuffer: Failed to allocate buffer: %s",
+ status.GetErrorMessage().c_str());
+ return NO_MEMORY;
+ }
+
+ size_t slot = status.get();
+ auto buffer_producer = queue_->GetBuffer(slot);
+
+ LOG_ALWAYS_FATAL_IF(buffer_producer == nullptr, "Failed to get buffer producer at slot: %zu",
+ slot);
+
+ buffers_[slot].mBufferProducer = buffer_producer;
+
+ return NO_ERROR;
+}
+
+status_t BufferHubProducer::RemoveBuffer(size_t slot) {
+ auto status = queue_->RemoveBuffer(slot);
+ if (!status) {
+ ALOGE("BufferHubProducer::RemoveBuffer: Failed to remove buffer: %s",
+ status.GetErrorMessage().c_str());
+ return INVALID_OPERATION;
+ }
+
+ // Reset in memory objects related the the buffer.
+ buffers_[slot].mBufferProducer = nullptr;
+ buffers_[slot].mGraphicBuffer = nullptr;
+ buffers_[slot].mBufferState.detachProducer();
+ return NO_ERROR;
+}
+
+status_t BufferHubProducer::FreeAllBuffers() {
+ for (size_t slot = 0; slot < BufferHubQueue::kMaxQueueCapacity; slot++) {
+ // Reset in memory objects related the the buffer.
+ buffers_[slot].mGraphicBuffer = nullptr;
+ buffers_[slot].mBufferState.reset();
+ buffers_[slot].mRequestBufferCalled = false;
+ buffers_[slot].mBufferProducer = nullptr;
+ buffers_[slot].mFence = Fence::NO_FENCE;
+ }
+
+ auto status = queue_->FreeAllBuffers();
+ if (!status) {
+ ALOGE("BufferHubProducer::FreeAllBuffers: Failed to free all buffers on "
+ "the queue: %s",
+ status.GetErrorMessage().c_str());
+ }
+
+ if (queue_->capacity() != 0 || queue_->count() != 0) {
+ LOG_ALWAYS_FATAL("BufferHubProducer::FreeAllBuffers: Not all buffers are freed.");
+ }
+
+ return NO_ERROR;
+}
+
+status_t BufferHubProducer::exportToParcel(Parcel* parcel) {
+ status_t res = TakeAsParcelable(&pending_producer_parcelable_);
+ if (res != NO_ERROR) return res;
+
+ if (!pending_producer_parcelable_.IsValid()) {
+ ALOGE("BufferHubProducer::exportToParcel: Invalid parcelable object.");
+ return BAD_VALUE;
+ }
+
+ res = parcel->writeUint32(USE_BUFFER_HUB);
+ if (res != NO_ERROR) {
+ ALOGE("BufferHubProducer::exportToParcel: Cannot write magic, res=%d.", res);
+ return res;
+ }
+
+ return pending_producer_parcelable_.writeToParcel(parcel);
+}
+
+IBinder* BufferHubProducer::onAsBinder() {
+ ALOGE("BufferHubProducer::onAsBinder: BufferHubProducer should never be used as an Binder "
+ "object.");
+ return nullptr;
+}
+
+} // namespace android
diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp
index 9da4ea80e0..f50379b3ed 100644
--- a/libs/gui/BufferItem.cpp
+++ b/libs/gui/BufferItem.cpp
@@ -39,8 +39,8 @@ static inline constexpr T to64(const uint32_t lo, const uint32_t hi) {
}
BufferItem::BufferItem() :
- mGraphicBuffer(nullptr),
- mFence(nullptr),
+ mGraphicBuffer(NULL),
+ mFence(NULL),
mCrop(Rect::INVALID_RECT),
mTransform(0),
mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
@@ -55,7 +55,8 @@ BufferItem::BufferItem() :
mSurfaceDamage(),
mAutoRefresh(false),
mQueuedBuffer(true),
- mIsStale(false) {
+ mIsStale(false),
+ mApi(0) {
}
BufferItem::~BufferItem() {}
@@ -84,30 +85,32 @@ size_t BufferItem::getPodSize() const {
addAligned(size, mAutoRefresh);
addAligned(size, mQueuedBuffer);
addAligned(size, mIsStale);
+ addAligned(size, mApi);
return size;
}
size_t BufferItem::getFlattenedSize() const {
size_t size = sizeof(uint32_t); // Flags
- if (mGraphicBuffer != nullptr) {
+ if (mGraphicBuffer != 0) {
size += mGraphicBuffer->getFlattenedSize();
size = FlattenableUtils::align<4>(size);
}
- if (mFence != nullptr) {
+ if (mFence != 0) {
size += mFence->getFlattenedSize();
size = FlattenableUtils::align<4>(size);
}
size += mSurfaceDamage.getFlattenedSize();
+ size += mHdrMetadata.getFlattenedSize();
size = FlattenableUtils::align<8>(size);
return size + getPodSize();
}
size_t BufferItem::getFdCount() const {
size_t count = 0;
- if (mGraphicBuffer != nullptr) {
+ if (mGraphicBuffer != 0) {
count += mGraphicBuffer->getFdCount();
}
- if (mFence != nullptr) {
+ if (mFence != 0) {
count += mFence->getFdCount();
}
return count;
@@ -134,13 +137,13 @@ status_t BufferItem::flatten(
FlattenableUtils::advance(buffer, size, sizeof(uint32_t));
flags = 0;
- if (mGraphicBuffer != nullptr) {
+ if (mGraphicBuffer != 0) {
status_t err = mGraphicBuffer->flatten(buffer, size, fds, count);
if (err) return err;
size -= FlattenableUtils::align<4>(buffer);
flags |= 1;
}
- if (mFence != nullptr) {
+ if (mFence != 0) {
status_t err = mFence->flatten(buffer, size, fds, count);
if (err) return err;
size -= FlattenableUtils::align<4>(buffer);
@@ -151,6 +154,10 @@ status_t BufferItem::flatten(
if (err) return err;
FlattenableUtils::advance(buffer, size, mSurfaceDamage.getFlattenedSize());
+ err = mHdrMetadata.flatten(buffer, size);
+ if (err) return err;
+ FlattenableUtils::advance(buffer, size, mHdrMetadata.getFlattenedSize());
+
// Check we still have enough space
if (size < getPodSize()) {
return NO_MEMORY;
@@ -172,6 +179,7 @@ status_t BufferItem::flatten(
writeAligned(buffer, size, mAutoRefresh);
writeAligned(buffer, size, mQueuedBuffer);
writeAligned(buffer, size, mIsStale);
+ writeAligned(buffer, size, mApi);
return NO_ERROR;
}
@@ -212,6 +220,10 @@ status_t BufferItem::unflatten(
if (err) return err;
FlattenableUtils::advance(buffer, size, mSurfaceDamage.getFlattenedSize());
+ err = mHdrMetadata.unflatten(buffer, size);
+ if (err) return err;
+ FlattenableUtils::advance(buffer, size, mHdrMetadata.getFlattenedSize());
+
// Check we still have enough space
if (size < getPodSize()) {
return NO_MEMORY;
@@ -238,6 +250,7 @@ status_t BufferItem::unflatten(
readAligned(buffer, size, mAutoRefresh);
readAligned(buffer, size, mQueuedBuffer);
readAligned(buffer, size, mIsStale);
+ readAligned(buffer, size, mApi);
return NO_ERROR;
}
diff --git a/libs/gui/BufferItemConsumer.cpp b/libs/gui/BufferItemConsumer.cpp
index 3aa4e449cc..89bc0c4c2d 100644
--- a/libs/gui/BufferItemConsumer.cpp
+++ b/libs/gui/BufferItemConsumer.cpp
@@ -49,16 +49,6 @@ BufferItemConsumer::BufferItemConsumer(
BufferItemConsumer::~BufferItemConsumer() {}
-void BufferItemConsumer::setName(const String8& name) {
- Mutex::Autolock _l(mMutex);
- if (mAbandoned) {
- BI_LOGE("setName: BufferItemConsumer is abandoned!");
- return;
- }
- mName = name;
- mConsumer->setConsumerName(name);
-}
-
void BufferItemConsumer::setBufferFreedListener(
const wp<BufferFreedListener>& listener) {
Mutex::Autolock _l(mMutex);
@@ -102,10 +92,13 @@ status_t BufferItemConsumer::releaseBuffer(const BufferItem &item,
Mutex::Autolock _l(mMutex);
err = addReleaseFenceLocked(item.mSlot, item.mGraphicBuffer, releaseFence);
+ if (err != OK) {
+ BI_LOGE("Failed to addReleaseFenceLocked");
+ }
err = releaseBufferLocked(item.mSlot, item.mGraphicBuffer, EGL_NO_DISPLAY,
EGL_NO_SYNC_KHR);
- if (err != OK) {
+ if (err != OK && err != IGraphicBufferConsumer::STALE_BUFFER_SLOT) {
BI_LOGE("Failed to release buffer: %s (%d)",
strerror(-err), err);
}
@@ -114,7 +107,7 @@ status_t BufferItemConsumer::releaseBuffer(const BufferItem &item,
void BufferItemConsumer::freeBufferLocked(int slotIndex) {
sp<BufferFreedListener> listener = mBufferFreedListener.promote();
- if (listener != nullptr && mSlots[slotIndex].mGraphicBuffer != nullptr) {
+ if (listener != NULL && mSlots[slotIndex].mGraphicBuffer != NULL) {
// Fire callback if we have a listener registered and the buffer being freed is valid.
BI_LOGV("actually calling onBufferFreed");
listener->onBufferFreed(mSlots[slotIndex].mGraphicBuffer);
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 7da4db4d3f..a8da1347cb 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -18,6 +18,11 @@
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
//#define LOG_NDEBUG 0
+#ifndef NO_BUFFERHUB
+#include <gui/BufferHubConsumer.h>
+#include <gui/BufferHubProducer.h>
+#endif
+
#include <gui/BufferQueue.h>
#include <gui/BufferQueueConsumer.h>
#include <gui/BufferQueueCore.h>
@@ -33,7 +38,7 @@ BufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {}
void BufferQueue::ProxyConsumerListener::onDisconnect() {
sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != nullptr) {
+ if (listener != NULL) {
listener->onDisconnect();
}
}
@@ -41,7 +46,7 @@ void BufferQueue::ProxyConsumerListener::onDisconnect() {
void BufferQueue::ProxyConsumerListener::onFrameAvailable(
const BufferItem& item) {
sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != nullptr) {
+ if (listener != NULL) {
listener->onFrameAvailable(item);
}
}
@@ -49,21 +54,21 @@ void BufferQueue::ProxyConsumerListener::onFrameAvailable(
void BufferQueue::ProxyConsumerListener::onFrameReplaced(
const BufferItem& item) {
sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != nullptr) {
+ if (listener != NULL) {
listener->onFrameReplaced(item);
}
}
void BufferQueue::ProxyConsumerListener::onBuffersReleased() {
sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != nullptr) {
+ if (listener != NULL) {
listener->onBuffersReleased();
}
}
void BufferQueue::ProxyConsumerListener::onSidebandStreamChanged() {
sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != nullptr) {
+ if (listener != NULL) {
listener->onSidebandStreamChanged();
}
}
@@ -80,25 +85,53 @@ void BufferQueue::ProxyConsumerListener::addAndGetFrameTimestamps(
void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer,
bool consumerIsSurfaceFlinger) {
- LOG_ALWAYS_FATAL_IF(outProducer == nullptr,
+ LOG_ALWAYS_FATAL_IF(outProducer == NULL,
"BufferQueue: outProducer must not be NULL");
- LOG_ALWAYS_FATAL_IF(outConsumer == nullptr,
+ LOG_ALWAYS_FATAL_IF(outConsumer == NULL,
"BufferQueue: outConsumer must not be NULL");
sp<BufferQueueCore> core(new BufferQueueCore());
- LOG_ALWAYS_FATAL_IF(core == nullptr,
+ LOG_ALWAYS_FATAL_IF(core == NULL,
"BufferQueue: failed to create BufferQueueCore");
sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger));
- LOG_ALWAYS_FATAL_IF(producer == nullptr,
+ LOG_ALWAYS_FATAL_IF(producer == NULL,
"BufferQueue: failed to create BufferQueueProducer");
sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));
- LOG_ALWAYS_FATAL_IF(consumer == nullptr,
+ LOG_ALWAYS_FATAL_IF(consumer == NULL,
"BufferQueue: failed to create BufferQueueConsumer");
*outProducer = producer;
*outConsumer = consumer;
}
+#ifndef NO_BUFFERHUB
+void BufferQueue::createBufferHubQueue(sp<IGraphicBufferProducer>* outProducer,
+ sp<IGraphicBufferConsumer>* outConsumer) {
+ LOG_ALWAYS_FATAL_IF(outProducer == NULL, "BufferQueue: outProducer must not be NULL");
+ LOG_ALWAYS_FATAL_IF(outConsumer == NULL, "BufferQueue: outConsumer must not be NULL");
+
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+
+ dvr::ProducerQueueConfigBuilder configBuilder;
+ std::shared_ptr<dvr::ProducerQueue> producerQueue =
+ dvr::ProducerQueue::Create(configBuilder.Build(), dvr::UsagePolicy{});
+ LOG_ALWAYS_FATAL_IF(producerQueue == NULL, "BufferQueue: failed to create ProducerQueue.");
+
+ std::shared_ptr<dvr::ConsumerQueue> consumerQueue = producerQueue->CreateConsumerQueue();
+ LOG_ALWAYS_FATAL_IF(consumerQueue == NULL, "BufferQueue: failed to create ConsumerQueue.");
+
+ producer = BufferHubProducer::Create(producerQueue);
+ consumer = BufferHubConsumer::Create(consumerQueue);
+
+ LOG_ALWAYS_FATAL_IF(producer == NULL, "BufferQueue: failed to create BufferQueueProducer");
+ LOG_ALWAYS_FATAL_IF(consumer == NULL, "BufferQueue: failed to create BufferQueueConsumer");
+
+ *outProducer = producer;
+ *outConsumer = consumer;
+}
+#endif
+
}; // namespace android
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 31eb29b8f6..d70e1422b0 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -35,7 +35,9 @@
#include <gui/IProducerListener.h>
#include <binder/IPCThreadState.h>
+#ifndef __ANDROID_VNDK__
#include <binder/PermissionCache.h>
+#endif
#include <system/window.h>
@@ -253,7 +255,7 @@ status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
// mGraphicBuffer to NULL to avoid unnecessarily remapping this buffer
// on the consumer side
if (outBuffer->mAcquireCalled) {
- outBuffer->mGraphicBuffer = nullptr;
+ outBuffer->mGraphicBuffer = NULL;
}
mCore->mQueue.erase(front);
@@ -270,7 +272,7 @@ status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
VALIDATE_CONSISTENCY();
}
- if (listener != nullptr) {
+ if (listener != NULL) {
for (int i = 0; i < numDroppedBuffers; ++i) {
listener->onBufferReleased();
}
@@ -319,10 +321,10 @@ status_t BufferQueueConsumer::attachBuffer(int* outSlot,
const sp<android::GraphicBuffer>& buffer) {
ATRACE_CALL();
- if (outSlot == nullptr) {
+ if (outSlot == NULL) {
BQ_LOGE("attachBuffer: outSlot must not be NULL");
return BAD_VALUE;
- } else if (buffer == nullptr) {
+ } else if (buffer == NULL) {
BQ_LOGE("attachBuffer: cannot attach NULL buffer");
return BAD_VALUE;
}
@@ -411,7 +413,7 @@ status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
ATRACE_BUFFER_INDEX(slot);
if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS ||
- releaseFence == nullptr) {
+ releaseFence == NULL) {
BQ_LOGE("releaseBuffer: slot %d out of range or fence %p NULL", slot,
releaseFence.get());
return BAD_VALUE;
@@ -463,7 +465,7 @@ status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber,
} // Autolock scope
// Call back without lock held
- if (listener != nullptr) {
+ if (listener != NULL) {
listener->onBufferReleased();
}
@@ -474,7 +476,7 @@ status_t BufferQueueConsumer::connect(
const sp<IConsumerListener>& consumerListener, bool controlledByApp) {
ATRACE_CALL();
- if (consumerListener == nullptr) {
+ if (consumerListener == NULL) {
BQ_LOGE("connect: consumerListener may not be NULL");
return BAD_VALUE;
}
@@ -502,13 +504,13 @@ status_t BufferQueueConsumer::disconnect() {
Mutex::Autolock lock(mCore->mMutex);
- if (mCore->mConsumerListener == nullptr) {
+ if (mCore->mConsumerListener == NULL) {
BQ_LOGE("disconnect: no consumer is connected");
return BAD_VALUE;
}
mCore->mIsAbandoned = true;
- mCore->mConsumerListener = nullptr;
+ mCore->mConsumerListener = NULL;
mCore->mQueue.clear();
mCore->freeAllBuffersLocked();
mCore->mSharedBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT;
@@ -519,7 +521,7 @@ status_t BufferQueueConsumer::disconnect() {
status_t BufferQueueConsumer::getReleasedBuffers(uint64_t *outSlotMask) {
ATRACE_CALL();
- if (outSlotMask == nullptr) {
+ if (outSlotMask == NULL) {
BQ_LOGE("getReleasedBuffers: outSlotMask may not be NULL");
return BAD_VALUE;
}
@@ -671,7 +673,7 @@ status_t BufferQueueConsumer::setMaxAcquiredBufferCount(
}
}
// Call back without lock held
- if (listener != nullptr) {
+ if (listener != NULL) {
listener->onBuffersReleased();
}
@@ -757,14 +759,20 @@ status_t BufferQueueConsumer::dumpState(const String8& prefix, String8* outResul
}
const IPCThreadState* ipc = IPCThreadState::self();
- const pid_t pid = ipc->getCallingPid();
const uid_t uid = ipc->getCallingUid();
+#ifndef __ANDROID_VNDK__
+ // permission check can't be done for vendors as vendors have no access to
+ // the PermissionController
+ const pid_t pid = ipc->getCallingPid();
if ((uid != shellUid) &&
!PermissionCache::checkPermission(String16("android.permission.DUMP"), pid, uid)) {
outResult->appendFormat("Permission Denial: can't dump BufferQueueConsumer "
"from pid=%d, uid=%d\n", pid, uid);
+#else
+ if (uid != shellUid) {
+#endif
android_errorWriteWithInfoLog(0x534e4554, "27046057",
- static_cast<int32_t>(uid), nullptr, 0);
+ static_cast<int32_t>(uid), NULL, 0);
return PERMISSION_DENIED;
}
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 0c7b7e20db..c8021e4d54 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -166,7 +166,7 @@ status_t BufferQueueProducer::setMaxDequeuedBufferCount(
} // Autolock scope
// Call back without lock held
- if (listener != nullptr) {
+ if (listener != NULL) {
listener->onBuffersReleased();
}
@@ -221,7 +221,7 @@ status_t BufferQueueProducer::setAsyncMode(bool async) {
} // Autolock scope
// Call back without lock held
- if (listener != nullptr) {
+ if (listener != NULL) {
listener->onBuffersReleased();
}
return NO_ERROR;
@@ -450,11 +450,11 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou
mSlots[found].mBufferState.dequeue();
- if ((buffer == nullptr) ||
+ if ((buffer == NULL) ||
buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage))
{
mSlots[found].mAcquireCalled = false;
- mSlots[found].mGraphicBuffer = nullptr;
+ mSlots[found].mGraphicBuffer = NULL;
mSlots[found].mRequestBufferCalled = false;
mSlots[found].mEglDisplay = EGL_NO_DISPLAY;
mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
@@ -472,7 +472,7 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou
BQ_LOGV("dequeueBuffer: setting buffer age to %" PRIu64,
mCore->mBufferAge);
- if (CC_UNLIKELY(mSlots[found].mFence == nullptr)) {
+ if (CC_UNLIKELY(mSlots[found].mFence == NULL)) {
BQ_LOGE("dequeueBuffer: about to return a NULL fence - "
"slot=%d w=%d h=%d format=%u",
found, buffer->width, buffer->height, buffer->format);
@@ -613,7 +613,7 @@ status_t BufferQueueProducer::detachBuffer(int slot) {
listener = mCore->mConsumerListener;
}
- if (listener != nullptr) {
+ if (listener != NULL) {
listener->onBuffersReleased();
}
@@ -624,10 +624,10 @@ status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
sp<Fence>* outFence) {
ATRACE_CALL();
- if (outBuffer == nullptr) {
+ if (outBuffer == NULL) {
BQ_LOGE("detachNextBuffer: outBuffer must not be NULL");
return BAD_VALUE;
- } else if (outFence == nullptr) {
+ } else if (outFence == NULL) {
BQ_LOGE("detachNextBuffer: outFence must not be NULL");
return BAD_VALUE;
}
@@ -671,7 +671,7 @@ status_t BufferQueueProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
listener = mCore->mConsumerListener;
}
- if (listener != nullptr) {
+ if (listener != NULL) {
listener->onBuffersReleased();
}
@@ -682,10 +682,10 @@ status_t BufferQueueProducer::attachBuffer(int* outSlot,
const sp<android::GraphicBuffer>& buffer) {
ATRACE_CALL();
- if (outSlot == nullptr) {
+ if (outSlot == NULL) {
BQ_LOGE("attachBuffer: outSlot must not be NULL");
return BAD_VALUE;
- } else if (buffer == nullptr) {
+ } else if (buffer == NULL) {
BQ_LOGE("attachBuffer: cannot attach NULL buffer");
return BAD_VALUE;
}
@@ -765,8 +765,9 @@ status_t BufferQueueProducer::queueBuffer(int slot,
&crop, &scalingMode, &transform, &acquireFence, &stickyTransform,
&getFrameTimestamps);
const Region& surfaceDamage = input.getSurfaceDamage();
+ const HdrMetadata& hdrMetadata = input.getHdrMetadata();
- if (acquireFence == nullptr) {
+ if (acquireFence == NULL) {
BQ_LOGE("queueBuffer: fence is NULL");
return BAD_VALUE;
}
@@ -825,9 +826,9 @@ status_t BufferQueueProducer::queueBuffer(int slot,
}
BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64 " dataSpace=%d"
- " crop=[%d,%d,%d,%d] transform=%#x scale=%s",
- slot, mCore->mFrameCounter + 1, requestedPresentTimestamp,
- dataSpace, crop.left, crop.top, crop.right, crop.bottom,
+ " validHdrMetadataTypes=0x%x crop=[%d,%d,%d,%d] transform=%#x scale=%s",
+ slot, mCore->mFrameCounter + 1, requestedPresentTimestamp, dataSpace,
+ hdrMetadata.validTypes, crop.left, crop.top, crop.right, crop.bottom,
transform,
BufferItem::scalingModeName(static_cast<uint32_t>(scalingMode)));
@@ -866,6 +867,7 @@ status_t BufferQueueProducer::queueBuffer(int slot,
item.mTimestamp = requestedPresentTimestamp;
item.mIsAutoTimestamp = isAutoTimestamp;
item.mDataSpace = dataSpace;
+ item.mHdrMetadata = hdrMetadata;
item.mFrameNumber = currentFrameNumber;
item.mSlot = slot;
item.mFence = acquireFence;
@@ -876,6 +878,7 @@ status_t BufferQueueProducer::queueBuffer(int slot,
item.mSurfaceDamage = surfaceDamage;
item.mQueuedBuffer = true;
item.mAutoRefresh = mCore->mSharedBufferMode && mCore->mAutoRefresh;
+ item.mApi = mCore->mConnectedApi;
mStickyTransform = stickyTransform;
@@ -970,9 +973,9 @@ status_t BufferQueueProducer::queueBuffer(int slot,
mCallbackCondition.wait(mCallbackMutex);
}
- if (frameAvailableListener != nullptr) {
+ if (frameAvailableListener != NULL) {
frameAvailableListener->onFrameAvailable(item);
- } else if (frameReplacedListener != nullptr) {
+ } else if (frameReplacedListener != NULL) {
frameReplacedListener->onFrameReplaced(item);
}
@@ -1037,7 +1040,7 @@ status_t BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "
"(state = %s)", slot, mSlots[slot].mBufferState.string());
return BAD_VALUE;
- } else if (fence == nullptr) {
+ } else if (fence == NULL) {
BQ_LOGE("cancelBuffer: fence is NULL");
return BAD_VALUE;
}
@@ -1067,7 +1070,7 @@ int BufferQueueProducer::query(int what, int *outValue) {
ATRACE_CALL();
Mutex::Autolock lock(mCore->mMutex);
- if (outValue == nullptr) {
+ if (outValue == NULL) {
BQ_LOGE("query: outValue was NULL");
return BAD_VALUE;
}
@@ -1118,6 +1121,9 @@ int BufferQueueProducer::query(int what, int *outValue) {
case NATIVE_WINDOW_CONSUMER_IS_PROTECTED:
value = static_cast<int32_t>(mCore->mConsumerIsProtected);
break;
+ case NATIVE_WINDOW_MAX_BUFFER_COUNT:
+ value = static_cast<int32_t>(mCore->mMaxBufferCount);
+ break;
default:
return BAD_VALUE;
}
@@ -1140,12 +1146,12 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
return NO_INIT;
}
- if (mCore->mConsumerListener == nullptr) {
+ if (mCore->mConsumerListener == NULL) {
BQ_LOGE("connect: BufferQueue has no consumer");
return NO_INIT;
}
- if (output == nullptr) {
+ if (output == NULL) {
BQ_LOGE("connect: output was NULL");
return BAD_VALUE;
}
@@ -1183,10 +1189,10 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,
output->nextFrameNumber = mCore->mFrameCounter + 1;
output->bufferReplaced = false;
- if (listener != nullptr) {
+ if (listener != NULL) {
// Set up a death notification so that we can disconnect
// automatically if the remote producer dies
- if (IInterface::asBinder(listener)->remoteBinder() != nullptr) {
+ if (IInterface::asBinder(listener)->remoteBinder() != NULL) {
status = IInterface::asBinder(listener)->linkToDeath(
static_cast<IBinder::DeathRecipient*>(this));
if (status != NO_ERROR) {
@@ -1263,7 +1269,7 @@ status_t BufferQueueProducer::disconnect(int api, DisconnectMode mode) {
mCore->freeAllBuffersLocked();
// Remove our death notification callback if we have one
- if (mCore->mLinkedToDeath != nullptr) {
+ if (mCore->mLinkedToDeath != NULL) {
sp<IBinder> token =
IInterface::asBinder(mCore->mLinkedToDeath);
// This can fail if we're here because of the death
@@ -1273,8 +1279,8 @@ status_t BufferQueueProducer::disconnect(int api, DisconnectMode mode) {
}
mCore->mSharedBufferSlot =
BufferQueueCore::INVALID_BUFFER_SLOT;
- mCore->mLinkedToDeath = nullptr;
- mCore->mConnectedProducerListener = nullptr;
+ mCore->mLinkedToDeath = NULL;
+ mCore->mConnectedProducerListener = NULL;
mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
mCore->mConnectedPid = -1;
mCore->mSidebandStream.clear();
@@ -1297,7 +1303,7 @@ status_t BufferQueueProducer::disconnect(int api, DisconnectMode mode) {
} // Autolock scope
// Call back without lock held
- if (listener != nullptr) {
+ if (listener != NULL) {
listener->onBuffersReleased();
listener->onDisconnect();
}
@@ -1313,7 +1319,7 @@ status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream)
listener = mCore->mConsumerListener;
} // Autolock scope
- if (listener != nullptr) {
+ if (listener != NULL) {
listener->onSidebandStreamChanged();
}
return NO_ERROR;
@@ -1328,6 +1334,7 @@ void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height,
uint32_t allocHeight = 0;
PixelFormat allocFormat = PIXEL_FORMAT_UNKNOWN;
uint64_t allocUsage = 0;
+ std::string allocName;
{ // Autolock scope
Mutex::Autolock lock(mCore->mMutex);
mCore->waitWhileAllocatingLocked();
@@ -1347,6 +1354,7 @@ void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height,
allocHeight = height > 0 ? height : mCore->mDefaultHeight;
allocFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
allocUsage = usage | mCore->mConsumerUsageBits;
+ allocName.assign(mCore->mConsumerName.string(), mCore->mConsumerName.size());
mCore->mIsAllocating = true;
} // Autolock scope
@@ -1355,7 +1363,7 @@ void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height,
for (size_t i = 0; i < newBufferCount; ++i) {
sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
allocWidth, allocHeight, allocFormat, BQ_LAYER_COUNT,
- allocUsage, {mConsumerName.string(), mConsumerName.size()});
+ allocUsage, allocName);
status_t result = graphicBuffer->initCheck();
@@ -1527,7 +1535,7 @@ void BufferQueueProducer::addAndGetFrameTimestamps(
Mutex::Autolock lock(mCore->mMutex);
listener = mCore->mConsumerListener;
}
- if (listener != nullptr) {
+ if (listener != NULL) {
listener->addAndGetFrameTimestamps(newTimestamps, outDelta);
}
}
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index 2a9d742fc9..f9e292e199 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -96,7 +96,7 @@ void ConsumerBase::onLastStrongRef(const void* id __attribute__((unused))) {
void ConsumerBase::freeBufferLocked(int slotIndex) {
CB_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
- mSlots[slotIndex].mGraphicBuffer = nullptr;
+ mSlots[slotIndex].mGraphicBuffer = 0;
mSlots[slotIndex].mFence = Fence::NO_FENCE;
mSlots[slotIndex].mFrameNumber = 0;
}
@@ -110,7 +110,7 @@ void ConsumerBase::onFrameAvailable(const BufferItem& item) {
listener = mFrameAvailableListener.promote();
}
- if (listener != nullptr) {
+ if (listener != NULL) {
CB_LOGV("actually calling onFrameAvailable");
listener->onFrameAvailable(item);
}
@@ -125,7 +125,7 @@ void ConsumerBase::onFrameReplaced(const BufferItem &item) {
listener = mFrameAvailableListener.promote();
}
- if (listener != nullptr) {
+ if (listener != NULL) {
CB_LOGV("actually calling onFrameReplaced");
listener->onFrameReplaced(item);
}
@@ -182,6 +182,16 @@ bool ConsumerBase::isAbandoned() {
return mAbandoned;
}
+void ConsumerBase::setName(const String8& name) {
+ Mutex::Autolock _l(mMutex);
+ if (mAbandoned) {
+ CB_LOGE("setName: ConsumerBase is abandoned!");
+ return;
+ }
+ mName = name;
+ mConsumer->setConsumerName(name);
+}
+
void ConsumerBase::setFrameAvailableListener(
const wp<FrameAvailableListener>& listener) {
CB_LOGV("setFrameAvailableListener");
@@ -237,6 +247,50 @@ status_t ConsumerBase::setDefaultBufferDataSpace(
return mConsumer->setDefaultBufferDataSpace(defaultDataSpace);
}
+status_t ConsumerBase::setConsumerUsageBits(uint64_t usage) {
+ Mutex::Autolock lock(mMutex);
+ if (mAbandoned) {
+ CB_LOGE("setConsumerUsageBits: ConsumerBase is abandoned!");
+ return NO_INIT;
+ }
+ return mConsumer->setConsumerUsageBits(usage);
+}
+
+status_t ConsumerBase::setTransformHint(uint32_t hint) {
+ Mutex::Autolock lock(mMutex);
+ if (mAbandoned) {
+ CB_LOGE("setTransformHint: ConsumerBase is abandoned!");
+ return NO_INIT;
+ }
+ return mConsumer->setTransformHint(hint);
+}
+
+status_t ConsumerBase::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
+ Mutex::Autolock lock(mMutex);
+ if (mAbandoned) {
+ CB_LOGE("setMaxAcquiredBufferCount: ConsumerBase is abandoned!");
+ return NO_INIT;
+ }
+ return mConsumer->setMaxAcquiredBufferCount(maxAcquiredBuffers);
+}
+
+sp<NativeHandle> ConsumerBase::getSidebandStream() const {
+ Mutex::Autolock _l(mMutex);
+ if (mAbandoned) {
+ CB_LOGE("getSidebandStream: ConsumerBase is abandoned!");
+ return nullptr;
+ }
+
+ sp<NativeHandle> stream;
+ status_t err = mConsumer->getSidebandStream(&stream);
+ if (err != NO_ERROR) {
+ CB_LOGE("failed to get sideband stream: %d", err);
+ return nullptr;
+ }
+
+ return stream;
+}
+
status_t ConsumerBase::getOccupancyHistory(bool forceFlush,
std::vector<OccupancyTracker::Segment>* outHistory) {
Mutex::Autolock _l(mMutex);
@@ -298,8 +352,8 @@ status_t ConsumerBase::acquireBufferLocked(BufferItem *item,
return err;
}
- if (item->mGraphicBuffer != nullptr) {
- if (mSlots[item->mSlot].mGraphicBuffer != nullptr) {
+ if (item->mGraphicBuffer != NULL) {
+ if (mSlots[item->mSlot].mGraphicBuffer != NULL) {
freeBufferLocked(item->mSlot);
}
mSlots[item->mSlot].mGraphicBuffer = item->mGraphicBuffer;
@@ -414,7 +468,7 @@ bool ConsumerBase::stillTracking(int slot,
if (slot < 0 || slot >= BufferQueue::NUM_BUFFER_SLOTS) {
return false;
}
- return (mSlots[slot].mGraphicBuffer != nullptr &&
+ return (mSlots[slot].mGraphicBuffer != NULL &&
mSlots[slot].mGraphicBuffer->handle == graphicBuffer->handle);
}
diff --git a/libs/gui/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp
index 9f09e0c0d4..8edf60400c 100644
--- a/libs/gui/CpuConsumer.cpp
+++ b/libs/gui/CpuConsumer.cpp
@@ -18,11 +18,11 @@
#define LOG_TAG "CpuConsumer"
//#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include <cutils/compiler.h>
-#include <utils/Log.h>
-#include <gui/BufferItem.h>
#include <gui/CpuConsumer.h>
+#include <gui/BufferItem.h>
+#include <utils/Log.h>
+
#define CC_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
//#define CC_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
//#define CC_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__)
@@ -44,20 +44,19 @@ CpuConsumer::CpuConsumer(const sp<IGraphicBufferConsumer>& bq,
mConsumer->setMaxAcquiredBufferCount(static_cast<int32_t>(maxLockedBuffers));
}
-CpuConsumer::~CpuConsumer() {
- // ConsumerBase destructor does all the work.
+size_t CpuConsumer::findAcquiredBufferLocked(uintptr_t id) const {
+ for (size_t i = 0; i < mMaxLockedBuffers; i++) {
+ const auto& ab = mAcquiredBuffers[i];
+ // note that this finds AcquiredBuffer::kUnusedId as well
+ if (ab.mLockedBufferId == id) {
+ return i;
+ }
+ }
+ return mMaxLockedBuffers; // an invalid index
}
-
-
-void CpuConsumer::setName(const String8& name) {
- Mutex::Autolock _l(mMutex);
- if (mAbandoned) {
- CC_LOGE("setName: CpuConsumer is abandoned!");
- return;
- }
- mName = name;
- mConsumer->setConsumerName(name);
+static uintptr_t getLockedBufferId(const CpuConsumer::LockedBuffer& buffer) {
+ return reinterpret_cast<uintptr_t>(buffer.data);
}
static bool isPossiblyYUV(PixelFormat format) {
@@ -88,10 +87,74 @@ static bool isPossiblyYUV(PixelFormat format) {
}
}
+status_t CpuConsumer::lockBufferItem(const BufferItem& item, LockedBuffer* outBuffer) const {
+ android_ycbcr ycbcr = android_ycbcr();
+
+ PixelFormat format = item.mGraphicBuffer->getPixelFormat();
+ PixelFormat flexFormat = format;
+ if (isPossiblyYUV(format)) {
+ int fenceFd = item.mFence.get() ? item.mFence->dup() : -1;
+ status_t err = item.mGraphicBuffer->lockAsyncYCbCr(GraphicBuffer::USAGE_SW_READ_OFTEN,
+ item.mCrop, &ycbcr, fenceFd);
+ if (err == OK) {
+ flexFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
+ if (format != HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ CC_LOGV("locking buffer of format %#x as flex YUV", format);
+ }
+ } else if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+ CC_LOGE("Unable to lock YCbCr buffer for CPU reading: %s (%d)", strerror(-err), err);
+ return err;
+ }
+ }
+
+ if (ycbcr.y != nullptr) {
+ outBuffer->data = reinterpret_cast<uint8_t*>(ycbcr.y);
+ outBuffer->stride = static_cast<uint32_t>(ycbcr.ystride);
+ outBuffer->dataCb = reinterpret_cast<uint8_t*>(ycbcr.cb);
+ outBuffer->dataCr = reinterpret_cast<uint8_t*>(ycbcr.cr);
+ outBuffer->chromaStride = static_cast<uint32_t>(ycbcr.cstride);
+ outBuffer->chromaStep = static_cast<uint32_t>(ycbcr.chroma_step);
+ } else {
+ // not flexible YUV; try lockAsync
+ void* bufferPointer = nullptr;
+ int fenceFd = item.mFence.get() ? item.mFence->dup() : -1;
+ status_t err = item.mGraphicBuffer->lockAsync(GraphicBuffer::USAGE_SW_READ_OFTEN,
+ item.mCrop, &bufferPointer, fenceFd);
+ if (err != OK) {
+ CC_LOGE("Unable to lock buffer for CPU reading: %s (%d)", strerror(-err), err);
+ return err;
+ }
+
+ outBuffer->data = reinterpret_cast<uint8_t*>(bufferPointer);
+ outBuffer->stride = item.mGraphicBuffer->getStride();
+ outBuffer->dataCb = nullptr;
+ outBuffer->dataCr = nullptr;
+ outBuffer->chromaStride = 0;
+ outBuffer->chromaStep = 0;
+ }
+
+ outBuffer->width = item.mGraphicBuffer->getWidth();
+ outBuffer->height = item.mGraphicBuffer->getHeight();
+ outBuffer->format = format;
+ outBuffer->flexFormat = flexFormat;
+
+ outBuffer->crop = item.mCrop;
+ outBuffer->transform = item.mTransform;
+ outBuffer->scalingMode = item.mScalingMode;
+ outBuffer->timestamp = item.mTimestamp;
+ outBuffer->dataSpace = item.mDataSpace;
+ outBuffer->frameNumber = item.mFrameNumber;
+
+ return OK;
+}
+
status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) {
status_t err;
if (!nativeBuffer) return BAD_VALUE;
+
+ Mutex::Autolock _l(mMutex);
+
if (mCurrentLockedBuffers == mMaxLockedBuffers) {
CC_LOGW("Max buffers have been locked (%zd), cannot lock anymore.",
mMaxLockedBuffers);
@@ -99,9 +162,6 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) {
}
BufferItem b;
-
- Mutex::Autolock _l(mMutex);
-
err = acquireBufferLocked(&b, 0);
if (err != OK) {
if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
@@ -112,94 +172,23 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) {
}
}
- int slot = b.mSlot;
-
- void *bufferPointer = nullptr;
- android_ycbcr ycbcr = android_ycbcr();
-
- PixelFormat format = mSlots[slot].mGraphicBuffer->getPixelFormat();
- PixelFormat flexFormat = format;
- if (isPossiblyYUV(format)) {
- if (b.mFence.get()) {
- err = mSlots[slot].mGraphicBuffer->lockAsyncYCbCr(
- GraphicBuffer::USAGE_SW_READ_OFTEN,
- b.mCrop,
- &ycbcr,
- b.mFence->dup());
- } else {
- err = mSlots[slot].mGraphicBuffer->lockYCbCr(
- GraphicBuffer::USAGE_SW_READ_OFTEN,
- b.mCrop,
- &ycbcr);
- }
- if (err == OK) {
- bufferPointer = ycbcr.y;
- flexFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
- if (format != HAL_PIXEL_FORMAT_YCbCr_420_888) {
- CC_LOGV("locking buffer of format %#x as flex YUV", format);
- }
- } else if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
- CC_LOGE("Unable to lock YCbCr buffer for CPU reading: %s (%d)",
- strerror(-err), err);
- return err;
- }
+ if (b.mGraphicBuffer == nullptr) {
+ b.mGraphicBuffer = mSlots[b.mSlot].mGraphicBuffer;
}
- if (bufferPointer == nullptr) { // not flexible YUV
- if (b.mFence.get()) {
- err = mSlots[slot].mGraphicBuffer->lockAsync(
- GraphicBuffer::USAGE_SW_READ_OFTEN,
- b.mCrop,
- &bufferPointer,
- b.mFence->dup());
- } else {
- err = mSlots[slot].mGraphicBuffer->lock(
- GraphicBuffer::USAGE_SW_READ_OFTEN,
- b.mCrop,
- &bufferPointer);
- }
- if (err != OK) {
- CC_LOGE("Unable to lock buffer for CPU reading: %s (%d)",
- strerror(-err), err);
- return err;
- }
+ err = lockBufferItem(b, nativeBuffer);
+ if (err != OK) {
+ return err;
}
- size_t lockedIdx = 0;
- for (; lockedIdx < static_cast<size_t>(mMaxLockedBuffers); lockedIdx++) {
- if (mAcquiredBuffers[lockedIdx].mSlot ==
- BufferQueue::INVALID_BUFFER_SLOT) {
- break;
- }
- }
- assert(lockedIdx < mMaxLockedBuffers);
-
- AcquiredBuffer &ab = mAcquiredBuffers.editItemAt(lockedIdx);
- ab.mSlot = slot;
- ab.mBufferPointer = bufferPointer;
- ab.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
-
- nativeBuffer->data =
- reinterpret_cast<uint8_t*>(bufferPointer);
- nativeBuffer->width = mSlots[slot].mGraphicBuffer->getWidth();
- nativeBuffer->height = mSlots[slot].mGraphicBuffer->getHeight();
- nativeBuffer->format = format;
- nativeBuffer->flexFormat = flexFormat;
- nativeBuffer->stride = (ycbcr.y != nullptr) ?
- static_cast<uint32_t>(ycbcr.ystride) :
- mSlots[slot].mGraphicBuffer->getStride();
-
- nativeBuffer->crop = b.mCrop;
- nativeBuffer->transform = b.mTransform;
- nativeBuffer->scalingMode = b.mScalingMode;
- nativeBuffer->timestamp = b.mTimestamp;
- nativeBuffer->dataSpace = b.mDataSpace;
- nativeBuffer->frameNumber = b.mFrameNumber;
-
- nativeBuffer->dataCb = reinterpret_cast<uint8_t*>(ycbcr.cb);
- nativeBuffer->dataCr = reinterpret_cast<uint8_t*>(ycbcr.cr);
- nativeBuffer->chromaStride = static_cast<uint32_t>(ycbcr.cstride);
- nativeBuffer->chromaStep = static_cast<uint32_t>(ycbcr.chroma_step);
+ // find an unused AcquiredBuffer
+ size_t lockedIdx = findAcquiredBufferLocked(AcquiredBuffer::kUnusedId);
+ ALOG_ASSERT(lockedIdx < mMaxLockedBuffers);
+ AcquiredBuffer& ab = mAcquiredBuffers.editItemAt(lockedIdx);
+
+ ab.mSlot = b.mSlot;
+ ab.mGraphicBuffer = b.mGraphicBuffer;
+ ab.mLockedBufferId = getLockedBufferId(*nativeBuffer);
mCurrentLockedBuffers++;
@@ -208,60 +197,34 @@ status_t CpuConsumer::lockNextBuffer(LockedBuffer *nativeBuffer) {
status_t CpuConsumer::unlockBuffer(const LockedBuffer &nativeBuffer) {
Mutex::Autolock _l(mMutex);
- size_t lockedIdx = 0;
- void *bufPtr = reinterpret_cast<void *>(nativeBuffer.data);
- for (; lockedIdx < static_cast<size_t>(mMaxLockedBuffers); lockedIdx++) {
- if (bufPtr == mAcquiredBuffers[lockedIdx].mBufferPointer) break;
- }
+ uintptr_t id = getLockedBufferId(nativeBuffer);
+ size_t lockedIdx =
+ (id != AcquiredBuffer::kUnusedId) ? findAcquiredBufferLocked(id) : mMaxLockedBuffers;
if (lockedIdx == mMaxLockedBuffers) {
CC_LOGE("%s: Can't find buffer to free", __FUNCTION__);
return BAD_VALUE;
}
- return releaseAcquiredBufferLocked(lockedIdx);
-}
+ AcquiredBuffer& ab = mAcquiredBuffers.editItemAt(lockedIdx);
-status_t CpuConsumer::releaseAcquiredBufferLocked(size_t lockedIdx) {
- status_t err;
- int fd = -1;
-
- err = mAcquiredBuffers[lockedIdx].mGraphicBuffer->unlockAsync(&fd);
+ int fenceFd = -1;
+ status_t err = ab.mGraphicBuffer->unlockAsync(&fenceFd);
if (err != OK) {
CC_LOGE("%s: Unable to unlock graphic buffer %zd", __FUNCTION__,
lockedIdx);
return err;
}
- int buf = mAcquiredBuffers[lockedIdx].mSlot;
- if (CC_LIKELY(fd != -1)) {
- sp<Fence> fence(new Fence(fd));
- addReleaseFenceLocked(
- mAcquiredBuffers[lockedIdx].mSlot,
- mSlots[buf].mGraphicBuffer,
- fence);
- }
- // release the buffer if it hasn't already been freed by the BufferQueue.
- // This can happen, for example, when the producer of this buffer
- // disconnected after this buffer was acquired.
- if (CC_LIKELY(mAcquiredBuffers[lockedIdx].mGraphicBuffer ==
- mSlots[buf].mGraphicBuffer)) {
- releaseBufferLocked(
- buf, mAcquiredBuffers[lockedIdx].mGraphicBuffer,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
- }
+ sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
+ addReleaseFenceLocked(ab.mSlot, ab.mGraphicBuffer, fence);
+ releaseBufferLocked(ab.mSlot, ab.mGraphicBuffer);
- AcquiredBuffer &ab = mAcquiredBuffers.editItemAt(lockedIdx);
- ab.mSlot = BufferQueue::INVALID_BUFFER_SLOT;
- ab.mBufferPointer = nullptr;
- ab.mGraphicBuffer.clear();
+ ab.reset();
mCurrentLockedBuffers--;
- return OK;
-}
-void CpuConsumer::freeBufferLocked(int slotIndex) {
- ConsumerBase::freeBufferLocked(slotIndex);
+ return OK;
}
} // namespace android
diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp
index f5cf1c4d5a..1757ec1cd3 100644
--- a/libs/gui/DisplayEventReceiver.cpp
+++ b/libs/gui/DisplayEventReceiver.cpp
@@ -34,9 +34,9 @@ namespace android {
DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource) {
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- if (sf != nullptr) {
+ if (sf != NULL) {
mEventConnection = sf->createDisplayEventConnection(vsyncSource);
- if (mEventConnection != nullptr) {
+ if (mEventConnection != NULL) {
mDataChannel = std::make_unique<gui::BitTube>();
mEventConnection->stealReceiveChannel(mDataChannel.get());
}
@@ -47,13 +47,13 @@ DisplayEventReceiver::~DisplayEventReceiver() {
}
status_t DisplayEventReceiver::initCheck() const {
- if (mDataChannel != nullptr)
+ if (mDataChannel != NULL)
return NO_ERROR;
return NO_INIT;
}
int DisplayEventReceiver::getFd() const {
- if (mDataChannel == nullptr)
+ if (mDataChannel == NULL)
return NO_INIT;
return mDataChannel->getFd();
@@ -63,7 +63,7 @@ status_t DisplayEventReceiver::setVsyncRate(uint32_t count) {
if (int32_t(count) < 0)
return BAD_VALUE;
- if (mEventConnection != nullptr) {
+ if (mEventConnection != NULL) {
mEventConnection->setVsyncRate(count);
return NO_ERROR;
}
@@ -71,7 +71,7 @@ status_t DisplayEventReceiver::setVsyncRate(uint32_t count) {
}
status_t DisplayEventReceiver::requestNextVsync() {
- if (mEventConnection != nullptr) {
+ if (mEventConnection != NULL) {
mEventConnection->requestNextVsync();
return NO_ERROR;
}
diff --git a/libs/gui/FrameTimestamps.cpp b/libs/gui/FrameTimestamps.cpp
index fccca97f54..a379ad6306 100644
--- a/libs/gui/FrameTimestamps.cpp
+++ b/libs/gui/FrameTimestamps.cpp
@@ -628,7 +628,6 @@ FrameEventHistoryDelta& FrameEventHistoryDelta::operator=(
ALOGE("FrameEventHistoryDelta assign clobbering history.");
}
mDeltas = std::move(src.mDeltas);
- ALOGE_IF(src.mDeltas.empty(), "Source mDeltas not empty.");
return *this;
}
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 59e78cc6bf..885efec9b9 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -31,6 +31,8 @@
#include <hardware/hardware.h>
+#include <math/mat4.h>
+
#include <gui/BufferItem.h>
#include <gui/GLConsumer.h>
#include <gui/ISurfaceComposer.h>
@@ -75,33 +77,7 @@ static const struct {
"_______________"
};
-// Transform matrices
-static float mtxIdentity[16] = {
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1,
-};
-static float mtxFlipH[16] = {
- -1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 1, 0, 0, 1,
-};
-static float mtxFlipV[16] = {
- 1, 0, 0, 0,
- 0, -1, 0, 0,
- 0, 0, 1, 0,
- 0, 1, 0, 1,
-};
-static float mtxRot90[16] = {
- 0, 1, 0, 0,
- -1, 0, 0, 0,
- 0, 0, 1, 0,
- 1, 0, 0, 1,
-};
-
-static void mtxMul(float out[16], const float a[16], const float b[16]);
+static const mat4 mtxIdentity;
Mutex GLConsumer::sStaticInitLock;
sp<GraphicBuffer> GLConsumer::sReleasedTexImageBuffer;
@@ -173,7 +149,7 @@ GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
{
GLC_LOGV("GLConsumer");
- memcpy(mCurrentTransformMatrix, mtxIdentity,
+ memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(),
sizeof(mCurrentTransformMatrix));
mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
@@ -202,7 +178,7 @@ GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t texTarget,
{
GLC_LOGV("GLConsumer");
- memcpy(mCurrentTransformMatrix, mtxIdentity,
+ memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(),
sizeof(mCurrentTransformMatrix));
mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
@@ -315,7 +291,7 @@ status_t GLConsumer::releaseTexImage() {
return err;
}
- if (mReleasedTexImage == nullptr) {
+ if (mReleasedTexImage == NULL) {
mReleasedTexImage = new EglImage(getDebugTexImageBuffer());
}
@@ -345,7 +321,7 @@ status_t GLConsumer::releaseTexImage() {
sp<GraphicBuffer> GLConsumer::getDebugTexImageBuffer() {
Mutex::Autolock _l(sStaticInitLock);
- if (CC_UNLIKELY(sReleasedTexImageBuffer == nullptr)) {
+ if (CC_UNLIKELY(sReleasedTexImageBuffer == NULL)) {
// The first time, create the debug texture in case the application
// continues to use it.
sp<GraphicBuffer> buffer = new GraphicBuffer(
@@ -381,7 +357,7 @@ status_t GLConsumer::acquireBufferLocked(BufferItem *item,
// If item->mGraphicBuffer is not null, this buffer has not been acquired
// before, so any prior EglImage created is using a stale buffer. This
// replaces any old EglImage with a new one (using the new buffer).
- if (item->mGraphicBuffer != nullptr) {
+ if (item->mGraphicBuffer != NULL) {
int slot = item->mSlot;
mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer);
}
@@ -455,7 +431,7 @@ status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item,
GLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)",
mCurrentTexture, mCurrentTextureImage != NULL ?
- mCurrentTextureImage->graphicBufferHandle() : nullptr,
+ mCurrentTextureImage->graphicBufferHandle() : 0,
slot, mSlots[slot].mGraphicBuffer->handle);
// Hang onto the pointer so that it isn't freed in the call to
@@ -515,7 +491,7 @@ status_t GLConsumer::bindTextureImageLocked() {
glBindTexture(mTexTarget, mTexName);
if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT &&
- mCurrentTextureImage == nullptr) {
+ mCurrentTextureImage == NULL) {
GLC_LOGE("bindTextureImage: no currently-bound texture");
return NO_INIT;
}
@@ -679,7 +655,7 @@ status_t GLConsumer::attachToContext(uint32_t tex) {
mTexName = tex;
mAttached = true;
- if (mCurrentTextureImage != nullptr) {
+ if (mCurrentTextureImage != NULL) {
// This may wait for a buffer a second time. This is likely required if
// this is a different context, since otherwise the wait could be skipped
// by bouncing through another context. For the same context the extra
@@ -700,7 +676,7 @@ status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) {
if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
if (SyncFeatures::getInstance().useNativeFenceSync()) {
EGLSyncKHR sync = eglCreateSyncKHR(dpy,
- EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
+ EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
if (sync == EGL_NO_SYNC_KHR) {
GLC_LOGE("syncForReleaseLocked: error creating EGL fence: %#x",
eglGetError());
@@ -744,7 +720,7 @@ status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) {
// Create a fence for the outstanding accesses in the current
// OpenGL ES context.
- fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, nullptr);
+ fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
if (fence == EGL_NO_SYNC_KHR) {
GLC_LOGE("syncForReleaseLocked: error creating fence: %#x",
eglGetError());
@@ -758,25 +734,6 @@ status_t GLConsumer::syncForReleaseLocked(EGLDisplay dpy) {
return OK;
}
-bool GLConsumer::isExternalFormat(PixelFormat format)
-{
- switch (format) {
- // supported YUV formats
- case HAL_PIXEL_FORMAT_YV12:
- // Legacy/deprecated YUV formats
- case HAL_PIXEL_FORMAT_YCbCr_422_SP:
- case HAL_PIXEL_FORMAT_YCrCb_420_SP:
- case HAL_PIXEL_FORMAT_YCbCr_422_I:
- return true;
- }
-
- // Any OEM format needs to be considered
- if (format>=0x100 && format<=0x1FF)
- return true;
-
- return false;
-}
-
uint32_t GLConsumer::getCurrentTextureTarget() const {
return mTexTarget;
}
@@ -795,11 +752,11 @@ void GLConsumer::setFilteringEnabled(bool enabled) {
bool needsRecompute = mFilteringEnabled != enabled;
mFilteringEnabled = enabled;
- if (needsRecompute && mCurrentTextureImage==nullptr) {
+ if (needsRecompute && mCurrentTextureImage==NULL) {
GLC_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL");
}
- if (needsRecompute && mCurrentTextureImage != nullptr) {
+ if (needsRecompute && mCurrentTextureImage != NULL) {
computeCurrentTransformMatrixLocked();
}
}
@@ -820,34 +777,37 @@ void GLConsumer::computeCurrentTransformMatrixLocked() {
void GLConsumer::computeTransformMatrix(float outTransform[16],
const sp<GraphicBuffer>& buf, const Rect& cropRect, uint32_t transform,
bool filtering) {
-
- float xform[16];
- for (int i = 0; i < 16; i++) {
- xform[i] = mtxIdentity[i];
- }
+ // Transform matrices
+ static const mat4 mtxFlipH(
+ -1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 1, 0, 0, 1
+ );
+ static const mat4 mtxFlipV(
+ 1, 0, 0, 0,
+ 0, -1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 1, 0, 1
+ );
+ static const mat4 mtxRot90(
+ 0, 1, 0, 0,
+ -1, 0, 0, 0,
+ 0, 0, 1, 0,
+ 1, 0, 0, 1
+ );
+
+ mat4 xform;
if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
- float result[16];
- mtxMul(result, xform, mtxFlipH);
- for (int i = 0; i < 16; i++) {
- xform[i] = result[i];
- }
+ xform *= mtxFlipH;
}
if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
- float result[16];
- mtxMul(result, xform, mtxFlipV);
- for (int i = 0; i < 16; i++) {
- xform[i] = result[i];
- }
+ xform *= mtxFlipV;
}
if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
- float result[16];
- mtxMul(result, xform, mtxRot90);
- for (int i = 0; i < 16; i++) {
- xform[i] = result[i];
- }
+ xform *= mtxRot90;
}
- float mtxBeforeFlipV[16];
if (!cropRect.isEmpty()) {
float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
float bufferWidth = buf->getWidth();
@@ -893,25 +853,63 @@ void GLConsumer::computeTransformMatrix(float outTransform[16],
sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
bufferHeight;
}
- float crop[16] = {
+
+ mat4 crop(
sx, 0, 0, 0,
0, sy, 0, 0,
0, 0, 1, 0,
- tx, ty, 0, 1,
- };
-
- mtxMul(mtxBeforeFlipV, crop, xform);
- } else {
- for (int i = 0; i < 16; i++) {
- mtxBeforeFlipV[i] = xform[i];
- }
+ tx, ty, 0, 1
+ );
+ xform = crop * xform;
}
// SurfaceFlinger expects the top of its window textures to be at a Y
// coordinate of 0, so GLConsumer must behave the same way. We don't
// want to expose this to applications, however, so we must add an
// additional vertical flip to the transform after all the other transforms.
- mtxMul(outTransform, mtxFlipV, mtxBeforeFlipV);
+ xform = mtxFlipV * xform;
+
+ memcpy(outTransform, xform.asArray(), sizeof(xform));
+}
+
+Rect GLConsumer::scaleDownCrop(const Rect& crop, uint32_t bufferWidth, uint32_t bufferHeight) {
+ Rect outCrop = crop;
+
+ uint32_t newWidth = static_cast<uint32_t>(crop.width());
+ uint32_t newHeight = static_cast<uint32_t>(crop.height());
+
+ if (newWidth * bufferHeight > newHeight * bufferWidth) {
+ newWidth = newHeight * bufferWidth / bufferHeight;
+ ALOGV("too wide: newWidth = %d", newWidth);
+ } else if (newWidth * bufferHeight < newHeight * bufferWidth) {
+ newHeight = newWidth * bufferHeight / bufferWidth;
+ ALOGV("too tall: newHeight = %d", newHeight);
+ }
+
+ uint32_t currentWidth = static_cast<uint32_t>(crop.width());
+ uint32_t currentHeight = static_cast<uint32_t>(crop.height());
+
+ // The crop is too wide
+ if (newWidth < currentWidth) {
+ uint32_t dw = currentWidth - newWidth;
+ auto halfdw = dw / 2;
+ outCrop.left += halfdw;
+ // Not halfdw because it would subtract 1 too few when dw is odd
+ outCrop.right -= (dw - halfdw);
+ // The crop is too tall
+ } else if (newHeight < currentHeight) {
+ uint32_t dh = currentHeight - newHeight;
+ auto halfdh = dh / 2;
+ outCrop.top += halfdh;
+ // Not halfdh because it would subtract 1 too few when dh is odd
+ outCrop.bottom -= (dh - halfdh);
+ }
+
+ ALOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
+ outCrop.left, outCrop.top,
+ outCrop.right,outCrop.bottom);
+
+ return outCrop;
}
nsecs_t GLConsumer::getTimestamp() {
@@ -940,50 +938,14 @@ sp<GraphicBuffer> GLConsumer::getCurrentBuffer(int* outSlot) const {
}
return (mCurrentTextureImage == nullptr) ?
- nullptr : mCurrentTextureImage->graphicBuffer();
+ NULL : mCurrentTextureImage->graphicBuffer();
}
Rect GLConsumer::getCurrentCrop() const {
Mutex::Autolock lock(mMutex);
-
- Rect outCrop = mCurrentCrop;
- if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
- uint32_t newWidth = static_cast<uint32_t>(mCurrentCrop.width());
- uint32_t newHeight = static_cast<uint32_t>(mCurrentCrop.height());
-
- if (newWidth * mDefaultHeight > newHeight * mDefaultWidth) {
- newWidth = newHeight * mDefaultWidth / mDefaultHeight;
- GLC_LOGV("too wide: newWidth = %d", newWidth);
- } else if (newWidth * mDefaultHeight < newHeight * mDefaultWidth) {
- newHeight = newWidth * mDefaultHeight / mDefaultWidth;
- GLC_LOGV("too tall: newHeight = %d", newHeight);
- }
-
- uint32_t currentWidth = static_cast<uint32_t>(mCurrentCrop.width());
- uint32_t currentHeight = static_cast<uint32_t>(mCurrentCrop.height());
-
- // The crop is too wide
- if (newWidth < currentWidth) {
- uint32_t dw = currentWidth - newWidth;
- auto halfdw = dw / 2;
- outCrop.left += halfdw;
- // Not halfdw because it would subtract 1 too few when dw is odd
- outCrop.right -= (dw - halfdw);
- // The crop is too tall
- } else if (newHeight < currentHeight) {
- uint32_t dh = currentHeight - newHeight;
- auto halfdh = dh / 2;
- outCrop.top += halfdh;
- // Not halfdh because it would subtract 1 too few when dh is odd
- outCrop.bottom -= (dh - halfdh);
- }
-
- GLC_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
- outCrop.left, outCrop.top,
- outCrop.right,outCrop.bottom);
- }
-
- return outCrop;
+ return (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP)
+ ? scaleDownCrop(mCurrentCrop, mDefaultWidth, mDefaultHeight)
+ : mCurrentCrop;
}
uint32_t GLConsumer::getCurrentTransform() const {
@@ -1006,11 +968,6 @@ std::shared_ptr<FenceTime> GLConsumer::getCurrentFenceTime() const {
return mCurrentFenceTime;
}
-status_t GLConsumer::doGLFenceWait() const {
- Mutex::Autolock lock(mMutex);
- return doGLFenceWaitLocked();
-}
-
status_t GLConsumer::doGLFenceWaitLocked() const {
EGLDisplay dpy = eglGetCurrentDisplay();
@@ -1027,7 +984,8 @@ status_t GLConsumer::doGLFenceWaitLocked() const {
}
if (mCurrentFence->isValid()) {
- if (SyncFeatures::getInstance().useWaitSync()) {
+ if (SyncFeatures::getInstance().useWaitSync() &&
+ SyncFeatures::getInstance().useNativeFenceSync()) {
// Create an EGLSyncKHR from the current fence.
int fenceFd = mCurrentFence->dup();
if (fenceFd == -1) {
@@ -1086,61 +1044,8 @@ void GLConsumer::abandonLocked() {
ConsumerBase::abandonLocked();
}
-void GLConsumer::setName(const String8& name) {
- Mutex::Autolock _l(mMutex);
- if (mAbandoned) {
- GLC_LOGE("setName: GLConsumer is abandoned!");
- return;
- }
- mName = name;
- mConsumer->setConsumerName(name);
-}
-
-status_t GLConsumer::setDefaultBufferFormat(PixelFormat defaultFormat) {
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- GLC_LOGE("setDefaultBufferFormat: GLConsumer is abandoned!");
- return NO_INIT;
- }
- return mConsumer->setDefaultBufferFormat(defaultFormat);
-}
-
-status_t GLConsumer::setDefaultBufferDataSpace(
- android_dataspace defaultDataSpace) {
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- GLC_LOGE("setDefaultBufferDataSpace: GLConsumer is abandoned!");
- return NO_INIT;
- }
- return mConsumer->setDefaultBufferDataSpace(defaultDataSpace);
-}
-
status_t GLConsumer::setConsumerUsageBits(uint64_t usage) {
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- GLC_LOGE("setConsumerUsageBits: GLConsumer is abandoned!");
- return NO_INIT;
- }
- usage |= DEFAULT_USAGE_FLAGS;
- return mConsumer->setConsumerUsageBits(usage);
-}
-
-status_t GLConsumer::setTransformHint(uint32_t hint) {
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- GLC_LOGE("setTransformHint: GLConsumer is abandoned!");
- return NO_INIT;
- }
- return mConsumer->setTransformHint(hint);
-}
-
-status_t GLConsumer::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- GLC_LOGE("setMaxAcquiredBufferCount: GLConsumer is abandoned!");
- return NO_INIT;
- }
- return mConsumer->setMaxAcquiredBufferCount(maxAcquiredBuffers);
+ return ConsumerBase::setConsumerUsageBits(usage | DEFAULT_USAGE_FLAGS);
}
void GLConsumer::dumpLocked(String8& result, const char* prefix) const
@@ -1155,28 +1060,6 @@ void GLConsumer::dumpLocked(String8& result, const char* prefix) const
ConsumerBase::dumpLocked(result, prefix);
}
-static void mtxMul(float out[16], const float a[16], const float b[16]) {
- out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
- out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
- out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
- out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
-
- out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
- out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
- out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
- out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
-
- out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
- out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
- out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
- out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
-
- out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
- out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
- out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
- out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
-}
-
GLConsumer::EglImage::EglImage(sp<GraphicBuffer> graphicBuffer) :
mGraphicBuffer(graphicBuffer),
mEglImage(EGL_NO_IMAGE_KHR),
@@ -1267,7 +1150,7 @@ EGLImageKHR GLConsumer::EglImage::createImage(EGLDisplay dpy,
attrs[3] = attrs[11];
attrs[4] = EGL_NONE;
}
- eglInitialize(dpy, nullptr, nullptr);
+ eglInitialize(dpy, 0, 0);
EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
if (image == EGL_NO_IMAGE_KHR) {
diff --git a/libs/gui/HdrMetadata.cpp b/libs/gui/HdrMetadata.cpp
new file mode 100644
index 0000000000..b715e431d5
--- /dev/null
+++ b/libs/gui/HdrMetadata.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gui/HdrMetadata.h>
+
+namespace android {
+
+size_t HdrMetadata::getFlattenedSize() const {
+ size_t size = sizeof(validTypes);
+ if (validTypes & SMPTE2086) {
+ size += sizeof(smpte2086);
+ }
+ if (validTypes & CTA861_3) {
+ size += sizeof(cta8613);
+ }
+ return size;
+}
+
+status_t HdrMetadata::flatten(void* buffer, size_t size) const {
+ if (size < getFlattenedSize()) {
+ return NO_MEMORY;
+ }
+
+ FlattenableUtils::write(buffer, size, validTypes);
+ if (validTypes & SMPTE2086) {
+ FlattenableUtils::write(buffer, size, smpte2086);
+ }
+ if (validTypes & CTA861_3) {
+ FlattenableUtils::write(buffer, size, cta8613);
+ }
+
+ return NO_ERROR;
+}
+
+status_t HdrMetadata::unflatten(void const* buffer, size_t size) {
+ if (size < sizeof(validTypes)) {
+ return NO_MEMORY;
+ }
+ FlattenableUtils::read(buffer, size, validTypes);
+ if (validTypes & SMPTE2086) {
+ if (size < sizeof(smpte2086)) {
+ return NO_MEMORY;
+ }
+ FlattenableUtils::read(buffer, size, smpte2086);
+ }
+ if (validTypes & CTA861_3) {
+ if (size < sizeof(cta8613)) {
+ return NO_MEMORY;
+ }
+ FlattenableUtils::read(buffer, size, cta8613);
+ }
+
+ return NO_ERROR;
+}
+
+bool HdrMetadata::operator==(const HdrMetadata& rhs) const {
+ if (validTypes != rhs.validTypes) return false;
+
+ if ((validTypes & SMPTE2086) == SMPTE2086) {
+ if (smpte2086.displayPrimaryRed.x != rhs.smpte2086.displayPrimaryRed.x ||
+ smpte2086.displayPrimaryRed.y != rhs.smpte2086.displayPrimaryRed.y ||
+ smpte2086.displayPrimaryGreen.x != rhs.smpte2086.displayPrimaryGreen.x ||
+ smpte2086.displayPrimaryGreen.y != rhs.smpte2086.displayPrimaryGreen.y ||
+ smpte2086.displayPrimaryBlue.x != rhs.smpte2086.displayPrimaryBlue.x ||
+ smpte2086.displayPrimaryBlue.y != rhs.smpte2086.displayPrimaryBlue.y ||
+ smpte2086.whitePoint.x != rhs.smpte2086.whitePoint.x ||
+ smpte2086.whitePoint.y != rhs.smpte2086.whitePoint.y ||
+ smpte2086.maxLuminance != rhs.smpte2086.maxLuminance ||
+ smpte2086.minLuminance != rhs.smpte2086.minLuminance) {
+ return false;
+ }
+ }
+
+ if ((validTypes & CTA861_3) == CTA861_3) {
+ if (cta8613.maxFrameAverageLightLevel != rhs.cta8613.maxFrameAverageLightLevel ||
+ cta8613.maxContentLightLevel != rhs.cta8613.maxContentLightLevel) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace android
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 23e9ddc014..0749fde1ad 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -27,6 +27,9 @@
#include <binder/Parcel.h>
#include <binder/IInterface.h>
+#ifndef NO_BUFFERHUB
+#include <gui/BufferHubProducer.h>
+#endif
#include <gui/BufferQueueDefs.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/IProducerListener.h>
@@ -187,10 +190,10 @@ public:
virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
sp<Fence>* outFence) {
- if (outBuffer == nullptr) {
+ if (outBuffer == NULL) {
ALOGE("detachNextBuffer: outBuffer must not be NULL");
return BAD_VALUE;
- } else if (outFence == nullptr) {
+ } else if (outFence == NULL) {
ALOGE("detachNextBuffer: outFence must not be NULL");
return BAD_VALUE;
}
@@ -298,7 +301,7 @@ public:
int api, bool producerControlledByApp, QueueBufferOutput* output) {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
- if (listener != nullptr) {
+ if (listener != NULL) {
data.writeInt32(1);
data.writeStrongBinder(IInterface::asBinder(listener));
} else {
@@ -653,6 +656,79 @@ IMPLEMENT_HYBRID_META_INTERFACE(GraphicBufferProducer, HGraphicBufferProducer,
// ----------------------------------------------------------------------
+status_t IGraphicBufferProducer::exportToParcel(Parcel* parcel) {
+ status_t res = OK;
+ res = parcel->writeUint32(USE_BUFFER_QUEUE);
+ if (res != NO_ERROR) {
+ ALOGE("exportToParcel: Cannot write magic, res=%d.", res);
+ return res;
+ }
+
+ return parcel->writeStrongBinder(IInterface::asBinder(this));
+}
+
+/* static */
+status_t IGraphicBufferProducer::exportToParcel(const sp<IGraphicBufferProducer>& producer,
+ Parcel* parcel) {
+ if (parcel == nullptr) {
+ ALOGE("exportToParcel: Invalid parcel object.");
+ return BAD_VALUE;
+ }
+
+ if (producer == nullptr) {
+ status_t res = OK;
+ res = parcel->writeUint32(IGraphicBufferProducer::USE_BUFFER_QUEUE);
+ if (res != NO_ERROR) return res;
+ return parcel->writeStrongBinder(nullptr);
+ } else {
+ return producer->exportToParcel(parcel);
+ }
+}
+
+/* static */
+sp<IGraphicBufferProducer> IGraphicBufferProducer::createFromParcel(const Parcel* parcel) {
+ uint32_t outMagic = 0;
+ status_t res = NO_ERROR;
+
+ res = parcel->readUint32(&outMagic);
+ if (res != NO_ERROR) {
+ ALOGE("createFromParcel: Failed to read magic, error=%d.", res);
+ return nullptr;
+ }
+
+ switch (outMagic) {
+ case USE_BUFFER_QUEUE: {
+ sp<IBinder> binder;
+ res = parcel->readNullableStrongBinder(&binder);
+ if (res != NO_ERROR) {
+ ALOGE("createFromParcel: Can't read strong binder.");
+ return nullptr;
+ }
+ return interface_cast<IGraphicBufferProducer>(binder);
+ }
+ case USE_BUFFER_HUB: {
+ ALOGE("createFromParcel: BufferHub not implemented.");
+#ifndef NO_BUFFERHUB
+ dvr::ProducerQueueParcelable producerParcelable;
+ res = producerParcelable.readFromParcel(parcel);
+ if (res != NO_ERROR) {
+ ALOGE("createFromParcel: Failed to read from parcel, error=%d", res);
+ return nullptr;
+ }
+ return BufferHubProducer::Create(std::move(producerParcelable));
+#else
+ return nullptr;
+#endif
+ }
+ default: {
+ ALOGE("createFromParcel: Unexpected mgaic: 0x%x.", outMagic);
+ return nullptr;
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------
+
status_t BnGraphicBufferProducer::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
@@ -662,8 +738,8 @@ status_t BnGraphicBufferProducer::onTransact(
int bufferIdx = data.readInt32();
sp<GraphicBuffer> buffer;
int result = requestBuffer(bufferIdx, &buffer);
- reply->writeInt32(buffer != nullptr);
- if (buffer != nullptr) {
+ reply->writeInt32(buffer != 0);
+ if (buffer != 0) {
reply->write(*buffer);
}
reply->writeInt32(result);
@@ -721,12 +797,12 @@ status_t BnGraphicBufferProducer::onTransact(
int32_t result = detachNextBuffer(&buffer, &fence);
reply->writeInt32(result);
if (result == NO_ERROR) {
- reply->writeInt32(buffer != nullptr);
- if (buffer != nullptr) {
+ reply->writeInt32(buffer != NULL);
+ if (buffer != NULL) {
reply->write(*buffer);
}
- reply->writeInt32(fence != nullptr);
- if (fence != nullptr) {
+ reply->writeInt32(fence != NULL);
+ if (fence != NULL) {
reply->write(*fence);
}
}
@@ -951,7 +1027,8 @@ constexpr size_t IGraphicBufferProducer::QueueBufferInput::minFlattenedSize() {
size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const {
return minFlattenedSize() +
fence->getFlattenedSize() +
- surfaceDamage.getFlattenedSize();
+ surfaceDamage.getFlattenedSize() +
+ hdrMetadata.getFlattenedSize();
}
size_t IGraphicBufferProducer::QueueBufferInput::getFdCount() const {
@@ -978,7 +1055,12 @@ status_t IGraphicBufferProducer::QueueBufferInput::flatten(
if (result != NO_ERROR) {
return result;
}
- return surfaceDamage.flatten(buffer, size);
+ result = surfaceDamage.flatten(buffer, size);
+ if (result != NO_ERROR) {
+ return result;
+ }
+ FlattenableUtils::advance(buffer, size, surfaceDamage.getFlattenedSize());
+ return hdrMetadata.flatten(buffer, size);
}
status_t IGraphicBufferProducer::QueueBufferInput::unflatten(
@@ -1002,7 +1084,12 @@ status_t IGraphicBufferProducer::QueueBufferInput::unflatten(
if (result != NO_ERROR) {
return result;
}
- return surfaceDamage.unflatten(buffer, size);
+ result = surfaceDamage.unflatten(buffer, size);
+ if (result != NO_ERROR) {
+ return result;
+ }
+ FlattenableUtils::advance(buffer, size, surfaceDamage.getFlattenedSize());
+ return hdrMetadata.unflatten(buffer, size);
}
// ----------------------------------------------------------------------------
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 8e7f814313..e22bc708c9 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -29,8 +29,7 @@
#include <gui/ISurfaceComposer.h>
#include <gui/ISurfaceComposerClient.h>
#include <gui/LayerDebugInfo.h>
-
-#include <private/gui/LayerState.h>
+#include <gui/LayerState.h>
#include <system/graphics.h>
@@ -44,6 +43,8 @@
namespace android {
+using ui::ColorMode;
+
class BpSurfaceComposer : public BpInterface<ISurfaceComposer>
{
public:
@@ -101,17 +102,13 @@ public:
remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply);
}
- virtual status_t captureScreen(const sp<IBinder>& display,
- const sp<IGraphicBufferProducer>& producer,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform,
- ISurfaceComposer::Rotation rotation)
- {
+ virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
+ Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+ int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform,
+ ISurfaceComposer::Rotation rotation) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeStrongBinder(display);
- data.writeStrongBinder(IInterface::asBinder(producer));
data.write(sourceCrop);
data.writeUint32(reqWidth);
data.writeUint32(reqHeight);
@@ -119,8 +116,46 @@ public:
data.writeInt32(maxLayerZ);
data.writeInt32(static_cast<int32_t>(useIdentityTransform));
data.writeInt32(static_cast<int32_t>(rotation));
- remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply);
- return reply.readInt32();
+ status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply);
+
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ err = reply.readInt32();
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ *outBuffer = new GraphicBuffer();
+ reply.read(**outBuffer);
+ return err;
+ }
+
+ virtual status_t captureLayers(const sp<IBinder>& layerHandleBinder,
+ sp<GraphicBuffer>* outBuffer, const Rect& sourceCrop,
+ float frameScale, bool childrenOnly) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ data.writeStrongBinder(layerHandleBinder);
+ data.write(sourceCrop);
+ data.writeFloat(frameScale);
+ data.writeBool(childrenOnly);
+ status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply);
+
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ err = reply.readInt32();
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ *outBuffer = new GraphicBuffer();
+ reply.read(**outBuffer);
+
+ return err;
}
virtual bool authenticateSurfaceTexture(
@@ -317,7 +352,7 @@ public:
}
virtual status_t getDisplayColorModes(const sp<IBinder>& display,
- Vector<android_color_mode_t>* outColorModes) {
+ Vector<ColorMode>* outColorModes) {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
@@ -340,34 +375,34 @@ public:
outColorModes->clear();
outColorModes->resize(numModes);
for (size_t i = 0; i < numModes; ++i) {
- outColorModes->replaceAt(static_cast<android_color_mode_t>(reply.readInt32()), i);
+ outColorModes->replaceAt(static_cast<ColorMode>(reply.readInt32()), i);
}
}
return result;
}
- virtual android_color_mode_t getActiveColorMode(const sp<IBinder>& display) {
+ virtual ColorMode getActiveColorMode(const sp<IBinder>& display) {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
ALOGE("getActiveColorMode failed to writeInterfaceToken: %d", result);
- return static_cast<android_color_mode_t>(result);
+ return static_cast<ColorMode>(result);
}
result = data.writeStrongBinder(display);
if (result != NO_ERROR) {
ALOGE("getActiveColorMode failed to writeStrongBinder: %d", result);
- return static_cast<android_color_mode_t>(result);
+ return static_cast<ColorMode>(result);
}
result = remote()->transact(BnSurfaceComposer::GET_ACTIVE_COLOR_MODE, data, &reply);
if (result != NO_ERROR) {
ALOGE("getActiveColorMode failed to transact: %d", result);
- return static_cast<android_color_mode_t>(result);
+ return static_cast<ColorMode>(result);
}
- return static_cast<android_color_mode_t>(reply.readInt32());
+ return static_cast<ColorMode>(reply.readInt32());
}
virtual status_t setActiveColorMode(const sp<IBinder>& display,
- android_color_mode_t colorMode) {
+ ColorMode colorMode) {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
@@ -379,7 +414,7 @@ public:
ALOGE("setActiveColorMode failed to writeStrongBinder: %d", result);
return result;
}
- result = data.writeInt32(colorMode);
+ result = data.writeInt32(static_cast<int32_t>(colorMode));
if (result != NO_ERROR) {
ALOGE("setActiveColorMode failed to writeInt32: %d", result);
return result;
@@ -571,8 +606,7 @@ status_t BnSurfaceComposer::onTransact(
case CAPTURE_SCREEN: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IBinder> display = data.readStrongBinder();
- sp<IGraphicBufferProducer> producer =
- interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
+ sp<GraphicBuffer> outBuffer;
Rect sourceCrop(Rect::EMPTY_RECT);
data.read(sourceCrop);
uint32_t reqWidth = data.readUint32();
@@ -582,11 +616,30 @@ status_t BnSurfaceComposer::onTransact(
bool useIdentityTransform = static_cast<bool>(data.readInt32());
int32_t rotation = data.readInt32();
- status_t res = captureScreen(display, producer,
- sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
- useIdentityTransform,
- static_cast<ISurfaceComposer::Rotation>(rotation));
+ status_t res = captureScreen(display, &outBuffer, sourceCrop, reqWidth, reqHeight,
+ minLayerZ, maxLayerZ, useIdentityTransform,
+ static_cast<ISurfaceComposer::Rotation>(rotation));
reply->writeInt32(res);
+ if (res == NO_ERROR) {
+ reply->write(*outBuffer);
+ }
+ return NO_ERROR;
+ }
+ case CAPTURE_LAYERS: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ sp<IBinder> layerHandleBinder = data.readStrongBinder();
+ sp<GraphicBuffer> outBuffer;
+ Rect sourceCrop(Rect::EMPTY_RECT);
+ data.read(sourceCrop);
+ float frameScale = data.readFloat();
+ bool childrenOnly = data.readBool();
+
+ status_t res = captureLayers(layerHandleBinder, &outBuffer, sourceCrop, frameScale,
+ childrenOnly);
+ reply->writeInt32(res);
+ if (res == NO_ERROR) {
+ reply->write(*outBuffer);
+ }
return NO_ERROR;
}
case AUTHENTICATE_SURFACE: {
@@ -688,7 +741,7 @@ status_t BnSurfaceComposer::onTransact(
}
case GET_DISPLAY_COLOR_MODES: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
- Vector<android_color_mode_t> colorModes;
+ Vector<ColorMode> colorModes;
sp<IBinder> display = nullptr;
status_t result = data.readStrongBinder(&display);
if (result != NO_ERROR) {
@@ -700,7 +753,7 @@ status_t BnSurfaceComposer::onTransact(
if (result == NO_ERROR) {
reply->writeUint32(static_cast<uint32_t>(colorModes.size()));
for (size_t i = 0; i < colorModes.size(); ++i) {
- reply->writeInt32(colorModes[i]);
+ reply->writeInt32(static_cast<int32_t>(colorModes[i]));
}
}
return NO_ERROR;
@@ -713,7 +766,7 @@ status_t BnSurfaceComposer::onTransact(
ALOGE("getActiveColorMode failed to readStrongBinder: %d", result);
return result;
}
- android_color_mode_t colorMode = getActiveColorMode(display);
+ ColorMode colorMode = getActiveColorMode(display);
result = reply->writeInt32(static_cast<int32_t>(colorMode));
return result;
}
@@ -732,7 +785,7 @@ status_t BnSurfaceComposer::onTransact(
return result;
}
result = setActiveColorMode(display,
- static_cast<android_color_mode_t>(colorModeInt));
+ static_cast<ColorMode>(colorModeInt));
result = reply->writeInt32(result);
return result;
}
diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp
index 679f44b57b..a6890eeb19 100644
--- a/libs/gui/ISurfaceComposerClient.cpp
+++ b/libs/gui/ISurfaceComposerClient.cpp
@@ -47,8 +47,8 @@ public:
~BpSurfaceComposerClient() override;
status_t createSurface(const String8& name, uint32_t width, uint32_t height, PixelFormat format,
- uint32_t flags, const sp<IBinder>& parent, uint32_t windowType,
- uint32_t ownerUid, sp<IBinder>* handle,
+ uint32_t flags, const sp<IBinder>& parent, int32_t windowType,
+ int32_t ownerUid, sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp) override {
return callRemote<decltype(&ISurfaceComposerClient::createSurface)>(Tag::CREATE_SURFACE,
name, width, height,
diff --git a/libs/gui/LayerDebugInfo.cpp b/libs/gui/LayerDebugInfo.cpp
index 57ddde075a..d3dc16d30e 100644
--- a/libs/gui/LayerDebugInfo.cpp
+++ b/libs/gui/LayerDebugInfo.cpp
@@ -43,7 +43,10 @@ status_t LayerDebugInfo::writeToParcel(Parcel* parcel) const {
RETURN_ON_ERROR(parcel->writeInt32(mHeight));
RETURN_ON_ERROR(parcel->write(mCrop));
RETURN_ON_ERROR(parcel->write(mFinalCrop));
- RETURN_ON_ERROR(parcel->writeFloat(mAlpha));
+ RETURN_ON_ERROR(parcel->writeFloat(mColor.r));
+ RETURN_ON_ERROR(parcel->writeFloat(mColor.g));
+ RETURN_ON_ERROR(parcel->writeFloat(mColor.b));
+ RETURN_ON_ERROR(parcel->writeFloat(mColor.a));
RETURN_ON_ERROR(parcel->writeUint32(mFlags));
RETURN_ON_ERROR(parcel->writeInt32(mPixelFormat));
RETURN_ON_ERROR(parcel->writeUint32(static_cast<uint32_t>(mDataSpace)));
@@ -79,7 +82,14 @@ status_t LayerDebugInfo::readFromParcel(const Parcel* parcel) {
RETURN_ON_ERROR(parcel->readInt32(&mHeight));
RETURN_ON_ERROR(parcel->read(mCrop));
RETURN_ON_ERROR(parcel->read(mFinalCrop));
- RETURN_ON_ERROR(parcel->readFloat(&mAlpha));
+ mColor.r = parcel->readFloat();
+ RETURN_ON_ERROR(parcel->errorCheck());
+ mColor.g = parcel->readFloat();
+ RETURN_ON_ERROR(parcel->errorCheck());
+ mColor.b = parcel->readFloat();
+ RETURN_ON_ERROR(parcel->errorCheck());
+ mColor.a = parcel->readFloat();
+ RETURN_ON_ERROR(parcel->errorCheck());
RETURN_ON_ERROR(parcel->readUint32(&mFlags));
RETURN_ON_ERROR(parcel->readInt32(&mPixelFormat));
// \todo [2017-07-25 kraita]: Static casting mDataSpace pointer to an uint32 does work. Better ways?
@@ -116,8 +126,10 @@ std::string to_string(const LayerDebugInfo& info) {
result.appendFormat("isOpaque=%1d, invalidate=%1d, ", info.mIsOpaque, info.mContentDirty);
result.appendFormat("dataspace=%s, ", dataspaceDetails(info.mDataSpace).c_str());
result.appendFormat("pixelformat=%s, ", decodePixelFormat(info.mPixelFormat).c_str());
- result.appendFormat("alpha=%.3f, flags=0x%08x, ",
- static_cast<double>(info.mAlpha), info.mFlags);
+ result.appendFormat("color=(%.3f,%.3f,%.3f,%.3f), flags=0x%08x, ",
+ static_cast<double>(info.mColor.r), static_cast<double>(info.mColor.g),
+ static_cast<double>(info.mColor.b), static_cast<double>(info.mColor.a),
+ info.mFlags);
result.appendFormat("tr=[%.2f, %.2f][%.2f, %.2f]",
static_cast<double>(info.mMatrix[0][0]), static_cast<double>(info.mMatrix[0][1]),
static_cast<double>(info.mMatrix[1][0]), static_cast<double>(info.mMatrix[1][1]));
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 9b06e63610..01acc2de20 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -18,7 +18,7 @@
#include <binder/Parcel.h>
#include <gui/ISurfaceComposerClient.h>
#include <gui/IGraphicBufferProducer.h>
-#include <private/gui/LayerState.h>
+#include <gui/LayerState.h>
namespace android {
@@ -45,6 +45,10 @@ status_t layer_state_t::write(Parcel& output) const
output.writeInt32(overrideScalingMode);
output.writeStrongBinder(IInterface::asBinder(barrierGbp));
output.writeStrongBinder(relativeLayerHandle);
+ output.writeStrongBinder(parentHandleForChild);
+ output.writeFloat(color.r);
+ output.writeFloat(color.g);
+ output.writeFloat(color.b);
output.write(transparentRegion);
return NO_ERROR;
}
@@ -77,6 +81,10 @@ status_t layer_state_t::read(const Parcel& input)
barrierGbp =
interface_cast<IGraphicBufferProducer>(input.readStrongBinder());
relativeLayerHandle = input.readStrongBinder();
+ parentHandleForChild = input.readStrongBinder();
+ color.r = input.readFloat();
+ color.g = input.readFloat();
+ color.b = input.readFloat();
input.read(transparentRegion);
return NO_ERROR;
}
@@ -128,5 +136,104 @@ status_t DisplayState::read(const Parcel& input) {
return NO_ERROR;
}
+void DisplayState::merge(const DisplayState& other) {
+ if (other.what & eSurfaceChanged) {
+ what |= eSurfaceChanged;
+ surface = other.surface;
+ }
+ if (other.what & eLayerStackChanged) {
+ what |= eLayerStackChanged;
+ layerStack = other.layerStack;
+ }
+ if (other.what & eDisplayProjectionChanged) {
+ what |= eDisplayProjectionChanged;
+ orientation = other.orientation;
+ viewport = other.viewport;
+ frame = other.frame;
+ }
+ if (other.what & eDisplaySizeChanged) {
+ what |= eDisplaySizeChanged;
+ width = other.width;
+ height = other.height;
+ }
+}
+
+void layer_state_t::merge(const layer_state_t& other) {
+ if (other.what & ePositionChanged) {
+ what |= ePositionChanged;
+ x = other.x;
+ y = other.y;
+ }
+ if (other.what & eLayerChanged) {
+ what |= eLayerChanged;
+ z = other.z;
+ }
+ if (other.what & eSizeChanged) {
+ what |= eSizeChanged;
+ w = other.w;
+ h = other.h;
+ }
+ if (other.what & eAlphaChanged) {
+ what |= eAlphaChanged;
+ alpha = other.alpha;
+ }
+ if (other.what & eMatrixChanged) {
+ what |= eMatrixChanged;
+ matrix = other.matrix;
+ }
+ if (other.what & eTransparentRegionChanged) {
+ what |= eTransparentRegionChanged;
+ transparentRegion = other.transparentRegion;
+ }
+ if (other.what & eFlagsChanged) {
+ what |= eFlagsChanged;
+ flags = other.flags;
+ mask = other.mask;
+ }
+ if (other.what & eLayerStackChanged) {
+ what |= eLayerStackChanged;
+ layerStack = other.layerStack;
+ }
+ if (other.what & eCropChanged) {
+ what |= eCropChanged;
+ crop = other.crop;
+ }
+ if (other.what & eDeferTransaction) {
+ what |= eDeferTransaction;
+ barrierHandle = other.barrierHandle;
+ barrierGbp = other.barrierGbp;
+ frameNumber = other.frameNumber;
+ }
+ if (other.what & eFinalCropChanged) {
+ what |= eFinalCropChanged;
+ finalCrop = other.finalCrop;
+ }
+ if (other.what & eOverrideScalingModeChanged) {
+ what |= eOverrideScalingModeChanged;
+ overrideScalingMode = other.overrideScalingMode;
+ }
+ if (other.what & eGeometryAppliesWithResize) {
+ what |= eGeometryAppliesWithResize;
+ }
+ if (other.what & eReparentChildren) {
+ what |= eReparentChildren;
+ reparentHandle = other.reparentHandle;
+ }
+ if (other.what & eDetachChildren) {
+ what |= eDetachChildren;
+ }
+ if (other.what & eRelativeLayerChanged) {
+ what |= eRelativeLayerChanged;
+ z = other.z;
+ relativeLayerHandle = other.relativeLayerHandle;
+ }
+ if (other.what & eReparent) {
+ what |= eReparent;
+ parentHandleForChild = other.parentHandleForChild;
+ }
+ if (other.what & eDestroySurface) {
+ what |= eDestroySurface;
+ }
+}
}; // namespace android
diff --git a/libs/gui/StreamSplitter.cpp b/libs/gui/StreamSplitter.cpp
index 2f8e104ea0..52c906775e 100644
--- a/libs/gui/StreamSplitter.cpp
+++ b/libs/gui/StreamSplitter.cpp
@@ -38,11 +38,11 @@ namespace android {
status_t StreamSplitter::createSplitter(
const sp<IGraphicBufferConsumer>& inputQueue,
sp<StreamSplitter>* outSplitter) {
- if (inputQueue == nullptr) {
+ if (inputQueue == NULL) {
ALOGE("createSplitter: inputQueue must not be NULL");
return BAD_VALUE;
}
- if (outSplitter == nullptr) {
+ if (outSplitter == NULL) {
ALOGE("createSplitter: outSplitter must not be NULL");
return BAD_VALUE;
}
@@ -74,7 +74,7 @@ StreamSplitter::~StreamSplitter() {
status_t StreamSplitter::addOutput(
const sp<IGraphicBufferProducer>& outputQueue) {
- if (outputQueue == nullptr) {
+ if (outputQueue == NULL) {
ALOGE("addOutput: outputQueue must not be NULL");
return BAD_VALUE;
}
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index e55e6e415a..339bd0fa4e 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -44,6 +44,9 @@
namespace android {
+using ui::ColorMode;
+using ui::Dataspace;
+
Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp)
: mGraphicBufferProducer(bufferProducer),
mCrop(Rect::EMPTY_RECT),
@@ -78,7 +81,7 @@ Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controll
mReqFormat = 0;
mReqUsage = 0;
mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
- mDataSpace = HAL_DATASPACE_UNKNOWN;
+ mDataSpace = Dataspace::UNKNOWN;
mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
mTransform = 0;
mStickyTransform = 0;
@@ -153,7 +156,7 @@ status_t Surface::getDisplayRefreshCycleDuration(nsecs_t* outRefreshDuration) {
ATRACE_CALL();
DisplayStatInfo stats;
- status_t result = composerService()->getDisplayStats(nullptr, &stats);
+ status_t result = composerService()->getDisplayStats(NULL, &stats);
if (result != NO_ERROR) {
return result;
}
@@ -326,7 +329,7 @@ status_t Surface::getWideColorSupport(bool* supported) {
sp<IBinder> display(
composerService()->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
- Vector<android_color_mode_t> colorModes;
+ Vector<ColorMode> colorModes;
status_t err =
composerService()->getDisplayColorModes(display, &colorModes);
@@ -338,11 +341,11 @@ status_t Surface::getWideColorSupport(bool* supported) {
&ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
*supported = false;
- for (android_color_mode_t colorMode : colorModes) {
+ for (ColorMode colorMode : colorModes) {
switch (colorMode) {
- case HAL_COLOR_MODE_DISPLAY_P3:
- case HAL_COLOR_MODE_ADOBE_RGB:
- case HAL_COLOR_MODE_DCI_P3:
+ case ColorMode::DISPLAY_P3:
+ case ColorMode::ADOBE_RGB:
+ case ColorMode::DCI_P3:
if (wideColorBoardConfig) {
*supported = true;
}
@@ -494,7 +497,7 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
if (mSharedBufferMode && mAutoRefresh && mSharedBufferSlot !=
BufferItem::INVALID_BUFFER_SLOT) {
sp<GraphicBuffer>& gbuf(mSlots[mSharedBufferSlot].buffer);
- if (gbuf != nullptr) {
+ if (gbuf != NULL) {
*buffer = gbuf.get();
*fenceFd = -1;
return OK;
@@ -534,7 +537,7 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
// this should never happen
- ALOGE_IF(fence == nullptr, "Surface::dequeueBuffer: received null Fence! buf=%d", buf);
+ ALOGE_IF(fence == NULL, "Surface::dequeueBuffer: received null Fence! buf=%d", buf);
if (result & IGraphicBufferProducer::RELEASE_ALL_BUFFERS) {
freeAllBuffers();
@@ -612,7 +615,7 @@ int Surface::cancelBuffer(android_native_buffer_t* buffer,
int Surface::getSlotFromBufferLocked(
android_native_buffer_t* buffer) const {
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- if (mSlots[i].buffer != nullptr &&
+ if (mSlots[i].buffer != NULL &&
mSlots[i].buffer->handle == buffer->handle) {
return i;
}
@@ -664,8 +667,12 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
IGraphicBufferProducer::QueueBufferOutput output;
IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp,
- mDataSpace, crop, mScalingMode, mTransform ^ mStickyTransform,
- fence, mStickyTransform, mEnableFrameTimestamps);
+ static_cast<android_dataspace>(mDataSpace), crop, mScalingMode,
+ mTransform ^ mStickyTransform, fence, mStickyTransform,
+ mEnableFrameTimestamps);
+
+ // we should send HDR metadata as needed if this becomes a bottleneck
+ input.setHdrMetadata(mHdrMetadata);
if (mConnectedToCpu || mDirtyRegion.bounds() == Rect::INVALID_RECT) {
input.setSurfaceDamage(Region::INVALID_REGION);
@@ -878,6 +885,10 @@ int Surface::query(int what, int* value) const {
*value = mGraphicBufferProducer != nullptr ? 1 : 0;
return NO_ERROR;
}
+ case NATIVE_WINDOW_DATASPACE: {
+ *value = static_cast<int>(mDataSpace);
+ return NO_ERROR;
+ }
}
}
return mGraphicBufferProducer->query(what, value);
@@ -944,6 +955,12 @@ int Surface::perform(int operation, va_list args)
case NATIVE_WINDOW_SET_BUFFERS_DATASPACE:
res = dispatchSetBuffersDataSpace(args);
break;
+ case NATIVE_WINDOW_SET_BUFFERS_SMPTE2086_METADATA:
+ res = dispatchSetBuffersSmpte2086Metadata(args);
+ break;
+ case NATIVE_WINDOW_SET_BUFFERS_CTA861_3_METADATA:
+ res = dispatchSetBuffersCta8613Metadata(args);
+ break;
case NATIVE_WINDOW_SET_SURFACE_DAMAGE:
res = dispatchSetSurfaceDamage(args);
break;
@@ -1083,11 +1100,22 @@ int Surface::dispatchSetSidebandStream(va_list args) {
}
int Surface::dispatchSetBuffersDataSpace(va_list args) {
- android_dataspace dataspace =
- static_cast<android_dataspace>(va_arg(args, int));
+ Dataspace dataspace = static_cast<Dataspace>(va_arg(args, int));
return setBuffersDataSpace(dataspace);
}
+int Surface::dispatchSetBuffersSmpte2086Metadata(va_list args) {
+ const android_smpte2086_metadata* metadata =
+ va_arg(args, const android_smpte2086_metadata*);
+ return setBuffersSmpte2086Metadata(metadata);
+}
+
+int Surface::dispatchSetBuffersCta8613Metadata(va_list args) {
+ const android_cta861_3_metadata* metadata =
+ va_arg(args, const android_cta861_3_metadata*);
+ return setBuffersCta8613Metadata(metadata);
+}
+
int Surface::dispatchSetSurfaceDamage(va_list args) {
android_native_rect_t* rects = va_arg(args, android_native_rect_t*);
size_t numRects = va_arg(args, size_t);
@@ -1236,7 +1264,7 @@ int Surface::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
ATRACE_CALL();
ALOGV("Surface::detachNextBuffer");
- if (outBuffer == nullptr || outFence == nullptr) {
+ if (outBuffer == NULL || outFence == NULL) {
return BAD_VALUE;
}
@@ -1245,8 +1273,8 @@ int Surface::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
mRemovedBuffers.clear();
}
- sp<GraphicBuffer> buffer(nullptr);
- sp<Fence> fence(nullptr);
+ sp<GraphicBuffer> buffer(NULL);
+ sp<Fence> fence(NULL);
status_t result = mGraphicBufferProducer->detachNextBuffer(
&buffer, &fence);
if (result != NO_ERROR) {
@@ -1254,19 +1282,19 @@ int Surface::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
}
*outBuffer = buffer;
- if (fence != nullptr && fence->isValid()) {
+ if (fence != NULL && fence->isValid()) {
*outFence = fence;
} else {
*outFence = Fence::NO_FENCE;
}
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- if (mSlots[i].buffer != nullptr &&
+ if (mSlots[i].buffer != NULL &&
mSlots[i].buffer->getId() == buffer->getId()) {
if (mReportRemovedBuffers) {
mRemovedBuffers.push_back(mSlots[i].buffer);
}
- mSlots[i].buffer = nullptr;
+ mSlots[i].buffer = NULL;
}
}
@@ -1317,7 +1345,7 @@ int Surface::setCrop(Rect const* rect)
ATRACE_CALL();
Rect realRect(Rect::EMPTY_RECT);
- if (rect == nullptr || rect->isEmpty()) {
+ if (rect == NULL || rect->isEmpty()) {
realRect.clear();
} else {
realRect = *rect;
@@ -1504,7 +1532,7 @@ int Surface::setBuffersTimestamp(int64_t timestamp)
return NO_ERROR;
}
-int Surface::setBuffersDataSpace(android_dataspace dataSpace)
+int Surface::setBuffersDataSpace(Dataspace dataSpace)
{
ALOGV("Surface::setBuffersDataSpace");
Mutex::Autolock lock(mMutex);
@@ -1512,9 +1540,39 @@ int Surface::setBuffersDataSpace(android_dataspace dataSpace)
return NO_ERROR;
}
+int Surface::setBuffersSmpte2086Metadata(const android_smpte2086_metadata* metadata) {
+ ALOGV("Surface::setBuffersSmpte2086Metadata");
+ Mutex::Autolock lock(mMutex);
+ if (metadata) {
+ mHdrMetadata.smpte2086 = *metadata;
+ mHdrMetadata.validTypes |= HdrMetadata::SMPTE2086;
+ } else {
+ mHdrMetadata.validTypes &= ~HdrMetadata::SMPTE2086;
+ }
+ return NO_ERROR;
+}
+
+int Surface::setBuffersCta8613Metadata(const android_cta861_3_metadata* metadata) {
+ ALOGV("Surface::setBuffersCta8613Metadata");
+ Mutex::Autolock lock(mMutex);
+ if (metadata) {
+ mHdrMetadata.cta8613 = *metadata;
+ mHdrMetadata.validTypes |= HdrMetadata::CTA861_3;
+ } else {
+ mHdrMetadata.validTypes &= ~HdrMetadata::CTA861_3;
+ }
+ return NO_ERROR;
+}
+
+Dataspace Surface::getBuffersDataSpace() {
+ ALOGV("Surface::getBuffersDataSpace");
+ Mutex::Autolock lock(mMutex);
+ return mDataSpace;
+}
+
void Surface::freeAllBuffers() {
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- mSlots[i].buffer = nullptr;
+ mSlots[i].buffer = 0;
}
}
@@ -1554,12 +1612,12 @@ static status_t copyBlt(
// src and dst with, height and format must be identical. no verification
// is done here.
status_t err;
- uint8_t* src_bits = nullptr;
+ uint8_t* src_bits = NULL;
err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(),
reinterpret_cast<void**>(&src_bits));
ALOGE_IF(err, "error locking src buffer %s", strerror(-err));
- uint8_t* dst_bits = nullptr;
+ uint8_t* dst_bits = NULL;
err = dst->lockAsync(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(),
reinterpret_cast<void**>(&dst_bits), *dstFenceFd);
ALOGE_IF(err, "error locking dst buffer %s", strerror(-err));
@@ -1607,7 +1665,7 @@ static status_t copyBlt(
status_t Surface::lock(
ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)
{
- if (mLockedBuffer != nullptr) {
+ if (mLockedBuffer != 0) {
ALOGE("Surface::lock failed, already locked");
return INVALID_OPERATION;
}
@@ -1639,7 +1697,7 @@ status_t Surface::lock(
// figure out if we can copy the frontbuffer back
const sp<GraphicBuffer>& frontBuffer(mPostedBuffer);
- const bool canCopyBack = (frontBuffer != nullptr &&
+ const bool canCopyBack = (frontBuffer != 0 &&
backBuffer->width == frontBuffer->width &&
backBuffer->height == frontBuffer->height &&
backBuffer->format == frontBuffer->format);
@@ -1701,7 +1759,7 @@ status_t Surface::lock(
status_t Surface::unlockAndPost()
{
- if (mLockedBuffer == nullptr) {
+ if (mLockedBuffer == 0) {
ALOGE("Surface::unlockAndPost failed, no locked buffer");
return INVALID_OPERATION;
}
@@ -1715,7 +1773,7 @@ status_t Surface::unlockAndPost()
mLockedBuffer->handle, strerror(-err));
mPostedBuffer = mLockedBuffer;
- mLockedBuffer = nullptr;
+ mLockedBuffer = 0;
return err;
}
@@ -1754,4 +1812,25 @@ status_t Surface::getAndFlushRemovedBuffers(std::vector<sp<GraphicBuffer>>* out)
return OK;
}
+status_t Surface::attachAndQueueBuffer(Surface* surface, sp<GraphicBuffer> buffer) {
+ if (buffer == nullptr) {
+ return BAD_VALUE;
+ }
+ int err = static_cast<ANativeWindow*>(surface)->perform(surface, NATIVE_WINDOW_API_CONNECT,
+ NATIVE_WINDOW_API_CPU);
+ if (err != OK) {
+ return err;
+ }
+ err = surface->attachBuffer(buffer->getNativeBuffer());
+ if (err != OK) {
+ return err;
+ }
+ err = static_cast<ANativeWindow*>(surface)->queueBuffer(surface, buffer->getNativeBuffer(), -1);
+ if (err != OK) {
+ return err;
+ }
+ err = surface->disconnect(NATIVE_WINDOW_API_CPU);
+ return err;
+}
+
}; // namespace android
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 053b9afb86..63560c4b89 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -21,7 +21,6 @@
#include <utils/Errors.h>
#include <utils/Log.h>
-#include <utils/Singleton.h>
#include <utils/SortedVector.h>
#include <utils/String8.h>
#include <utils/threads.h>
@@ -37,13 +36,15 @@
#include <gui/IGraphicBufferProducer.h>
#include <gui/ISurfaceComposer.h>
#include <gui/ISurfaceComposerClient.h>
+#include <gui/LayerState.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <private/gui/ComposerService.h>
-#include <private/gui/LayerState.h>
namespace android {
+
+using ui::ColorMode;
// ---------------------------------------------------------------------------
ANDROID_SINGLETON_STATIC_INSTANCE(ComposerService);
@@ -80,7 +81,7 @@ void ComposerService::connectLocked() {
/*static*/ sp<ISurfaceComposer> ComposerService::getComposerService() {
ComposerService& instance = ComposerService::getInstance();
Mutex::Autolock _l(instance.mLock);
- if (instance.mComposerService == nullptr) {
+ if (instance.mComposerService == NULL) {
ComposerService::getInstance().connectLocked();
assert(instance.mComposerService != NULL);
ALOGD("ComposerService reconnected");
@@ -91,239 +92,150 @@ void ComposerService::connectLocked() {
void ComposerService::composerServiceDied()
{
Mutex::Autolock _l(mLock);
- mComposerService = nullptr;
- mDeathObserver = nullptr;
+ mComposerService = NULL;
+ mDeathObserver = NULL;
}
// ---------------------------------------------------------------------------
-static inline
-int compare_type(const ComposerState& lhs, const ComposerState& rhs) {
- if (lhs.client < rhs.client) return -1;
- if (lhs.client > rhs.client) return 1;
- if (lhs.state.surface < rhs.state.surface) return -1;
- if (lhs.state.surface > rhs.state.surface) return 1;
- return 0;
-}
-
-static inline
-int compare_type(const DisplayState& lhs, const DisplayState& rhs) {
- return compare_type(lhs.token, rhs.token);
-}
-
-class Composer : public Singleton<Composer>
-{
- friend class Singleton<Composer>;
-
- mutable Mutex mLock;
- SortedVector<ComposerState> mComposerStates;
- SortedVector<DisplayState > mDisplayStates;
- uint32_t mForceSynchronous;
- uint32_t mTransactionNestCount;
- bool mAnimation;
-
- Composer() : Singleton<Composer>(),
- mForceSynchronous(0), mTransactionNestCount(0),
- mAnimation(false)
- { }
-
- void openGlobalTransactionImpl();
- void closeGlobalTransactionImpl(bool synchronous);
- void setAnimationTransactionImpl();
- status_t enableVSyncInjectionsImpl(bool enable);
- status_t injectVSyncImpl(nsecs_t when);
-
- layer_state_t* getLayerStateLocked(
- const sp<SurfaceComposerClient>& client, const sp<IBinder>& id);
-
- DisplayState& getDisplayStateLocked(const sp<IBinder>& token);
-
-public:
- sp<IBinder> createDisplay(const String8& displayName, bool secure);
- void destroyDisplay(const sp<IBinder>& display);
- sp<IBinder> getBuiltInDisplay(int32_t id);
-
- status_t setPosition(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
- float x, float y);
- status_t setSize(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
- uint32_t w, uint32_t h);
- status_t setLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
- int32_t z);
- status_t setRelativeLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
- const sp<IBinder>& relativeTo, int32_t z);
- status_t setFlags(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
- uint32_t flags, uint32_t mask);
- status_t setTransparentRegionHint(
- const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
- const Region& transparentRegion);
- status_t setAlpha(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
- float alpha);
- status_t setMatrix(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
- float dsdx, float dtdx, float dtdy, float dsdy);
- status_t setOrientation(int orientation);
- status_t setCrop(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
- const Rect& crop);
- status_t setFinalCrop(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, const Rect& crop);
- status_t setLayerStack(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, uint32_t layerStack);
- status_t deferTransactionUntil(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, const sp<IBinder>& handle,
- uint64_t frameNumber);
- status_t deferTransactionUntil(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, const sp<Surface>& barrierSurface,
- uint64_t frameNumber);
- status_t reparentChildren(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id,
- const sp<IBinder>& newParentHandle);
- status_t detachChildren(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id);
- status_t setOverrideScalingMode(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, int32_t overrideScalingMode);
- status_t setGeometryAppliesWithResize(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id);
-
- status_t setDisplaySurface(const sp<IBinder>& token,
- sp<IGraphicBufferProducer> bufferProducer);
- void setDisplayLayerStack(const sp<IBinder>& token, uint32_t layerStack);
- void setDisplayProjection(const sp<IBinder>& token,
- uint32_t orientation,
- const Rect& layerStackRect,
- const Rect& displayRect);
- void setDisplaySize(const sp<IBinder>& token, uint32_t width, uint32_t height);
-
- static void setAnimationTransaction() {
- Composer::getInstance().setAnimationTransactionImpl();
- }
-
- static void openGlobalTransaction() {
- Composer::getInstance().openGlobalTransactionImpl();
+SurfaceComposerClient::Transaction::Transaction(const Transaction& other) :
+ mForceSynchronous(other.mForceSynchronous),
+ mTransactionNestCount(other.mTransactionNestCount),
+ mAnimation(other.mAnimation),
+ mEarlyWakeup(other.mEarlyWakeup) {
+ mDisplayStates = other.mDisplayStates;
+ mComposerStates = other.mComposerStates;
+}
+
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Transaction&& other) {
+ for (auto const& kv : other.mComposerStates) {
+ if (mComposerStates.count(kv.first) == 0) {
+ mComposerStates[kv.first] = kv.second;
+ } else {
+ mComposerStates[kv.first].state.merge(kv.second.state);
+ }
}
+ other.mComposerStates.clear();
- static void closeGlobalTransaction(bool synchronous) {
- Composer::getInstance().closeGlobalTransactionImpl(synchronous);
+ for (auto const& state : other.mDisplayStates) {
+ ssize_t index = mDisplayStates.indexOf(state);
+ if (index < 0) {
+ mDisplayStates.add(state);
+ } else {
+ mDisplayStates.editItemAt(static_cast<size_t>(index)).merge(state);
+ }
}
+ other.mDisplayStates.clear();
- static status_t enableVSyncInjections(bool enable) {
- return Composer::getInstance().enableVSyncInjectionsImpl(enable);
- }
+ return *this;
+}
- static status_t injectVSync(nsecs_t when) {
- return Composer::getInstance().injectVSyncImpl(when);
+status_t SurfaceComposerClient::Transaction::apply(bool synchronous) {
+ if (mStatus != NO_ERROR) {
+ return mStatus;
}
-};
-
-ANDROID_SINGLETON_STATIC_INSTANCE(Composer);
-
-// ---------------------------------------------------------------------------
-sp<IBinder> Composer::createDisplay(const String8& displayName, bool secure) {
- return ComposerService::getComposerService()->createDisplay(displayName,
- secure);
-}
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
-void Composer::destroyDisplay(const sp<IBinder>& display) {
- return ComposerService::getComposerService()->destroyDisplay(display);
-}
+ Vector<ComposerState> composerStates;
+ Vector<DisplayState> displayStates;
+ uint32_t flags = 0;
-sp<IBinder> Composer::getBuiltInDisplay(int32_t id) {
- return ComposerService::getComposerService()->getBuiltInDisplay(id);
-}
+ mForceSynchronous |= synchronous;
-void Composer::openGlobalTransactionImpl() {
- { // scope for the lock
- Mutex::Autolock _l(mLock);
- mTransactionNestCount += 1;
+ for (auto const& kv : mComposerStates){
+ composerStates.add(kv.second);
}
-}
-void Composer::closeGlobalTransactionImpl(bool synchronous) {
- sp<ISurfaceComposer> sm(ComposerService::getComposerService());
-
- Vector<ComposerState> transaction;
- Vector<DisplayState> displayTransaction;
- uint32_t flags = 0;
+ mComposerStates.clear();
- { // scope for the lock
- Mutex::Autolock _l(mLock);
- mForceSynchronous |= synchronous;
- if (!mTransactionNestCount) {
- ALOGW("At least one call to closeGlobalTransaction() was not matched by a prior "
- "call to openGlobalTransaction().");
- } else if (--mTransactionNestCount) {
- return;
- }
+ displayStates = mDisplayStates;
+ mDisplayStates.clear();
- transaction = mComposerStates;
- mComposerStates.clear();
+ if (mForceSynchronous) {
+ flags |= ISurfaceComposer::eSynchronous;
+ }
+ if (mAnimation) {
+ flags |= ISurfaceComposer::eAnimation;
+ }
+ if (mEarlyWakeup) {
+ flags |= ISurfaceComposer::eEarlyWakeup;
+ }
- displayTransaction = mDisplayStates;
- mDisplayStates.clear();
+ mForceSynchronous = false;
+ mAnimation = false;
+ mEarlyWakeup = false;
- if (mForceSynchronous) {
- flags |= ISurfaceComposer::eSynchronous;
- }
- if (mAnimation) {
- flags |= ISurfaceComposer::eAnimation;
- }
+ sf->setTransactionState(composerStates, displayStates, flags);
+ mStatus = NO_ERROR;
+ return NO_ERROR;
+}
- mForceSynchronous = false;
- mAnimation = false;
- }
+// ---------------------------------------------------------------------------
- sm->setTransactionState(transaction, displayTransaction, flags);
+sp<IBinder> SurfaceComposerClient::createDisplay(const String8& displayName, bool secure) {
+ return ComposerService::getComposerService()->createDisplay(displayName,
+ secure);
}
-status_t Composer::enableVSyncInjectionsImpl(bool enable) {
- sp<ISurfaceComposer> sm(ComposerService::getComposerService());
- return sm->enableVSyncInjections(enable);
+void SurfaceComposerClient::destroyDisplay(const sp<IBinder>& display) {
+ return ComposerService::getComposerService()->destroyDisplay(display);
}
-status_t Composer::injectVSyncImpl(nsecs_t when) {
- sp<ISurfaceComposer> sm(ComposerService::getComposerService());
- return sm->injectVSync(when);
+sp<IBinder> SurfaceComposerClient::getBuiltInDisplay(int32_t id) {
+ return ComposerService::getComposerService()->getBuiltInDisplay(id);
}
-void Composer::setAnimationTransactionImpl() {
- Mutex::Autolock _l(mLock);
+void SurfaceComposerClient::Transaction::setAnimationTransaction() {
mAnimation = true;
}
-layer_state_t* Composer::getLayerStateLocked(
- const sp<SurfaceComposerClient>& client, const sp<IBinder>& id) {
-
- ComposerState s;
- s.client = client->mClient;
- s.state.surface = id;
+void SurfaceComposerClient::Transaction::setEarlyWakeup() {
+ mEarlyWakeup = true;
+}
- ssize_t index = mComposerStates.indexOf(s);
- if (index < 0) {
+layer_state_t* SurfaceComposerClient::Transaction::getLayerState(const sp<SurfaceControl>& sc) {
+ if (mComposerStates.count(sc) == 0) {
// we don't have it, add an initialized layer_state to our list
- index = mComposerStates.add(s);
+ ComposerState s;
+ s.client = sc->getClient()->mClient;
+ s.state.surface = sc->getHandle();
+ mComposerStates[sc] = s;
}
- ComposerState* const out = mComposerStates.editArray();
- return &(out[index].state);
+ return &(mComposerStates[sc].state);
}
-status_t Composer::setPosition(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, float x, float y) {
- Mutex::Autolock _l(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
- if (!s)
- return BAD_INDEX;
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setPosition(
+ const sp<SurfaceControl>& sc, float x, float y) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
s->what |= layer_state_t::ePositionChanged;
s->x = x;
s->y = y;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::setSize(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, uint32_t w, uint32_t h) {
- Mutex::Autolock _l(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
- if (!s)
- return BAD_INDEX;
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::show(
+ const sp<SurfaceControl>& sc) {
+ return setFlags(sc, 0, layer_state_t::eLayerHidden);
+}
+
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::hide(
+ const sp<SurfaceControl>& sc) {
+ return setFlags(sc, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden);
+}
+
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSize(
+ const sp<SurfaceControl>& sc, uint32_t w, uint32_t h) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
s->what |= layer_state_t::eSizeChanged;
s->w = w;
s->h = h;
@@ -331,41 +243,41 @@ status_t Composer::setSize(const sp<SurfaceComposerClient>& client,
// Resizing a surface makes the transaction synchronous.
mForceSynchronous = true;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::setLayer(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, int32_t z) {
- Mutex::Autolock _l(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
- if (!s)
- return BAD_INDEX;
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLayer(
+ const sp<SurfaceControl>& sc, int32_t z) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
s->what |= layer_state_t::eLayerChanged;
s->z = z;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::setRelativeLayer(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, const sp<IBinder>& relativeTo,
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setRelativeLayer(const sp<SurfaceControl>& sc, const sp<IBinder>& relativeTo,
int32_t z) {
- Mutex::Autolock _l(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
+ layer_state_t* s = getLayerState(sc);
if (!s) {
- return BAD_INDEX;
+ mStatus = BAD_INDEX;
}
s->what |= layer_state_t::eRelativeLayerChanged;
s->relativeLayerHandle = relativeTo;
s->z = z;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::setFlags(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, uint32_t flags,
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFlags(
+ const sp<SurfaceControl>& sc, uint32_t flags,
uint32_t mask) {
- Mutex::Autolock _l(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
- if (!s)
- return BAD_INDEX;
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
if ((mask & layer_state_t::eLayerOpaque) ||
(mask & layer_state_t::eLayerHidden) ||
(mask & layer_state_t::eLayerSecure)) {
@@ -374,50 +286,54 @@ status_t Composer::setFlags(const sp<SurfaceComposerClient>& client,
s->flags &= ~mask;
s->flags |= (flags & mask);
s->mask |= mask;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::setTransparentRegionHint(
- const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setTransparentRegionHint(
+ const sp<SurfaceControl>& sc,
const Region& transparentRegion) {
- Mutex::Autolock _l(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
- if (!s)
- return BAD_INDEX;
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
s->what |= layer_state_t::eTransparentRegionChanged;
s->transparentRegion = transparentRegion;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::setAlpha(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, float alpha) {
- Mutex::Autolock _l(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
- if (!s)
- return BAD_INDEX;
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAlpha(
+ const sp<SurfaceControl>& sc, float alpha) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
s->what |= layer_state_t::eAlphaChanged;
s->alpha = alpha;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::setLayerStack(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, uint32_t layerStack) {
- Mutex::Autolock _l(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
- if (!s)
- return BAD_INDEX;
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLayerStack(
+ const sp<SurfaceControl>& sc, uint32_t layerStack) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
s->what |= layer_state_t::eLayerStackChanged;
s->layerStack = layerStack;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::setMatrix(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, float dsdx, float dtdx,
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setMatrix(
+ const sp<SurfaceControl>& sc, float dsdx, float dtdx,
float dtdy, float dsdy) {
- Mutex::Autolock _l(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
- if (!s)
- return BAD_INDEX;
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
s->what |= layer_state_t::eMatrixChanged;
layer_state_t::matrix22_t matrix;
matrix.dsdx = dsdx;
@@ -425,93 +341,115 @@ status_t Composer::setMatrix(const sp<SurfaceComposerClient>& client,
matrix.dsdy = dsdy;
matrix.dtdy = dtdy;
s->matrix = matrix;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::setCrop(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, const Rect& crop) {
- Mutex::Autolock _l(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
- if (!s)
- return BAD_INDEX;
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCrop(
+ const sp<SurfaceControl>& sc, const Rect& crop) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
s->what |= layer_state_t::eCropChanged;
s->crop = crop;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::setFinalCrop(const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, const Rect& crop) {
- Mutex::Autolock _l(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFinalCrop(const sp<SurfaceControl>& sc, const Rect& crop) {
+ layer_state_t* s = getLayerState(sc);
if (!s) {
- return BAD_INDEX;
+ mStatus = BAD_INDEX;
+ return *this;
}
s->what |= layer_state_t::eFinalCropChanged;
s->finalCrop = crop;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::deferTransactionUntil(
- const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::deferTransactionUntil(
+ const sp<SurfaceControl>& sc,
const sp<IBinder>& handle, uint64_t frameNumber) {
- Mutex::Autolock lock(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
+ layer_state_t* s = getLayerState(sc);
if (!s) {
- return BAD_INDEX;
+ mStatus = BAD_INDEX;
+ return *this;
}
s->what |= layer_state_t::eDeferTransaction;
s->barrierHandle = handle;
s->frameNumber = frameNumber;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::deferTransactionUntil(
- const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::deferTransactionUntil(
+ const sp<SurfaceControl>& sc,
const sp<Surface>& barrierSurface, uint64_t frameNumber) {
- Mutex::Autolock lock(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
+ layer_state_t* s = getLayerState(sc);
if (!s) {
- return BAD_INDEX;
+ mStatus = BAD_INDEX;
+ return *this;
}
s->what |= layer_state_t::eDeferTransaction;
s->barrierGbp = barrierSurface->getIGraphicBufferProducer();
s->frameNumber = frameNumber;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::reparentChildren(
- const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id,
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::reparentChildren(
+ const sp<SurfaceControl>& sc,
const sp<IBinder>& newParentHandle) {
- Mutex::Autolock lock(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
+ layer_state_t* s = getLayerState(sc);
if (!s) {
- return BAD_INDEX;
+ mStatus = BAD_INDEX;
+ return *this;
}
s->what |= layer_state_t::eReparentChildren;
s->reparentHandle = newParentHandle;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::detachChildren(
- const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id) {
- Mutex::Autolock lock(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::reparent(
+ const sp<SurfaceControl>& sc,
+ const sp<IBinder>& newParentHandle) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+ s->what |= layer_state_t::eReparent;
+ s->parentHandleForChild = newParentHandle;
+ return *this;
+}
+
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColor(
+ const sp<SurfaceControl>& sc,
+ const half3& color) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+ s->what |= layer_state_t::eColorChanged;
+ s->color = color;
+ return *this;
+}
+
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::detachChildren(
+ const sp<SurfaceControl>& sc) {
+ layer_state_t* s = getLayerState(sc);
if (!s) {
- return BAD_INDEX;
+ mStatus = BAD_INDEX;
}
s->what |= layer_state_t::eDetachChildren;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::setOverrideScalingMode(
- const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id, int32_t overrideScalingMode) {
- Mutex::Autolock lock(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setOverrideScalingMode(
+ const sp<SurfaceControl>& sc, int32_t overrideScalingMode) {
+ layer_state_t* s = getLayerState(sc);
if (!s) {
- return BAD_INDEX;
+ mStatus = BAD_INDEX;
+ return *this;
}
switch (overrideScalingMode) {
@@ -524,29 +462,40 @@ status_t Composer::setOverrideScalingMode(
default:
ALOGE("unknown scaling mode: %d",
overrideScalingMode);
- return BAD_VALUE;
+ mStatus = BAD_VALUE;
+ return *this;
}
s->what |= layer_state_t::eOverrideScalingModeChanged;
s->overrideScalingMode = overrideScalingMode;
- return NO_ERROR;
+ return *this;
}
-status_t Composer::setGeometryAppliesWithResize(
- const sp<SurfaceComposerClient>& client,
- const sp<IBinder>& id) {
- Mutex::Autolock lock(mLock);
- layer_state_t* s = getLayerStateLocked(client, id);
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setGeometryAppliesWithResize(
+ const sp<SurfaceControl>& sc) {
+ layer_state_t* s = getLayerState(sc);
if (!s) {
- return BAD_INDEX;
+ mStatus = BAD_INDEX;
+ return *this;
}
s->what |= layer_state_t::eGeometryAppliesWithResize;
- return NO_ERROR;
+ return *this;
+}
+
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::destroySurface(
+ const sp<SurfaceControl>& sc) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+ s->what |= layer_state_t::eDestroySurface;
+ return *this;
}
// ---------------------------------------------------------------------------
-DisplayState& Composer::getDisplayStateLocked(const sp<IBinder>& token) {
+DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp<IBinder>& token) {
DisplayState s;
s.token = token;
ssize_t index = mDisplayStates.indexOf(s);
@@ -558,8 +507,8 @@ DisplayState& Composer::getDisplayStateLocked(const sp<IBinder>& token) {
return mDisplayStates.editItemAt(static_cast<size_t>(index));
}
-status_t Composer::setDisplaySurface(const sp<IBinder>& token,
- sp<IGraphicBufferProducer> bufferProducer) {
+status_t SurfaceComposerClient::Transaction::setDisplaySurface(const sp<IBinder>& token,
+ const sp<IGraphicBufferProducer>& bufferProducer) {
if (bufferProducer.get() != nullptr) {
// Make sure that composition can never be stalled by a virtual display
// consumer that isn't processing buffers fast enough.
@@ -571,27 +520,24 @@ status_t Composer::setDisplaySurface(const sp<IBinder>& token,
return err;
}
}
- Mutex::Autolock _l(mLock);
- DisplayState& s(getDisplayStateLocked(token));
+ DisplayState& s(getDisplayState(token));
s.surface = bufferProducer;
s.what |= DisplayState::eSurfaceChanged;
return NO_ERROR;
}
-void Composer::setDisplayLayerStack(const sp<IBinder>& token,
+void SurfaceComposerClient::Transaction::setDisplayLayerStack(const sp<IBinder>& token,
uint32_t layerStack) {
- Mutex::Autolock _l(mLock);
- DisplayState& s(getDisplayStateLocked(token));
+ DisplayState& s(getDisplayState(token));
s.layerStack = layerStack;
s.what |= DisplayState::eLayerStackChanged;
}
-void Composer::setDisplayProjection(const sp<IBinder>& token,
+void SurfaceComposerClient::Transaction::setDisplayProjection(const sp<IBinder>& token,
uint32_t orientation,
const Rect& layerStackRect,
const Rect& displayRect) {
- Mutex::Autolock _l(mLock);
- DisplayState& s(getDisplayStateLocked(token));
+ DisplayState& s(getDisplayState(token));
s.orientation = orientation;
s.viewport = layerStackRect;
s.frame = displayRect;
@@ -599,9 +545,8 @@ void Composer::setDisplayProjection(const sp<IBinder>& token,
mForceSynchronous = true; // TODO: do we actually still need this?
}
-void Composer::setDisplaySize(const sp<IBinder>& token, uint32_t width, uint32_t height) {
- Mutex::Autolock _l(mLock);
- DisplayState& s(getDisplayStateLocked(token));
+void SurfaceComposerClient::Transaction::setDisplaySize(const sp<IBinder>& token, uint32_t width, uint32_t height) {
+ DisplayState& s(getDisplayState(token));
s.width = width;
s.height = height;
s.what |= DisplayState::eDisplaySizeChanged;
@@ -610,23 +555,28 @@ void Composer::setDisplaySize(const sp<IBinder>& token, uint32_t width, uint32_t
// ---------------------------------------------------------------------------
SurfaceComposerClient::SurfaceComposerClient()
- : mStatus(NO_INIT), mComposer(Composer::getInstance())
+ : mStatus(NO_INIT)
{
}
SurfaceComposerClient::SurfaceComposerClient(const sp<IGraphicBufferProducer>& root)
- : mStatus(NO_INIT), mComposer(Composer::getInstance()), mParent(root)
+ : mStatus(NO_INIT), mParent(root)
+{
+}
+
+SurfaceComposerClient::SurfaceComposerClient(const sp<ISurfaceComposerClient>& client)
+ : mStatus(NO_ERROR), mClient(client)
{
}
void SurfaceComposerClient::onFirstRef() {
- sp<ISurfaceComposer> sm(ComposerService::getComposerService());
- if (sm != nullptr) {
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ if (sf != 0 && mStatus == NO_INIT) {
auto rootProducer = mParent.promote();
sp<ISurfaceComposerClient> conn;
- conn = (rootProducer != nullptr) ? sm->createScopedConnection(rootProducer) :
- sm->createConnection();
- if (conn != nullptr) {
+ conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
+ sf->createConnection();
+ if (conn != 0) {
mClient = conn;
mStatus = NO_ERROR;
}
@@ -648,15 +598,15 @@ sp<IBinder> SurfaceComposerClient::connection() const {
status_t SurfaceComposerClient::linkToComposerDeath(
const sp<IBinder::DeathRecipient>& recipient,
void* cookie, uint32_t flags) {
- sp<ISurfaceComposer> sm(ComposerService::getComposerService());
- return IInterface::asBinder(sm)->linkToDeath(recipient, cookie, flags);
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ return IInterface::asBinder(sf)->linkToDeath(recipient, cookie, flags);
}
void SurfaceComposerClient::dispose() {
// this can be called more than once.
sp<ISurfaceComposerClient> client;
Mutex::Autolock _lm(mLock);
- if (mClient != nullptr) {
+ if (mClient != 0) {
client = mClient; // hold ref while lock is held
mClient.clear();
}
@@ -670,10 +620,28 @@ sp<SurfaceControl> SurfaceComposerClient::createSurface(
PixelFormat format,
uint32_t flags,
SurfaceControl* parent,
- uint32_t windowType,
- uint32_t ownerUid)
+ int32_t windowType,
+ int32_t ownerUid)
+{
+ sp<SurfaceControl> s;
+ createSurfaceChecked(name, w, h, format, &s, flags, parent, windowType, ownerUid);
+ return s;
+}
+
+status_t SurfaceComposerClient::createSurfaceChecked(
+ const String8& name,
+ uint32_t w,
+ uint32_t h,
+ PixelFormat format,
+ sp<SurfaceControl>* outSurface,
+ uint32_t flags,
+ SurfaceControl* parent,
+ int32_t windowType,
+ int32_t ownerUid)
{
sp<SurfaceControl> sur;
+ status_t err = mStatus;
+
if (mStatus == NO_ERROR) {
sp<IBinder> handle;
sp<IBinder> parentHandle;
@@ -682,27 +650,14 @@ sp<SurfaceControl> SurfaceComposerClient::createSurface(
if (parent != nullptr) {
parentHandle = parent->getHandle();
}
- status_t err = mClient->createSurface(name, w, h, format, flags, parentHandle,
+ err = mClient->createSurface(name, w, h, format, flags, parentHandle,
windowType, ownerUid, &handle, &gbp);
ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
if (err == NO_ERROR) {
- sur = new SurfaceControl(this, handle, gbp);
+ *outSurface = new SurfaceControl(this, handle, gbp, true /* owned */);
}
}
- return sur;
-}
-
-sp<IBinder> SurfaceComposerClient::createDisplay(const String8& displayName,
- bool secure) {
- return Composer::getInstance().createDisplay(displayName, secure);
-}
-
-void SurfaceComposerClient::destroyDisplay(const sp<IBinder>& display) {
- Composer::getInstance().destroyDisplay(display);
-}
-
-sp<IBinder> SurfaceComposerClient::getBuiltInDisplay(int32_t id) {
- return Composer::getInstance().getBuiltInDisplay(id);
+ return err;
}
status_t SurfaceComposerClient::destroySurface(const sp<IBinder>& sid) {
@@ -727,152 +682,18 @@ status_t SurfaceComposerClient::getLayerFrameStats(const sp<IBinder>& token,
return mClient->getLayerFrameStats(token, outStats);
}
-inline Composer& SurfaceComposerClient::getComposer() {
- return mComposer;
-}
-
// ----------------------------------------------------------------------------
-void SurfaceComposerClient::openGlobalTransaction() {
- Composer::openGlobalTransaction();
-}
-
-void SurfaceComposerClient::closeGlobalTransaction(bool synchronous) {
- Composer::closeGlobalTransaction(synchronous);
-}
-
-void SurfaceComposerClient::setAnimationTransaction() {
- Composer::setAnimationTransaction();
-}
-
status_t SurfaceComposerClient::enableVSyncInjections(bool enable) {
- return Composer::enableVSyncInjections(enable);
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ return sf->enableVSyncInjections(enable);
}
status_t SurfaceComposerClient::injectVSync(nsecs_t when) {
- return Composer::injectVSync(when);
-}
-
-// ----------------------------------------------------------------------------
-
-status_t SurfaceComposerClient::setCrop(const sp<IBinder>& id, const Rect& crop) {
- return getComposer().setCrop(this, id, crop);
-}
-
-status_t SurfaceComposerClient::setFinalCrop(const sp<IBinder>& id,
- const Rect& crop) {
- return getComposer().setFinalCrop(this, id, crop);
-}
-
-status_t SurfaceComposerClient::setPosition(const sp<IBinder>& id, float x, float y) {
- return getComposer().setPosition(this, id, x, y);
-}
-
-status_t SurfaceComposerClient::setSize(const sp<IBinder>& id, uint32_t w, uint32_t h) {
- return getComposer().setSize(this, id, w, h);
-}
-
-status_t SurfaceComposerClient::setLayer(const sp<IBinder>& id, int32_t z) {
- return getComposer().setLayer(this, id, z);
-}
-
-status_t SurfaceComposerClient::setRelativeLayer(const sp<IBinder>& id,
- const sp<IBinder>& relativeTo, int32_t z) {
- return getComposer().setRelativeLayer(this, id, relativeTo, z);
-}
-
-status_t SurfaceComposerClient::hide(const sp<IBinder>& id) {
- return getComposer().setFlags(this, id,
- layer_state_t::eLayerHidden,
- layer_state_t::eLayerHidden);
-}
-
-status_t SurfaceComposerClient::show(const sp<IBinder>& id) {
- return getComposer().setFlags(this, id,
- 0,
- layer_state_t::eLayerHidden);
-}
-
-status_t SurfaceComposerClient::setFlags(const sp<IBinder>& id, uint32_t flags,
- uint32_t mask) {
- return getComposer().setFlags(this, id, flags, mask);
-}
-
-status_t SurfaceComposerClient::setTransparentRegionHint(const sp<IBinder>& id,
- const Region& transparentRegion) {
- return getComposer().setTransparentRegionHint(this, id, transparentRegion);
-}
-
-status_t SurfaceComposerClient::setAlpha(const sp<IBinder>& id, float alpha) {
- return getComposer().setAlpha(this, id, alpha);
-}
-
-status_t SurfaceComposerClient::setLayerStack(const sp<IBinder>& id, uint32_t layerStack) {
- return getComposer().setLayerStack(this, id, layerStack);
-}
-
-status_t SurfaceComposerClient::setMatrix(const sp<IBinder>& id, float dsdx, float dtdx,
- float dtdy, float dsdy) {
- return getComposer().setMatrix(this, id, dsdx, dtdx, dtdy, dsdy);
-}
-
-status_t SurfaceComposerClient::deferTransactionUntil(const sp<IBinder>& id,
- const sp<IBinder>& handle, uint64_t frameNumber) {
- return getComposer().deferTransactionUntil(this, id, handle, frameNumber);
-}
-
-status_t SurfaceComposerClient::deferTransactionUntil(const sp<IBinder>& id,
- const sp<Surface>& barrierSurface, uint64_t frameNumber) {
- return getComposer().deferTransactionUntil(this, id, barrierSurface, frameNumber);
-}
-
-status_t SurfaceComposerClient::reparentChildren(const sp<IBinder>& id,
- const sp<IBinder>& newParentHandle) {
- return getComposer().reparentChildren(this, id, newParentHandle);
-}
-
-status_t SurfaceComposerClient::detachChildren(const sp<IBinder>& id) {
- return getComposer().detachChildren(this, id);
-}
-
-status_t SurfaceComposerClient::setOverrideScalingMode(
- const sp<IBinder>& id, int32_t overrideScalingMode) {
- return getComposer().setOverrideScalingMode(
- this, id, overrideScalingMode);
+ sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ return sf->injectVSync(when);
}
-status_t SurfaceComposerClient::setGeometryAppliesWithResize(
- const sp<IBinder>& id) {
- return getComposer().setGeometryAppliesWithResize(this, id);
-}
-
-// ----------------------------------------------------------------------------
-
-status_t SurfaceComposerClient::setDisplaySurface(const sp<IBinder>& token,
- sp<IGraphicBufferProducer> bufferProducer) {
- return Composer::getInstance().setDisplaySurface(token, bufferProducer);
-}
-
-void SurfaceComposerClient::setDisplayLayerStack(const sp<IBinder>& token,
- uint32_t layerStack) {
- Composer::getInstance().setDisplayLayerStack(token, layerStack);
-}
-
-void SurfaceComposerClient::setDisplayProjection(const sp<IBinder>& token,
- uint32_t orientation,
- const Rect& layerStackRect,
- const Rect& displayRect) {
- Composer::getInstance().setDisplayProjection(token, orientation,
- layerStackRect, displayRect);
-}
-
-void SurfaceComposerClient::setDisplaySize(const sp<IBinder>& token,
- uint32_t width, uint32_t height) {
- Composer::getInstance().setDisplaySize(token, width, height);
-}
-
-// ----------------------------------------------------------------------------
-
status_t SurfaceComposerClient::getDisplayConfigs(
const sp<IBinder>& display, Vector<DisplayInfo>* configs)
{
@@ -906,16 +727,16 @@ status_t SurfaceComposerClient::setActiveConfig(const sp<IBinder>& display, int
}
status_t SurfaceComposerClient::getDisplayColorModes(const sp<IBinder>& display,
- Vector<android_color_mode_t>* outColorModes) {
+ Vector<ColorMode>* outColorModes) {
return ComposerService::getComposerService()->getDisplayColorModes(display, outColorModes);
}
-android_color_mode_t SurfaceComposerClient::getActiveColorMode(const sp<IBinder>& display) {
+ColorMode SurfaceComposerClient::getActiveColorMode(const sp<IBinder>& display) {
return ComposerService::getComposerService()->getActiveColorMode(display);
}
status_t SurfaceComposerClient::setActiveColorMode(const sp<IBinder>& display,
- android_color_mode_t colorMode) {
+ ColorMode colorMode) {
return ComposerService::getComposerService()->setActiveColorMode(display, colorMode);
}
@@ -940,149 +761,37 @@ status_t SurfaceComposerClient::getHdrCapabilities(const sp<IBinder>& display,
// ----------------------------------------------------------------------------
-status_t ScreenshotClient::capture(
- const sp<IBinder>& display,
- const sp<IGraphicBufferProducer>& producer,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform) {
- sp<ISurfaceComposer> s(ComposerService::getComposerService());
- if (s == nullptr) return NO_INIT;
- return s->captureScreen(display, producer, sourceCrop,
- reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform);
-}
-
-status_t ScreenshotClient::captureToBuffer(const sp<IBinder>& display,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform,
- uint32_t rotation,
- sp<GraphicBuffer>* outBuffer) {
+status_t ScreenshotClient::capture(const sp<IBinder>& display, Rect sourceCrop, uint32_t reqWidth,
+ uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ,
+ bool useIdentityTransform, uint32_t rotation,
+ sp<GraphicBuffer>* outBuffer) {
sp<ISurfaceComposer> s(ComposerService::getComposerService());
- if (s == nullptr) return NO_INIT;
-
- sp<IGraphicBufferConsumer> gbpConsumer;
- sp<IGraphicBufferProducer> producer;
- BufferQueue::createBufferQueue(&producer, &gbpConsumer);
- sp<BufferItemConsumer> consumer(new BufferItemConsumer(gbpConsumer,
- GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_NEVER,
- 1, true));
-
- status_t ret = s->captureScreen(display, producer, sourceCrop, reqWidth, reqHeight,
- minLayerZ, maxLayerZ, useIdentityTransform,
- static_cast<ISurfaceComposer::Rotation>(rotation));
+ if (s == NULL) return NO_INIT;
+ status_t ret = s->captureScreen(display, outBuffer, sourceCrop, reqWidth, reqHeight, minLayerZ,
+ maxLayerZ, useIdentityTransform,
+ static_cast<ISurfaceComposer::Rotation>(rotation));
if (ret != NO_ERROR) {
return ret;
}
- BufferItem b;
- consumer->acquireBuffer(&b, 0, true);
- *outBuffer = b.mGraphicBuffer;
return ret;
}
-ScreenshotClient::ScreenshotClient()
- : mHaveBuffer(false) {
- memset(&mBuffer, 0, sizeof(mBuffer));
-}
-
-ScreenshotClient::~ScreenshotClient() {
- ScreenshotClient::release();
-}
-
-sp<CpuConsumer> ScreenshotClient::getCpuConsumer() const {
- if (mCpuConsumer == nullptr) {
- sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&mProducer, &consumer);
- mCpuConsumer = new CpuConsumer(consumer, 1);
- mCpuConsumer->setName(String8("ScreenshotClient"));
- }
- return mCpuConsumer;
-}
-
-status_t ScreenshotClient::update(const sp<IBinder>& display,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform, uint32_t rotation) {
+status_t ScreenshotClient::captureLayers(const sp<IBinder>& layerHandle, Rect sourceCrop,
+ float frameScale, sp<GraphicBuffer>* outBuffer) {
sp<ISurfaceComposer> s(ComposerService::getComposerService());
- if (s == nullptr) return NO_INIT;
- sp<CpuConsumer> cpuConsumer = getCpuConsumer();
-
- if (mHaveBuffer) {
- mCpuConsumer->unlockBuffer(mBuffer);
- memset(&mBuffer, 0, sizeof(mBuffer));
- mHaveBuffer = false;
- }
-
- status_t err = s->captureScreen(display, mProducer, sourceCrop,
- reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform,
- static_cast<ISurfaceComposer::Rotation>(rotation));
-
- if (err == NO_ERROR) {
- err = mCpuConsumer->lockNextBuffer(&mBuffer);
- if (err == NO_ERROR) {
- mHaveBuffer = true;
- }
- }
- return err;
-}
-
-status_t ScreenshotClient::update(const sp<IBinder>& display,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform) {
-
- return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight,
- minLayerZ, maxLayerZ, useIdentityTransform, ISurfaceComposer::eRotateNone);
-}
-
-status_t ScreenshotClient::update(const sp<IBinder>& display, Rect sourceCrop,
- bool useIdentityTransform) {
- return ScreenshotClient::update(display, sourceCrop, 0, 0,
- INT32_MIN, INT32_MAX,
- useIdentityTransform, ISurfaceComposer::eRotateNone);
-}
-
-status_t ScreenshotClient::update(const sp<IBinder>& display, Rect sourceCrop,
- uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform) {
- return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight,
- INT32_MIN, INT32_MAX,
- useIdentityTransform, ISurfaceComposer::eRotateNone);
-}
-
-void ScreenshotClient::release() {
- if (mHaveBuffer) {
- mCpuConsumer->unlockBuffer(mBuffer);
- memset(&mBuffer, 0, sizeof(mBuffer));
- mHaveBuffer = false;
- }
- mCpuConsumer.clear();
-}
-
-void const* ScreenshotClient::getPixels() const {
- return mBuffer.data;
-}
-
-uint32_t ScreenshotClient::getWidth() const {
- return mBuffer.width;
-}
-
-uint32_t ScreenshotClient::getHeight() const {
- return mBuffer.height;
-}
-
-PixelFormat ScreenshotClient::getFormat() const {
- return mBuffer.format;
-}
-
-uint32_t ScreenshotClient::getStride() const {
- return mBuffer.stride;
-}
-
-size_t ScreenshotClient::getSize() const {
- return mBuffer.stride * mBuffer.height * bytesPerPixel(mBuffer.format);
+ if (s == NULL) return NO_INIT;
+ status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale,
+ false /* childrenOnly */);
+ return ret;
}
-android_dataspace ScreenshotClient::getDataSpace() const {
- return mBuffer.dataSpace;
+status_t ScreenshotClient::captureChildLayers(const sp<IBinder>& layerHandle, Rect sourceCrop,
+ float frameScale, sp<GraphicBuffer>* outBuffer) {
+ sp<ISurfaceComposer> s(ComposerService::getComposerService());
+ if (s == NULL) return NO_INIT;
+ status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale,
+ true /* childrenOnly */);
+ return ret;
}
-
// ----------------------------------------------------------------------------
}; // namespace android
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index 08e3b60f6c..5eafbb3555 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -48,8 +48,9 @@ namespace android {
SurfaceControl::SurfaceControl(
const sp<SurfaceComposerClient>& client,
const sp<IBinder>& handle,
- const sp<IGraphicBufferProducer>& gbp)
- : mClient(client), mHandle(handle), mGraphicBufferProducer(gbp)
+ const sp<IGraphicBufferProducer>& gbp,
+ bool owned)
+ : mClient(client), mHandle(handle), mGraphicBufferProducer(gbp), mOwned(owned)
{
}
@@ -60,7 +61,9 @@ SurfaceControl::~SurfaceControl()
void SurfaceControl::destroy()
{
- if (isValid()) {
+ // Avoid destroying the server-side surface if we are not the owner of it, meaning that we
+ // retrieved it from another process.
+ if (isValid() && mOwned) {
mClient->destroySurface(mHandle);
}
// clear all references and trigger an IPC now, to make sure things
@@ -83,7 +86,7 @@ void SurfaceControl::clear()
}
void SurfaceControl::disconnect() {
- if (mGraphicBufferProducer != nullptr) {
+ if (mGraphicBufferProducer != NULL) {
mGraphicBufferProducer->disconnect(
BufferQueueCore::CURRENTLY_CONNECTED_API);
}
@@ -92,117 +95,11 @@ void SurfaceControl::disconnect() {
bool SurfaceControl::isSameSurface(
const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs)
{
- if (lhs == nullptr || rhs == nullptr)
+ if (lhs == 0 || rhs == 0)
return false;
return lhs->mHandle == rhs->mHandle;
}
-status_t SurfaceControl::setLayerStack(uint32_t layerStack) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setLayerStack(mHandle, layerStack);
-}
-
-status_t SurfaceControl::setLayer(int32_t layer) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setLayer(mHandle, layer);
-}
-
-status_t SurfaceControl::setRelativeLayer(const sp<IBinder>& relativeTo, int32_t layer) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setRelativeLayer(mHandle, relativeTo, layer);
-}
-
-status_t SurfaceControl::setPosition(float x, float y) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setPosition(mHandle, x, y);
-}
-status_t SurfaceControl::setGeometryAppliesWithResize() {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setGeometryAppliesWithResize(mHandle);
-}
-status_t SurfaceControl::setSize(uint32_t w, uint32_t h) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setSize(mHandle, w, h);
-}
-status_t SurfaceControl::hide() {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->hide(mHandle);
-}
-status_t SurfaceControl::show() {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->show(mHandle);
-}
-status_t SurfaceControl::setFlags(uint32_t flags, uint32_t mask) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setFlags(mHandle, flags, mask);
-}
-status_t SurfaceControl::setTransparentRegionHint(const Region& transparent) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setTransparentRegionHint(mHandle, transparent);
-}
-status_t SurfaceControl::setAlpha(float alpha) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setAlpha(mHandle, alpha);
-}
-status_t SurfaceControl::setMatrix(float dsdx, float dtdx, float dtdy, float dsdy) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setMatrix(mHandle, dsdx, dtdx, dtdy, dsdy);
-}
-status_t SurfaceControl::setCrop(const Rect& crop) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setCrop(mHandle, crop);
-}
-status_t SurfaceControl::setFinalCrop(const Rect& crop) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setFinalCrop(mHandle, crop);
-}
-
-status_t SurfaceControl::deferTransactionUntil(const sp<IBinder>& handle,
- uint64_t frameNumber) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->deferTransactionUntil(mHandle, handle, frameNumber);
-}
-
-status_t SurfaceControl::deferTransactionUntil(const sp<Surface>& handle,
- uint64_t frameNumber) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->deferTransactionUntil(mHandle, handle, frameNumber);
-}
-
-status_t SurfaceControl::reparentChildren(const sp<IBinder>& newParentHandle) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->reparentChildren(mHandle, newParentHandle);
-}
-
-status_t SurfaceControl::detachChildren() {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->detachChildren(mHandle);
-}
-
-status_t SurfaceControl::setOverrideScalingMode(int32_t overrideScalingMode) {
- status_t err = validate();
- if (err < 0) return err;
- return mClient->setOverrideScalingMode(mHandle, overrideScalingMode);
-}
-
status_t SurfaceControl::clearLayerFrameStats() const {
status_t err = validate();
if (err < 0) return err;
@@ -219,7 +116,7 @@ status_t SurfaceControl::getLayerFrameStats(FrameStats* outStats) const {
status_t SurfaceControl::validate() const
{
- if (mHandle==nullptr || mClient==nullptr) {
+ if (mHandle==0 || mClient==0) {
ALOGE("invalid handle (%p) or client (%p)",
mHandle.get(), mClient.get());
return NO_INIT;
@@ -231,7 +128,7 @@ status_t SurfaceControl::writeSurfaceToParcel(
const sp<SurfaceControl>& control, Parcel* parcel)
{
sp<IGraphicBufferProducer> bp;
- if (control != nullptr) {
+ if (control != NULL) {
bp = control->mGraphicBufferProducer;
}
return parcel->writeStrongBinder(IInterface::asBinder(bp));
@@ -249,7 +146,7 @@ sp<Surface> SurfaceControl::generateSurfaceLocked() const
sp<Surface> SurfaceControl::getSurface() const
{
Mutex::Autolock _l(mLock);
- if (mSurfaceData == nullptr) {
+ if (mSurfaceData == 0) {
return generateSurfaceLocked();
}
return mSurfaceData;
@@ -267,5 +164,35 @@ sp<IBinder> SurfaceControl::getHandle() const
return mHandle;
}
+sp<SurfaceComposerClient> SurfaceControl::getClient() const
+{
+ return mClient;
+}
+
+void SurfaceControl::writeToParcel(Parcel* parcel)
+{
+ parcel->writeStrongBinder(ISurfaceComposerClient::asBinder(mClient->getClient()));
+ parcel->writeStrongBinder(mHandle);
+ parcel->writeStrongBinder(IGraphicBufferProducer::asBinder(mGraphicBufferProducer));
+}
+
+sp<SurfaceControl> SurfaceControl::readFromParcel(Parcel* parcel)
+{
+ sp<IBinder> client = parcel->readStrongBinder();
+ sp<IBinder> handle = parcel->readStrongBinder();
+ if (client == nullptr || handle == nullptr)
+ {
+ ALOGE("Invalid parcel");
+ return nullptr;
+ }
+ sp<IBinder> gbp;
+ parcel->readNullableStrongBinder(&gbp);
+
+ // We aren't the original owner of the surface.
+ return new SurfaceControl(new SurfaceComposerClient(
+ interface_cast<ISurfaceComposerClient>(client)),
+ handle.get(), interface_cast<IGraphicBufferProducer>(gbp), false /* owned */);
+}
+
// ----------------------------------------------------------------------------
}; // namespace android
diff --git a/libs/gui/SyncFeatures.cpp b/libs/gui/SyncFeatures.cpp
index fcae05c8ad..afa15c5cda 100644
--- a/libs/gui/SyncFeatures.cpp
+++ b/libs/gui/SyncFeatures.cpp
@@ -41,7 +41,7 @@ SyncFeatures::SyncFeatures() : Singleton<SyncFeatures>(),
// This can only be called after EGL has been initialized; otherwise the
// check below will abort.
const char* exts = eglQueryStringImplementationANDROID(dpy, EGL_EXTENSIONS);
- LOG_ALWAYS_FATAL_IF(exts == nullptr, "eglQueryStringImplementationANDROID failed");
+ LOG_ALWAYS_FATAL_IF(exts == NULL, "eglQueryStringImplementationANDROID failed");
if (strstr(exts, "EGL_ANDROID_native_fence_sync")) {
// This makes GLConsumer use the EGL_ANDROID_native_fence_sync
// extension to create Android native fences to signal when all
diff --git a/libs/gui/include/gui/BufferHubConsumer.h b/libs/gui/include/gui/BufferHubConsumer.h
new file mode 100644
index 0000000000..d38077014b
--- /dev/null
+++ b/libs/gui/include/gui/BufferHubConsumer.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_GUI_BUFFERHUBCONSUMER_H_
+#define ANDROID_GUI_BUFFERHUBCONSUMER_H_
+
+#include <gui/IGraphicBufferConsumer.h>
+#include <private/dvr/buffer_hub_queue_client.h>
+#include <private/dvr/buffer_hub_queue_parcelable.h>
+
+namespace android {
+
+class BufferHubConsumer : public IGraphicBufferConsumer {
+public:
+ // Creates a BufferHubConsumer instance by importing an existing producer queue.
+ static sp<BufferHubConsumer> Create(const std::shared_ptr<dvr::ConsumerQueue>& queue);
+
+ // Creates a BufferHubConsumer instance by importing an existing producer
+ // parcelable. Note that this call takes the ownership of the parcelable
+ // object and is guaranteed to succeed if parcelable object is valid.
+ static sp<BufferHubConsumer> Create(dvr::ConsumerQueueParcelable parcelable);
+
+ // See |IGraphicBufferConsumer::acquireBuffer|
+ status_t acquireBuffer(BufferItem* buffer, nsecs_t presentWhen,
+ uint64_t maxFrameNumber = 0) override;
+
+ // See |IGraphicBufferConsumer::detachBuffer|
+ status_t detachBuffer(int slot) override;
+
+ // See |IGraphicBufferConsumer::attachBuffer|
+ status_t attachBuffer(int* outSlot, const sp<GraphicBuffer>& buffer) override;
+
+ // See |IGraphicBufferConsumer::releaseBuffer|
+ status_t releaseBuffer(int buf, uint64_t frameNumber, EGLDisplay display, EGLSyncKHR fence,
+ const sp<Fence>& releaseFence) override;
+
+ // See |IGraphicBufferConsumer::consumerConnect|
+ status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp) override;
+
+ // See |IGraphicBufferConsumer::consumerDisconnect|
+ status_t consumerDisconnect() override;
+
+ // See |IGraphicBufferConsumer::getReleasedBuffers|
+ status_t getReleasedBuffers(uint64_t* slotMask) override;
+
+ // See |IGraphicBufferConsumer::setDefaultBufferSize|
+ status_t setDefaultBufferSize(uint32_t w, uint32_t h) override;
+
+ // See |IGraphicBufferConsumer::setMaxBufferCount|
+ status_t setMaxBufferCount(int bufferCount) override;
+
+ // See |IGraphicBufferConsumer::setMaxAcquiredBufferCount|
+ status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers) override;
+
+ // See |IGraphicBufferConsumer::setConsumerName|
+ status_t setConsumerName(const String8& name) override;
+
+ // See |IGraphicBufferConsumer::setDefaultBufferFormat|
+ status_t setDefaultBufferFormat(PixelFormat defaultFormat) override;
+
+ // See |IGraphicBufferConsumer::setDefaultBufferDataSpace|
+ status_t setDefaultBufferDataSpace(android_dataspace defaultDataSpace) override;
+
+ // See |IGraphicBufferConsumer::setConsumerUsageBits|
+ status_t setConsumerUsageBits(uint64_t usage) override;
+
+ // See |IGraphicBufferConsumer::setConsumerIsProtected|
+ status_t setConsumerIsProtected(bool isProtected) override;
+
+ // See |IGraphicBufferConsumer::setTransformHint|
+ status_t setTransformHint(uint32_t hint) override;
+
+ // See |IGraphicBufferConsumer::getSidebandStream|
+ status_t getSidebandStream(sp<NativeHandle>* outStream) const override;
+
+ // See |IGraphicBufferConsumer::getOccupancyHistory|
+ status_t getOccupancyHistory(bool forceFlush,
+ std::vector<OccupancyTracker::Segment>* outHistory) override;
+
+ // See |IGraphicBufferConsumer::discardFreeBuffers|
+ status_t discardFreeBuffers() override;
+
+ // See |IGraphicBufferConsumer::dumpState|
+ status_t dumpState(const String8& prefix, String8* outResult) const override;
+
+ // BufferHubConsumer provides its own logic to cast to a binder object.
+ IBinder* onAsBinder() override;
+
+private:
+ // Private constructor to force use of |Create|.
+ BufferHubConsumer() = default;
+
+ // Concrete implementation backed by BufferHubBuffer.
+ std::shared_ptr<dvr::ConsumerQueue> mQueue;
+};
+
+} // namespace android
+
+#endif // ANDROID_GUI_BUFFERHUBCONSUMER_H_
diff --git a/libs/gui/include/gui/BufferHubProducer.h b/libs/gui/include/gui/BufferHubProducer.h
new file mode 100644
index 0000000000..23c9909826
--- /dev/null
+++ b/libs/gui/include/gui/BufferHubProducer.h
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_GUI_BUFFERHUBPRODUCER_H_
+#define ANDROID_GUI_BUFFERHUBPRODUCER_H_
+
+#include <gui/BufferSlot.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <private/dvr/buffer_hub_queue_client.h>
+#include <private/dvr/buffer_hub_queue_parcelable.h>
+
+namespace android {
+
+class BufferHubProducer : public IGraphicBufferProducer {
+public:
+ static constexpr int kNoConnectedApi = -1;
+
+ // TODO(b/36187402) The actual implementation of BufferHubQueue's consumer
+ // side logic doesn't limit the number of buffer it can acquire
+ // simultaneously. We need a way for consumer logic to configure and enforce
+ // that.
+ static constexpr int kDefaultUndequeuedBuffers = 1;
+
+ // Creates a BufferHubProducer instance by importing an existing prodcuer
+ // queue.
+ static sp<BufferHubProducer> Create(const std::shared_ptr<dvr::ProducerQueue>& producer);
+
+ // Creates a BufferHubProducer instance by importing an existing prodcuer
+ // parcelable. Note that this call takes the ownership of the parcelable
+ // object and is guaranteed to succeed if parcelable object is valid.
+ static sp<BufferHubProducer> Create(dvr::ProducerQueueParcelable parcelable);
+
+ // See |IGraphicBufferProducer::requestBuffer|
+ status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override;
+
+ // For the BufferHub based implementation. All buffers in the queue are
+ // allowed to be dequeued from the consumer side. It call always returns
+ // 0 for |NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS| query. Thus setting
+ // |max_dequeued_buffers| here can be considered the same as setting queue
+ // capacity.
+ //
+ // See |IGraphicBufferProducer::setMaxDequeuedBufferCount| for more info
+ status_t setMaxDequeuedBufferCount(int max_dequeued_buffers) override;
+
+ // See |IGraphicBufferProducer::setAsyncMode|
+ status_t setAsyncMode(bool async) override;
+
+ // See |IGraphicBufferProducer::dequeueBuffer|
+ status_t dequeueBuffer(int* out_slot, sp<Fence>* out_fence, uint32_t width, uint32_t height,
+ PixelFormat format, uint64_t usage, uint64_t* outBufferAge,
+ FrameEventHistoryDelta* outTimestamps) override;
+
+ // See |IGraphicBufferProducer::detachBuffer|
+ status_t detachBuffer(int slot) override;
+
+ // See |IGraphicBufferProducer::detachNextBuffer|
+ status_t detachNextBuffer(sp<GraphicBuffer>* out_buffer, sp<Fence>* out_fence) override;
+
+ // See |IGraphicBufferProducer::attachBuffer|
+ status_t attachBuffer(int* out_slot, const sp<GraphicBuffer>& buffer) override;
+
+ // See |IGraphicBufferProducer::queueBuffer|
+ status_t queueBuffer(int slot, const QueueBufferInput& input,
+ QueueBufferOutput* output) override;
+
+ // See |IGraphicBufferProducer::cancelBuffer|
+ status_t cancelBuffer(int slot, const sp<Fence>& fence) override;
+
+ // See |IGraphicBufferProducer::query|
+ status_t query(int what, int* out_value) override;
+
+ // See |IGraphicBufferProducer::connect|
+ status_t connect(const sp<IProducerListener>& listener, int api,
+ bool producer_controlled_by_app, QueueBufferOutput* output) override;
+
+ // See |IGraphicBufferProducer::disconnect|
+ status_t disconnect(int api, DisconnectMode mode = DisconnectMode::Api) override;
+
+ // See |IGraphicBufferProducer::setSidebandStream|
+ status_t setSidebandStream(const sp<NativeHandle>& stream) override;
+
+ // See |IGraphicBufferProducer::allocateBuffers|
+ void allocateBuffers(uint32_t width, uint32_t height, PixelFormat format,
+ uint64_t usage) override;
+
+ // See |IGraphicBufferProducer::allowAllocation|
+ status_t allowAllocation(bool allow) override;
+
+ // See |IGraphicBufferProducer::setGenerationNumber|
+ status_t setGenerationNumber(uint32_t generation_number) override;
+
+ // See |IGraphicBufferProducer::getConsumerName|
+ String8 getConsumerName() const override;
+
+ // See |IGraphicBufferProducer::setSharedBufferMode|
+ status_t setSharedBufferMode(bool shared_buffer_mode) override;
+
+ // See |IGraphicBufferProducer::setAutoRefresh|
+ status_t setAutoRefresh(bool auto_refresh) override;
+
+ // See |IGraphicBufferProducer::setDequeueTimeout|
+ status_t setDequeueTimeout(nsecs_t timeout) override;
+
+ // See |IGraphicBufferProducer::getLastQueuedBuffer|
+ status_t getLastQueuedBuffer(sp<GraphicBuffer>* out_buffer, sp<Fence>* out_fence,
+ float out_transform_matrix[16]) override;
+
+ // See |IGraphicBufferProducer::getFrameTimestamps|
+ void getFrameTimestamps(FrameEventHistoryDelta* /*outDelta*/) override;
+
+ // See |IGraphicBufferProducer::getUniqueId|
+ status_t getUniqueId(uint64_t* out_id) const override;
+
+ // See |IGraphicBufferProducer::getConsumerUsage|
+ status_t getConsumerUsage(uint64_t* out_usage) const override;
+
+ // Takes out the current producer as a binder parcelable object. Note that the
+ // producer must be disconnected to be exportable. After successful export,
+ // the producer queue can no longer be connected again. Returns NO_ERROR when
+ // takeout is successful and out_parcelable will hold the new parcelable
+ // object. Also note that out_parcelable cannot be NULL and must points to an
+ // invalid parcelable.
+ status_t TakeAsParcelable(dvr::ProducerQueueParcelable* out_parcelable);
+
+ IBinder* onAsBinder() override;
+
+protected:
+ // See |IGraphicBufferProducer::exportToParcel|
+ status_t exportToParcel(Parcel* parcel) override;
+
+private:
+ using LocalHandle = pdx::LocalHandle;
+
+ // Private constructor to force use of |Create|.
+ BufferHubProducer() {}
+
+ static uint64_t genUniqueId() {
+ static std::atomic<uint32_t> counter{0};
+ static uint64_t id = static_cast<uint64_t>(getpid()) << 32;
+ return id | counter++;
+ }
+
+ // Allocate new buffer through BufferHub and add it into |queue_| for
+ // bookkeeping.
+ status_t AllocateBuffer(uint32_t width, uint32_t height, uint32_t layer_count,
+ PixelFormat format, uint64_t usage);
+
+ // Remove a buffer via BufferHubRPC.
+ status_t RemoveBuffer(size_t slot);
+
+ // Free all buffers which are owned by the prodcuer. Note that if graphic
+ // buffers are acquired by the consumer, we can't .
+ status_t FreeAllBuffers();
+
+ // Concreate implementation backed by BufferHubBuffer.
+ std::shared_ptr<dvr::ProducerQueue> queue_;
+
+ // Mutex for thread safety.
+ std::mutex mutex_;
+
+ // Connect client API, should be one of the NATIVE_WINDOW_API_* flags.
+ int connected_api_{kNoConnectedApi};
+
+ // |max_buffer_count_| sets the capacity of the underlying buffer queue.
+ int32_t max_buffer_count_{dvr::BufferHubQueue::kMaxQueueCapacity};
+
+ // |max_dequeued_buffer_count_| set the maximum number of buffers that can
+ // be dequeued at the same momment.
+ int32_t max_dequeued_buffer_count_{1};
+
+ // Sets how long dequeueBuffer or attachBuffer will block if a buffer or
+ // slot is not yet available. The timeout is stored in milliseconds.
+ int dequeue_timeout_ms_{dvr::BufferHubQueue::kNoTimeOut};
+
+ // |generation_number_| stores the current generation number of the attached
+ // producer. Any attempt to attach a buffer with a different generation
+ // number will fail.
+ // TOOD(b/38137191) Currently not used as we don't support
+ // IGraphicBufferProducer::detachBuffer.
+ uint32_t generation_number_{0};
+
+ // |buffers_| stores the buffers that have been dequeued from
+ // |dvr::BufferHubQueue|, It is initialized to invalid buffers, and gets
+ // filled in with the result of |Dequeue|.
+ // TODO(jwcai) The buffer allocated to a slot will also be replaced if the
+ // requested buffer usage or geometry differs from that of the buffer
+ // allocated to a slot.
+ struct BufferHubSlot : public BufferSlot {
+ BufferHubSlot() : mBufferProducer(nullptr), mIsReallocating(false) {}
+ // BufferSlot comes from android framework, using m prefix to comply with
+ // the name convention with the reset of data fields from BufferSlot.
+ std::shared_ptr<dvr::BufferProducer> mBufferProducer;
+ bool mIsReallocating;
+ };
+ BufferHubSlot buffers_[dvr::BufferHubQueue::kMaxQueueCapacity];
+
+ // A uniqueId used by IGraphicBufferProducer interface.
+ const uint64_t unique_id_{genUniqueId()};
+
+ // A pending parcelable object which keeps the bufferhub channel alive.
+ dvr::ProducerQueueParcelable pending_producer_parcelable_;
+};
+
+} // namespace android
+
+#endif // ANDROID_GUI_BUFFERHUBPRODUCER_H_
diff --git a/libs/gui/include/gui/BufferItem.h b/libs/gui/include/gui/BufferItem.h
index 55637a9be4..218bb424fb 100644
--- a/libs/gui/include/gui/BufferItem.h
+++ b/libs/gui/include/gui/BufferItem.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_GUI_BUFFERITEM_H
#define ANDROID_GUI_BUFFERITEM_H
+#include <gui/HdrMetadata.h>
+
#include <ui/FenceTime.h>
#include <ui/Rect.h>
#include <ui/Region.h>
@@ -86,6 +88,9 @@ class BufferItem : public Flattenable<BufferItem> {
// dataSpace is format-dependent.
android_dataspace mDataSpace;
+ // mHdrMetadata is the HDR metadata associated with this buffer slot.
+ HdrMetadata mHdrMetadata;
+
// mFrameNumber is the number of the queued frame for this slot.
uint64_t mFrameNumber;
@@ -122,6 +127,9 @@ class BufferItem : public Flattenable<BufferItem> {
// Indicates that this BufferItem contains a stale buffer which has already
// been released by the BufferQueue.
bool mIsStale;
+
+ // Indicates the API (NATIVE_WINDOW_API_xxx) that queues the buffer.
+ int mApi;
};
} // namespace android
diff --git a/libs/gui/include/gui/BufferItemConsumer.h b/libs/gui/include/gui/BufferItemConsumer.h
index d9c57757f5..a905610ee2 100644
--- a/libs/gui/include/gui/BufferItemConsumer.h
+++ b/libs/gui/include/gui/BufferItemConsumer.h
@@ -57,10 +57,6 @@ class BufferItemConsumer: public ConsumerBase
~BufferItemConsumer() override;
- // set the name of the BufferItemConsumer that will be used to identify it in
- // log messages.
- void setName(const String8& name);
-
// setBufferFreedListener sets the listener object that will be notified
// when an old buffer is being freed.
void setBufferFreedListener(const wp<BufferFreedListener>& listener);
diff --git a/libs/gui/include/gui/BufferQueue.h b/libs/gui/include/gui/BufferQueue.h
index ba5cbf7eb4..da952744f3 100644
--- a/libs/gui/include/gui/BufferQueue.h
+++ b/libs/gui/include/gui/BufferQueue.h
@@ -79,6 +79,12 @@ public:
sp<IGraphicBufferConsumer>* outConsumer,
bool consumerIsSurfaceFlinger = false);
+#ifndef NO_BUFFERHUB
+ // Creates an IGraphicBufferProducer and IGraphicBufferConsumer pair backed by BufferHub.
+ static void createBufferHubQueue(sp<IGraphicBufferProducer>* outProducer,
+ sp<IGraphicBufferConsumer>* outConsumer);
+#endif
+
BufferQueue() = delete; // Create through createBufferQueue
};
diff --git a/libs/gui/include/gui/ConsumerBase.h b/libs/gui/include/gui/ConsumerBase.h
index e9fc8fd1ea..366ced380b 100644
--- a/libs/gui/include/gui/ConsumerBase.h
+++ b/libs/gui/include/gui/ConsumerBase.h
@@ -89,6 +89,18 @@ public:
// See IGraphicBufferConsumer::setDefaultBufferDataSpace
status_t setDefaultBufferDataSpace(android_dataspace defaultDataSpace);
+ // See IGraphicBufferConsumer::setConsumerUsageBits
+ status_t setConsumerUsageBits(uint64_t usage);
+
+ // See IGraphicBufferConsumer::setTransformHint
+ status_t setTransformHint(uint32_t hint);
+
+ // See IGraphicBufferConsumer::setMaxAcquiredBufferCount
+ status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers);
+
+ // See IGraphicBufferConsumer::getSidebandStream
+ sp<NativeHandle> getSidebandStream() const;
+
// See IGraphicBufferConsumer::getOccupancyHistory
status_t getOccupancyHistory(bool forceFlush,
std::vector<OccupancyTracker::Segment>* outHistory);
@@ -187,7 +199,7 @@ protected:
// ConsumerBase::releaseBufferLocked.
virtual status_t releaseBufferLocked(int slot,
const sp<GraphicBuffer> graphicBuffer,
- EGLDisplay display, EGLSyncKHR eglFence);
+ EGLDisplay display = EGL_NO_DISPLAY, EGLSyncKHR eglFence = EGL_NO_SYNC_KHR);
// returns true iff the slot still has the graphicBuffer in it.
bool stillTracking(int slot, const sp<GraphicBuffer> graphicBuffer);
diff --git a/libs/gui/include/gui/CpuConsumer.h b/libs/gui/include/gui/CpuConsumer.h
index 58602bf321..d375611e5b 100644
--- a/libs/gui/include/gui/CpuConsumer.h
+++ b/libs/gui/include/gui/CpuConsumer.h
@@ -94,12 +94,6 @@ class CpuConsumer : public ConsumerBase
CpuConsumer(const sp<IGraphicBufferConsumer>& bq,
size_t maxLockedBuffers, bool controlledByApp = false);
- virtual ~CpuConsumer();
-
- // set the name of the CpuConsumer that will be used to identify it in
- // log messages.
- void setName(const String8& name);
-
// Gets the next graphics buffer from the producer and locks it for CPU use,
// filling out the passed-in locked buffer structure with the native pointer
// and metadata. Returns BAD_VALUE if no new buffer is available, and
@@ -119,31 +113,39 @@ class CpuConsumer : public ConsumerBase
private:
// Maximum number of buffers that can be locked at a time
- size_t mMaxLockedBuffers;
-
- status_t releaseAcquiredBufferLocked(size_t lockedIdx);
-
- virtual void freeBufferLocked(int slotIndex);
+ const size_t mMaxLockedBuffers;
// Tracking for buffers acquired by the user
struct AcquiredBuffer {
+ static constexpr uintptr_t kUnusedId = 0;
+
// Need to track the original mSlot index and the buffer itself because
// the mSlot entry may be freed/reused before the acquired buffer is
// released.
int mSlot;
sp<GraphicBuffer> mGraphicBuffer;
- void *mBufferPointer;
+ uintptr_t mLockedBufferId;
AcquiredBuffer() :
mSlot(BufferQueue::INVALID_BUFFER_SLOT),
- mBufferPointer(NULL) {
+ mLockedBufferId(kUnusedId) {
+ }
+
+ void reset() {
+ mSlot = BufferQueue::INVALID_BUFFER_SLOT;
+ mGraphicBuffer.clear();
+ mLockedBufferId = kUnusedId;
}
};
+
+ size_t findAcquiredBufferLocked(uintptr_t id) const;
+
+ status_t lockBufferItem(const BufferItem& item, LockedBuffer* outBuffer) const;
+
Vector<AcquiredBuffer> mAcquiredBuffers;
// Count of currently locked buffers
size_t mCurrentLockedBuffers;
-
};
} // namespace android
diff --git a/libs/gui/include/gui/GLConsumer.h b/libs/gui/include/gui/GLConsumer.h
index 75f2ccaaea..71ed3bf239 100644
--- a/libs/gui/include/gui/GLConsumer.h
+++ b/libs/gui/include/gui/GLConsumer.h
@@ -138,6 +138,10 @@ public:
const sp<GraphicBuffer>& buf, const Rect& cropRect,
uint32_t transform, bool filtering);
+ // Scale the crop down horizontally or vertically such that it has the
+ // same aspect ratio as the buffer does.
+ static Rect scaleDownCrop(const Rect& crop, uint32_t bufferWidth, uint32_t bufferHeight);
+
// getTimestamp retrieves the timestamp associated with the texture image
// set by the most recent call to updateTexImage.
//
@@ -197,22 +201,9 @@ public:
// buffer is ready to be read from.
std::shared_ptr<FenceTime> getCurrentFenceTime() const;
- // doGLFenceWait inserts a wait command into the OpenGL ES command stream
- // to ensure that it is safe for future OpenGL ES commands to access the
- // current texture buffer.
- status_t doGLFenceWait() const;
-
- // set the name of the GLConsumer that will be used to identify it in
- // log messages.
- void setName(const String8& name);
-
- // These functions call the corresponding BufferQueue implementation
- // so the refactoring can proceed smoothly
- status_t setDefaultBufferFormat(PixelFormat defaultFormat);
- status_t setDefaultBufferDataSpace(android_dataspace defaultDataSpace);
+ // setConsumerUsageBits overrides the ConsumerBase method to OR
+ // DEFAULT_USAGE_FLAGS to usage.
status_t setConsumerUsageBits(uint64_t usage);
- status_t setTransformHint(uint32_t hint);
- status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers);
// detachFromContext detaches the GLConsumer from the calling thread's
// current OpenGL ES context. This context must be the same as the context
@@ -267,8 +258,6 @@ protected:
return releaseBufferLocked(slot, graphicBuffer, mEglDisplay, eglFence);
}
- static bool isExternalFormat(PixelFormat format);
-
struct PendingRelease {
PendingRelease() : isPending(false), currentTexture(-1),
graphicBuffer(), display(nullptr), fence(nullptr) {}
diff --git a/libs/gui/include/gui/HdrMetadata.h b/libs/gui/include/gui/HdrMetadata.h
new file mode 100644
index 0000000000..9800602d6c
--- /dev/null
+++ b/libs/gui/include/gui/HdrMetadata.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <system/graphics.h>
+#include <utils/Flattenable.h>
+
+namespace android {
+
+struct HdrMetadata : public LightFlattenable<HdrMetadata> {
+ enum Type : uint32_t {
+ SMPTE2086 = 1 << 0,
+ CTA861_3 = 1 << 1,
+ };
+ uint32_t validTypes{0};
+
+ android_smpte2086_metadata smpte2086{};
+ android_cta861_3_metadata cta8613{};
+
+ // LightFlattenable
+ bool isFixedSize() const { return false; }
+ size_t getFlattenedSize() const;
+ status_t flatten(void* buffer, size_t size) const;
+ status_t unflatten(void const* buffer, size_t size);
+
+ bool operator==(const HdrMetadata& rhs) const;
+};
+
+} // namespace android
diff --git a/libs/gui/include/gui/IGraphicBufferProducer.h b/libs/gui/include/gui/IGraphicBufferProducer.h
index 039dc0d657..887654e05b 100644
--- a/libs/gui/include/gui/IGraphicBufferProducer.h
+++ b/libs/gui/include/gui/IGraphicBufferProducer.h
@@ -31,6 +31,7 @@
#include <ui/Region.h>
#include <gui/FrameTimestamps.h>
+#include <gui/HdrMetadata.h>
#include <hidl/HybridInterface.h>
#include <android/hardware/graphics/bufferqueue/1.0/IGraphicBufferProducer.h>
@@ -72,6 +73,14 @@ public:
RELEASE_ALL_BUFFERS = 0x2,
};
+ enum {
+ // A parcelable magic indicates using Binder BufferQueue as transport
+ // backend.
+ USE_BUFFER_QUEUE = 0x62717565, // 'bque'
+ // A parcelable magic indicates using BufferHub as transport backend.
+ USE_BUFFER_HUB = 0x62687562, // 'bhub'
+ };
+
// requestBuffer requests a new buffer for the given index. The server (i.e.
// the IGraphicBufferProducer implementation) assigns the newly created
// buffer to the given slot index, and the client is expected to mirror the
@@ -354,6 +363,9 @@ public:
const Region& getSurfaceDamage() const { return surfaceDamage; }
void setSurfaceDamage(const Region& damage) { surfaceDamage = damage; }
+ const HdrMetadata& getHdrMetadata() const { return hdrMetadata; }
+ void setHdrMetadata(const HdrMetadata& metadata) { hdrMetadata = metadata; }
+
private:
int64_t timestamp{0};
int isAutoTimestamp{0};
@@ -365,6 +377,7 @@ public:
sp<Fence> fence;
Region surfaceDamage;
bool getFrameTimestamps{false};
+ HdrMetadata hdrMetadata;
};
struct QueueBufferOutput : public Flattenable<QueueBufferOutput> {
@@ -599,6 +612,24 @@ public:
// returned by querying the now deprecated
// NATIVE_WINDOW_CONSUMER_USAGE_BITS attribute.
virtual status_t getConsumerUsage(uint64_t* outUsage) const = 0;
+
+ // Static method exports any IGraphicBufferProducer object to a parcel. It
+ // handles null producer as well.
+ static status_t exportToParcel(const sp<IGraphicBufferProducer>& producer,
+ Parcel* parcel);
+
+ // Factory method that creates a new IBGP instance from the parcel.
+ static sp<IGraphicBufferProducer> createFromParcel(const Parcel* parcel);
+
+protected:
+ // Exports the current producer as a binder parcelable object. Note that the
+ // producer must be disconnected to be exportable. After successful export,
+ // the producer queue can no longer be connected again. Returns NO_ERROR
+ // when the export is successful and writes an implementation defined
+ // parcelable object into the parcel. For traditional Android BufferQueue,
+ // it writes a strong binder object; for BufferHub, it writes a
+ // ProducerQueueParcelable object.
+ virtual status_t exportToParcel(Parcel* parcel);
};
// ----------------------------------------------------------------------------
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index b2267426a8..e40157206d 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -29,6 +29,8 @@
#include <ui/FrameStats.h>
#include <ui/PixelFormat.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicTypes.h>
#include <vector>
@@ -59,6 +61,11 @@ public:
enum {
eSynchronous = 0x01,
eAnimation = 0x02,
+
+ // Indicates that this transaction will likely result in a lot of layers being composed, and
+ // thus, SurfaceFlinger should wake-up earlier to avoid missing frame deadlines. In this
+ // case SurfaceFlinger will wake up at (sf vsync offset - debug.sf.early_phase_offset_ns)
+ eEarlyWakeup = 0x04
};
enum {
@@ -159,20 +166,25 @@ public:
virtual status_t setActiveConfig(const sp<IBinder>& display, int id) = 0;
virtual status_t getDisplayColorModes(const sp<IBinder>& display,
- Vector<android_color_mode_t>* outColorModes) = 0;
- virtual android_color_mode_t getActiveColorMode(const sp<IBinder>& display) = 0;
+ Vector<ui::ColorMode>* outColorModes) = 0;
+ virtual ui::ColorMode getActiveColorMode(const sp<IBinder>& display) = 0;
virtual status_t setActiveColorMode(const sp<IBinder>& display,
- android_color_mode_t colorMode) = 0;
+ ui::ColorMode colorMode) = 0;
/* Capture the specified screen. requires READ_FRAME_BUFFER permission
* This function will fail if there is a secure window on screen.
*/
- virtual status_t captureScreen(const sp<IBinder>& display,
- const sp<IGraphicBufferProducer>& producer,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform,
- Rotation rotation = eRotateNone) = 0;
+ virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
+ Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+ int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform,
+ Rotation rotation = eRotateNone) = 0;
+
+ /**
+ * Capture a subtree of the layer hierarchy, potentially ignoring the root node.
+ */
+ virtual status_t captureLayers(const sp<IBinder>& layerHandleBinder,
+ sp<GraphicBuffer>* outBuffer, const Rect& sourceCrop,
+ float frameScale = 1.0, bool childrenOnly = false) = 0;
/* Clears the frame statistics for animations.
*
@@ -226,6 +238,7 @@ public:
SET_ACTIVE_CONFIG,
CONNECT_DISPLAY,
CAPTURE_SCREEN,
+ CAPTURE_LAYERS,
CLEAR_ANIMATION_FRAME_STATS,
GET_ANIMATION_FRAME_STATS,
SET_POWER_MODE,
diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h
index 2c613ea8c5..8dfc99a4b7 100644
--- a/libs/gui/include/gui/ISurfaceComposerClient.h
+++ b/libs/gui/include/gui/ISurfaceComposerClient.h
@@ -41,7 +41,7 @@ public:
eCursorWindow = 0x00002000,
eFXSurfaceNormal = 0x00000000,
- eFXSurfaceDim = 0x00020000,
+ eFXSurfaceColor = 0x00020000,
eFXSurfaceMask = 0x000F0000,
};
@@ -49,8 +49,8 @@ public:
* Requires ACCESS_SURFACE_FLINGER permission
*/
virtual status_t createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format,
- uint32_t flags, const sp<IBinder>& parent, uint32_t windowType,
- uint32_t ownerUid, sp<IBinder>* handle,
+ uint32_t flags, const sp<IBinder>& parent, int32_t windowType,
+ int32_t ownerUid, sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp) = 0;
/*
diff --git a/libs/gui/include/gui/LayerDebugInfo.h b/libs/gui/include/gui/LayerDebugInfo.h
index 8453e043ef..92bd8c5b28 100644
--- a/libs/gui/include/gui/LayerDebugInfo.h
+++ b/libs/gui/include/gui/LayerDebugInfo.h
@@ -22,6 +22,7 @@
#include <ui/Region.h>
#include <string>
+#include <math/vec4.h>
namespace android {
@@ -52,7 +53,7 @@ public:
int32_t mHeight = -1;
Rect mCrop = Rect::INVALID_RECT;
Rect mFinalCrop = Rect::INVALID_RECT;
- float mAlpha = 0.f;
+ half4 mColor = half4(1.0_hf, 1.0_hf, 1.0_hf, 0.0_hf);
uint32_t mFlags = 0;
PixelFormat mPixelFormat = PIXEL_FORMAT_NONE;
android_dataspace mDataSpace = HAL_DATASPACE_UNKNOWN;
diff --git a/libs/gui/include/private/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 307c764702..788962e490 100644
--- a/libs/gui/include/private/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -25,6 +25,7 @@
#include <ui/Region.h>
#include <ui/Rect.h>
#include <gui/IGraphicBufferProducer.h>
+#include <math/vec3.h>
namespace android {
@@ -59,7 +60,10 @@ struct layer_state_t {
eGeometryAppliesWithResize = 0x00001000,
eReparentChildren = 0x00002000,
eDetachChildren = 0x00004000,
- eRelativeLayerChanged = 0x00008000
+ eRelativeLayerChanged = 0x00008000,
+ eReparent = 0x00010000,
+ eColorChanged = 0x00020000,
+ eDestroySurface = 0x00040000
};
layer_state_t()
@@ -74,6 +78,7 @@ struct layer_state_t {
matrix.dsdy = matrix.dtdx = 0.0f;
}
+ void merge(const layer_state_t& other);
status_t write(Parcel& output) const;
status_t read(const Parcel& input);
@@ -107,6 +112,10 @@ struct layer_state_t {
sp<IBinder> relativeLayerHandle;
+ sp<IBinder> parentHandleForChild;
+
+ half3 color;
+
// non POD must be last. see write/read
Region transparentRegion;
};
@@ -137,6 +146,7 @@ struct DisplayState {
};
DisplayState();
+ void merge(const DisplayState& other);
uint32_t what;
sp<IBinder> token;
@@ -150,6 +160,20 @@ struct DisplayState {
status_t read(const Parcel& input);
};
+static inline
+int compare_type(const ComposerState& lhs, const ComposerState& rhs) {
+ if (lhs.client < rhs.client) return -1;
+ if (lhs.client > rhs.client) return 1;
+ if (lhs.state.surface < rhs.state.surface) return -1;
+ if (lhs.state.surface > rhs.state.surface) return 1;
+ return 0;
+}
+
+static inline
+int compare_type(const DisplayState& lhs, const DisplayState& rhs) {
+ return compare_type(lhs.token, rhs.token);
+}
+
}; // namespace android
#endif // ANDROID_SF_LAYER_STATE_H
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 55dd6bf067..9aeafae198 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -17,10 +17,12 @@
#ifndef ANDROID_GUI_SURFACE_H
#define ANDROID_GUI_SURFACE_H
-#include <gui/IGraphicBufferProducer.h>
#include <gui/BufferQueueDefs.h>
+#include <gui/HdrMetadata.h>
+#include <gui/IGraphicBufferProducer.h>
#include <ui/ANativeObjectBase.h>
+#include <ui/GraphicTypes.h>
#include <ui/Region.h>
#include <utils/Condition.h>
@@ -214,6 +216,8 @@ private:
int dispatchUnlockAndPost(va_list args);
int dispatchSetSidebandStream(va_list args);
int dispatchSetBuffersDataSpace(va_list args);
+ int dispatchSetBuffersSmpte2086Metadata(va_list args);
+ int dispatchSetBuffersCta8613Metadata(va_list args);
int dispatchSetSurfaceDamage(va_list args);
int dispatchSetSharedBufferMode(va_list args);
int dispatchSetAutoRefresh(va_list args);
@@ -242,7 +246,9 @@ protected:
virtual int setBuffersTransform(uint32_t transform);
virtual int setBuffersStickyTransform(uint32_t transform);
virtual int setBuffersTimestamp(int64_t timestamp);
- virtual int setBuffersDataSpace(android_dataspace dataSpace);
+ virtual int setBuffersDataSpace(ui::Dataspace dataSpace);
+ virtual int setBuffersSmpte2086Metadata(const android_smpte2086_metadata* metadata);
+ virtual int setBuffersCta8613Metadata(const android_cta861_3_metadata* metadata);
virtual int setCrop(Rect const* rect);
virtual int setUsage(uint64_t reqUsage);
virtual void setSurfaceDamage(android_native_rect_t* rects, size_t numRects);
@@ -281,6 +287,10 @@ public:
// detachNextBuffer, or attachBuffer call.
status_t getAndFlushRemovedBuffers(std::vector<sp<GraphicBuffer>>* out);
+ ui::Dataspace getBuffersDataSpace();
+
+ static status_t attachAndQueueBuffer(Surface* surface, sp<GraphicBuffer> buffer);
+
protected:
enum { NUM_BUFFER_SLOTS = BufferQueueDefs::NUM_BUFFER_SLOTS };
enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };
@@ -331,9 +341,13 @@ protected:
int64_t mTimestamp;
// mDataSpace is the buffer dataSpace that will be used for the next buffer
- // queue operation. It defaults to HAL_DATASPACE_UNKNOWN, which
+ // queue operation. It defaults to Dataspace::UNKNOWN, which
// means that the buffer contains some type of color data.
- android_dataspace mDataSpace;
+ ui::Dataspace mDataSpace;
+
+ // mHdrMetadata is the HDR metadata that will be used for the next buffer
+ // queue operation. There is no HDR metadata by default.
+ HdrMetadata mHdrMetadata;
// mCrop is the crop rectangle that will be used for the next buffer
// that gets queued. It is set by calling setCrop.
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 145c0597bd..377fe68c41 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -19,6 +19,7 @@
#include <stdint.h>
#include <sys/types.h>
+#include <unordered_map>
#include <binder/IBinder.h>
@@ -28,17 +29,19 @@
#include <utils/threads.h>
#include <ui/FrameStats.h>
+#include <ui/GraphicTypes.h>
#include <ui/PixelFormat.h>
#include <gui/CpuConsumer.h>
#include <gui/SurfaceControl.h>
+#include <math/vec3.h>
+#include <gui/LayerState.h>
namespace android {
// ---------------------------------------------------------------------------
struct DisplayInfo;
-class Composer;
class HdrCapabilities;
class ISurfaceComposerClient;
class IGraphicBufferProducer;
@@ -51,6 +54,7 @@ class SurfaceComposerClient : public RefBase
friend class Composer;
public:
SurfaceComposerClient();
+ SurfaceComposerClient(const sp<ISurfaceComposerClient>& client);
SurfaceComposerClient(const sp<IGraphicBufferProducer>& parent);
virtual ~SurfaceComposerClient();
@@ -85,13 +89,14 @@ public:
// Gets the list of supported color modes for the given display
static status_t getDisplayColorModes(const sp<IBinder>& display,
- Vector<android_color_mode_t>* outColorModes);
+ Vector<ui::ColorMode>* outColorModes);
// Gets the active color mode for the given display
- static android_color_mode_t getActiveColorMode(const sp<IBinder>& display);
+ static ui::ColorMode getActiveColorMode(const sp<IBinder>& display);
// Sets the active color mode for the given display
- static status_t setActiveColorMode(const sp<IBinder>& display, android_color_mode_t colorMode);
+ static status_t setActiveColorMode(const sp<IBinder>& display,
+ ui::ColorMode colorMode);
/* Triggers screen on/off or low power mode and waits for it to complete */
static void setDisplayPowerMode(const sp<IBinder>& display, int mode);
@@ -107,8 +112,20 @@ public:
PixelFormat format, // pixel-format desired
uint32_t flags = 0, // usage flags
SurfaceControl* parent = nullptr, // parent
- uint32_t windowType = 0, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.)
- uint32_t ownerUid = 0 // UID of the task
+ int32_t windowType = -1, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.)
+ int32_t ownerUid = -1 // UID of the task
+ );
+
+ status_t createSurfaceChecked(
+ const String8& name,// name of the surface
+ uint32_t w, // width in pixel
+ uint32_t h, // height in pixel
+ PixelFormat format, // pixel-format desired
+ sp<SurfaceControl>* outSurface,
+ uint32_t flags = 0, // usage flags
+ SurfaceControl* parent = nullptr, // parent
+ int32_t windowType = -1, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.)
+ int32_t ownerUid = -1 // UID of the task
);
//! Create a virtual display
@@ -121,157 +138,185 @@ public:
//! Possible values for id are eDisplayIdMain and eDisplayIdHdmi.
static sp<IBinder> getBuiltInDisplay(int32_t id);
- // ------------------------------------------------------------------------
- // Composer parameters
- // All composer parameters must be changed within a transaction
- // several surfaces can be updated in one transaction, all changes are
- // committed at once when the transaction is closed.
- // closeGlobalTransaction() requires an IPC with the server.
-
- //! Open a composer transaction on all active SurfaceComposerClients.
- static void openGlobalTransaction();
-
- //! Close a composer transaction on all active SurfaceComposerClients.
- static void closeGlobalTransaction(bool synchronous = false);
-
static status_t enableVSyncInjections(bool enable);
static status_t injectVSync(nsecs_t when);
- //! Flag the currently open transaction as an animation transaction.
- static void setAnimationTransaction();
-
- status_t hide(const sp<IBinder>& id);
- status_t show(const sp<IBinder>& id);
- status_t setFlags(const sp<IBinder>& id, uint32_t flags, uint32_t mask);
- status_t setTransparentRegionHint(const sp<IBinder>& id, const Region& transparent);
- status_t setLayer(const sp<IBinder>& id, int32_t layer);
- status_t setRelativeLayer(const sp<IBinder>& id,
- const sp<IBinder>& relativeTo, int32_t layer);
- status_t setAlpha(const sp<IBinder>& id, float alpha=1.0f);
- status_t setMatrix(const sp<IBinder>& id, float dsdx, float dtdx, float dtdy, float dsdy);
- status_t setPosition(const sp<IBinder>& id, float x, float y);
- status_t setSize(const sp<IBinder>& id, uint32_t w, uint32_t h);
- status_t setCrop(const sp<IBinder>& id, const Rect& crop);
- status_t setFinalCrop(const sp<IBinder>& id, const Rect& crop);
- status_t setLayerStack(const sp<IBinder>& id, uint32_t layerStack);
- status_t deferTransactionUntil(const sp<IBinder>& id,
- const sp<IBinder>& handle, uint64_t frameNumber);
- status_t deferTransactionUntil(const sp<IBinder>& id,
- const sp<Surface>& handle, uint64_t frameNumber);
- status_t reparentChildren(const sp<IBinder>& id,
- const sp<IBinder>& newParentHandle);
- status_t detachChildren(const sp<IBinder>& id);
- status_t setOverrideScalingMode(const sp<IBinder>& id,
- int32_t overrideScalingMode);
- status_t setGeometryAppliesWithResize(const sp<IBinder>& id);
+ struct SCHash {
+ std::size_t operator()(const sp<SurfaceControl>& sc) const {
+ return std::hash<SurfaceControl *>{}(sc.get());
+ }
+ };
+
+ class Transaction {
+ std::unordered_map<sp<SurfaceControl>, ComposerState, SCHash> mComposerStates;
+ SortedVector<DisplayState > mDisplayStates;
+ uint32_t mForceSynchronous = 0;
+ uint32_t mTransactionNestCount = 0;
+ bool mAnimation = false;
+ bool mEarlyWakeup = false;
+
+ int mStatus = NO_ERROR;
+
+ layer_state_t* getLayerState(const sp<SurfaceControl>& sc);
+ DisplayState& getDisplayState(const sp<IBinder>& token);
+
+ public:
+ Transaction() = default;
+ virtual ~Transaction() = default;
+ Transaction(Transaction const& other);
+
+ status_t apply(bool synchronous = false);
+ // Merge another transaction in to this one, clearing other
+ // as if it had been applied.
+ Transaction& merge(Transaction&& other);
+ Transaction& show(const sp<SurfaceControl>& sc);
+ Transaction& hide(const sp<SurfaceControl>& sc);
+ Transaction& setPosition(const sp<SurfaceControl>& sc,
+ float x, float y);
+ Transaction& setSize(const sp<SurfaceControl>& sc,
+ uint32_t w, uint32_t h);
+ Transaction& setLayer(const sp<SurfaceControl>& sc,
+ int32_t z);
+
+ // Sets a Z order relative to the Surface specified by "relativeTo" but
+ // without becoming a full child of the relative. Z-ordering works exactly
+ // as if it were a child however.
+ //
+ // As a nod to sanity, only non-child surfaces may have a relative Z-order.
+ //
+ // This overrides any previous call and is overriden by any future calls
+ // to setLayer.
+ //
+ // If the relative is removed, the Surface will have no layer and be
+ // invisible, until the next time set(Relative)Layer is called.
+ Transaction& setRelativeLayer(const sp<SurfaceControl>& sc,
+ const sp<IBinder>& relativeTo, int32_t z);
+ Transaction& setFlags(const sp<SurfaceControl>& sc,
+ uint32_t flags, uint32_t mask);
+ Transaction& setTransparentRegionHint(const sp<SurfaceControl>& sc,
+ const Region& transparentRegion);
+ Transaction& setAlpha(const sp<SurfaceControl>& sc,
+ float alpha);
+ Transaction& setMatrix(const sp<SurfaceControl>& sc,
+ float dsdx, float dtdx, float dtdy, float dsdy);
+ Transaction& setCrop(const sp<SurfaceControl>& sc, const Rect& crop);
+ Transaction& setFinalCrop(const sp<SurfaceControl>& sc, const Rect& crop);
+ Transaction& setLayerStack(const sp<SurfaceControl>& sc, uint32_t layerStack);
+ // Defers applying any changes made in this transaction until the Layer
+ // identified by handle reaches the given frameNumber. If the Layer identified
+ // by handle is removed, then we will apply this transaction regardless of
+ // what frame number has been reached.
+ Transaction& deferTransactionUntil(const sp<SurfaceControl>& sc,
+ const sp<IBinder>& handle,
+ uint64_t frameNumber);
+ // A variant of deferTransactionUntil which identifies the Layer we wait for by
+ // Surface instead of Handle. Useful for clients which may not have the
+ // SurfaceControl for some of their Surfaces. Otherwise behaves identically.
+ Transaction& deferTransactionUntil(const sp<SurfaceControl>& sc,
+ const sp<Surface>& barrierSurface,
+ uint64_t frameNumber);
+ // Reparents all children of this layer to the new parent handle.
+ Transaction& reparentChildren(const sp<SurfaceControl>& sc,
+ const sp<IBinder>& newParentHandle);
+
+ /// Reparents the current layer to the new parent handle. The new parent must not be null.
+ // This can be used instead of reparentChildren if the caller wants to
+ // only re-parent a specific child.
+ Transaction& reparent(const sp<SurfaceControl>& sc,
+ const sp<IBinder>& newParentHandle);
+
+ Transaction& setColor(const sp<SurfaceControl>& sc, const half3& color);
+
+ // Detaches all child surfaces (and their children recursively)
+ // from their SurfaceControl.
+ // The child SurfaceControls will not throw exceptions or return errors,
+ // but transactions will have no effect.
+ // The child surfaces will continue to follow their parent surfaces,
+ // and remain eligible for rendering, but their relative state will be
+ // frozen. We use this in the WindowManager, in app shutdown/relaunch
+ // scenarios, where the app would otherwise clean up its child Surfaces.
+ // Sometimes the WindowManager needs to extend their lifetime slightly
+ // in order to perform an exit animation or prevent flicker.
+ Transaction& detachChildren(const sp<SurfaceControl>& sc);
+ // Set an override scaling mode as documented in <system/window.h>
+ // the override scaling mode will take precedence over any client
+ // specified scaling mode. -1 will clear the override scaling mode.
+ Transaction& setOverrideScalingMode(const sp<SurfaceControl>& sc,
+ int32_t overrideScalingMode);
+
+ // If the size changes in this transaction, all geometry updates specified
+ // in this transaction will not complete until a buffer of the new size
+ // arrives. As some elements normally apply immediately, this enables
+ // freezing the total geometry of a surface until a resize is completed.
+ Transaction& setGeometryAppliesWithResize(const sp<SurfaceControl>& sc);
+
+ Transaction& destroySurface(const sp<SurfaceControl>& sc);
+
+ status_t setDisplaySurface(const sp<IBinder>& token,
+ const sp<IGraphicBufferProducer>& bufferProducer);
+
+ void setDisplayLayerStack(const sp<IBinder>& token, uint32_t layerStack);
+
+ /* setDisplayProjection() defines the projection of layer stacks
+ * to a given display.
+ *
+ * - orientation defines the display's orientation.
+ * - layerStackRect defines which area of the window manager coordinate
+ * space will be used.
+ * - displayRect defines where on the display will layerStackRect be
+ * mapped to. displayRect is specified post-orientation, that is
+ * it uses the orientation seen by the end-user.
+ */
+ void setDisplayProjection(const sp<IBinder>& token,
+ uint32_t orientation,
+ const Rect& layerStackRect,
+ const Rect& displayRect);
+ void setDisplaySize(const sp<IBinder>& token, uint32_t width, uint32_t height);
+ void setAnimationTransaction();
+ void setEarlyWakeup();
+ };
status_t destroySurface(const sp<IBinder>& id);
status_t clearLayerFrameStats(const sp<IBinder>& token) const;
status_t getLayerFrameStats(const sp<IBinder>& token, FrameStats* outStats) const;
-
static status_t clearAnimationFrameStats();
static status_t getAnimationFrameStats(FrameStats* outStats);
static status_t getHdrCapabilities(const sp<IBinder>& display,
HdrCapabilities* outCapabilities);
- static status_t setDisplaySurface(const sp<IBinder>& token,
- sp<IGraphicBufferProducer> bufferProducer);
- static void setDisplayLayerStack(const sp<IBinder>& token,
- uint32_t layerStack);
- static void setDisplaySize(const sp<IBinder>& token, uint32_t width, uint32_t height);
-
- /* setDisplayProjection() defines the projection of layer stacks
- * to a given display.
- *
- * - orientation defines the display's orientation.
- * - layerStackRect defines which area of the window manager coordinate
- * space will be used.
- * - displayRect defines where on the display will layerStackRect be
- * mapped to. displayRect is specified post-orientation, that is
- * it uses the orientation seen by the end-user.
- */
static void setDisplayProjection(const sp<IBinder>& token,
uint32_t orientation,
const Rect& layerStackRect,
const Rect& displayRect);
+ inline sp<ISurfaceComposerClient> getClient() { return mClient; }
+
private:
virtual void onFirstRef();
- Composer& getComposer();
mutable Mutex mLock;
status_t mStatus;
sp<ISurfaceComposerClient> mClient;
- Composer& mComposer;
wp<IGraphicBufferProducer> mParent;
};
// ---------------------------------------------------------------------------
-class ScreenshotClient
-{
+class ScreenshotClient {
public:
// if cropping isn't required, callers may pass in a default Rect, e.g.:
// capture(display, producer, Rect(), reqWidth, ...);
- static status_t capture(
- const sp<IBinder>& display,
- const sp<IGraphicBufferProducer>& producer,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform);
- static status_t captureToBuffer(
- const sp<IBinder>& display,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform,
- uint32_t rotation,
- sp<GraphicBuffer>* outbuffer);
-private:
- mutable sp<CpuConsumer> mCpuConsumer;
- mutable sp<IGraphicBufferProducer> mProducer;
- CpuConsumer::LockedBuffer mBuffer;
- bool mHaveBuffer;
-
-public:
- ScreenshotClient();
- ~ScreenshotClient();
-
- // frees the previous screenshot and captures a new one
- // if cropping isn't required, callers may pass in a default Rect, e.g.:
- // update(display, Rect(), useIdentityTransform);
- status_t update(const sp<IBinder>& display,
- Rect sourceCrop, bool useIdentityTransform);
- status_t update(const sp<IBinder>& display,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- bool useIdentityTransform);
- status_t update(const sp<IBinder>& display,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform);
- status_t update(const sp<IBinder>& display,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform, uint32_t rotation);
-
- sp<CpuConsumer> getCpuConsumer() const;
-
- // release memory occupied by the screenshot
- void release();
-
- // pixels are valid until this object is freed or
- // release() or update() is called
- void const* getPixels() const;
-
- uint32_t getWidth() const;
- uint32_t getHeight() const;
- PixelFormat getFormat() const;
- uint32_t getStride() const;
- // size of allocated memory in bytes
- size_t getSize() const;
- android_dataspace getDataSpace() const;
+ static status_t capture(const sp<IBinder>& display, Rect sourceCrop, uint32_t reqWidth,
+ uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ,
+ bool useIdentityTransform, uint32_t rotation,
+ sp<GraphicBuffer>* outBuffer);
+ static status_t captureLayers(const sp<IBinder>& layerHandle, Rect sourceCrop, float frameScale,
+ sp<GraphicBuffer>* outBuffer);
+ static status_t captureChildLayers(const sp<IBinder>& layerHandle, Rect sourceCrop,
+ float frameScale, sp<GraphicBuffer>* outBuffer);
};
// ---------------------------------------------------------------------------
diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h
index c15209d32c..bd987dd638 100644
--- a/libs/gui/include/gui/SurfaceControl.h
+++ b/libs/gui/include/gui/SurfaceControl.h
@@ -29,6 +29,7 @@
#include <ui/Region.h>
#include <gui/ISurfaceComposerClient.h>
+#include <math/vec3.h>
namespace android {
@@ -43,6 +44,9 @@ class SurfaceComposerClient;
class SurfaceControl : public RefBase
{
public:
+ static sp<SurfaceControl> readFromParcel(Parcel* parcel);
+ void writeToParcel(Parcel* parcel);
+
static bool isValid(const sp<SurfaceControl>& surface) {
return (surface != 0) && surface->isValid();
}
@@ -60,87 +64,6 @@ public:
// disconnect any api that's connected
void disconnect();
- status_t setLayerStack(uint32_t layerStack);
- status_t setLayer(int32_t layer);
-
- // Sets a Z order relative to the Surface specified by "relativeTo" but
- // without becoming a full child of the relative. Z-ordering works exactly
- // as if it were a child however.
- //
- // As a nod to sanity, only non-child surfaces may have a relative Z-order.
- //
- // This overrides any previous and is overriden by any future calls
- // to setLayer.
- //
- // If the relative dissapears, the Surface will have no layer and be
- // invisible, until the next time set(Relative)Layer is called.
- //
- // TODO: This is probably a hack. Currently it exists only to work around
- // some framework usage of the hidden APPLICATION_MEDIA_OVERLAY window type
- // which allows inserting a window between a SurfaceView and it's main application
- // window. However, since we are using child windows for the SurfaceView, but not using
- // child windows elsewhere in O, the WindowManager can't set the layer appropriately.
- // This is only used by the "TvInputService" and following the port of ViewRootImpl
- // to child surfaces, we can then port this and remove this method.
- status_t setRelativeLayer(const sp<IBinder>& relativeTo, int32_t layer);
- status_t setPosition(float x, float y);
- status_t setSize(uint32_t w, uint32_t h);
- status_t hide();
- status_t show();
- status_t setFlags(uint32_t flags, uint32_t mask);
- status_t setTransparentRegionHint(const Region& transparent);
- status_t setAlpha(float alpha=1.0f);
-
- // Experimentarily it appears that the matrix transforms the
- // on-screen rectangle and it's contents before the position is
- // applied.
- //
- // TODO: Test with other combinations to find approximate transformation rules.
- //
- // For example:
- // Layer sized (W,H) set to position (x,y) with matrix M=[-1, 0, 0, 1] (Horizontal flip) gives
- // [((0, 0), (W, H)) x M] + (x,y) = ((-W, 0), (0, H)) + (x,y) = ((-W + x, y), (x, H+y))
- status_t setMatrix(float dsdx, float dtdx, float dtdy, float dsdy);
- status_t setCrop(const Rect& crop);
- status_t setFinalCrop(const Rect& crop);
-
- // If the size changes in this transaction, all geometry updates specified
- // in this transaction will not complete until a buffer of the new size
- // arrives. As some elements normally apply immediately, this enables
- // freezing the total geometry of a surface until a resize is completed.
- status_t setGeometryAppliesWithResize();
-
- // Defers applying any changes made in this transaction until the Layer
- // identified by handle reaches the given frameNumber. If the Layer identified
- // by handle is removed, then we will apply this transaction regardless of
- // what frame number has been reached.
- status_t deferTransactionUntil(const sp<IBinder>& handle, uint64_t frameNumber);
-
- // A variant of deferTransactionUntil which identifies the Layer we wait for by
- // Surface instead of Handle. Useful for clients which may not have the
- // SurfaceControl for some of their Surfaces. Otherwise behaves identically.
- status_t deferTransactionUntil(const sp<Surface>& barrier, uint64_t frameNumber);
-
- // Reparents all children of this layer to the new parent handle.
- status_t reparentChildren(const sp<IBinder>& newParentHandle);
-
- // Detaches all child surfaces (and their children recursively)
- // from their SurfaceControl.
- // The child SurfaceControl's will not throw exceptions or return errors,
- // but transactions will have no effect.
- // The child surfaces will continue to follow their parent surfaces,
- // and remain eligible for rendering, but their relative state will be
- // frozen. We use this in the WindowManager, in app shutdown/relaunch
- // scenarios, where the app would otherwise clean up its child Surfaces.
- // Sometimes the WindowManager needs to extend their lifetime slightly
- // in order to perform an exit animation or prevent flicker.
- status_t detachChildren();
-
- // Set an override scaling mode as documented in <system/window.h>
- // the override scaling mode will take precedence over any client
- // specified scaling mode. -1 will clear the override scaling mode.
- status_t setOverrideScalingMode(int32_t overrideScalingMode);
-
static status_t writeSurfaceToParcel(
const sp<SurfaceControl>& control, Parcel* parcel);
@@ -151,6 +74,8 @@ public:
status_t clearLayerFrameStats() const;
status_t getLayerFrameStats(FrameStats* outStats) const;
+ sp<SurfaceComposerClient> getClient() const;
+
private:
// can't be copied
SurfaceControl& operator = (SurfaceControl& rhs);
@@ -162,7 +87,8 @@ private:
SurfaceControl(
const sp<SurfaceComposerClient>& client,
const sp<IBinder>& handle,
- const sp<IGraphicBufferProducer>& gbp);
+ const sp<IGraphicBufferProducer>& gbp,
+ bool owned);
~SurfaceControl();
@@ -175,6 +101,7 @@ private:
sp<IGraphicBufferProducer> mGraphicBufferProducer;
mutable Mutex mLock;
mutable sp<Surface> mSurfaceData;
+ bool mOwned;
};
}; // namespace android
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index 908959ce1a..01e90e0eb8 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -49,3 +49,35 @@ cc_test {
"libnativewindow"
],
}
+
+// Build a separate binary for each source file to $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE)
+cc_test {
+ name: "libgui_separate_binary_test",
+ test_suites: ["device-tests"],
+
+ clang: true,
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+
+ test_per_src: true,
+ srcs: [
+ "SurfaceParcelable_test.cpp",
+ ],
+
+ shared_libs: [
+ "liblog",
+ "libbinder",
+ "libcutils",
+ "libgui",
+ "libui",
+ "libutils",
+ "libbufferhubqueue", // TODO(b/70046255): Remove these once BufferHub is integrated into libgui.
+ "libpdx_default_transport",
+ ],
+
+ header_libs: [
+ "libdvr_headers",
+ ],
+}
diff --git a/libs/gui/tests/CpuConsumer_test.cpp b/libs/gui/tests/CpuConsumer_test.cpp
index 588e54142f..36be7d9368 100644
--- a/libs/gui/tests/CpuConsumer_test.cpp
+++ b/libs/gui/tests/CpuConsumer_test.cpp
@@ -33,6 +33,7 @@
#include <utils/Mutex.h>
#include <utils/Condition.h>
+#include <thread>
#include <vector>
#define CPU_CONSUMER_TEST_FORMAT_RAW 0
#define CPU_CONSUMER_TEST_FORMAT_Y8 0
@@ -681,6 +682,70 @@ TEST_P(CpuConsumerTest, FromCpuLockMax) {
}
}
+TEST_P(CpuConsumerTest, FromCpuInvalid) {
+ status_t err = mCC->lockNextBuffer(nullptr);
+ ASSERT_EQ(BAD_VALUE, err) << "lockNextBuffer did not fail";
+
+ CpuConsumer::LockedBuffer b;
+ err = mCC->unlockBuffer(b);
+ ASSERT_EQ(BAD_VALUE, err) << "unlockBuffer did not fail";
+}
+
+TEST_P(CpuConsumerTest, FromCpuMultiThread) {
+ CpuConsumerTestParams params = GetParam();
+ ASSERT_NO_FATAL_FAILURE(configureANW(mANW, params, params.maxLockedBuffers + 1));
+
+ for (int i = 0; i < 10; i++) {
+ std::atomic<int> threadReadyCount(0);
+ auto lockAndUnlock = [&]() {
+ threadReadyCount++;
+ // busy wait
+ while (threadReadyCount < params.maxLockedBuffers + 1);
+
+ CpuConsumer::LockedBuffer b;
+ status_t err = mCC->lockNextBuffer(&b);
+ if (err == NO_ERROR) {
+ usleep(1000);
+ err = mCC->unlockBuffer(b);
+ ASSERT_NO_ERROR(err, "Could not unlock buffer: ");
+ } else if (err == NOT_ENOUGH_DATA) {
+ // there are params.maxLockedBuffers+1 threads so one of the
+ // threads might get this error
+ } else {
+ FAIL() << "Could not lock buffer";
+ }
+ };
+
+ // produce buffers
+ for (int j = 0; j < params.maxLockedBuffers + 1; j++) {
+ const int64_t time = 1234L;
+ uint32_t stride;
+ ASSERT_NO_FATAL_FAILURE(produceOneFrame(mANW, params, time, &stride));
+ }
+
+ // spawn threads
+ std::vector<std::thread> threads;
+ for (int j = 0; j < params.maxLockedBuffers + 1; j++) {
+ threads.push_back(std::thread(lockAndUnlock));
+ }
+
+ // join threads
+ for (auto& thread : threads) {
+ thread.join();
+ }
+
+ // we produced N+1 buffers, but the threads might only consume N
+ CpuConsumer::LockedBuffer b;
+ if (mCC->lockNextBuffer(&b) == NO_ERROR) {
+ mCC->unlockBuffer(b);
+ }
+
+ if (HasFatalFailure()) {
+ break;
+ }
+ }
+}
+
CpuConsumerTestParams y8TestSets[] = {
{ 512, 512, 1, HAL_PIXEL_FORMAT_Y8},
{ 512, 512, 3, HAL_PIXEL_FORMAT_Y8},
diff --git a/libs/gui/tests/GLTest.cpp b/libs/gui/tests/GLTest.cpp
index 1739d9c7ca..a91552f7fe 100644
--- a/libs/gui/tests/GLTest.cpp
+++ b/libs/gui/tests/GLTest.cpp
@@ -22,6 +22,8 @@
namespace android {
+using Transaction = SurfaceComposerClient::Transaction;
+
static int abs(int value) {
return value > 0 ? value : -value;
}
@@ -68,10 +70,10 @@ void GLTest::SetUp() {
ASSERT_TRUE(mSurfaceControl != NULL);
ASSERT_TRUE(mSurfaceControl->isValid());
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
- ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
- SurfaceComposerClient::closeGlobalTransaction();
+ Transaction t;
+ ASSERT_EQ(NO_ERROR, t.setLayer(mSurfaceControl, 0x7FFFFFFF)
+ .show(mSurfaceControl)
+ .apply());
sp<ANativeWindow> window = mSurfaceControl->getSurface();
mEglSurface = createWindowSurface(mEglDisplay, mGlConfig, window);
diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp
index dd23bd4cb2..a35cf11174 100644
--- a/libs/gui/tests/IGraphicBufferProducer_test.cpp
+++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp
@@ -42,6 +42,10 @@
#define TEST_CONTROLLED_BY_APP false
#define TEST_PRODUCER_USAGE_BITS (0)
+#ifndef USE_BUFFER_HUB_AS_BUFFER_QUEUE
+#define USE_BUFFER_HUB_AS_BUFFER_QUEUE 0
+#endif
+
namespace android {
namespace {
@@ -66,9 +70,15 @@ namespace {
const int QUEUE_BUFFER_INPUT_SCALING_MODE = 0;
const int QUEUE_BUFFER_INPUT_TRANSFORM = 0;
const sp<Fence> QUEUE_BUFFER_INPUT_FENCE = Fence::NO_FENCE;
+
+ // Enums to control which IGraphicBufferProducer backend to test.
+ enum IGraphicBufferProducerTestCode {
+ USE_BUFFER_QUEUE_PRODUCER = 0,
+ USE_BUFFER_HUB_PRODUCER,
+ };
}; // namespace anonymous
-class IGraphicBufferProducerTest : public ::testing::Test {
+class IGraphicBufferProducerTest : public ::testing::TestWithParam<uint32_t> {
protected:
IGraphicBufferProducerTest() {}
@@ -81,10 +91,27 @@ protected:
mDC = new DummyConsumer;
- BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+ switch (GetParam()) {
+ case USE_BUFFER_QUEUE_PRODUCER: {
+ BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+ break;
+ }
+ case USE_BUFFER_HUB_PRODUCER: {
+ BufferQueue::createBufferHubQueue(&mProducer, &mConsumer);
+ break;
+ }
+ default: {
+ // Should never reach here.
+ LOG_ALWAYS_FATAL("Invalid test params: %u", GetParam());
+ break;
+ }
+ }
// Test check: Can't connect producer if no consumer yet
- ASSERT_EQ(NO_INIT, TryConnectProducer());
+ if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
+ // TODO(b/73267953): Make BufferHub honor producer and consumer connection.
+ ASSERT_EQ(NO_INIT, TryConnectProducer());
+ }
// Must connect consumer before producer connects will succeed.
ASSERT_OK(mConsumer->consumerConnect(mDC, /*controlledByApp*/false));
@@ -229,7 +256,7 @@ protected: // accessible from test body
sp<IGraphicBufferConsumer> mConsumer;
};
-TEST_F(IGraphicBufferProducerTest, ConnectFirst_ReturnsError) {
+TEST_P(IGraphicBufferProducerTest, ConnectFirst_ReturnsError) {
IGraphicBufferProducer::QueueBufferOutput output;
// NULL output returns BAD_VALUE
@@ -247,7 +274,7 @@ TEST_F(IGraphicBufferProducerTest, ConnectFirst_ReturnsError) {
// TODO: get a token from a dead process somehow
}
-TEST_F(IGraphicBufferProducerTest, ConnectAgain_ReturnsError) {
+TEST_P(IGraphicBufferProducerTest, ConnectAgain_ReturnsError) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
// Can't connect when there is already a producer connected
@@ -259,20 +286,23 @@ TEST_F(IGraphicBufferProducerTest, ConnectAgain_ReturnsError) {
ASSERT_OK(mConsumer->consumerDisconnect());
// Can't connect when IGBP is abandoned
- EXPECT_EQ(NO_INIT, mProducer->connect(TEST_TOKEN,
- TEST_API,
- TEST_CONTROLLED_BY_APP,
- &output));
+ if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
+ // TODO(b/73267953): Make BufferHub honor producer and consumer connection.
+ EXPECT_EQ(NO_INIT, mProducer->connect(TEST_TOKEN,
+ TEST_API,
+ TEST_CONTROLLED_BY_APP,
+ &output));
+ }
}
-TEST_F(IGraphicBufferProducerTest, Disconnect_Succeeds) {
+TEST_P(IGraphicBufferProducerTest, Disconnect_Succeeds) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
ASSERT_OK(mProducer->disconnect(TEST_API));
}
-TEST_F(IGraphicBufferProducerTest, Disconnect_ReturnsError) {
+TEST_P(IGraphicBufferProducerTest, Disconnect_ReturnsError) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
// Must disconnect with same API number
@@ -283,7 +313,7 @@ TEST_F(IGraphicBufferProducerTest, Disconnect_ReturnsError) {
// TODO: somehow kill mProducer so that this returns DEAD_OBJECT
}
-TEST_F(IGraphicBufferProducerTest, Query_Succeeds) {
+TEST_P(IGraphicBufferProducerTest, Query_Succeeds) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
int32_t value = -1;
@@ -308,7 +338,7 @@ TEST_F(IGraphicBufferProducerTest, Query_Succeeds) {
}
-TEST_F(IGraphicBufferProducerTest, Query_ReturnsError) {
+TEST_P(IGraphicBufferProducerTest, Query_ReturnsError) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
// One past the end of the last 'query' enum value. Update this if we add more enums.
@@ -334,14 +364,17 @@ TEST_F(IGraphicBufferProducerTest, Query_ReturnsError) {
ASSERT_OK(mConsumer->consumerDisconnect());
// BQ was abandoned
- EXPECT_EQ(NO_INIT, mProducer->query(NATIVE_WINDOW_FORMAT, &value));
+ if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
+ // TODO(b/73267953): Make BufferHub honor producer and consumer connection.
+ EXPECT_EQ(NO_INIT, mProducer->query(NATIVE_WINDOW_FORMAT, &value));
+ }
// TODO: other things in window.h that are supported by Surface::query
// but not by BufferQueue::query
}
// TODO: queue under more complicated situations not involving just a single buffer
-TEST_F(IGraphicBufferProducerTest, Queue_Succeeds) {
+TEST_P(IGraphicBufferProducerTest, Queue_Succeeds) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
int dequeuedSlot = -1;
@@ -371,16 +404,21 @@ TEST_F(IGraphicBufferProducerTest, Queue_Succeeds) {
EXPECT_EQ(DEFAULT_WIDTH, output.width);
EXPECT_EQ(DEFAULT_HEIGHT, output.height);
EXPECT_EQ(DEFAULT_TRANSFORM_HINT, output.transformHint);
+
// Since queueBuffer was called exactly once
- EXPECT_EQ(1u, output.numPendingBuffers);
- EXPECT_EQ(2u, output.nextFrameNumber);
+ if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
+ // TODO(b/70041889): BufferHubProducer need to support metadata: numPendingBuffers
+ EXPECT_EQ(1u, output.numPendingBuffers);
+ // TODO(b/70041952): BufferHubProducer need to support metadata: nextFrameNumber
+ EXPECT_EQ(2u, output.nextFrameNumber);
+ }
}
// Buffer was not in the dequeued state
EXPECT_EQ(BAD_VALUE, mProducer->queueBuffer(dequeuedSlot, input, &output));
}
-TEST_F(IGraphicBufferProducerTest, Queue_ReturnsError) {
+TEST_P(IGraphicBufferProducerTest, Queue_ReturnsError) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
// Invalid slot number
@@ -463,15 +501,16 @@ TEST_F(IGraphicBufferProducerTest, Queue_ReturnsError) {
ASSERT_OK(mConsumer->consumerDisconnect());
// The buffer queue has been abandoned.
- {
+ if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
IGraphicBufferProducer::QueueBufferOutput output;
+ // TODO(b/73267953): Make BufferHub honor producer and consumer connection.
EXPECT_EQ(NO_INIT, mProducer->queueBuffer(dequeuedSlot, input, &output));
}
}
-TEST_F(IGraphicBufferProducerTest, CancelBuffer_DoesntCrash) {
+TEST_P(IGraphicBufferProducerTest, CancelBuffer_DoesntCrash) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
int dequeuedSlot = -1;
@@ -488,7 +527,7 @@ TEST_F(IGraphicBufferProducerTest, CancelBuffer_DoesntCrash) {
mProducer->cancelBuffer(dequeuedSlot, dequeuedFence);
}
-TEST_F(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Succeeds) {
+TEST_P(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Succeeds) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
int minUndequeuedBuffers;
ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
@@ -540,7 +579,7 @@ TEST_F(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Succeeds) {
ASSERT_OK(mProducer->setMaxDequeuedBufferCount(maxBuffers-1));
}
-TEST_F(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Fails) {
+TEST_P(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Fails) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
int minUndequeuedBuffers;
ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
@@ -578,12 +617,19 @@ TEST_F(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Fails) {
ASSERT_OK(mConsumer->consumerDisconnect());
// Fail because the buffer queue was abandoned
- EXPECT_EQ(NO_INIT, mProducer->setMaxDequeuedBufferCount(minBuffers))
- << "bufferCount: " << minBuffers;
-
+ if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
+ // TODO(b/73267953): Make BufferHub honor producer and consumer connection.
+ EXPECT_EQ(NO_INIT, mProducer->setMaxDequeuedBufferCount(minBuffers))
+ << "bufferCount: " << minBuffers;
+ }
}
-TEST_F(IGraphicBufferProducerTest, SetAsyncMode_Succeeds) {
+TEST_P(IGraphicBufferProducerTest, SetAsyncMode_Succeeds) {
+ if (GetParam() == USE_BUFFER_HUB_PRODUCER) {
+ // TODO(b/36724099): Add support for BufferHubProducer::setAsyncMode(true)
+ return;
+ }
+
ASSERT_OK(mConsumer->setMaxAcquiredBufferCount(1)) << "maxAcquire: " << 1;
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
ASSERT_OK(mProducer->setAsyncMode(true)) << "async mode: " << true;
@@ -609,7 +655,7 @@ TEST_F(IGraphicBufferProducerTest, SetAsyncMode_Succeeds) {
}
}
-TEST_F(IGraphicBufferProducerTest, SetAsyncMode_Fails) {
+TEST_P(IGraphicBufferProducerTest, SetAsyncMode_Fails) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
// Prerequisite to fail out a valid setBufferCount call
{
@@ -628,11 +674,13 @@ TEST_F(IGraphicBufferProducerTest, SetAsyncMode_Fails) {
ASSERT_OK(mConsumer->consumerDisconnect());
// Fail because the buffer queue was abandoned
- EXPECT_EQ(NO_INIT, mProducer->setAsyncMode(false)) << "asyncMode: "
- << false;
+ if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
+ // TODO(b/36724099): Make BufferHub honor producer and consumer connection.
+ EXPECT_EQ(NO_INIT, mProducer->setAsyncMode(false)) << "asyncMode: " << false;
+ }
}
-TEST_F(IGraphicBufferProducerTest,
+TEST_P(IGraphicBufferProducerTest,
DisconnectedProducerReturnsError_dequeueBuffer) {
int slot = -1;
sp<Fence> fence;
@@ -642,15 +690,18 @@ TEST_F(IGraphicBufferProducerTest,
TEST_PRODUCER_USAGE_BITS, nullptr, nullptr));
}
-TEST_F(IGraphicBufferProducerTest,
+TEST_P(IGraphicBufferProducerTest,
DisconnectedProducerReturnsError_detachNextBuffer) {
sp<Fence> fence;
sp<GraphicBuffer> buffer;
- ASSERT_EQ(NO_INIT, mProducer->detachNextBuffer(&buffer, &fence));
+ if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
+ // TODO(b/38137191): Implement BufferHubProducer::detachBuffer
+ ASSERT_EQ(NO_INIT, mProducer->detachNextBuffer(&buffer, &fence));
+ }
}
-TEST_F(IGraphicBufferProducerTest,
+TEST_P(IGraphicBufferProducerTest,
DisconnectedProducerReturnsError_requestBuffer) {
ASSERT_NO_FATAL_FAILURE(ConnectProducer());
@@ -674,7 +725,7 @@ TEST_F(IGraphicBufferProducerTest,
}
-TEST_F(IGraphicBufferProducerTest,
+TEST_P(IGraphicBufferProducerTest,
DisconnectedProducerReturnsError_detachBuffer) {
int slot = -1;
sp<Fence> fence;
@@ -684,10 +735,13 @@ TEST_F(IGraphicBufferProducerTest,
ASSERT_OK(mProducer->disconnect(TEST_API));
- ASSERT_EQ(NO_INIT, mProducer->detachBuffer(slot));
+ if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
+ // TODO(b/38137191): Implement BufferHubProducer::detachBuffer
+ ASSERT_EQ(NO_INIT, mProducer->detachBuffer(slot));
+ }
}
-TEST_F(IGraphicBufferProducerTest,
+TEST_P(IGraphicBufferProducerTest,
DisconnectedProducerReturnsError_queueBuffer) {
int slot = -1;
sp<Fence> fence;
@@ -704,7 +758,7 @@ TEST_F(IGraphicBufferProducerTest,
ASSERT_EQ(NO_INIT, mProducer->queueBuffer(slot, input, &output));
}
-TEST_F(IGraphicBufferProducerTest,
+TEST_P(IGraphicBufferProducerTest,
DisconnectedProducerReturnsError_cancelBuffer) {
int slot = -1;
sp<Fence> fence;
@@ -717,7 +771,7 @@ TEST_F(IGraphicBufferProducerTest,
ASSERT_EQ(NO_INIT, mProducer->cancelBuffer(slot, fence));
}
-TEST_F(IGraphicBufferProducerTest,
+TEST_P(IGraphicBufferProducerTest,
DisconnectedProducerReturnsError_attachBuffer) {
int slot = -1;
sp<Fence> fence;
@@ -725,11 +779,27 @@ TEST_F(IGraphicBufferProducerTest,
setupDequeueRequestBuffer(&slot, &fence, &buffer);
- ASSERT_OK(mProducer->detachBuffer(slot));
+ if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
+ // TODO(b/38137191): Implement BufferHubProducer::detachBuffer
+ ASSERT_OK(mProducer->detachBuffer(slot));
+ }
ASSERT_OK(mProducer->disconnect(TEST_API));
- ASSERT_EQ(NO_INIT, mProducer->attachBuffer(&slot, buffer));
+ if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
+ // TODO(b/69981968): Implement BufferHubProducer::attachBuffer
+ ASSERT_EQ(NO_INIT, mProducer->attachBuffer(&slot, buffer));
+ }
}
+#if USE_BUFFER_HUB_AS_BUFFER_QUEUE
+INSTANTIATE_TEST_CASE_P(IGraphicBufferProducerBackends, IGraphicBufferProducerTest,
+ ::testing::Values(USE_BUFFER_QUEUE_PRODUCER, USE_BUFFER_HUB_PRODUCER));
+#else
+// TODO(b/70046255): Remove the #ifdef here and always tests both backends once BufferHubQueue can
+// pass all existing libgui tests.
+INSTANTIATE_TEST_CASE_P(IGraphicBufferProducerBackends, IGraphicBufferProducerTest,
+ ::testing::Values(USE_BUFFER_QUEUE_PRODUCER));
+#endif
+
} // namespace android
diff --git a/libs/gui/tests/SurfaceParcelable_test.cpp b/libs/gui/tests/SurfaceParcelable_test.cpp
new file mode 100644
index 0000000000..686dc82f3e
--- /dev/null
+++ b/libs/gui/tests/SurfaceParcelable_test.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "SurfaceParcelable_test"
+
+#include <gtest/gtest.h>
+
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <gui/BufferHubProducer.h>
+#include <gui/BufferQueue.h>
+#include <gui/view/Surface.h>
+#include <utils/Log.h>
+
+namespace android {
+
+static const String16 kTestServiceName = String16("SurfaceParcelableTestService");
+static const String16 kSurfaceName = String16("TEST_SURFACE");
+static const uint32_t kBufferWidth = 100;
+static const uint32_t kBufferHeight = 1;
+static const uint32_t kBufferFormat = HAL_PIXEL_FORMAT_BLOB;
+
+enum SurfaceParcelableTestServiceCode {
+ CREATE_BUFFER_QUEUE_SURFACE = IBinder::FIRST_CALL_TRANSACTION,
+ CREATE_BUFFER_HUB_SURFACE,
+};
+
+class SurfaceParcelableTestService : public BBinder {
+public:
+ SurfaceParcelableTestService() {
+ // BufferQueue
+ BufferQueue::createBufferQueue(&mBufferQueueProducer, &mBufferQueueConsumer);
+
+ // BufferHub
+ dvr::ProducerQueueConfigBuilder configBuilder;
+ mProducerQueue = dvr::ProducerQueue::Create(configBuilder.SetDefaultWidth(kBufferWidth)
+ .SetDefaultHeight(kBufferHeight)
+ .SetDefaultFormat(kBufferFormat)
+ .Build(),
+ dvr::UsagePolicy{});
+ mBufferHubProducer = BufferHubProducer::Create(mProducerQueue);
+ }
+
+ ~SurfaceParcelableTestService() = default;
+
+ virtual status_t onTransact(uint32_t code, const Parcel& /*data*/, Parcel* reply,
+ uint32_t /*flags*/ = 0) {
+ switch (code) {
+ case CREATE_BUFFER_QUEUE_SURFACE: {
+ view::Surface surfaceShim;
+ surfaceShim.name = kSurfaceName;
+ surfaceShim.graphicBufferProducer = mBufferQueueProducer;
+ return surfaceShim.writeToParcel(reply);
+ }
+ case CREATE_BUFFER_HUB_SURFACE: {
+ view::Surface surfaceShim;
+ surfaceShim.name = kSurfaceName;
+ surfaceShim.graphicBufferProducer = mBufferHubProducer;
+ return surfaceShim.writeToParcel(reply);
+ }
+ default:
+ return UNKNOWN_TRANSACTION;
+ };
+ }
+
+protected:
+ sp<IGraphicBufferProducer> mBufferQueueProducer;
+ sp<IGraphicBufferConsumer> mBufferQueueConsumer;
+
+ std::shared_ptr<dvr::ProducerQueue> mProducerQueue;
+ sp<IGraphicBufferProducer> mBufferHubProducer;
+};
+
+static int runBinderServer() {
+ ProcessState::self()->startThreadPool();
+
+ sp<IServiceManager> sm = defaultServiceManager();
+ sp<SurfaceParcelableTestService> service = new SurfaceParcelableTestService;
+ sm->addService(kTestServiceName, service, false);
+
+ ALOGI("Binder server running...");
+
+ while (true) {
+ int stat, retval;
+ retval = wait(&stat);
+ if (retval == -1 && errno == ECHILD) {
+ break;
+ }
+ }
+
+ ALOGI("Binder server exiting...");
+ return 0;
+}
+
+class SurfaceParcelableTest : public ::testing::TestWithParam<uint32_t> {
+protected:
+ virtual void SetUp() {
+ mService = defaultServiceManager()->getService(kTestServiceName);
+ if (mService == nullptr) {
+ ALOGE("Failed to connect to the test service.");
+ return;
+ }
+
+ ALOGI("Binder service is ready for client.");
+ }
+
+ status_t GetSurface(view::Surface* surfaceShim) {
+ ALOGI("...Test: %d", GetParam());
+
+ uint32_t opCode = GetParam();
+ Parcel data;
+ Parcel reply;
+ status_t error = mService->transact(opCode, data, &reply);
+ if (error != NO_ERROR) {
+ ALOGE("Failed to get surface over binder, error=%d.", error);
+ return error;
+ }
+
+ error = surfaceShim->readFromParcel(&reply);
+ if (error != NO_ERROR) {
+ ALOGE("Failed to get surface from parcel, error=%d.", error);
+ return error;
+ }
+
+ return NO_ERROR;
+ }
+
+private:
+ sp<IBinder> mService;
+};
+
+TEST_P(SurfaceParcelableTest, SendOverBinder) {
+ view::Surface surfaceShim;
+ EXPECT_EQ(GetSurface(&surfaceShim), NO_ERROR);
+ EXPECT_EQ(surfaceShim.name, kSurfaceName);
+ EXPECT_FALSE(surfaceShim.graphicBufferProducer == nullptr);
+}
+
+INSTANTIATE_TEST_CASE_P(SurfaceBackends, SurfaceParcelableTest,
+ ::testing::Values(CREATE_BUFFER_QUEUE_SURFACE, CREATE_BUFFER_HUB_SURFACE));
+
+} // namespace android
+
+int main(int argc, char** argv) {
+ pid_t pid = fork();
+ if (pid == 0) {
+ android::ProcessState::self()->startThreadPool();
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+
+ } else {
+ ALOGI("Test process pid: %d.", pid);
+ return android::runBinderServer();
+ }
+}
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index ca43c68f92..2c02ba657d 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -22,6 +22,7 @@
#include <binder/ProcessState.h>
#include <configstore/Utils.h>
#include <cutils/properties.h>
+#include <inttypes.h>
#include <gui/BufferItemConsumer.h>
#include <gui/IDisplayEventConnection.h>
#include <gui/IProducerListener.h>
@@ -41,10 +42,16 @@ using namespace std::chrono_literals;
// retrieve wide-color and hdr settings from configstore
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
+using ui::ColorMode;
+
+using Transaction = SurfaceComposerClient::Transaction;
static bool hasWideColorDisplay =
getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
+static bool hasHdrDisplay =
+ getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasHDRDisplay>(false);
+
class FakeSurfaceComposer;
class FakeProducerFrameEventHistory;
@@ -52,7 +59,6 @@ static constexpr uint64_t NO_FRAME_INDEX = std::numeric_limits<uint64_t>::max();
class SurfaceTest : public ::testing::Test {
protected:
-
SurfaceTest() {
ProcessState::self()->startThreadPool();
}
@@ -69,10 +75,10 @@ protected:
ASSERT_TRUE(mSurfaceControl != NULL);
ASSERT_TRUE(mSurfaceControl->isValid());
- SurfaceComposerClient::openGlobalTransaction();
- ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7fffffff));
- ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
- SurfaceComposerClient::closeGlobalTransaction();
+ Transaction t;
+ ASSERT_EQ(NO_ERROR, t.setLayer(mSurfaceControl, 0x7fffffff)
+ .show(mSurfaceControl)
+ .apply());
mSurface = mSurfaceControl->getSurface();
ASSERT_TRUE(mSurface != NULL);
@@ -87,6 +93,16 @@ protected:
sp<SurfaceControl> mSurfaceControl;
};
+TEST_F(SurfaceTest, CreateSurfaceReturnsErrorBadClient) {
+ mComposerClient->dispose();
+ ASSERT_EQ(NO_INIT, mComposerClient->initCheck());
+
+ sp<SurfaceControl> sc;
+ status_t err = mComposerClient->createSurfaceChecked(
+ String8("Test Surface"), 32, 32, PIXEL_FORMAT_RGBA_8888, &sc, 0);
+ ASSERT_EQ(NO_INIT, err);
+}
+
TEST_F(SurfaceTest, QueuesToWindowComposerIsTrueWhenVisible) {
sp<ANativeWindow> anw(mSurface);
int result = -123;
@@ -114,14 +130,11 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) {
sp<ANativeWindow> anw(mSurface);
// Verify the screenshot works with no protected buffers.
- sp<IGraphicBufferProducer> producer;
- sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer);
- sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1);
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
sp<IBinder> display(sf->getBuiltInDisplay(
ISurfaceComposer::eDisplayIdMain));
- ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(),
+ sp<GraphicBuffer> outBuffer;
+ ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(),
64, 64, 0, 0x7fffffff, false));
ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(),
@@ -152,7 +165,7 @@ TEST_F(SurfaceTest, ScreenshotsOfProtectedBuffersSucceed) {
&buf));
ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf, -1));
}
- ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(),
+ ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(),
64, 64, 0, 0x7fffffff, false));
}
@@ -295,6 +308,68 @@ TEST_F(SurfaceTest, GetWideColorSupport) {
ASSERT_EQ(hasWideColorDisplay, supported);
}
+TEST_F(SurfaceTest, GetHdrSupport) {
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+
+ sp<DummyConsumer> dummyConsumer(new DummyConsumer);
+ consumer->consumerConnect(dummyConsumer, false);
+ consumer->setConsumerName(String8("TestConsumer"));
+
+ sp<Surface> surface = new Surface(producer);
+ sp<ANativeWindow> window(surface);
+ native_window_api_connect(window.get(), NATIVE_WINDOW_API_CPU);
+
+ bool supported;
+ status_t result = surface->getHdrSupport(&supported);
+ ASSERT_EQ(NO_ERROR, result);
+
+ // NOTE: This is not a CTS test.
+ // This test verifies that when the BoardConfig TARGET_HAS_HDR_DISPLAY
+ // is TRUE, getHdrSupport is also true.
+ // TODO: Add check for an HDR color mode on the primary display.
+ ASSERT_EQ(hasHdrDisplay, supported);
+}
+
+TEST_F(SurfaceTest, SetHdrMetadata) {
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+
+ sp<DummyConsumer> dummyConsumer(new DummyConsumer);
+ consumer->consumerConnect(dummyConsumer, false);
+ consumer->setConsumerName(String8("TestConsumer"));
+
+ sp<Surface> surface = new Surface(producer);
+ sp<ANativeWindow> window(surface);
+ native_window_api_connect(window.get(), NATIVE_WINDOW_API_CPU);
+
+ bool supported;
+ status_t result = surface->getHdrSupport(&supported);
+ ASSERT_EQ(NO_ERROR, result);
+
+ if (!hasHdrDisplay || !supported) {
+ return;
+ }
+ const android_smpte2086_metadata smpte2086 = {
+ {0.680, 0.320},
+ {0.265, 0.690},
+ {0.150, 0.060},
+ {0.3127, 0.3290},
+ 100.0,
+ 0.1,
+ };
+ const android_cta861_3_metadata cta861_3 = {
+ 78.0,
+ 62.0,
+ };
+ int error = native_window_set_buffers_smpte2086_metadata(window.get(), &smpte2086);
+ ASSERT_EQ(error, NO_ERROR);
+ error = native_window_set_buffers_cta861_3_metadata(window.get(), &cta861_3);
+ ASSERT_EQ(error, NO_ERROR);
+}
+
TEST_F(SurfaceTest, DynamicSetBufferCount) {
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
@@ -512,21 +587,26 @@ public:
return NO_ERROR;
}
status_t getDisplayColorModes(const sp<IBinder>& /*display*/,
- Vector<android_color_mode_t>* /*outColorModes*/) override {
+ Vector<ColorMode>* /*outColorModes*/) override {
return NO_ERROR;
}
- android_color_mode_t getActiveColorMode(const sp<IBinder>& /*display*/)
+ ColorMode getActiveColorMode(const sp<IBinder>& /*display*/)
override {
- return HAL_COLOR_MODE_NATIVE;
+ return ColorMode::NATIVE;
}
status_t setActiveColorMode(const sp<IBinder>& /*display*/,
- android_color_mode_t /*colorMode*/) override { return NO_ERROR; }
+ ColorMode /*colorMode*/) override { return NO_ERROR; }
status_t captureScreen(const sp<IBinder>& /*display*/,
- const sp<IGraphicBufferProducer>& /*producer*/,
+ sp<GraphicBuffer>* /*outBuffer*/,
Rect /*sourceCrop*/, uint32_t /*reqWidth*/, uint32_t /*reqHeight*/,
int32_t /*minLayerZ*/, int32_t /*maxLayerZ*/,
bool /*useIdentityTransform*/,
Rotation /*rotation*/) override { return NO_ERROR; }
+ virtual status_t captureLayers(const sp<IBinder>& /*parentHandle*/,
+ sp<GraphicBuffer>* /*outBuffer*/, const Rect& /*sourceCrop*/,
+ float /*frameScale*/, bool /*childrenOnly*/) override {
+ return NO_ERROR;
+ }
status_t clearAnimationFrameStats() override { return NO_ERROR; }
status_t getAnimationFrameStats(FrameStats* /*outStats*/) const override {
return NO_ERROR;
@@ -800,7 +880,7 @@ protected:
(iOldFrame == NO_FRAME_INDEX) ? nullptr : &mFrames[iOldFrame];
FrameEvents* newFrame = &mFrames[iNewFrame];
- uint64_t nOldFrame = iOldFrame + 1;
+ uint64_t nOldFrame = (iOldFrame == NO_FRAME_INDEX) ? 0 : iOldFrame + 1;
uint64_t nNewFrame = iNewFrame + 1;
// Latch, Composite, and Release the frames in a plausible order.
diff --git a/libs/gui/view/Surface.cpp b/libs/gui/view/Surface.cpp
index 5ed3d3bebb..d64dfd55be 100644
--- a/libs/gui/view/Surface.cpp
+++ b/libs/gui/view/Surface.cpp
@@ -45,10 +45,7 @@ status_t Surface::writeToParcel(Parcel* parcel, bool nameAlreadyWritten) const {
if (res != OK) return res;
}
- res = parcel->writeStrongBinder(
- IGraphicBufferProducer::asBinder(graphicBufferProducer));
-
- return res;
+ return IGraphicBufferProducer::exportToParcel(graphicBufferProducer, parcel);
}
status_t Surface::readFromParcel(const Parcel* parcel) {
@@ -70,16 +67,7 @@ status_t Surface::readFromParcel(const Parcel* parcel, bool nameAlreadyRead) {
}
}
- sp<IBinder> binder;
-
- res = parcel->readNullableStrongBinder(&binder);
- if (res != OK) {
- ALOGE("%s: Can't read strong binder", __FUNCTION__);
- return res;
- }
-
- graphicBufferProducer = interface_cast<IGraphicBufferProducer>(binder);
-
+ graphicBufferProducer = IGraphicBufferProducer::createFromParcel(parcel);
return OK;
}