Merge "Refactor IonBuffer to use GraphicBuffer"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 1cf00f5..9434d56 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1536,7 +1536,7 @@
if (is_redirecting) {
ds.bugreport_dir_ = dirname(use_outfile);
std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
- std::string device_name = android::base::GetProperty("ro.product.device", "UNKNOWN_DEVICE");
+ std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(use_outfile),
device_name.c_str(), build_id.c_str());
if (do_add_date) {
diff --git a/include/gui/BufferItemConsumer.h b/include/gui/BufferItemConsumer.h
index ec77ec7..db7e944 100644
--- a/include/gui/BufferItemConsumer.h
+++ b/include/gui/BufferItemConsumer.h
@@ -37,6 +37,10 @@
public:
typedef ConsumerBase::FrameAvailableListener FrameAvailableListener;
+ struct BufferFreedListener : public virtual RefBase {
+ virtual void onBufferFreed(const wp<GraphicBuffer>& graphicBuffer) = 0;
+ };
+
enum { DEFAULT_MAX_BUFFERS = -1 };
enum { INVALID_BUFFER_SLOT = BufferQueue::INVALID_BUFFER_SLOT };
enum { NO_BUFFER_AVAILABLE = BufferQueue::NO_BUFFER_AVAILABLE };
@@ -57,6 +61,10 @@
// 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);
+
// Gets the next graphics buffer from the producer, filling out the
// passed-in BufferItem structure. Returns NO_BUFFER_AVAILABLE if the queue
// of buffers is empty, and INVALID_OPERATION if the maximum number of
@@ -81,6 +89,13 @@
status_t releaseBuffer(const BufferItem &item,
const sp<Fence>& releaseFence = Fence::NO_FENCE);
+ private:
+ void freeBufferLocked(int slotIndex) override;
+
+ // mBufferFreedListener is the listener object that will be called when
+ // an old buffer is being freed. If it is not NULL it will be called from
+ // freeBufferLocked.
+ wp<BufferFreedListener> mBufferFreedListener;
};
} // namespace android
diff --git a/include/gui/FrameTimestamps.h b/include/gui/FrameTimestamps.h
index bda3c5c..cbb4491 100644
--- a/include/gui/FrameTimestamps.h
+++ b/include/gui/FrameTimestamps.h
@@ -105,7 +105,7 @@
struct CompositorTiming {
nsecs_t deadline{0};
nsecs_t interval{16666667};
- nsecs_t presentLatency{0};
+ nsecs_t presentLatency{16666667};
};
// A short history of frames that are synchronized between the consumer and
diff --git a/libs/gui/BufferItemConsumer.cpp b/libs/gui/BufferItemConsumer.cpp
index 3491043..d9d50db 100644
--- a/libs/gui/BufferItemConsumer.cpp
+++ b/libs/gui/BufferItemConsumer.cpp
@@ -22,7 +22,7 @@
#include <gui/BufferItem.h>
#include <gui/BufferItemConsumer.h>
-//#define BI_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
+#define BI_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
//#define BI_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
//#define BI_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__)
//#define BI_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__)
@@ -57,6 +57,12 @@
mConsumer->setConsumerName(name);
}
+void BufferItemConsumer::setBufferFreedListener(
+ const wp<BufferFreedListener>& listener) {
+ Mutex::Autolock _l(mMutex);
+ mBufferFreedListener = listener;
+}
+
status_t BufferItemConsumer::acquireBuffer(BufferItem *item,
nsecs_t presentWhen, bool waitForFence) {
status_t err;
@@ -104,4 +110,14 @@
return err;
}
+void BufferItemConsumer::freeBufferLocked(int slotIndex) {
+ sp<BufferFreedListener> listener = mBufferFreedListener.promote();
+ 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);
+ }
+ ConsumerBase::freeBufferLocked(slotIndex);
+}
+
} // namespace android
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index da6f13d..58227e6 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -52,6 +52,8 @@
mComposerClient = new SurfaceComposerClient;
ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
+ // TODO(brianderson): The following sometimes fails and is a source of
+ // test flakiness.
mSurfaceControl = mComposerClient->createSurface(
String8("Test Surface"), 32, 32, PIXEL_FORMAT_RGBA_8888, 0);
@@ -526,7 +528,7 @@
};
-class GetFrameTimestampsTest : public SurfaceTest {
+class GetFrameTimestampsTest : public ::testing::Test {
protected:
struct FenceAndFenceTime {
explicit FenceAndFenceTime(FenceToFenceTimeMap& fenceMap)
@@ -616,11 +618,9 @@
RefreshEvents mRefreshes[3];
};
- GetFrameTimestampsTest() : SurfaceTest() {}
+ GetFrameTimestampsTest() {}
virtual void SetUp() {
- SurfaceTest::SetUp();
-
BufferQueue::createBufferQueue(&mProducer, &mConsumer);
mFakeConsumer = new FakeConsumer;
mCfeh = &mFakeConsumer->mFrameEventHistory;
diff --git a/libs/hwc2on1adapter/HWC2On1Adapter.cpp b/libs/hwc2on1adapter/HWC2On1Adapter.cpp
index 5ad05c7..03297ca 100644
--- a/libs/hwc2on1adapter/HWC2On1Adapter.cpp
+++ b/libs/hwc2on1adapter/HWC2On1Adapter.cpp
@@ -245,6 +245,11 @@
return asFP<HWC2_PFN_VALIDATE_DISPLAY>(
displayHook<decltype(&Display::validate),
&Display::validate, uint32_t*, uint32_t*>);
+ case FunctionDescriptor::GetClientTargetSupport:
+ return asFP<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(
+ displayHook<decltype(&Display::getClientTargetSupport),
+ &Display::getClientTargetSupport, uint32_t, uint32_t,
+ int32_t, int32_t>);
// Layer functions
case FunctionDescriptor::SetCursorPosition:
@@ -1009,6 +1014,22 @@
return Error::None;
}
+Error HWC2On1Adapter::Display::getClientTargetSupport(uint32_t width, uint32_t height,
+ int32_t format, int32_t dataspace){
+ if (mActiveConfig == nullptr) {
+ return Error::Unsupported;
+ }
+
+ if (width == mActiveConfig->getAttribute(Attribute::Width) &&
+ height == mActiveConfig->getAttribute(Attribute::Height) &&
+ format == HAL_PIXEL_FORMAT_RGBA_8888 &&
+ dataspace == HAL_DATASPACE_UNKNOWN) {
+ return Error::None;
+ }
+
+ return Error::Unsupported;
+}
+
static constexpr uint32_t ATTRIBUTES_WITH_COLOR[] = {
HWC_DISPLAY_VSYNC_PERIOD,
HWC_DISPLAY_WIDTH,
diff --git a/libs/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h b/libs/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h
index a1d2c88..3badfce 100644
--- a/libs/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h
+++ b/libs/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h
@@ -248,6 +248,9 @@
HWC2::Error updateLayerZ(hwc2_layer_t layerId, uint32_t z);
+ HWC2::Error getClientTargetSupport(uint32_t width, uint32_t height,
+ int32_t format, int32_t dataspace);
+
// Read configs from HWC1 device
void populateConfigs();
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index ef49995..572cb4e 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -97,8 +97,6 @@
AHARDWAREBUFFER_USAGE0_GPU_SAMPLED_IMAGE = 1ULL << 10,
/* The buffer will be written to by the GPU */
AHARDWAREBUFFER_USAGE0_GPU_COLOR_OUTPUT = 1ULL << 11,
- /* The buffer will be used as a cubemap texture */
- AHARDWAREBUFFER_USAGE0_GPU_CUBEMAP = 1ULL << 13,
/* The buffer will be used as a shader storage or uniform buffer object*/
AHARDWAREBUFFER_USAGE0_GPU_DATA_BUFFER = 1ULL << 14,
/* The buffer must not be used outside of a protected hardware path */
diff --git a/libs/vr/libbufferhubqueue/Android.bp b/libs/vr/libbufferhubqueue/Android.bp
index 10198fd..b976097 100644
--- a/libs/vr/libbufferhubqueue/Android.bp
+++ b/libs/vr/libbufferhubqueue/Android.bp
@@ -45,6 +45,7 @@
cflags = [ "-DLOGTAG=\"libbufferhubqueue\"" ],
srcs: sourceFiles,
export_include_dirs: includeFiles,
+ export_static_lib_headers: staticLibraries,
static_libs: staticLibraries,
shared_libs: sharedLibraries,
}
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index bad9503..a8077b9 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -13,9 +13,6 @@
#include <pdx/file_handle.h>
#include <private/dvr/bufferhub_rpc.h>
-using android::pdx::LocalHandle;
-using android::pdx::LocalChannelHandle;
-
namespace android {
namespace dvr {
@@ -28,6 +25,7 @@
buffers_(BufferHubQueue::kMaxQueueCapacity),
epollhup_pending_(BufferHubQueue::kMaxQueueCapacity, false),
available_buffers_(BufferHubQueue::kMaxQueueCapacity),
+ fences_(BufferHubQueue::kMaxQueueCapacity),
capacity_(0) {
Initialize();
}
@@ -41,6 +39,7 @@
buffers_(BufferHubQueue::kMaxQueueCapacity),
epollhup_pending_(BufferHubQueue::kMaxQueueCapacity, false),
available_buffers_(BufferHubQueue::kMaxQueueCapacity),
+ fences_(BufferHubQueue::kMaxQueueCapacity),
capacity_(0) {
Initialize();
}
@@ -134,7 +133,7 @@
int events = status.get();
if (events & EPOLLIN) {
- int ret = OnBufferReady(buffer);
+ int ret = OnBufferReady(buffer, &fences_[slot]);
if (ret < 0) {
ALOGE("Failed to set buffer ready: %s", strerror(-ret));
return;
@@ -254,7 +253,8 @@
std::shared_ptr<BufferHubBuffer> BufferHubQueue::Dequeue(int timeout,
size_t* slot,
- void* meta) {
+ void* meta,
+ LocalHandle* fence) {
ALOGD("Dequeue: count=%zu, timeout=%d", count(), timeout);
if (count() == 0 && !WaitForBuffers(timeout))
@@ -263,6 +263,8 @@
std::shared_ptr<BufferHubBuffer> buf;
BufferInfo& buffer_info = available_buffers_.Front();
+ *fence = std::move(fences_[buffer_info.slot]);
+
// Report current pos as the output slot.
std::swap(buffer_info.slot, *slot);
// Swap buffer from vector to be returned later.
@@ -373,15 +375,21 @@
return BufferHubQueue::DetachBuffer(slot);
}
-std::shared_ptr<BufferProducer> ProducerQueue::Dequeue(int timeout,
- size_t* slot) {
- auto buf = BufferHubQueue::Dequeue(timeout, slot, nullptr);
+std::shared_ptr<BufferProducer> ProducerQueue::Dequeue(
+ int timeout, size_t* slot, LocalHandle* release_fence) {
+ if (slot == nullptr || release_fence == nullptr) {
+ ALOGE("invalid parameter, slot=%p, release_fence=%p", slot, release_fence);
+ return nullptr;
+ }
+
+ auto buf = BufferHubQueue::Dequeue(timeout, slot, nullptr, release_fence);
return std::static_pointer_cast<BufferProducer>(buf);
}
-int ProducerQueue::OnBufferReady(std::shared_ptr<BufferHubBuffer> buf) {
+int ProducerQueue::OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
+ LocalHandle* release_fence) {
auto buffer = std::static_pointer_cast<BufferProducer>(buf);
- return buffer->GainAsync();
+ return buffer->Gain(release_fence);
}
ConsumerQueue::ConsumerQueue(LocalChannelHandle handle, size_t meta_size)
@@ -431,9 +439,9 @@
return BufferHubQueue::AddBuffer(buf, slot);
}
-std::shared_ptr<BufferConsumer> ConsumerQueue::Dequeue(int timeout,
- size_t* slot, void* meta,
- size_t meta_size) {
+std::shared_ptr<BufferConsumer> ConsumerQueue::Dequeue(
+ int timeout, size_t* slot, void* meta, size_t meta_size,
+ LocalHandle* acquire_fence) {
if (meta_size != meta_size_) {
ALOGE(
"metadata size (%zu) for the dequeuing buffer does not match metadata "
@@ -441,14 +449,21 @@
meta_size, meta_size_);
return nullptr;
}
- auto buf = BufferHubQueue::Dequeue(timeout, slot, meta);
+
+ if (slot == nullptr || meta == nullptr || acquire_fence == nullptr) {
+ ALOGE("invalid parameter, slot=%p, meta=%p, acquire_fence=%p", slot, meta,
+ acquire_fence);
+ return nullptr;
+ }
+
+ auto buf = BufferHubQueue::Dequeue(timeout, slot, meta, acquire_fence);
return std::static_pointer_cast<BufferConsumer>(buf);
}
-int ConsumerQueue::OnBufferReady(std::shared_ptr<BufferHubBuffer> buf) {
+int ConsumerQueue::OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
+ LocalHandle* acquire_fence) {
auto buffer = std::static_pointer_cast<BufferConsumer>(buf);
- LocalHandle fence;
- return buffer->Acquire(&fence, meta_buffer_tmp_.get(), meta_size_);
+ return buffer->Acquire(acquire_fence, meta_buffer_tmp_.get(), meta_size_);
}
int ConsumerQueue::OnBufferAllocated() {
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
index 7ddf49b..0deb764 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
@@ -83,8 +83,9 @@
std::shared_ptr<BufferProducer> buffer_producer;
for (size_t retry = 0; retry < BufferHubQueue::kMaxQueueCapacity; retry++) {
+ LocalHandle fence;
buffer_producer =
- core_->producer_->Dequeue(core_->dequeue_timeout_ms_, &slot);
+ core_->producer_->Dequeue(core_->dequeue_timeout_ms_, &slot, &fence);
if (!buffer_producer)
return NO_MEMORY;
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
index 1f2830a..feaf3d7 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
@@ -20,6 +20,7 @@
// automatically re-requeued when released by the remote side.
class BufferHubQueue : public pdx::Client {
public:
+ using LocalHandle = pdx::LocalHandle;
using LocalChannelHandle = pdx::LocalChannelHandle;
template <typename T>
using Status = pdx::Status<T>;
@@ -91,14 +92,15 @@
// while specifying a timeout equal to zero cause |Dequeue()| to return
// immediately, even if no buffers are available.
std::shared_ptr<BufferHubBuffer> Dequeue(int timeout, size_t* slot,
- void* meta);
+ void* meta, LocalHandle* fence);
// Wait for buffers to be released and re-add them to the queue.
bool WaitForBuffers(int timeout);
void HandleBufferEvent(size_t slot, const epoll_event& event);
void HandleQueueEvent(const epoll_event& event);
- virtual int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf) = 0;
+ virtual int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
+ LocalHandle* fence) = 0;
// Called when a buffer is allocated remotely.
virtual int OnBufferAllocated() = 0;
@@ -202,6 +204,10 @@
// prevent the buffer from being deleted.
RingBuffer<BufferInfo> available_buffers_;
+ // Fences (acquire fence for consumer and release fence for consumer) , one
+ // for each buffer slot.
+ std::vector<LocalHandle> fences_;
+
// Keep track with how many buffers have been added into the queue.
size_t capacity_;
@@ -274,7 +280,8 @@
// Dequeue a producer buffer to write. The returned buffer in |Gain|'ed mode,
// and caller should call Post() once it's done writing to release the buffer
// to the consumer side.
- std::shared_ptr<BufferProducer> Dequeue(int timeout, size_t* slot);
+ std::shared_ptr<BufferProducer> Dequeue(int timeout, size_t* slot,
+ LocalHandle* release_fence);
private:
friend BASE;
@@ -287,7 +294,8 @@
ProducerQueue(size_t meta_size, int usage_set_mask, int usage_clear_mask,
int usage_deny_set_mask, int usage_deny_clear_mask);
- int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf) override;
+ int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
+ LocalHandle* release_fence) override;
// Producer buffer is always allocated from the client (i.e. local) side.
int OnBufferAllocated() override { return 0; }
@@ -316,14 +324,11 @@
// Dequeue() is done with the corect metadata type and size with those used
// when the buffer is orignally created.
template <typename Meta>
- std::shared_ptr<BufferConsumer> Dequeue(int timeout, size_t* slot,
- Meta* meta) {
- return Dequeue(timeout, slot, meta, sizeof(*meta));
+ std::shared_ptr<BufferConsumer> Dequeue(int timeout, size_t* slot, Meta* meta,
+ LocalHandle* acquire_fence) {
+ return Dequeue(timeout, slot, meta, sizeof(*meta), acquire_fence);
}
- std::shared_ptr<BufferConsumer> Dequeue(int timeout, size_t* slot, void* meta,
- size_t meta_size);
-
private:
friend BASE;
@@ -335,9 +340,14 @@
// consumer.
int AddBuffer(const std::shared_ptr<BufferConsumer>& buf, size_t slot);
- int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf) override;
+ int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
+ LocalHandle* acquire_fence) override;
int OnBufferAllocated() override;
+
+ std::shared_ptr<BufferConsumer> Dequeue(int timeout, size_t* slot, void* meta,
+ size_t meta_size,
+ LocalHandle* acquire_fence);
};
} // namespace dvr
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
index 841554e..811543d 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
@@ -59,12 +59,13 @@
// But dequeue multiple times.
for (size_t i = 0; i < nb_dequeue_times; i++) {
size_t slot;
- auto p1 = producer_queue_->Dequeue(0, &slot);
+ LocalHandle fence;
+ auto p1 = producer_queue_->Dequeue(0, &slot, &fence);
ASSERT_NE(nullptr, p1);
size_t mi = i;
ASSERT_EQ(p1->Post(LocalHandle(), &mi, sizeof(mi)), 0);
size_t mo;
- auto c1 = consumer_queue_->Dequeue(100, &slot, &mo);
+ auto c1 = consumer_queue_->Dequeue(100, &slot, &mo, &fence);
ASSERT_NE(nullptr, c1);
ASSERT_EQ(mi, mo);
c1->Release(LocalHandle());
@@ -91,19 +92,21 @@
ASSERT_EQ(consumer_queue_->capacity(), i);
// Dequeue returns nullptr since no buffer is ready to consumer, but
// this implicitly triggers buffer import and bump up |capacity|.
- auto consumer_null = consumer_queue_->Dequeue(0, &slot, &seq);
+ LocalHandle fence;
+ auto consumer_null = consumer_queue_->Dequeue(0, &slot, &seq, &fence);
ASSERT_EQ(nullptr, consumer_null);
ASSERT_EQ(consumer_queue_->capacity(), i + 1);
}
for (size_t i = 0; i < nb_buffer; i++) {
+ LocalHandle fence;
// First time, there is no buffer available to dequeue.
- auto buffer_null = consumer_queue_->Dequeue(0, &slot, &seq);
+ auto buffer_null = consumer_queue_->Dequeue(0, &slot, &seq, &fence);
ASSERT_EQ(nullptr, buffer_null);
// Make sure Producer buffer is Post()'ed so that it's ready to Accquire
// in the consumer's Dequeue() function.
- auto producer = producer_queue_->Dequeue(0, &slot);
+ auto producer = producer_queue_->Dequeue(0, &slot, &fence);
ASSERT_NE(nullptr, producer);
uint64_t seq_in = static_cast<uint64_t>(i);
@@ -111,7 +114,7 @@
// Second time, the just |Post()|'ed buffer should be dequeued.
uint64_t seq_out = 0;
- auto consumer = consumer_queue_->Dequeue(0, &slot, &seq_out);
+ auto consumer = consumer_queue_->Dequeue(0, &slot, &seq_out, &fence);
ASSERT_NE(nullptr, consumer);
ASSERT_EQ(seq_in, seq_out);
}
@@ -132,11 +135,12 @@
for (auto mi : ms) {
size_t slot;
- auto p1 = producer_queue_->Dequeue(0, &slot);
+ LocalHandle fence;
+ auto p1 = producer_queue_->Dequeue(0, &slot, &fence);
ASSERT_NE(nullptr, p1);
ASSERT_EQ(p1->Post(LocalHandle(-1), &mi, sizeof(mi)), 0);
TestMetadata mo;
- auto c1 = consumer_queue_->Dequeue(0, &slot, &mo);
+ auto c1 = consumer_queue_->Dequeue(0, &slot, &mo, &fence);
ASSERT_EQ(mi.a, mo.a);
ASSERT_EQ(mi.b, mo.b);
ASSERT_EQ(mi.c, mo.c);
@@ -150,13 +154,14 @@
int64_t mi = 3;
size_t slot;
- auto p1 = producer_queue_->Dequeue(0, &slot);
+ LocalHandle fence;
+ auto p1 = producer_queue_->Dequeue(0, &slot, &fence);
ASSERT_NE(nullptr, p1);
ASSERT_EQ(p1->Post(LocalHandle(-1), &mi, sizeof(mi)), 0);
int32_t mo;
// Acquire a buffer with mismatched metadata is not OK.
- auto c1 = consumer_queue_->Dequeue(0, &slot, &mo);
+ auto c1 = consumer_queue_->Dequeue(0, &slot, &mo, &fence);
ASSERT_EQ(nullptr, c1);
}
@@ -165,12 +170,13 @@
AllocateBuffer();
size_t slot;
- auto p1 = producer_queue_->Dequeue(0, &slot);
+ LocalHandle fence;
+ auto p1 = producer_queue_->Dequeue(0, &slot, &fence);
ASSERT_NE(nullptr, p1);
int64_t mo;
producer_queue_->Enqueue(p1, slot);
- auto c1 = consumer_queue_->Dequeue(0, &slot, &mo);
+ auto c1 = consumer_queue_->Dequeue(0, &slot, &mo, &fence);
ASSERT_EQ(nullptr, c1);
}
@@ -179,12 +185,13 @@
size_t s1;
AllocateBuffer();
- auto p1 = producer_queue_->Dequeue(0, &s1);
+ LocalHandle fence;
+ auto p1 = producer_queue_->Dequeue(0, &s1, &fence);
ASSERT_NE(nullptr, p1);
// producer queue is exhausted
size_t s2;
- auto p2_null = producer_queue_->Dequeue(0, &s2);
+ auto p2_null = producer_queue_->Dequeue(0, &s2, &fence);
ASSERT_EQ(nullptr, p2_null);
// dynamically add buffer.
@@ -193,7 +200,7 @@
ASSERT_EQ(producer_queue_->capacity(), 2U);
// now we can dequeue again
- auto p2 = producer_queue_->Dequeue(0, &s2);
+ auto p2 = producer_queue_->Dequeue(0, &s2, &fence);
ASSERT_NE(nullptr, p2);
ASSERT_EQ(producer_queue_->count(), 0U);
// p1 and p2 should have different slot number
@@ -206,14 +213,14 @@
int64_t seq = 1;
ASSERT_EQ(p1->Post(LocalHandle(), seq), 0);
size_t cs1, cs2;
- auto c1 = consumer_queue_->Dequeue(0, &cs1, &seq);
+ auto c1 = consumer_queue_->Dequeue(0, &cs1, &seq, &fence);
ASSERT_NE(nullptr, c1);
ASSERT_EQ(consumer_queue_->count(), 0U);
ASSERT_EQ(consumer_queue_->capacity(), 2U);
ASSERT_EQ(cs1, s1);
ASSERT_EQ(p2->Post(LocalHandle(), seq), 0);
- auto c2 = consumer_queue_->Dequeue(0, &cs2, &seq);
+ auto c2 = consumer_queue_->Dequeue(0, &cs2, &seq, &fence);
ASSERT_NE(nullptr, c2);
ASSERT_EQ(cs2, s2);
}
@@ -229,7 +236,8 @@
kBufferSliceCount, &slot);
ASSERT_EQ(ret, 0);
- auto p1 = producer_queue_->Dequeue(0, &slot);
+ LocalHandle fence;
+ auto p1 = producer_queue_->Dequeue(0, &slot, &fence);
ASSERT_EQ(p1->usage() & set_mask, set_mask);
}
@@ -244,7 +252,8 @@
kBufferSliceCount, &slot);
ASSERT_EQ(ret, 0);
- auto p1 = producer_queue_->Dequeue(0, &slot);
+ LocalHandle fence;
+ auto p1 = producer_queue_->Dequeue(0, &slot, &fence);
ASSERT_EQ(p1->usage() & clear_mask, 0);
}
diff --git a/libs/vr/libdisplay/display_client.cpp b/libs/vr/libdisplay/display_client.cpp
index 54098e8..dcdd994 100644
--- a/libs/vr/libdisplay/display_client.cpp
+++ b/libs/vr/libdisplay/display_client.cpp
@@ -148,18 +148,22 @@
}
}
-std::shared_ptr<BufferProducer> DisplaySurfaceClient::AllocateBuffer(
- uint32_t* buffer_index) {
- auto status = InvokeRemoteMethod<DisplayRPC::AllocateBuffer>();
- if (!status) {
- ALOGE("DisplaySurfaceClient::AllocateBuffer: Failed to allocate buffer: %s",
+std::shared_ptr<ProducerQueue> DisplaySurfaceClient::GetProducerQueue() {
+ if (producer_queue_ == nullptr) {
+ // Create producer queue through DisplayRPC
+ auto status = InvokeRemoteMethod<DisplayRPC::CreateBufferQueue>();
+ if (!status) {
+ ALOGE(
+ "DisplaySurfaceClient::GetProducerQueue: failed to create producer "
+ "queue: %s",
status.GetErrorMessage().c_str());
- return nullptr;
- }
+ return nullptr;
+ }
- if (buffer_index)
- *buffer_index = status.get().first;
- return BufferProducer::Import(status.take().second);
+ producer_queue_ =
+ ProducerQueue::Import<DisplaySurfaceMetadata>(status.take());
+ }
+ return producer_queue_;
}
volatile DisplaySurfaceMetadata* DisplaySurfaceClient::GetMetadataBufferPtr() {
diff --git a/libs/vr/libdisplay/include/private/dvr/display_client.h b/libs/vr/libdisplay/include/private/dvr/display_client.h
index 034b7b4..e1471c3 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_client.h
@@ -5,6 +5,7 @@
#include <pdx/client.h>
#include <pdx/file_handle.h>
#include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/buffer_hub_queue_client.h>
#include <private/dvr/display_rpc.h>
namespace android {
@@ -62,13 +63,9 @@
void SetBlurBehind(bool blur_behind);
void SetAttributes(const DisplaySurfaceAttributes& attributes);
- // |out_buffer_index| will receive a unique index for this buffer within the
- // surface. The first buffer gets 0, second gets 1, and so on. This index
- // can be used to deliver metadata for buffers that are queued for display.
- std::shared_ptr<BufferProducer> AllocateBuffer(uint32_t* out_buffer_index);
- std::shared_ptr<BufferProducer> AllocateBuffer() {
- return AllocateBuffer(nullptr);
- }
+ // Get the producer end of the buffer queue that transports graphics buffer
+ // from the application side to the compositor side.
+ std::shared_ptr<ProducerQueue> GetProducerQueue();
// Get the shared memory metadata buffer for this display surface. If it is
// not yet allocated, this will allocate it.
@@ -93,6 +90,9 @@
bool blur_behind_;
DisplaySurfaceMetadata* mapped_metadata_buffer_;
+ // TODO(jwcai) Add support for multiple queues.
+ std::shared_ptr<ProducerQueue> producer_queue_;
+
DisplaySurfaceClient(const DisplaySurfaceClient&) = delete;
void operator=(const DisplaySurfaceClient&) = delete;
};
diff --git a/libs/vr/libdisplay/include/private/dvr/display_rpc.h b/libs/vr/libdisplay/include/private/dvr/display_rpc.h
index d37aed7..465fbae 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_rpc.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_rpc.h
@@ -212,7 +212,7 @@
kOpGetMetrics = 0,
kOpGetEdsCapture,
kOpCreateSurface,
- kOpAllocateBuffer,
+ kOpCreateBufferQueue,
kOpSetAttributes,
kOpGetMetadataBuffer,
kOpCreateVideoMeshSurface,
@@ -233,8 +233,8 @@
PDX_REMOTE_METHOD(CreateSurface, kOpCreateSurface,
int(int width, int height, int format, int usage,
DisplaySurfaceFlags flags));
- PDX_REMOTE_METHOD(AllocateBuffer, kOpAllocateBuffer,
- std::pair<std::uint32_t, LocalChannelHandle>(Void));
+ PDX_REMOTE_METHOD(CreateBufferQueue, kOpCreateBufferQueue,
+ LocalChannelHandle(Void));
PDX_REMOTE_METHOD(SetAttributes, kOpSetAttributes,
int(const DisplaySurfaceAttributes& attributes));
PDX_REMOTE_METHOD(GetMetadataBuffer, kOpGetMetadataBuffer,
diff --git a/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h b/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h
index 87e9c9f..4b1fa98 100644
--- a/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h
+++ b/libs/vr/libdisplay/include/private/dvr/native_buffer_queue.h
@@ -14,57 +14,27 @@
namespace android {
namespace dvr {
-// NativeBufferQueue manages a queue of NativeBufferProducers allocated from a
-// DisplaySurfaceClient. Buffers are automatically re-enqueued when released by
-// the consumer side.
+// A wrapper over dvr::ProducerQueue that caches EGLImage.
class NativeBufferQueue {
public:
// Create a queue with the given number of free buffers.
- NativeBufferQueue(const std::shared_ptr<DisplaySurfaceClient>& surface,
- size_t capacity);
NativeBufferQueue(EGLDisplay display,
const std::shared_ptr<DisplaySurfaceClient>& surface,
size_t capacity);
- ~NativeBufferQueue();
- std::shared_ptr<DisplaySurfaceClient> surface() const { return surface_; }
+ size_t GetQueueCapacity() const { return producer_queue_->capacity(); }
// Dequeue a buffer from the free queue, blocking until one is available.
NativeBufferProducer* Dequeue();
- // Enqueue a buffer at the end of the free queue.
- void Enqueue(NativeBufferProducer* buf);
-
- // Get the number of free buffers in the queue.
- size_t GetFreeBufferCount() const;
-
- // Get the total number of buffers managed by this queue.
- size_t GetQueueCapacity() const;
-
- // Accessors for display surface buffer attributes.
- int width() const { return surface_->width(); }
- int height() const { return surface_->height(); }
- int format() const { return surface_->format(); }
- int usage() const { return surface_->usage(); }
+ // An noop here to keep Vulkan path in GraphicsContext happy.
+ // TODO(jwcai, cort) Move Vulkan path into GVR/Google3.
+ void Enqueue(NativeBufferProducer* buffer) {}
private:
- // Wait for buffers to be released and enqueue them.
- bool WaitForBuffers();
-
- std::shared_ptr<DisplaySurfaceClient> surface_;
-
- // A list of strong pointers to the buffers, used for managing buffer
- // lifetime.
- std::vector<android::sp<NativeBufferProducer>> buffers_;
-
- // Used to implement queue semantics.
- RingBuffer<NativeBufferProducer*> buffer_queue_;
-
- // Epoll fd used to wait for BufferHub events.
- int epoll_fd_;
-
- NativeBufferQueue(const NativeBufferQueue&) = delete;
- void operator=(NativeBufferQueue&) = delete;
+ EGLDisplay display_;
+ std::shared_ptr<ProducerQueue> producer_queue_;
+ std::vector<sp<NativeBufferProducer>> buffers_;
};
} // namespace dvr
diff --git a/libs/vr/libdisplay/include/private/dvr/video_mesh_surface_client.h b/libs/vr/libdisplay/include/private/dvr/video_mesh_surface_client.h
index e52d0b9..3a7f125 100644
--- a/libs/vr/libdisplay/include/private/dvr/video_mesh_surface_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/video_mesh_surface_client.h
@@ -25,7 +25,7 @@
private:
friend BASE;
- std::shared_ptr<android::dvr::ProducerQueue> producer_queue_;
+ std::shared_ptr<ProducerQueue> producer_queue_;
VideoMeshSurfaceMetadata* mapped_metadata_buffer_;
explicit VideoMeshSurfaceClient(LocalChannelHandle handle);
diff --git a/libs/vr/libdisplay/native_buffer_queue.cpp b/libs/vr/libdisplay/native_buffer_queue.cpp
index 8dd0ee0..d516d63 100644
--- a/libs/vr/libdisplay/native_buffer_queue.cpp
+++ b/libs/vr/libdisplay/native_buffer_queue.cpp
@@ -13,138 +13,51 @@
namespace dvr {
NativeBufferQueue::NativeBufferQueue(
- const std::shared_ptr<DisplaySurfaceClient>& surface, size_t capacity)
- : NativeBufferQueue(nullptr, surface, capacity) {}
-
-NativeBufferQueue::NativeBufferQueue(
EGLDisplay display, const std::shared_ptr<DisplaySurfaceClient>& surface,
size_t capacity)
- : surface_(surface),
- buffers_(capacity),
- buffer_queue_(capacity) {
- LOG_ALWAYS_FATAL_IF(!surface);
-
- epoll_fd_ = epoll_create(64);
- if (epoll_fd_ < 0) {
- ALOGE("NativeBufferQueue::NativeBufferQueue: Failed to create epoll fd: %s",
- strerror(errno));
- return;
- }
-
- // The kSurfaceBufferMaxCount must be >= the capacity so that shader code
- // can bind surface buffer array data.
- LOG_ALWAYS_FATAL_IF(kSurfaceBufferMaxCount < capacity);
+ : display_(display), buffers_(capacity) {
+ std::shared_ptr<ProducerQueue> queue = surface->GetProducerQueue();
for (size_t i = 0; i < capacity; i++) {
- uint32_t buffer_index = 0;
- auto buffer = surface_->AllocateBuffer(&buffer_index);
- if (!buffer) {
- ALOGE("NativeBufferQueue::NativeBufferQueue: Failed to allocate buffer!");
- return;
- }
-
- // TODO(jbates): store an index associated with each buffer so that we can
- // determine which index in DisplaySurfaceMetadata it is associated
- // with.
- buffers_.push_back(new NativeBufferProducer(buffer, display, buffer_index));
- NativeBufferProducer* native_buffer = buffers_.back().get();
-
- epoll_event event = {.events = EPOLLIN | EPOLLET,
- .data = {.ptr = native_buffer}};
- if (epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, buffer->event_fd(), &event) <
- 0) {
+ size_t slot;
+ // TODO(jwcai) Should change to use BufferViewPort's spec to config.
+ int ret =
+ queue->AllocateBuffer(surface->width(), surface->height(),
+ surface->format(), surface->usage(), 1, &slot);
+ if (ret < 0) {
ALOGE(
- "NativeBufferQueue::NativeBufferQueue: Failed to add buffer producer "
- "to epoll set: %s",
- strerror(errno));
+ "NativeBufferQueue::NativeBufferQueue: Failed to allocate buffer, "
+ "error=%d",
+ ret);
return;
}
- Enqueue(native_buffer);
- }
-}
-
-NativeBufferQueue::~NativeBufferQueue() {
- if (epoll_fd_ >= 0)
- close(epoll_fd_);
-}
-
-bool NativeBufferQueue::WaitForBuffers() {
- ATRACE_NAME("NativeBufferQueue::WaitForBuffers");
- // Intentionally set this to one so that we don't waste time retrieving too
- // many buffers.
- constexpr size_t kMaxEvents = 1;
- std::array<epoll_event, kMaxEvents> events;
-
- while (buffer_queue_.IsEmpty()) {
- int num_events = epoll_wait(epoll_fd_, events.data(), events.size(), -1);
- if (num_events < 0 && errno != EINTR) {
- ALOGE("NativeBufferQueue:WaitForBuffers: Failed to wait for buffers: %s",
- strerror(errno));
- return false;
- }
-
- ALOGD_IF(TRACE, "NativeBufferQueue::WaitForBuffers: num_events=%d",
- num_events);
-
- for (int i = 0; i < num_events; i++) {
- NativeBufferProducer* buffer =
- static_cast<NativeBufferProducer*>(events[i].data.ptr);
- ALOGD_IF(TRACE,
- "NativeBufferQueue::WaitForBuffers: event %d: buffer_id=%d "
- "events=0x%x",
- i, buffer->buffer()->id(), events[i].events);
-
- if (events[i].events & EPOLLIN) {
- const int ret = buffer->GainAsync();
- if (ret < 0) {
- ALOGE("NativeBufferQueue::WaitForBuffers: Failed to gain buffer: %s",
- strerror(-ret));
- continue;
- }
-
- Enqueue(buffer);
- }
- }
+ ALOGD_IF(TRACE,
+ "NativeBufferQueue::NativeBufferQueue: New buffer allocated at "
+ "slot=%zu",
+ slot);
}
- return true;
-}
-
-void NativeBufferQueue::Enqueue(NativeBufferProducer* buf) {
- ATRACE_NAME("NativeBufferQueue::Enqueue");
- if (buffer_queue_.IsFull()) {
- ALOGE("NativeBufferQueue::Enqueue: Queue is full!");
- return;
- }
-
- buffer_queue_.Append(buf);
+ producer_queue_ = std::move(queue);
}
NativeBufferProducer* NativeBufferQueue::Dequeue() {
ATRACE_NAME("NativeBufferQueue::Dequeue");
- ALOGD_IF(TRACE, "NativeBufferQueue::Dequeue: count=%zd",
- buffer_queue_.GetSize());
- if (buffer_queue_.IsEmpty() && !WaitForBuffers())
- return nullptr;
+ // This never times out.
+ size_t slot;
+ pdx::LocalHandle fence;
+ std::shared_ptr<BufferProducer> buffer =
+ producer_queue_->Dequeue(-1, &slot, &fence);
- NativeBufferProducer* buf = buffer_queue_.Front();
- buffer_queue_.PopFront();
- if (buf == nullptr) {
- ALOGE("NativeBufferQueue::Dequeue: Buffer at tail was nullptr!!!");
- return nullptr;
+ if (buffers_[slot] == nullptr) {
+ buffers_[slot] = new NativeBufferProducer(buffer, display_, slot);
}
- return buf;
-}
-
-size_t NativeBufferQueue::GetFreeBufferCount() const {
- return buffer_queue_.GetSize();
-}
-
-size_t NativeBufferQueue::GetQueueCapacity() const {
- return buffer_queue_.GetCapacity();
+ ALOGD_IF(TRACE,
+ "NativeBufferQueue::Dequeue: dequeue buffer at slot=%zu, buffer=%p",
+ slot, buffers_[slot].get());
+ return buffers_[slot].get();
}
} // namespace dvr
diff --git a/libs/vr/libeds/Android.bp b/libs/vr/libeds/Android.bp
index cb6784cb..187cbbf 100644
--- a/libs/vr/libeds/Android.bp
+++ b/libs/vr/libeds/Android.bp
@@ -81,7 +81,8 @@
"libgmock",
"libeds",
] + staticLibraries + [
- "libbufferhub"
+ "libbufferhub",
+ "libbufferhubqueue",
],
}
diff --git a/libs/vr/libpdx/private/pdx/rpc/remote_method.h b/libs/vr/libpdx/private/pdx/rpc/remote_method.h
index 49bee40..679503c 100644
--- a/libs/vr/libpdx/private/pdx/rpc/remote_method.h
+++ b/libs/vr/libpdx/private/pdx/rpc/remote_method.h
@@ -25,10 +25,9 @@
// Evaluates to true if the method type is <any>(Void), false otherwise.
template <typename RemoteMethodType>
using IsVoidMethod = typename std::integral_constant<
- bool,
- RemoteMethodType::Traits::Arity == 1 &&
- std::is_same<typename RemoteMethodType::Traits::template Arg<0>,
- Void>::value>;
+ bool, RemoteMethodType::Traits::Arity == 1 &&
+ std::is_same<typename RemoteMethodType::Traits::template Arg<0>,
+ Void>::value>;
// Utility to determine if a method is of type <any>(Void).
template <typename RemoteMethodType>
@@ -274,7 +273,9 @@
void DispatchRemoteMethod(
Class& instance, ChannelHandle<Mode> (Class::*method)(Message&, Args...),
Message& message, std::size_t max_capacity = InitialBufferCapacity) {
- using Signature = typename RemoteMethodType::template RewriteArgs<Args...>;
+ using Signature =
+ typename RemoteMethodType::template RewriteSignature<ChannelHandle<Mode>,
+ Args...>;
rpc::ServicePayload<ReceiveBuffer> payload(message);
payload.Resize(max_capacity);
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index 4ad7c23..3f79a7b 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -20,7 +20,6 @@
"display_manager_service.cpp",
"display_service.cpp",
"display_surface.cpp",
- "epoll_event_dispatcher.cpp",
"hardware_composer.cpp",
"screenshot_service.cpp",
"surface_channel.cpp",
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index bb70c5c..fdb84c5 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -90,7 +90,7 @@
return 0;
// Direct the surface specific messages to the surface instance.
- case DisplayRPC::AllocateBuffer::Opcode:
+ case DisplayRPC::CreateBufferQueue::Opcode:
case DisplayRPC::SetAttributes::Opcode:
case DisplayRPC::GetMetadataBuffer::Opcode:
case DisplayRPC::CreateVideoMeshSurface::Opcode:
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index b207e4d..9d116c1 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -14,7 +14,6 @@
#include "acquired_buffer.h"
#include "display_surface.h"
-#include "epoll_event_dispatcher.h"
#include "hardware_composer.h"
namespace android {
@@ -99,7 +98,6 @@
DisplayService(const DisplayService&) = delete;
void operator=(const DisplayService&) = delete;
- EpollEventDispatcher dispatcher_;
HardwareComposer hardware_composer_;
DisplayConfigurationUpdateNotifier update_notifier_;
};
diff --git a/libs/vr/libvrflinger/display_surface.cpp b/libs/vr/libvrflinger/display_surface.cpp
index d427ea6..66808ca 100644
--- a/libs/vr/libvrflinger/display_surface.cpp
+++ b/libs/vr/libvrflinger/display_surface.cpp
@@ -26,7 +26,7 @@
: SurfaceChannel(service, surface_id, SurfaceTypeEnum::Normal,
sizeof(DisplaySurfaceMetadata)),
process_id_(process_id),
- posted_buffers_(kMaxPostedBuffers),
+ acquired_buffers_(kMaxPostedBuffers),
video_mesh_surfaces_updated_(false),
width_(width),
height_(height),
@@ -40,7 +40,6 @@
manager_visible_(false),
manager_z_order_(0),
manager_blur_(0.0f),
- allocated_buffer_index_(0),
layer_order_(0) {}
DisplaySurface::~DisplaySurface() {
@@ -84,71 +83,107 @@
client_blur_behind_ = blur_behind;
}
+void DisplaySurface::DequeueBuffersLocked() {
+ if (consumer_queue_ == nullptr) {
+ ALOGE(
+ "DisplaySurface::DequeueBuffersLocked: Consumer queue is not "
+ "initialized.");
+ return;
+ }
+
+ size_t slot;
+ uint64_t sequence;
+ while (true) {
+ LocalHandle acquire_fence;
+ auto buffer_consumer =
+ consumer_queue_->Dequeue(0, &slot, &sequence, &acquire_fence);
+ if (!buffer_consumer) {
+ ALOGD_IF(TRACE,
+ "DisplaySurface::DequeueBuffersLocked: We have dequeued all "
+ "available buffers.");
+ return;
+ }
+
+ if (!IsVisible()) {
+ ATRACE_NAME("DropFrameOnInvisibleSurface");
+ ALOGD_IF(TRACE,
+ "DisplaySurface::DequeueBuffersLocked: Discarding buffer_id=%d "
+ "on invisible surface.",
+ buffer_consumer->id());
+ buffer_consumer->Discard();
+ continue;
+ }
+
+ if (acquired_buffers_.IsFull()) {
+ ALOGE(
+ "DisplaySurface::DequeueBuffersLocked: Posted buffers full, "
+ "overwriting.");
+ acquired_buffers_.PopBack();
+ }
+
+ acquired_buffers_.Append(
+ AcquiredBuffer(buffer_consumer, std::move(acquire_fence), sequence));
+ }
+}
+
+AcquiredBuffer DisplaySurface::AcquireCurrentBuffer() {
+ std::lock_guard<std::mutex> autolock(lock_);
+ DequeueBuffersLocked();
+
+ if (acquired_buffers_.IsEmpty()) {
+ ALOGE(
+ "DisplaySurface::AcquireCurrentBuffer: attempt to acquire buffer when "
+ "none are posted.");
+ return AcquiredBuffer();
+ }
+ AcquiredBuffer buffer = std::move(acquired_buffers_.Front());
+ acquired_buffers_.PopFront();
+ ALOGD_IF(TRACE, "DisplaySurface::AcquireCurrentBuffer: buffer: %p",
+ buffer.buffer().get());
+ return buffer;
+}
+
AcquiredBuffer DisplaySurface::AcquireNewestAvailableBuffer(
AcquiredBuffer* skipped_buffer) {
std::lock_guard<std::mutex> autolock(lock_);
+ DequeueBuffersLocked();
+
AcquiredBuffer buffer;
int frames = 0;
// Basic latency stopgap for when the application misses a frame:
// If the application recovers on the 2nd or 3rd (etc) frame after
// missing, this code will skip frames to catch up by checking if
// the next frame is also available.
- while (!posted_buffers_.IsEmpty() && posted_buffers_.Front().IsAvailable()) {
+ while (!acquired_buffers_.IsEmpty() &&
+ acquired_buffers_.Front().IsAvailable()) {
// Capture the skipped buffer into the result parameter.
// Note that this API only supports skipping one buffer per vsync.
if (frames > 0 && skipped_buffer)
*skipped_buffer = std::move(buffer);
++frames;
- buffer = std::move(posted_buffers_.Front());
- posted_buffers_.PopFront();
+ buffer = std::move(acquired_buffers_.Front());
+ acquired_buffers_.PopFront();
if (frames == 2)
break;
}
+ ALOGD_IF(TRACE, "DisplaySurface::AcquireNewestAvailableBuffer: buffer: %p",
+ buffer.buffer().get());
return buffer;
}
-bool DisplaySurface::IsBufferAvailable() const {
+bool DisplaySurface::IsBufferAvailable() {
std::lock_guard<std::mutex> autolock(lock_);
- return !posted_buffers_.IsEmpty() && posted_buffers_.Front().IsAvailable();
+ DequeueBuffersLocked();
+
+ return !acquired_buffers_.IsEmpty() &&
+ acquired_buffers_.Front().IsAvailable();
}
-bool DisplaySurface::IsBufferPosted() const {
+bool DisplaySurface::IsBufferPosted() {
std::lock_guard<std::mutex> autolock(lock_);
- return !posted_buffers_.IsEmpty();
-}
+ DequeueBuffersLocked();
-AcquiredBuffer DisplaySurface::AcquireCurrentBuffer() {
- std::lock_guard<std::mutex> autolock(lock_);
- if (posted_buffers_.IsEmpty()) {
- ALOGE("Error: attempt to acquire buffer when none are posted.");
- return AcquiredBuffer();
- }
- AcquiredBuffer buffer = std::move(posted_buffers_.Front());
- posted_buffers_.PopFront();
- return buffer;
-}
-
-int DisplaySurface::GetConsumers(std::vector<LocalChannelHandle>* consumers) {
- std::lock_guard<std::mutex> autolock(lock_);
- std::vector<LocalChannelHandle> items;
-
- for (auto pair : buffers_) {
- const auto& buffer = pair.second;
-
- Status<LocalChannelHandle> consumer_channel = buffer->CreateConsumer();
- if (!consumer_channel) {
- ALOGE(
- "DisplaySurface::GetConsumers: Failed to get a new consumer for "
- "buffer %d: %s",
- buffer->id(), consumer_channel.GetErrorMessage().c_str());
- return -consumer_channel.error();
- }
-
- items.push_back(consumer_channel.take());
- }
-
- *consumers = std::move(items);
- return 0;
+ return !acquired_buffers_.IsEmpty();
}
int DisplaySurface::HandleMessage(pdx::Message& message) {
@@ -158,9 +193,9 @@
*this, &DisplaySurface::OnClientSetAttributes, message);
break;
- case DisplayRPC::AllocateBuffer::Opcode:
- DispatchRemoteMethod<DisplayRPC::AllocateBuffer>(
- *this, &DisplaySurface::OnAllocateBuffer, message);
+ case DisplayRPC::CreateBufferQueue::Opcode:
+ DispatchRemoteMethod<DisplayRPC::CreateBufferQueue>(
+ *this, &DisplaySurface::OnCreateBufferQueue, message);
break;
case DisplayRPC::CreateVideoMeshSurface::Opcode:
@@ -226,58 +261,20 @@
return 0;
}
-// Allocates a new buffer for the DisplaySurface associated with this channel.
-std::pair<uint32_t, LocalChannelHandle> DisplaySurface::OnAllocateBuffer(
- pdx::Message& message) {
- // Inject flag to enable framebuffer compression for the application buffers.
- // TODO(eieio,jbates): Make this configurable per hardware platform.
- const int usage = usage_ | GRALLOC_USAGE_QCOM_FRAMEBUFFER_COMPRESSION;
- const int slice_count =
- (flags_ & static_cast<int>(DisplaySurfaceFlagsEnum::SeparateGeometry))
- ? 2
- : 1;
+LocalChannelHandle DisplaySurface::OnCreateBufferQueue(Message& message) {
+ ATRACE_NAME("DisplaySurface::OnCreateBufferQueue");
- ALOGI_IF(
- TRACE,
- "DisplaySurface::OnAllocateBuffer: width=%d height=%d format=%x usage=%x "
- "slice_count=%d",
- width_, height_, format_, usage, slice_count);
-
- // Create a producer buffer to hand back to the sender.
- auto producer = BufferProducer::Create(width_, height_, format_, usage,
- sizeof(uint64_t), slice_count);
- if (!producer)
- REPLY_ERROR_RETURN(message, EINVAL, {});
-
- // Create and import a consumer attached to the producer.
- Status<LocalChannelHandle> consumer_channel = producer->CreateConsumer();
- if (!consumer_channel)
- REPLY_ERROR_RETURN(message, consumer_channel.error(), {});
-
- std::shared_ptr<BufferConsumer> consumer =
- BufferConsumer::Import(consumer_channel.take());
- if (!consumer)
- REPLY_ERROR_RETURN(message, ENOMEM, {});
-
- // Add the consumer to this surface.
- int err = AddConsumer(consumer);
- if (err < 0) {
- ALOGE("DisplaySurface::OnAllocateBuffer: failed to add consumer: buffer=%d",
- consumer->id());
- REPLY_ERROR_RETURN(message, -err, {});
+ if (consumer_queue_ != nullptr) {
+ ALOGE(
+ "DisplaySurface::OnCreateBufferQueue: A ProdcuerQueue has already been "
+ "created and transported to DisplayClient.");
+ REPLY_ERROR_RETURN(message, EALREADY, {});
}
- // Move the channel handle so that it doesn't get closed when the producer
- // goes out of scope.
- std::pair<uint32_t, LocalChannelHandle> return_value(
- allocated_buffer_index_, std::move(producer->GetChannelHandle()));
+ auto producer = ProducerQueue::Create<uint64_t>();
+ consumer_queue_ = producer->CreateConsumerQueue();
- // Save buffer index, associated with the buffer id so that it can be looked
- // up later.
- buffer_id_to_index_[consumer->id()] = allocated_buffer_index_;
- ++allocated_buffer_index_;
-
- return return_value;
+ return std::move(producer->GetChannelHandle());
}
RemoteChannelHandle DisplaySurface::OnCreateVideoMeshSurface(
@@ -319,103 +316,6 @@
return status.take();
}
-int DisplaySurface::AddConsumer(
- const std::shared_ptr<BufferConsumer>& consumer) {
- ALOGD_IF(TRACE, "DisplaySurface::AddConsumer: buffer_id=%d", consumer->id());
- // Add the consumer to the epoll dispatcher, edge-triggered.
- int err = service()->dispatcher_.AddEventHandler(
- consumer->event_fd(), EPOLLET | EPOLLIN | EPOLLHUP,
- std::bind(&DisplaySurface::HandleConsumerEvents,
- std::static_pointer_cast<DisplaySurface>(shared_from_this()),
- consumer, std::placeholders::_1));
- if (err) {
- ALOGE(
- "DisplaySurface::AddConsumer: failed to add epoll event handler for "
- "consumer: %s",
- strerror(-err));
- return err;
- }
-
- // Add the consumer to the list of buffers for this surface.
- std::lock_guard<std::mutex> autolock(lock_);
- buffers_.insert(std::make_pair(consumer->id(), consumer));
- return 0;
-}
-
-void DisplaySurface::RemoveConsumer(
- const std::shared_ptr<BufferConsumer>& consumer) {
- ALOGD_IF(TRACE, "DisplaySurface::RemoveConsumer: buffer_id=%d",
- consumer->id());
- service()->dispatcher_.RemoveEventHandler(consumer->event_fd());
-
- std::lock_guard<std::mutex> autolock(lock_);
- buffers_.erase(consumer->id());
-}
-
-void DisplaySurface::RemoveConsumerUnlocked(
- const std::shared_ptr<BufferConsumer>& consumer) {
- ALOGD_IF(TRACE, "DisplaySurface::RemoveConsumerUnlocked: buffer_id=%d",
- consumer->id());
- service()->dispatcher_.RemoveEventHandler(consumer->event_fd());
- buffers_.erase(consumer->id());
-}
-
-void DisplaySurface::OnPostConsumer(
- const std::shared_ptr<BufferConsumer>& consumer) {
- ATRACE_NAME("DisplaySurface::OnPostConsumer");
- std::lock_guard<std::mutex> autolock(lock_);
-
- if (!IsVisible()) {
- ALOGD_IF(TRACE,
- "DisplaySurface::OnPostConsumer: Discarding buffer_id=%d on "
- "invisible surface.",
- consumer->id());
- consumer->Discard();
- return;
- }
-
- if (posted_buffers_.IsFull()) {
- ALOGE("Error: posted buffers full, overwriting");
- posted_buffers_.PopBack();
- }
-
- int error;
- posted_buffers_.Append(AcquiredBuffer(consumer, &error));
-
- // Remove the consumer if the other end was closed.
- if (posted_buffers_.Back().IsEmpty() && error == -EPIPE)
- RemoveConsumerUnlocked(consumer);
-}
-
-void DisplaySurface::HandleConsumerEvents(
- const std::shared_ptr<BufferConsumer>& consumer, int events) {
- auto status = consumer->GetEventMask(events);
- if (!status) {
- ALOGW(
- "DisplaySurface::HandleConsumerEvents: Failed to get event mask for "
- "consumer: %s",
- status.GetErrorMessage().c_str());
- return;
- }
-
- events = status.get();
- if (events & EPOLLHUP) {
- ALOGD_IF(TRACE,
- "DisplaySurface::HandleConsumerEvents: removing event handler for "
- "buffer=%d",
- consumer->id());
- RemoveConsumer(consumer);
- } else if (events & EPOLLIN) {
- // BufferHub uses EPOLLIN to signal consumer ownership.
- ALOGD_IF(TRACE,
- "DisplaySurface::HandleConsumerEvents: posting buffer=%d for "
- "process=%d",
- consumer->id(), process_id_);
-
- OnPostConsumer(consumer);
- }
-}
-
std::vector<std::shared_ptr<VideoMeshSurface>>
DisplaySurface::GetVideoMeshSurfaces() {
std::lock_guard<std::mutex> autolock(lock_);
diff --git a/libs/vr/libvrflinger/display_surface.h b/libs/vr/libvrflinger/display_surface.h
index fa34057..feb173e 100644
--- a/libs/vr/libvrflinger/display_surface.h
+++ b/libs/vr/libvrflinger/display_surface.h
@@ -13,7 +13,6 @@
#include <vector>
#include "acquired_buffer.h"
-#include "epoll_event_dispatcher.h"
#include "surface_channel.h"
#include "video_mesh_surface.h"
@@ -65,19 +64,8 @@
return buffer_id_to_index_[buffer_id];
}
- // Gets a new set of consumers for all of the surface's buffers. These
- // consumers are independent from the consumers maintained internally to the
- // surface and may be passed to other processes over IPC.
- int GetConsumers(std::vector<pdx::LocalChannelHandle>* consumers);
-
- template <class A>
- void ForEachBuffer(A action) {
- std::lock_guard<std::mutex> autolock(lock_);
- std::for_each(buffers_.begin(), buffers_.end(), action);
- }
-
- bool IsBufferAvailable() const;
- bool IsBufferPosted() const;
+ bool IsBufferAvailable();
+ bool IsBufferPosted();
AcquiredBuffer AcquireCurrentBuffer();
// Get the newest buffer. Up to one buffer will be skipped. If a buffer is
@@ -119,12 +107,6 @@
// Returns whether a frame is available without locking the mutex.
bool IsFrameAvailableNoLock() const;
- // Handles epoll events for BufferHub consumers. Events are mainly generated
- // by producers posting buffers ready for display. This handler runs on the
- // epoll event thread.
- void HandleConsumerEvents(const std::shared_ptr<BufferConsumer>& consumer,
- int events);
-
// Dispatches display surface messages to the appropriate handlers. This
// handler runs on the displayd message dispatch thread.
int HandleMessage(pdx::Message& message) override;
@@ -133,33 +115,22 @@
int OnClientSetAttributes(pdx::Message& message,
const DisplaySurfaceAttributes& attributes);
- // Allocates a buffer with the display surface geometry and settings and
- // returns it to the client.
- std::pair<uint32_t, pdx::LocalChannelHandle> OnAllocateBuffer(
- pdx::Message& message);
+ // Creates a BufferHubQueue associated with this surface and returns the PDX
+ // handle of its producer side to the client.
+ pdx::LocalChannelHandle OnCreateBufferQueue(pdx::Message& message);
- // Creates a video mesh surface associated with this surface and returns it
- // to the client.
+ // Creates a video mesh surface associated with this surface and returns its
+ // PDX handle to the client.
pdx::RemoteChannelHandle OnCreateVideoMeshSurface(pdx::Message& message);
- // Sets the current buffer for the display surface, discarding the previous
- // buffer if it is not already claimed. Runs on the epoll event thread.
- void OnPostConsumer(const std::shared_ptr<BufferConsumer>& consumer);
-
// Client interface (called through IPC) to set visibility and z order.
void ClientSetVisible(bool visible);
void ClientSetZOrder(int z_order);
void ClientSetExcludeFromBlur(bool exclude_from_blur);
void ClientSetBlurBehind(bool blur_behind);
- // Runs on the displayd message dispatch thread.
- int AddConsumer(const std::shared_ptr<BufferConsumer>& consumer);
-
- // Runs on the epoll event thread.
- void RemoveConsumer(const std::shared_ptr<BufferConsumer>& consumer);
-
- // Runs on the epoll and display post thread.
- void RemoveConsumerUnlocked(const std::shared_ptr<BufferConsumer>& consumer);
+ // Dequeue all available buffers from the consumer queue.
+ void DequeueBuffersLocked();
DisplaySurface(const DisplaySurface&) = delete;
void operator=(const DisplaySurface&) = delete;
@@ -169,11 +140,16 @@
// Synchronizes access to mutable state below between message dispatch thread,
// epoll event thread, and frame post thread.
mutable std::mutex lock_;
- std::unordered_map<int, std::shared_ptr<BufferConsumer>> buffers_;
+
+ // The consumer end of a BufferHubQueue. VrFlinger allocates and controls the
+ // buffer queue and pass producer end to the app and the consumer end to
+ // compositor.
+ // TODO(jwcai) Add support for multiple buffer queues per display surface.
+ std::shared_ptr<ConsumerQueue> consumer_queue_;
// In a triple-buffered surface, up to kMaxPostedBuffers buffers may be
// posted and pending.
- RingBuffer<AcquiredBuffer> posted_buffers_;
+ RingBuffer<AcquiredBuffer> acquired_buffers_;
// Provides access to VideoMeshSurface. Here we don't want to increase
// the reference count immediately on allocation, will leave it into
@@ -194,8 +170,6 @@
bool manager_visible_;
int manager_z_order_;
float manager_blur_;
- // The monotonically increasing index for allocated buffers in this surface.
- uint32_t allocated_buffer_index_;
int layer_order_;
// Maps from the buffer id to the corresponding allocated buffer index.
diff --git a/libs/vr/libvrflinger/epoll_event_dispatcher.cpp b/libs/vr/libvrflinger/epoll_event_dispatcher.cpp
deleted file mode 100644
index b37e76e..0000000
--- a/libs/vr/libvrflinger/epoll_event_dispatcher.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-#include "epoll_event_dispatcher.h"
-
-#include <log/log.h>
-#include <sys/epoll.h>
-#include <sys/eventfd.h>
-#include <sys/prctl.h>
-
-#include <dvr/performance_client_api.h>
-
-namespace android {
-namespace dvr {
-
-EpollEventDispatcher::EpollEventDispatcher()
- : exit_thread_(false), epoll_fd_(-1), event_fd_(-1) {
- epoll_fd_ = epoll_create(64);
- if (epoll_fd_ < 0) {
- ALOGE("Failed to create epoll fd: %s", strerror(errno));
- return;
- }
-
- event_fd_ = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
- if (event_fd_ < 0) {
- ALOGE("Failed to create event for epolling: %s", strerror(errno));
- return;
- }
-
- // Add watch for eventfd. This should only watch for EPOLLIN, which gets set
- // when eventfd_write occurs. Use "this" as a unique sentinal value to
- // identify events from the event fd.
- epoll_event event = {.events = EPOLLIN, .data = {.ptr = this}};
- if (epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, event_fd_, &event) < 0) {
- ALOGE("Failed to add eventfd to epoll set because: %s", strerror(errno));
- return;
- }
-
- thread_ = std::thread(&EpollEventDispatcher::EventThread, this);
-}
-
-EpollEventDispatcher::~EpollEventDispatcher() {
- Stop();
-
- close(epoll_fd_);
- close(event_fd_);
-}
-
-void EpollEventDispatcher::Stop() {
- exit_thread_.store(true);
- eventfd_write(event_fd_, 1);
-}
-
-int EpollEventDispatcher::AddEventHandler(int fd, int event_mask,
- Handler handler) {
- std::lock_guard<std::mutex> lock(lock_);
-
- epoll_event event;
- event.events = event_mask;
- event.data.ptr = &(handlers_[fd] = handler);
-
- ALOGD_IF(
- TRACE,
- "EpollEventDispatcher::AddEventHandler: fd=%d event_mask=0x%x handler=%p",
- fd, event_mask, event.data.ptr);
-
- int err = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &event);
- return err < 0 ? -errno : 0;
-}
-
-int EpollEventDispatcher::RemoveEventHandler(int fd) {
- ALOGD_IF(TRACE, "EpollEventDispatcher::RemoveEventHandler: fd=%d", fd);
- std::lock_guard<std::mutex> lock(lock_);
-
- epoll_event dummy; // See BUGS in man 2 epoll_ctl.
- if (epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, &dummy) < 0) {
- ALOGE("Failed to remove fd from epoll set because: %s", strerror(errno));
- return -errno;
- }
-
- // If the fd was valid above, add it to the list of ids to remove.
- removed_handlers_.push_back(fd);
-
- // Wake up the event thread to clean up.
- eventfd_write(event_fd_, 1);
-
- return 0;
-}
-
-void EpollEventDispatcher::EventThread() {
- prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("EpollEvent"), 0, 0, 0);
-
- const int error = dvrSetSchedulerClass(0, "graphics");
- LOG_ALWAYS_FATAL_IF(
- error < 0,
- "EpollEventDispatcher::EventThread: Failed to set scheduler class: %s",
- strerror(-error));
-
- const size_t kMaxNumEvents = 128;
- epoll_event events[kMaxNumEvents];
-
- while (!exit_thread_.load()) {
- int num_events = epoll_wait(epoll_fd_, events, kMaxNumEvents, -1);
- if (num_events < 0 && errno != EINTR)
- break;
-
- ALOGD_IF(TRACE, "EpollEventDispatcher::EventThread: num_events=%d",
- num_events);
-
- for (int i = 0; i < num_events; i++) {
- ALOGD_IF(
- TRACE,
- "EpollEventDispatcher::EventThread: event %d: handler=%p events=0x%x",
- i, events[i].data.ptr, events[i].events);
-
- if (events[i].data.ptr == this) {
- // Clear pending event on event_fd_. Serialize the read with respect to
- // writes from other threads.
- std::lock_guard<std::mutex> lock(lock_);
- eventfd_t value;
- eventfd_read(event_fd_, &value);
- } else {
- auto handler = reinterpret_cast<Handler*>(events[i].data.ptr);
- if (handler)
- (*handler)(events[i].events);
- }
- }
-
- // Remove any handlers that have been posted for removal. This is done here
- // instead of in RemoveEventHandler() to prevent races between the dispatch
- // thread and the code requesting the removal. Handlers are guaranteed to
- // stay alive between exiting epoll_wait() and the dispatch loop above.
- std::lock_guard<std::mutex> lock(lock_);
- for (auto handler_fd : removed_handlers_) {
- ALOGD_IF(TRACE,
- "EpollEventDispatcher::EventThread: removing handler: fd=%d",
- handler_fd);
- handlers_.erase(handler_fd);
- }
- removed_handlers_.clear();
- }
-}
-
-} // namespace dvr
-} // namespace android
diff --git a/libs/vr/libvrflinger/epoll_event_dispatcher.h b/libs/vr/libvrflinger/epoll_event_dispatcher.h
deleted file mode 100644
index 43bca2e..0000000
--- a/libs/vr/libvrflinger/epoll_event_dispatcher.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef ANDROID_DVR_SERVICES_DISPLAYD_EPOLL_EVENT_DISPATCHER_H_
-#define ANDROID_DVR_SERVICES_DISPLAYD_EPOLL_EVENT_DISPATCHER_H_
-
-#include <sys/epoll.h>
-
-#include <atomic>
-#include <functional>
-#include <mutex>
-#include <thread>
-#include <unordered_map>
-#include <vector>
-
-namespace android {
-namespace dvr {
-
-class EpollEventDispatcher {
- public:
- // Function type for event handlers. The handler receives a bitmask of the
- // epoll events that occurred on the file descriptor associated with the
- // handler.
- using Handler = std::function<void(int)>;
-
- EpollEventDispatcher();
- ~EpollEventDispatcher();
-
- // |handler| is called on the internal dispatch thread when |fd| is signaled
- // by events in |event_mask|.
- // Return 0 on success or a negative error code on failure.
- int AddEventHandler(int fd, int event_mask, Handler handler);
- int RemoveEventHandler(int fd);
-
- void Stop();
-
- private:
- void EventThread();
-
- std::thread thread_;
- std::atomic<bool> exit_thread_;
-
- // Protects handlers_ and removed_handlers_ and serializes operations on
- // epoll_fd_ and event_fd_.
- std::mutex lock_;
-
- // Maintains a map of fds to event handlers. This is primarily to keep any
- // references alive that may be bound in the std::function instances. It is
- // not used at dispatch time to avoid performance problems with different
- // versions of std::unordered_map.
- std::unordered_map<int, Handler> handlers_;
-
- // List of fds to be removed from the map. The actual removal is performed
- // by the event dispatch thread to avoid races.
- std::vector<int> removed_handlers_;
-
- int epoll_fd_;
- int event_fd_;
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_SERVICES_DISPLAYD_EPOLL_EVENT_DISPATCHER_H_
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index f801d9b..53c2ac2 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -1485,6 +1485,8 @@
handle = acquired_buffer_.buffer()->native_handle();
acquire_fence_fd_.Reset(acquired_buffer_.ClaimAcquireFence().Release());
} else {
+ // TODO(jwcai) Note: this is the GPU compositor's layer, and we need the
+ // mechanism to accept distorted layers from VrCore.
right = direct_buffer_->width();
bottom = direct_buffer_->height();
handle = direct_buffer_->handle();
diff --git a/libs/vr/libvrflinger/video_compositor.cpp b/libs/vr/libvrflinger/video_compositor.cpp
index 6b39a3c..411e3a3 100644
--- a/libs/vr/libvrflinger/video_compositor.cpp
+++ b/libs/vr/libvrflinger/video_compositor.cpp
@@ -79,7 +79,9 @@
// queued in order from the producer side.
// TODO(jwcai) Use |metadata.timestamp_ns| to schedule video frames
// accurately.
- auto buffer_consumer = consumer_queue_->Dequeue(0, &slot, &metadata);
+ LocalHandle acquire_fence;
+ auto buffer_consumer =
+ consumer_queue_->Dequeue(0, &slot, &metadata, &acquire_fence);
if (buffer_consumer) {
// Create a new texture if it hasn't been created yet, or the same slot
diff --git a/libs/vr/libvrsensor/Android.bp b/libs/vr/libvrsensor/Android.bp
index f973c47..6d48f18 100644
--- a/libs/vr/libvrsensor/Android.bp
+++ b/libs/vr/libvrsensor/Android.bp
@@ -23,6 +23,7 @@
staticLibraries = [
"libbufferhub",
+ "libbufferhubqueue",
"libdvrcommon",
"libpdx_default_transport",
]
diff --git a/services/sensorservice/Android.bp b/services/sensorservice/Android.bp
new file mode 100644
index 0000000..8c2300e
--- /dev/null
+++ b/services/sensorservice/Android.bp
@@ -0,0 +1,3 @@
+subdirs = [
+ "hidl"
+]
diff --git a/services/sensorservice/hidl/Android.bp b/services/sensorservice/hidl/Android.bp
new file mode 100644
index 0000000..f00c297
--- /dev/null
+++ b/services/sensorservice/hidl/Android.bp
@@ -0,0 +1,28 @@
+cc_library_shared {
+ name: "libsensorservicehidl",
+ srcs: [
+ "DirectReportChannel.cpp",
+ "SensorManager.cpp",
+ "utils.cpp",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ shared_libs: [
+ "libbase",
+ "libhidlbase",
+ "libhidltransport",
+ "libutils",
+ "libsensor",
+ "android.frameworks.sensorservice@1.0",
+ "android.hardware.sensors@1.0",
+ "android.hidl.base@1.0",
+ ],
+ export_include_dirs: [
+ "include/"
+ ],
+ local_include_dirs: [
+ "include/sensorservicehidl/"
+ ]
+}
diff --git a/services/sensorservice/hidl/DirectReportChannel.cpp b/services/sensorservice/hidl/DirectReportChannel.cpp
new file mode 100644
index 0000000..9caba47
--- /dev/null
+++ b/services/sensorservice/hidl/DirectReportChannel.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2017 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 "DirectReportChannel.h"
+#include "utils.h"
+
+namespace android {
+namespace frameworks {
+namespace sensorservice {
+namespace V1_0 {
+namespace implementation {
+
+DirectReportChannel::DirectReportChannel(::android::SensorManager& manager, int channelId)
+ : mManager(manager), mId(channelId) {}
+
+DirectReportChannel::~DirectReportChannel() {
+ mManager.destroyDirectChannel(mId);
+}
+
+// Methods from ::android::frameworks::sensorservice::V1_0::IDirectReportChannel follow.
+Return<Result> DirectReportChannel::configure(int32_t sensorHandle, RateLevel rate) {
+ return convertResult(mManager.configureDirectChannel(mId,
+ static_cast<int>(sensorHandle), static_cast<int>(rate)));
+}
+
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace sensorservice
+} // namespace frameworks
+} // namespace android
diff --git a/services/sensorservice/hidl/DirectReportChannel.h b/services/sensorservice/hidl/DirectReportChannel.h
new file mode 100644
index 0000000..f4cd4e7
--- /dev/null
+++ b/services/sensorservice/hidl/DirectReportChannel.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 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_FRAMEWORKS_SENSORSERVICE_V1_0_DIRECTREPORTCHANNEL_H
+#define ANDROID_FRAMEWORKS_SENSORSERVICE_V1_0_DIRECTREPORTCHANNEL_H
+
+#include <android/frameworks/sensorservice/1.0/IDirectReportChannel.h>
+#include <android/frameworks/sensorservice/1.0/types.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <sensor/SensorManager.h>
+
+namespace android {
+namespace frameworks {
+namespace sensorservice {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::frameworks::sensorservice::V1_0::IDirectReportChannel;
+using ::android::hardware::sensors::V1_0::RateLevel;
+using ::android::hidl::base::V1_0::DebugInfo;
+using ::android::hidl::base::V1_0::IBase;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct DirectReportChannel : public IDirectReportChannel {
+
+ DirectReportChannel(::android::SensorManager& manager, int channelId);
+ ~DirectReportChannel();
+
+ // Methods from ::android::frameworks::sensorservice::V1_0::IDirectReportChannel follow.
+ Return<Result> configure(int32_t sensorHandle, RateLevel rate) override;
+
+private:
+ ::android::SensorManager& mManager;
+ const int mId;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace sensorservice
+} // namespace frameworks
+} // namespace android
+
+#endif // ANDROID_FRAMEWORKS_SENSORSERVICE_V1_0_DIRECTREPORTCHANNEL_H
diff --git a/services/sensorservice/hidl/SensorManager.cpp b/services/sensorservice/hidl/SensorManager.cpp
new file mode 100644
index 0000000..b55efb0
--- /dev/null
+++ b/services/sensorservice/hidl/SensorManager.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+// LOG_TAG defined via build flag.
+#ifndef LOG_TAG
+#define LOG_TAG "HidlSensorManager"
+#endif
+#include <android-base/logging.h>
+
+#include "DirectReportChannel.h"
+#include "SensorManager.h"
+#include "utils.h"
+
+namespace android {
+namespace frameworks {
+namespace sensorservice {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::frameworks::sensorservice::V1_0::IDirectReportChannel;
+using ::android::hardware::sensors::V1_0::SensorInfo;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Void;
+using ::android::sp;
+
+SensorManager::SensorManager()
+ : mManager{::android::SensorManager::getInstanceForPackage(
+ String16(ISensorManager::descriptor))} {
+}
+
+// Methods from ::android::frameworks::sensorservice::V1_0::ISensorManager follow.
+Return<void> SensorManager::getSensorList(getSensorList_cb _hidl_cb) {
+ ::android::Sensor const* const* list;
+ ssize_t count = mManager.getSensorList(&list);
+ if (count < 0 || !list) {
+ LOG(ERROR) << "::android::SensorManager::getSensorList encounters " << count;
+ _hidl_cb({}, Result::UNKNOWN_ERROR);
+ return Void();
+ }
+ hidl_vec<SensorInfo> ret;
+ ret.resize(static_cast<size_t>(count));
+ for (ssize_t i = 0; i < count; ++i) {
+ ret[i] = convertSensor(*list[i]);
+ }
+ _hidl_cb(ret, Result::OK);
+ return Void();
+}
+
+Return<void> SensorManager::getDefaultSensor(SensorType type, getDefaultSensor_cb _hidl_cb) {
+ ::android::Sensor const* sensor = mManager.getDefaultSensor(static_cast<int>(type));
+ if (!sensor) {
+ _hidl_cb({}, Result::NOT_EXIST);
+ return Void();
+ }
+ _hidl_cb(convertSensor(*sensor), Result::OK);
+ return Void();
+}
+
+template<typename Callback>
+void createDirectChannel(::android::SensorManager& manager, size_t size, int type,
+ const native_handle_t* handle, const Callback& _hidl_cb) {
+
+ int channelId = manager.createDirectChannel(
+ size, type, handle);
+ if (channelId < 0) {
+ _hidl_cb(nullptr, convertResult(channelId));
+ return;
+ }
+ if (channelId == 0) {
+ _hidl_cb(nullptr, Result::UNKNOWN_ERROR);
+ return;
+ }
+
+ _hidl_cb(sp<IDirectReportChannel>(new DirectReportChannel(manager, channelId)),
+ Result::OK);
+}
+
+Return<void> SensorManager::createAshmemDirectChannel(
+ const hidl_memory& mem, uint64_t size,
+ createAshmemDirectChannel_cb _hidl_cb) {
+ if (size > mem.size()) {
+ _hidl_cb(nullptr, Result::BAD_VALUE);
+ return Void();
+ }
+
+ createDirectChannel(mManager, size, SENSOR_DIRECT_MEM_TYPE_ASHMEM,
+ mem.handle(), _hidl_cb);
+
+ return Void();
+}
+
+Return<void> SensorManager::createGrallocDirectChannel(
+ const hidl_handle& buffer, uint64_t size,
+ createGrallocDirectChannel_cb _hidl_cb) {
+
+ createDirectChannel(mManager, size, SENSOR_DIRECT_MEM_TYPE_GRALLOC,
+ buffer.getNativeHandle(), _hidl_cb);
+
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace sensorservice
+} // namespace frameworks
+} // namespace android
diff --git a/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h b/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
new file mode 100644
index 0000000..484e624
--- /dev/null
+++ b/services/sensorservice/hidl/include/sensorservicehidl/SensorManager.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2017 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_FRAMEWORKS_SENSORSERVICE_V1_0_SENSORMANAGER_H
+#define ANDROID_FRAMEWORKS_SENSORSERVICE_V1_0_SENSORMANAGER_H
+
+#include <android/frameworks/sensorservice/1.0/ISensorManager.h>
+#include <android/frameworks/sensorservice/1.0/types.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <sensor/SensorManager.h>
+
+namespace android {
+namespace frameworks {
+namespace sensorservice {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::sensors::V1_0::SensorType;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::Return;
+
+struct SensorManager : public ISensorManager {
+
+ SensorManager();
+
+ // Methods from ::android::frameworks::sensorservice::V1_0::ISensorManager follow.
+ Return<void> getSensorList(getSensorList_cb _hidl_cb) override;
+ Return<void> getDefaultSensor(SensorType type, getDefaultSensor_cb _hidl_cb) override;
+ Return<void> createAshmemDirectChannel(const hidl_memory& mem, uint64_t size, createAshmemDirectChannel_cb _hidl_cb) override;
+ Return<void> createGrallocDirectChannel(const hidl_handle& buffer, uint64_t size, createGrallocDirectChannel_cb _hidl_cb) override;
+
+private:
+ ::android::SensorManager& mManager;
+
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace sensorservice
+} // namespace frameworks
+} // namespace android
+
+#endif // ANDROID_FRAMEWORKS_SENSORSERVICE_V1_0_SENSORMANAGER_H
diff --git a/services/sensorservice/hidl/utils.cpp b/services/sensorservice/hidl/utils.cpp
new file mode 100644
index 0000000..4e02741
--- /dev/null
+++ b/services/sensorservice/hidl/utils.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2017 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 "utils.h"
+
+namespace android {
+namespace frameworks {
+namespace sensorservice {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::Sensor;
+using ::android::hardware::hidl_string;
+using ::android::hardware::sensors::V1_0::SensorInfo;
+
+SensorInfo convertSensor(const Sensor &src) {
+ SensorInfo dst;
+ const String8& name = src.getName();
+ const String8& vendor = src.getVendor();
+ dst.name = hidl_string{name.string(), name.size()};
+ dst.vendor = hidl_string{vendor.string(), vendor.size()};
+ dst.version = src.getVersion();
+ dst.sensorHandle = src.getHandle();
+ dst.type = static_cast<::android::hardware::sensors::V1_0::SensorType>(
+ src.getType());
+ // FIXME maxRange uses maxValue because ::android::Sensor wraps the
+ // internal sensor_t in this way.
+ dst.maxRange = src.getMaxValue();
+ dst.resolution = src.getResolution();
+ dst.power = src.getPowerUsage();
+ dst.minDelay = src.getMinDelay();
+ dst.fifoReservedEventCount = src.getFifoReservedEventCount();
+ dst.fifoMaxEventCount = src.getFifoMaxEventCount();
+ dst.typeAsString = src.getStringType();
+ dst.requiredPermission = src.getRequiredPermission();
+ dst.maxDelay = src.getMaxDelay();
+ dst.flags = src.getFlags();
+ return dst;
+}
+
+Result convertResult(status_t status) {
+ switch (status) {
+ case OK:
+ return Result::OK;
+ case NAME_NOT_FOUND:
+ return Result::NOT_EXIST;
+ case NO_MEMORY:
+ return Result::NO_MEMORY;
+ case NO_INIT:
+ return Result::NO_INIT;
+ case BAD_VALUE:
+ return Result::BAD_VALUE;
+ case INVALID_OPERATION:
+ return Result::INVALID_OPERATION;
+ default:
+ return Result::UNKNOWN_ERROR;
+ }
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace sensorservice
+} // namespace frameworks
+} // namespace android
diff --git a/services/sensorservice/hidl/utils.h b/services/sensorservice/hidl/utils.h
new file mode 100644
index 0000000..0606e69
--- /dev/null
+++ b/services/sensorservice/hidl/utils.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 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_FRAMEWORKS_SENSORSERVICE_V1_0_UTILS_H
+#define ANDROID_FRAMEWORKS_SENSORSERVICE_V1_0_UTILS_H
+
+#include <android/frameworks/sensorservice/1.0/types.h>
+#include <android/hardware/sensors/1.0/types.h>
+#include <hidl/HidlSupport.h>
+#include <sensor/Sensor.h>
+namespace android {
+namespace frameworks {
+namespace sensorservice {
+namespace V1_0 {
+namespace implementation {
+
+::android::hardware::sensors::V1_0::SensorInfo convertSensor(const ::android::Sensor &src);
+Result convertResult(status_t status);
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace sensorservice
+} // namespace frameworks
+} // namespace android
+
+#endif // ANDROID_FRAMEWORKS_SENSORSERVICE_V1_0_UTILS_H
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 3aab4cf..a6ea750 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -69,16 +69,6 @@
LOCAL_CFLAGS += -DNUM_FRAMEBUFFER_SURFACE_BUFFERS=$(NUM_FRAMEBUFFER_SURFACE_BUFFERS)
endif
-ifeq ($(TARGET_RUNNING_WITHOUT_SYNC_FRAMEWORK),true)
- LOCAL_CFLAGS += -DRUNNING_WITHOUT_SYNC_FRAMEWORK
-endif
-
-ifneq ($(MAX_VIRTUAL_DISPLAY_DIMENSION),)
- LOCAL_CFLAGS += -DMAX_VIRTUAL_DISPLAY_DIMENSION=$(MAX_VIRTUAL_DISPLAY_DIMENSION)
-else
- LOCAL_CFLAGS += -DMAX_VIRTUAL_DISPLAY_DIMENSION=0
-endif
-
LOCAL_CFLAGS += -fvisibility=hidden -Werror=format
LOCAL_HEADER_LIBRARIES := \
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index d7654f1..bd9b8aa 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -216,7 +216,8 @@
return BAD_VALUE;
}
- // This method is only here to handle the kIgnorePresentFences case.
+ // This method is only here to handle the !SurfaceFlinger::hasSyncFramework
+ // case.
bool hasAnyEventListeners() {
if (kTraceDetailedInfo) ATRACE_CALL();
Mutex::Autolock lock(mMutex);
@@ -376,7 +377,8 @@
DispSync::DispSync(const char* name) :
mName(name),
mRefreshSkipCount(0),
- mThread(new DispSyncThread(name)) {
+ mThread(new DispSyncThread(name)),
+ mIgnorePresentFences(!SurfaceFlinger::hasSyncFramework){
mPresentTimeOffset = SurfaceFlinger::dispSyncPresentTimeOffset;
mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
@@ -397,7 +399,7 @@
// Even if we're just ignoring the fences, the zero-phase tracing is
// not needed because any time there is an event registered we will
// turn on the HW vsync events.
- if (!kIgnorePresentFences && kEnableZeroPhaseTracer) {
+ if (!mIgnorePresentFences && kEnableZeroPhaseTracer) {
addEventListener("ZeroPhaseTracer", 0, new ZeroPhaseTracer());
}
}
@@ -476,7 +478,7 @@
resetErrorLocked();
}
- if (kIgnorePresentFences) {
+ if (mIgnorePresentFences) {
// If we don't have the sync framework we will never have
// addPresentFence called. This means we have no way to know whether
// or not we're synchronized with the HW vsyncs, so we just request
@@ -641,7 +643,7 @@
void DispSync::dump(String8& result) const {
Mutex::Autolock lock(mMutex);
result.appendFormat("present fences are %s\n",
- kIgnorePresentFences ? "ignored" : "used");
+ mIgnorePresentFences ? "ignored" : "used");
result.appendFormat("mPeriod: %" PRId64 " ns (%.3f fps; skipCount=%d)\n",
mPeriod, 1000000000.0 / mPeriod, mRefreshSkipCount);
result.appendFormat("mPhase: %" PRId64 " ns\n", mPhase);
diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h
index 5b7083d..82ae795 100644
--- a/services/surfaceflinger/DispSync.h
+++ b/services/surfaceflinger/DispSync.h
@@ -25,15 +25,6 @@
namespace android {
-// Ignore present (retire) fences if the device doesn't have support for the
-// sync framework
-#if defined(RUNNING_WITHOUT_SYNC_FRAMEWORK)
-static const bool kIgnorePresentFences = true;
-#else
-static const bool kIgnorePresentFences = false;
-#endif
-
-
class String8;
class Fence;
class DispSyncThread;
@@ -186,6 +177,10 @@
// This is the offset from the present fence timestamps to the corresponding
// vsync event.
int64_t mPresentTimeOffset;
+
+ // Ignore present (retire) fences if the device doesn't have support for the
+ // sync framework
+ bool mIgnorePresentFences;
};
}
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 9af4402..11df4e2 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -118,6 +118,9 @@
mNativeWindow = surface = new Surface(producer, false);
ANativeWindow* const window = mNativeWindow.get();
+#ifdef USE_HWC2
+ mActiveColorMode = static_cast<android_color_mode_t>(-1);
+#endif
/*
* Create our display's surface
*/
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 6644bd9..23b7a45 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -267,12 +267,12 @@
return NO_MEMORY;
}
- if (MAX_VIRTUAL_DISPLAY_DIMENSION != 0 &&
- (width > MAX_VIRTUAL_DISPLAY_DIMENSION ||
- height > MAX_VIRTUAL_DISPLAY_DIMENSION)) {
+ if (SurfaceFlinger::maxVirtualDisplaySize != 0 &&
+ (width > SurfaceFlinger::maxVirtualDisplaySize ||
+ height > SurfaceFlinger::maxVirtualDisplaySize)) {
ALOGE("createVirtualDisplay: Can't create a virtual display with"
- " a dimension > %u (tried %u x %u)",
- MAX_VIRTUAL_DISPLAY_DIMENSION, width, height);
+ " a dimension > %" PRIu64 " (tried %u x %u)",
+ SurfaceFlinger::maxVirtualDisplaySize, width, height);
return INVALID_OPERATION;
}
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 295b229..861a7d9 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -760,9 +760,7 @@
mHwcLayers[hwcId].forceClientComposition = true;
}
-#endif
-#ifdef USE_HWC2
void Layer::setPerFrameData(const sp<const DisplayDevice>& displayDevice) {
// Apply this display's projection's viewport to the visible region
// before giving it to the HWC HAL.
@@ -865,6 +863,10 @@
static_cast<int32_t>(error));
}
}
+
+android_dataspace Layer::getDataSpace() const {
+ return mCurrentState.dataSpace;
+}
#else
void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
HWComposer::HWCLayerInterface& layer) {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 6b228b0..afe6074 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -261,6 +261,8 @@
void forceClientComposition(int32_t hwcId);
void setPerFrameData(const sp<const DisplayDevice>& displayDevice);
+ android_dataspace getDataSpace() const;
+
// callIntoHwc exists so we can update our local state and call
// acceptDisplayChanges without unnecessarily updating the device's state
void setCompositionType(int32_t hwcId, HWC2::Composition type,
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 5f1d16f..06dd903 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -99,6 +99,7 @@
namespace android {
+
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
@@ -115,6 +116,8 @@
bool SurfaceFlinger::useContextPriority;
int64_t SurfaceFlinger::dispSyncPresentTimeOffset;
bool SurfaceFlinger::useHwcForRgbToYuv;
+uint64_t SurfaceFlinger::maxVirtualDisplaySize;
+bool SurfaceFlinger::hasSyncFramework;
SurfaceFlinger::SurfaceFlinger()
: BnSurfaceComposer(),
@@ -158,6 +161,7 @@
,mEnterVrMode(false)
#endif
{
+ ALOGI("SurfaceFlinger is starting");
vsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::vsyncEventPhaseOffsetNs>(1000000);
@@ -165,7 +169,8 @@
sfVsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::vsyncSfEventPhaseOffsetNs>(1000000);
- ALOGI("SurfaceFlinger is starting");
+ hasSyncFramework = getBool< ISurfaceFlingerConfigs,
+ &ISurfaceFlingerConfigs::hasSyncFramework>(true);
useContextPriority = getBool< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::useContextPriority>(false);
@@ -176,6 +181,9 @@
useHwcForRgbToYuv = getBool< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::useHwcForRGBtoYUV>(false);
+ maxVirtualDisplaySize = getUInt64<ISurfaceFlingerConfigs,
+ &ISurfaceFlingerConfigs::maxVirtualDisplaySize>(0);
+
// debugging stuff...
char value[PROPERTY_VALUE_MAX];
@@ -1121,7 +1129,7 @@
}
void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) {
- std::lock_guard<std::mutex> lock(mCompositeTimingLock);
+ std::lock_guard<std::mutex> lock(mCompositorTimingLock);
*compositorTiming = mCompositorTiming;
}
@@ -1418,34 +1426,39 @@
mCompositePresentTimes.pop();
}
+ setCompositorTimingSnapped(
+ vsyncPhase, vsyncInterval, compositeToPresentLatency);
+}
+
+void SurfaceFlinger::setCompositorTimingSnapped(nsecs_t vsyncPhase,
+ nsecs_t vsyncInterval, nsecs_t compositeToPresentLatency) {
// Integer division and modulo round toward 0 not -inf, so we need to
// treat negative and positive offsets differently.
- nsecs_t idealLatency = (sfVsyncPhaseOffsetNs >= 0) ?
+ nsecs_t idealLatency = (sfVsyncPhaseOffsetNs > 0) ?
(vsyncInterval - (sfVsyncPhaseOffsetNs % vsyncInterval)) :
((-sfVsyncPhaseOffsetNs) % vsyncInterval);
+ // Just in case sfVsyncPhaseOffsetNs == -vsyncInterval.
+ if (idealLatency <= 0) {
+ idealLatency = vsyncInterval;
+ }
+
// Snap the latency to a value that removes scheduling jitter from the
// composition and present times, which often have >1ms of jitter.
// Reducing jitter is important if an app attempts to extrapolate
// something (such as user input) to an accurate diasplay time.
// Snapping also allows an app to precisely calculate sfVsyncPhaseOffsetNs
// with (presentLatency % interval).
- nsecs_t snappedCompositeToPresentLatency = -1;
- if (compositeToPresentLatency >= 0) {
- nsecs_t bias = vsyncInterval / 2;
- int64_t extraVsyncs =
- (compositeToPresentLatency - idealLatency + bias) /
- vsyncInterval;
- nsecs_t extraLatency = extraVsyncs * vsyncInterval;
- snappedCompositeToPresentLatency = idealLatency + extraLatency;
- }
+ nsecs_t bias = vsyncInterval / 2;
+ int64_t extraVsyncs =
+ (compositeToPresentLatency - idealLatency + bias) / vsyncInterval;
+ nsecs_t snappedCompositeToPresentLatency = (extraVsyncs > 0) ?
+ idealLatency + (extraVsyncs * vsyncInterval) : idealLatency;
- std::lock_guard<std::mutex> lock(mCompositeTimingLock);
+ std::lock_guard<std::mutex> lock(mCompositorTimingLock);
mCompositorTiming.deadline = vsyncPhase - idealLatency;
mCompositorTiming.interval = vsyncInterval;
- if (snappedCompositeToPresentLatency >= 0) {
- mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
- }
+ mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
}
void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
@@ -1492,10 +1505,15 @@
// since updateCompositorTiming has snapping logic.
updateCompositorTiming(
vsyncPhase, vsyncInterval, refreshStartTime, displayFenceTime);
+ CompositorTiming compositorTiming;
+ {
+ std::lock_guard<std::mutex> lock(mCompositorTimingLock);
+ compositorTiming = mCompositorTiming;
+ }
mDrawingState.traverseInZOrder([&](Layer* layer) {
bool frameLatched = layer->onPostComposition(glCompositionDoneFenceTime,
- *presentFenceTime, *retireFenceTime, mCompositorTiming);
+ *presentFenceTime, *retireFenceTime, compositorTiming);
if (frameLatched) {
recordBufferingStats(layer->getName().string(),
layer->getOccupancyHistory(false));
@@ -1510,7 +1528,7 @@
}
}
- if (kIgnorePresentFences) {
+ if (!hasSyncFramework) {
if (hw->isDisplayOn()) {
enableHardwareVsync();
}
@@ -2974,10 +2992,9 @@
const nsecs_t period = activeConfig->getVsyncPeriod();
mAnimFrameTracker.setDisplayRefreshPeriod(period);
- {
- std::lock_guard<std::mutex> lock(mCompositeTimingLock);
- mCompositorTiming.interval = period;
- }
+ // Use phase of 0 since phase is not known.
+ // Use latency of 0, which will snap to the ideal latency.
+ setCompositorTimingSnapped(0, period, 0);
}
void SurfaceFlinger::initializeDisplays() {
@@ -3243,6 +3260,8 @@
result.appendFormat(" PRESENT_TIME_OFFSET=%" PRId64 , dispSyncPresentTimeOffset);
result.appendFormat(" FORCE_HWC_FOR_RBG_TO_YUV=%d", useHwcForRgbToYuv);
+ result.appendFormat(" MAX_VIRT_DISPLAY_DIM=%" PRIu64, maxVirtualDisplaySize);
+ result.appendFormat(" RUNNING_WITHOUT_SYNC_FRAMEWORK=%d", !hasSyncFramework);
result.append("]");
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index e6ccc41..921ecf6 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -105,7 +105,6 @@
{
public:
-
// This is the phase offset in nanoseconds of the software vsync event
// relative to the vsync event reported by HWComposer. The software vsync
// event is when SurfaceFlinger and Choreographer-based applications run each
@@ -129,6 +128,9 @@
static int64_t vsyncPhaseOffsetNs;
static int64_t sfVsyncPhaseOffsetNs;
+ // If fences from sync Framework are supported.
+ static bool hasSyncFramework;
+
// Instruct the Render Engine to use EGL_IMG_context_priority is available.
static bool useContextPriority;
@@ -142,6 +144,10 @@
// GL composition.
static bool useHwcForRgbToYuv;
+ // Maximum dimension supported by HWC for virtual display.
+ // Equal to min(max_height, max_width).
+ static uint64_t maxVirtualDisplaySize;
+
static char const* getServiceName() ANDROID_API {
return "SurfaceFlinger";
}
@@ -460,6 +466,9 @@
void updateCompositorTiming(
nsecs_t vsyncPhase, nsecs_t vsyncInterval, nsecs_t compositeTime,
std::shared_ptr<FenceTime>& presentFenceTime);
+ void setCompositorTimingSnapped(
+ nsecs_t vsyncPhase, nsecs_t vsyncInterval,
+ nsecs_t compositeToPresentLatency);
void rebuildLayerStacks();
void setUpHWComposer();
void doComposition();
@@ -630,7 +639,7 @@
bool mHWVsyncAvailable;
// protected by mCompositorTimingLock;
- mutable std::mutex mCompositeTimingLock;
+ mutable std::mutex mCompositorTimingLock;
CompositorTiming mCompositorTiming;
// Only accessed from the main thread.
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 6f6c08b..e8147cf 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -114,6 +114,8 @@
bool SurfaceFlinger::useContextPriority;
int64_t SurfaceFlinger::dispSyncPresentTimeOffset;
bool SurfaceFlinger::useHwcForRgbToYuv;
+uint64_t SurfaceFlinger::maxVirtualDisplaySize;
+bool SurfaceFlinger::hasSyncFramework;
SurfaceFlinger::SurfaceFlinger()
: BnSurfaceComposer(),
@@ -150,13 +152,19 @@
mLastSwapTime(0),
mNumLayers(0)
{
+ ALOGI("SurfaceFlinger is starting");
+
vsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::vsyncEventPhaseOffsetNs>(1000000);
sfVsyncPhaseOffsetNs = getInt64< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::vsyncSfEventPhaseOffsetNs>(1000000);
- ALOGI("SurfaceFlinger is starting");
+ maxVirtualDisplaySize = getUInt64<ISurfaceFlingerConfigs,
+ &ISurfaceFlingerConfigs::maxVirtualDisplaySize>(0);
+
+ hasSyncFramework = getBool< ISurfaceFlingerConfigs,
+ &ISurfaceFlingerConfigs::hasSyncFramework>(true);
useContextPriority = getBool< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::useContextPriority>(false);
@@ -1040,7 +1048,7 @@
}
void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) {
- std::lock_guard<std::mutex> lock(mCompositeTimingLock);
+ std::lock_guard<std::mutex> lock(mCompositorTimingLock);
*compositorTiming = mCompositorTiming;
}
@@ -1203,34 +1211,39 @@
mCompositePresentTimes.pop();
}
+ setCompositorTimingSnapped(
+ vsyncPhase, vsyncInterval, compositeToPresentLatency);
+}
+
+void SurfaceFlinger::setCompositorTimingSnapped(nsecs_t vsyncPhase,
+ nsecs_t vsyncInterval, nsecs_t compositeToPresentLatency) {
// Integer division and modulo round toward 0 not -inf, so we need to
// treat negative and positive offsets differently.
- nsecs_t idealLatency = (sfVsyncPhaseOffsetNs >= 0) ?
+ nsecs_t idealLatency = (sfVsyncPhaseOffsetNs > 0) ?
(vsyncInterval - (sfVsyncPhaseOffsetNs % vsyncInterval)) :
((-sfVsyncPhaseOffsetNs) % vsyncInterval);
+ // Just in case sfVsyncPhaseOffsetNs == -vsyncInterval.
+ if (idealLatency <= 0) {
+ idealLatency = vsyncInterval;
+ }
+
// Snap the latency to a value that removes scheduling jitter from the
// composition and present times, which often have >1ms of jitter.
// Reducing jitter is important if an app attempts to extrapolate
// something (such as user input) to an accurate diasplay time.
// Snapping also allows an app to precisely calculate sfVsyncPhaseOffsetNs
// with (presentLatency % interval).
- nsecs_t snappedCompositeToPresentLatency = -1;
- if (compositeToPresentLatency >= 0) {
- nsecs_t bias = vsyncInterval / 2;
- int64_t extraVsyncs =
- (compositeToPresentLatency - idealLatency + bias) /
- vsyncInterval;
- nsecs_t extraLatency = extraVsyncs * vsyncInterval;
- snappedCompositeToPresentLatency = idealLatency + extraLatency;
- }
+ nsecs_t bias = vsyncInterval / 2;
+ int64_t extraVsyncs =
+ (compositeToPresentLatency - idealLatency + bias) / vsyncInterval;
+ nsecs_t snappedCompositeToPresentLatency = (extraVsyncs > 0) ?
+ idealLatency + (extraVsyncs * vsyncInterval) : idealLatency;
- std::lock_guard<std::mutex> lock(mCompositeTimingLock);
+ std::lock_guard<std::mutex> lock(mCompositorTimingLock);
mCompositorTiming.deadline = vsyncPhase - idealLatency;
mCompositorTiming.interval = vsyncInterval;
- if (snappedCompositeToPresentLatency >= 0) {
- mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
- }
+ mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
}
void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
@@ -1262,10 +1275,15 @@
// since updateCompositorTiming has snapping logic.
updateCompositorTiming(
vsyncPhase, vsyncInterval, refreshStartTime, retireFenceTime);
+ CompositorTiming compositorTiming;
+ {
+ std::lock_guard<std::mutex> lock(mCompositorTimingLock);
+ compositorTiming = mCompositorTiming;
+ }
mDrawingState.traverseInZOrder([&](Layer* layer) {
bool frameLatched = layer->onPostComposition(glCompositionDoneFenceTime,
- presentFenceTime, retireFenceTime, mCompositorTiming);
+ presentFenceTime, retireFenceTime, compositorTiming);
if (frameLatched) {
recordBufferingStats(layer->getName().string(),
layer->getOccupancyHistory(false));
@@ -1280,7 +1298,7 @@
}
}
- if (kIgnorePresentFences) {
+ if (!hasSyncFramework) {
if (hw->isDisplayOn()) {
enableHardwareVsync();
}
@@ -1701,9 +1719,9 @@
ALOGE_IF(status != NO_ERROR,
"Unable to query height (%d)", status);
if (mUseHwcVirtualDisplays &&
- (MAX_VIRTUAL_DISPLAY_DIMENSION == 0 ||
- (width <= MAX_VIRTUAL_DISPLAY_DIMENSION &&
- height <= MAX_VIRTUAL_DISPLAY_DIMENSION))) {
+ (SurfaceFlinger::maxVirtualDisplaySize == 0 ||
+ (width <= static_cast<int>(SurfaceFlinger::maxVirtualDisplaySize) &&
+ height <= static_cast<int>(SurfaceFlinger::maxVirtualDisplaySize)))) {
hwcDisplayId = allocateHwcDisplayId(state.type);
}
@@ -2750,6 +2768,10 @@
const nsecs_t period =
getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
mAnimFrameTracker.setDisplayRefreshPeriod(period);
+
+ // Use phase of 0 since phase is not known.
+ // Use latency of 0, which will snap to the ideal latency.
+ setCompositorTimingSnapped(0, period, 0);
}
void SurfaceFlinger::initializeDisplays() {
@@ -3015,6 +3037,8 @@
result.appendFormat(" PRESENT_TIME_OFFSET=%" PRId64, dispSyncPresentTimeOffset);
result.appendFormat(" FORCE_HWC_FOR_RBG_TO_YUV=%d", useHwcForRgbToYuv);
+ result.appendFormat(" MAX_VIRT_DISPLAY_DIM=%" PRIu64, maxVirtualDisplaySize);
+ result.appendFormat(" RUNNING_WITHOUT_SYNC_FRAMEWORK=%d", !hasSyncFramework);
result.append("]");
}
diff --git a/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp b/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
index 99e21ec..60ca818 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
+++ b/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
@@ -312,32 +312,12 @@
return Error::BAD_CONFIG;
}
- int error = 0;
- auto display_client = DisplayClient::Create(&error);
- SystemDisplayMetrics metrics;
-
- if (error) {
- ALOGE("Could not connect to display service : %s(%d)", strerror(error), error);
- } else {
- error = display_client->GetDisplayMetrics(&metrics);
-
- if (error) {
- ALOGE("Could not get display metrics from display service : %s(%d)", strerror(error), error);
- }
- }
-
- if (error) {
- metrics.display_native_width = 1080;
- metrics.display_native_height = 1920;
- ALOGI("Setting display metrics to default : width=%d height=%d", metrics.display_native_width, metrics.display_native_height);
- }
-
switch (attribute) {
case IComposerClient::Attribute::WIDTH:
- *outValue = metrics.display_native_width;
+ *outValue = 1080;
break;
case IComposerClient::Attribute::HEIGHT:
- *outValue = metrics.display_native_height;
+ *outValue = 1920;
break;
case IComposerClient::Attribute::VSYNC_PERIOD:
*outValue = 1000 * 1000 * 1000 / 30; // 30fps
diff --git a/services/vr/vr_window_manager/surface_flinger_view.cpp b/services/vr/vr_window_manager/surface_flinger_view.cpp
index 46eb880..8411806 100644
--- a/services/vr/vr_window_manager/surface_flinger_view.cpp
+++ b/services/vr/vr_window_manager/surface_flinger_view.cpp
@@ -39,29 +39,9 @@
vr_composer_view_->Initialize(GetComposerViewFromIComposer(
vr_hwcomposer_.get()));
- int error = 0;
- auto display_client = DisplayClient::Create(&error);
- SystemDisplayMetrics metrics;
-
- if (error) {
- ALOGE("Could not connect to display service : %s(%d)", strerror(error), error);
- } else {
- error = display_client->GetDisplayMetrics(&metrics);
-
- if (error) {
- ALOGE("Could not get display metrics from display service : %s(%d)", strerror(error), error);
- }
- }
-
- if (error) {
- metrics.display_native_height = 1920;
- metrics.display_native_width = 1080;
- ALOGI("Setting display metrics to default : width=%d height=%d", metrics.display_native_height, metrics.display_native_width);
- }
-
// TODO(alexst): Refactor ShellView to account for orientation and change this back.
- width_ = metrics.display_native_height;
- height_ = metrics.display_native_width;
+ width_ = 1920;
+ height_ = 1080;
return true;
}
diff --git a/vulkan/include/vulkan/vulkan.h b/vulkan/include/vulkan/vulkan.h
index 2293960..4b3b8bf 100644
--- a/vulkan/include/vulkan/vulkan.h
+++ b/vulkan/include/vulkan/vulkan.h
@@ -3306,14 +3306,14 @@
VK_COLOR_SPACE_SRGB_NONLINEAR_KHR = 0,
VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT = 1000104001,
VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT = 1000104002,
- VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT = 1000104003,
- VK_COLOR_SPACE_DCI_P3_LINEAR_EXT = 1000104004,
- VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT = 1000104005,
- VK_COLOR_SPACE_BT709_LINEAR_EXT = 1000104006,
- VK_COLOR_SPACE_BT709_NONLINEAR_EXT = 1000104007,
- VK_COLOR_SPACE_BT2020_LINEAR_EXT = 1000104008,
- VK_COLOR_SPACE_BT2020_170M_EXT = 1000104009,
- VK_COLOR_SPACE_BT2020_ST2084_EXT = 1000104010,
+ VK_COLOR_SPACE_DCI_P3_LINEAR_EXT = 1000104003,
+ VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT = 1000104004,
+ VK_COLOR_SPACE_BT709_LINEAR_EXT = 1000104005,
+ VK_COLOR_SPACE_BT709_NONLINEAR_EXT = 1000104006,
+ VK_COLOR_SPACE_BT2020_LINEAR_EXT = 1000104007,
+ VK_COLOR_SPACE_HDR10_ST2084_EXT = 1000104008,
+ VK_COLOR_SPACE_DOLBYVISION_EXT = 1000104009,
+ VK_COLOR_SPACE_HDR10_HLG_EXT = 1000104010,
VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT = 1000104011,
VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT = 1000104012,
VK_COLOR_SPACE_PASS_THROUGH_EXT = 1000104013,
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index b24bc1b..f7695ea 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -411,8 +411,6 @@
return HAL_DATASPACE_DISPLAY_P3;
case VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT:
return HAL_DATASPACE_V0_SCRGB_LINEAR;
- case VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT:
- return HAL_DATASPACE_V0_SCRGB;
case VK_COLOR_SPACE_DCI_P3_LINEAR_EXT:
return HAL_DATASPACE_DCI_P3_LINEAR;
case VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT:
@@ -421,14 +419,20 @@
return HAL_DATASPACE_V0_SRGB_LINEAR;
case VK_COLOR_SPACE_BT709_NONLINEAR_EXT:
return HAL_DATASPACE_V0_SRGB;
- case VK_COLOR_SPACE_BT2020_170M_EXT:
- return static_cast<android_dataspace>(
- HAL_DATASPACE_STANDARD_BT2020 |
- HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_RANGE_FULL);
- case VK_COLOR_SPACE_BT2020_ST2084_EXT:
+ case VK_COLOR_SPACE_BT2020_LINEAR_EXT:
+ return HAL_DATASPACE_BT2020_LINEAR;
+ case VK_COLOR_SPACE_HDR10_ST2084_EXT:
return static_cast<android_dataspace>(
HAL_DATASPACE_STANDARD_BT2020 | HAL_DATASPACE_TRANSFER_ST2084 |
HAL_DATASPACE_RANGE_FULL);
+ case VK_COLOR_SPACE_DOLBYVISION_EXT:
+ return static_cast<android_dataspace>(
+ HAL_DATASPACE_STANDARD_BT2020 | HAL_DATASPACE_TRANSFER_ST2084 |
+ HAL_DATASPACE_RANGE_FULL);
+ case VK_COLOR_SPACE_HDR10_HLG_EXT:
+ return static_cast<android_dataspace>(
+ HAL_DATASPACE_STANDARD_BT2020 | HAL_DATASPACE_TRANSFER_HLG |
+ HAL_DATASPACE_RANGE_FULL);
case VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT:
return static_cast<android_dataspace>(
HAL_DATASPACE_STANDARD_ADOBE_RGB |