Snap for 5949240 from 858a972d1ce2eb048066c8a136e28f24bda5dc24 to sdk-release
Change-Id: I0524f6eefdb739f976075141907fa5824f6ca064
diff --git a/BUILD.gn b/BUILD.gn
index 52f4635..c6e0201 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -4,6 +4,7 @@
"android-emu/android/base/AlignedBuf.h",
"android-emu/android/base/Pool.cpp",
"android-emu/android/base/Pool.h",
+ "android-emu/android/base/ring_buffer.c",
"android-emu/android/base/SubAllocator.cpp",
"android-emu/android/base/SubAllocator.h",
"android-emu/android/base/files/MemStream.cpp",
@@ -91,6 +92,14 @@
"PAGE_SIZE=4096",
]
+ cflags_c = [
+ "-Wno-missing-field-initializers",
+ "-Wno-newline-eof",
+ "-Wno-unused-function",
+ "-Wno-unused-value",
+ "-Wno-unused-variable",
+ ]
+
cflags_cc = [
"-Wno-missing-field-initializers",
"-Wno-newline-eof",
diff --git a/android-emu/Android.mk b/android-emu/Android.mk
index 9ef32cd..6de495e 100644
--- a/android-emu/Android.mk
+++ b/android-emu/Android.mk
@@ -16,6 +16,7 @@
android/base/files/Stream.cpp \
android/base/files/StreamSerializing.cpp \
android/base/Pool.cpp \
+ android/base/ring_buffer.c \
android/base/StringFormat.cpp \
android/base/SubAllocator.cpp \
android/base/synchronization/AndroidMessageChannel.cpp \
diff --git a/android-emu/CMakeLists.txt b/android-emu/CMakeLists.txt
index ffa1fd2..e6482d8 100644
--- a/android-emu/CMakeLists.txt
+++ b/android-emu/CMakeLists.txt
@@ -1,8 +1,8 @@
# This is an autogenerated file! Do not edit!
# instead run make from .../device/generic/goldfish-opengl
# which will re-generate this file.
-android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/android-emu/Android.mk" "74426692eff285e93994e82bdc6a648312c8a6e7f0b2daf22fe255ac5bfd3b64")
-set(androidemu_src android/base/AlignedBuf.cpp android/base/files/MemStream.cpp android/base/files/Stream.cpp android/base/files/StreamSerializing.cpp android/base/Pool.cpp android/base/StringFormat.cpp android/base/SubAllocator.cpp android/base/synchronization/AndroidMessageChannel.cpp android/base/threads/AndroidFunctorThread.cpp android/base/threads/AndroidThreadStore.cpp android/base/threads/AndroidThread_pthread.cpp android/base/threads/AndroidWorkPool.cpp android/base/Tracing.cpp android/utils/debug.c)
+android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/android-emu/Android.mk" "3654f06acfa661c75b91fe271337a63a77326a69b4247026996c40bff8138bde")
+set(androidemu_src android/base/AlignedBuf.cpp android/base/files/MemStream.cpp android/base/files/Stream.cpp android/base/files/StreamSerializing.cpp android/base/Pool.cpp android/base/ring_buffer.c android/base/StringFormat.cpp android/base/SubAllocator.cpp android/base/synchronization/AndroidMessageChannel.cpp android/base/threads/AndroidFunctorThread.cpp android/base/threads/AndroidThreadStore.cpp android/base/threads/AndroidThread_pthread.cpp android/base/threads/AndroidWorkPool.cpp android/base/Tracing.cpp android/utils/debug.c)
android_add_shared_library(androidemu)
target_include_directories(androidemu PRIVATE ${GOLDFISH_DEVICE_ROOT}/android-emu ${GOLDFISH_DEVICE_ROOT}/./host/include/libOpenglRender ${GOLDFISH_DEVICE_ROOT}/./system/include ${GOLDFISH_DEVICE_ROOT}/./../../../external/qemu/android/android-emugl/guest)
target_compile_definitions(androidemu PRIVATE "-DWITH_GLES2" "-DPLATFORM_SDK_VERSION=29" "-DGOLDFISH_HIDL_GRALLOC" "-DEMULATOR_OPENGL_POST_O=1" "-DHOST_BUILD" "-DANDROID" "-DGL_GLEXT_PROTOTYPES" "-DPAGE_SIZE=4096" "-DGOLDFISH_VULKAN" "-DLOG_TAG=\"androidemu\"")
diff --git a/android-emu/android/base/ring_buffer.c b/android-emu/android/base/ring_buffer.c
new file mode 100644
index 0000000..ef26d1d
--- /dev/null
+++ b/android-emu/android/base/ring_buffer.c
@@ -0,0 +1,521 @@
+// Copyright 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "android/base/ring_buffer.h"
+
+#include <errno.h>
+#include <string.h>
+#ifdef _MSC_VER
+#include "msvc-posix.h"
+#else
+#include <sys/time.h>
+#endif
+
+#if (defined(__i386__) || defined(__x86_64__))
+#define RING_BUFFER_X86 1
+#else
+#define RING_BUFFER_X86 0
+#endif
+
+#if RING_BUFFER_X86
+#include <emmintrin.h>
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <sched.h>
+#include <unistd.h>
+#endif
+
+#define RING_BUFFER_MASK (RING_BUFFER_SIZE - 1)
+
+#define RING_BUFFER_VERSION 1
+
+static inline void ring_buffer_pause() {
+#if RING_BUFFER_X86
+ _mm_pause();
+#else
+ // TODO(lfy) analog of pause on ARM
+#endif
+}
+
+void ring_buffer_init(struct ring_buffer* r) {
+ r->guest_version = 1;
+ r->write_pos = 0;
+ r->read_pos = 0;
+
+ r->read_live_count = 0;
+ r->read_yield_count = 0;
+ r->read_sleep_us_count = 0;
+
+ r->state = 0;
+}
+
+static uint32_t get_ring_pos(uint32_t index) {
+ return index & RING_BUFFER_MASK;
+}
+
+bool ring_buffer_can_write(const struct ring_buffer* r, uint32_t bytes) {
+ uint32_t read_view;
+ __atomic_load(&r->read_pos, &read_view, __ATOMIC_SEQ_CST);
+ return get_ring_pos(read_view - r->write_pos - 1) >= bytes;
+}
+
+bool ring_buffer_can_read(const struct ring_buffer* r, uint32_t bytes) {
+ uint32_t write_view;
+ __atomic_load(&r->write_pos, &write_view, __ATOMIC_SEQ_CST);
+ return get_ring_pos(write_view - r->read_pos) >= bytes;
+}
+
+long ring_buffer_write(
+ struct ring_buffer* r, const void* data, uint32_t step_size, uint32_t steps) {
+ const uint8_t* data_bytes = (const uint8_t*)data;
+ uint32_t i;
+
+ for (i = 0; i < steps; ++i) {
+ if (!ring_buffer_can_write(r, step_size)) {
+ errno = -EAGAIN;
+ return (long)i;
+ }
+
+ // Needs to be split up into 2 writes for the edge case.
+ uint32_t available_at_end =
+ RING_BUFFER_SIZE - get_ring_pos(r->write_pos);
+
+ if (step_size > available_at_end) {
+ uint32_t remaining = step_size - available_at_end;
+ memcpy(
+ &r->buf[get_ring_pos(r->write_pos)],
+ data_bytes + i * step_size,
+ available_at_end);
+ memcpy(
+ &r->buf[get_ring_pos(r->write_pos + available_at_end)],
+ data_bytes + i * step_size + available_at_end,
+ remaining);
+ } else {
+ memcpy(
+ &r->buf[get_ring_pos(r->write_pos)],
+ data_bytes + i * step_size,
+ step_size);
+ }
+
+ __atomic_add_fetch(&r->write_pos, step_size, __ATOMIC_SEQ_CST);
+ }
+
+ errno = 0;
+ return (long)steps;
+}
+
+long ring_buffer_read(
+ struct ring_buffer* r, void* data, uint32_t step_size, uint32_t steps) {
+ uint8_t* data_bytes = (uint8_t*)data;
+ uint32_t i;
+
+ for (i = 0; i < steps; ++i) {
+ if (!ring_buffer_can_read(r, step_size)) {
+ errno = -EAGAIN;
+ return (long)i;
+ }
+
+ // Needs to be split up into 2 reads for the edge case.
+ uint32_t available_at_end =
+ RING_BUFFER_SIZE - get_ring_pos(r->read_pos);
+
+ if (step_size > available_at_end) {
+ uint32_t remaining = step_size - available_at_end;
+ memcpy(
+ data_bytes + i * step_size,
+ &r->buf[get_ring_pos(r->read_pos)],
+ available_at_end);
+ memcpy(
+ data_bytes + i * step_size + available_at_end,
+ &r->buf[get_ring_pos(r->read_pos + available_at_end)],
+ remaining);
+ } else {
+ memcpy(
+ data_bytes + i * step_size,
+ &r->buf[get_ring_pos(r->read_pos)],
+ step_size);
+ }
+
+ __atomic_add_fetch(&r->read_pos, step_size, __ATOMIC_SEQ_CST);
+ }
+
+ errno = 0;
+ return (long)steps;
+}
+
+uint32_t ring_buffer_calc_shift(uint32_t size) {
+ uint32_t shift = 0;
+ while ((1 << shift) < size) {
+ ++shift;
+ }
+
+ // if size is not a power of 2,
+ if ((1 << shift) > size) {
+ --shift;
+ }
+ return shift;
+}
+
+void ring_buffer_view_init(
+ struct ring_buffer* r,
+ struct ring_buffer_view* v,
+ uint8_t* buf,
+ uint32_t size) {
+
+ uint32_t shift = ring_buffer_calc_shift(size);
+
+ ring_buffer_init(r);
+
+ v->buf = buf;
+ v->size = (1 << shift);
+ v->mask = (1 << shift) - 1;
+}
+
+void ring_buffer_init_view_only(
+ struct ring_buffer_view* v,
+ uint8_t* buf,
+ uint32_t size) {
+
+ uint32_t shift = ring_buffer_calc_shift(size);
+
+ v->buf = buf;
+ v->size = (1 << shift);
+ v->mask = (1 << shift) - 1;
+}
+
+static uint32_t ring_buffer_view_get_ring_pos(
+ const struct ring_buffer_view* v,
+ uint32_t index) {
+ return index & v->mask;
+}
+
+bool ring_buffer_view_can_write(
+ const struct ring_buffer* r,
+ const struct ring_buffer_view* v,
+ uint32_t bytes) {
+ uint32_t read_view;
+ __atomic_load(&r->read_pos, &read_view, __ATOMIC_SEQ_CST);
+ return ring_buffer_view_get_ring_pos(
+ v, read_view - r->write_pos - 1) >= bytes;
+}
+
+bool ring_buffer_view_can_read(
+ const struct ring_buffer* r,
+ const struct ring_buffer_view* v,
+ uint32_t bytes) {
+ uint32_t write_view;
+ __atomic_load(&r->write_pos, &write_view, __ATOMIC_SEQ_CST);
+ return ring_buffer_view_get_ring_pos(
+ v, write_view - r->read_pos) >= bytes;
+}
+
+uint32_t ring_buffer_available_read(
+ const struct ring_buffer* r,
+ const struct ring_buffer_view* v) {
+ uint32_t write_view;
+ __atomic_load(&r->write_pos, &write_view, __ATOMIC_SEQ_CST);
+ if (v) {
+ return ring_buffer_view_get_ring_pos(
+ v, write_view - r->read_pos);
+ } else {
+ return get_ring_pos(write_view - r->read_pos);
+ }
+}
+
+long ring_buffer_view_write(
+ struct ring_buffer* r,
+ struct ring_buffer_view* v,
+ const void* data, uint32_t step_size, uint32_t steps) {
+
+ uint8_t* data_bytes = (uint8_t*)data;
+ uint32_t i;
+
+ for (i = 0; i < steps; ++i) {
+ if (!ring_buffer_view_can_write(r, v, step_size)) {
+ errno = -EAGAIN;
+ return (long)i;
+ }
+
+ // Needs to be split up into 2 writes for the edge case.
+ uint32_t available_at_end =
+ v->size - ring_buffer_view_get_ring_pos(v, r->write_pos);
+
+ if (step_size > available_at_end) {
+ uint32_t remaining = step_size - available_at_end;
+ memcpy(
+ &v->buf[ring_buffer_view_get_ring_pos(v, r->write_pos)],
+ data_bytes + i * step_size,
+ available_at_end);
+ memcpy(
+ &v->buf[ring_buffer_view_get_ring_pos(v, r->write_pos + available_at_end)],
+ data_bytes + i * step_size + available_at_end,
+ remaining);
+ } else {
+ memcpy(
+ &v->buf[ring_buffer_view_get_ring_pos(v, r->write_pos)],
+ data_bytes + i * step_size,
+ step_size);
+ }
+
+ __atomic_add_fetch(&r->write_pos, step_size, __ATOMIC_SEQ_CST);
+ }
+
+ errno = 0;
+ return (long)steps;
+
+}
+
+long ring_buffer_view_read(
+ struct ring_buffer* r,
+ struct ring_buffer_view* v,
+ void* data, uint32_t step_size, uint32_t steps) {
+ uint8_t* data_bytes = (uint8_t*)data;
+ uint32_t i;
+
+ for (i = 0; i < steps; ++i) {
+ if (!ring_buffer_view_can_read(r, v, step_size)) {
+ errno = -EAGAIN;
+ return (long)i;
+ }
+
+ // Needs to be split up into 2 reads for the edge case.
+ uint32_t available_at_end =
+ v->size - ring_buffer_view_get_ring_pos(v, r->read_pos);
+
+ if (step_size > available_at_end) {
+ uint32_t remaining = step_size - available_at_end;
+ memcpy(
+ data_bytes + i * step_size,
+ &v->buf[ring_buffer_view_get_ring_pos(v, r->read_pos)],
+ available_at_end);
+ memcpy(
+ data_bytes + i * step_size + available_at_end,
+ &v->buf[ring_buffer_view_get_ring_pos(v, r->read_pos + available_at_end)],
+ remaining);
+ } else {
+ memcpy(data_bytes + i * step_size,
+ &v->buf[ring_buffer_view_get_ring_pos(v, r->read_pos)],
+ step_size);
+ }
+ __atomic_add_fetch(&r->read_pos, step_size, __ATOMIC_SEQ_CST);
+ }
+
+ errno = 0;
+ return (long)steps;
+}
+
+void ring_buffer_yield() {
+#ifdef _WIN32
+ if (!SwitchToThread()) {
+ Sleep(0);
+ }
+#else
+ sched_yield();
+#endif
+}
+
+static void ring_buffer_sleep() {
+#ifdef _WIN32
+ Sleep(2);
+#else
+ usleep(2000);
+#endif
+}
+
+static uint64_t ring_buffer_curr_us() {
+ uint64_t res;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ res = tv.tv_sec * 1000000ULL + tv.tv_usec;
+ return res;
+}
+
+static const uint32_t yield_backoff_us = 1000;
+static const uint32_t sleep_backoff_us = 2000;
+
+bool ring_buffer_wait_write(
+ const struct ring_buffer* r,
+ const struct ring_buffer_view* v,
+ uint32_t bytes,
+ uint64_t timeout_us) {
+
+ bool can_write =
+ v ? ring_buffer_view_can_write(r, v, bytes) :
+ ring_buffer_can_write(r, bytes);
+
+ while (!can_write) {
+ ring_buffer_yield();
+ can_write =
+ v ? ring_buffer_view_can_write(r, v, bytes) :
+ ring_buffer_can_write(r, bytes);
+ }
+
+ return true;
+}
+
+bool ring_buffer_wait_read(
+ const struct ring_buffer* r,
+ const struct ring_buffer_view* v,
+ uint32_t bytes,
+ uint64_t timeout_us) {
+
+ bool can_read =
+ v ? ring_buffer_view_can_read(r, v, bytes) :
+ ring_buffer_can_read(r, bytes);
+
+ while (!can_read) {
+ ring_buffer_yield();
+ can_read =
+ v ? ring_buffer_view_can_read(r, v, bytes) :
+ ring_buffer_can_read(r, bytes);
+ }
+
+ ((struct ring_buffer*)r)->read_live_count++;
+ return true;
+}
+
+static uint32_t get_step_size(
+ struct ring_buffer* r,
+ struct ring_buffer_view* v,
+ uint32_t bytes) {
+
+ uint32_t step_shift = 0;
+ uint32_t available = v ? (v->size >> 1) : (RING_BUFFER_SIZE >> 1);
+ uint32_t res = available < bytes ? available : bytes;
+
+ return res;
+}
+
+void ring_buffer_write_fully(
+ struct ring_buffer* r,
+ struct ring_buffer_view* v,
+ const void* data,
+ uint32_t bytes) {
+
+ uint32_t candidate_step = get_step_size(r, v, bytes);
+ uint32_t processed = 0;
+
+ uint8_t* dst = (uint8_t*)data;
+
+ while (processed < bytes) {
+ if (bytes - processed < candidate_step) {
+ candidate_step = bytes - processed;
+ }
+
+ long processed_here = 0;
+ ring_buffer_wait_write(r, v, candidate_step, (uint64_t)(-1));
+
+ if (v) {
+ processed_here = ring_buffer_view_write(r, v, dst + processed, candidate_step, 1);
+ } else {
+ processed_here = ring_buffer_write(r, dst + processed, candidate_step, 1);
+ }
+
+ processed += processed_here ? candidate_step : 0;
+ }
+}
+
+void ring_buffer_read_fully(
+ struct ring_buffer* r,
+ struct ring_buffer_view* v,
+ void* data,
+ uint32_t bytes) {
+
+ uint32_t candidate_step = get_step_size(r, v, bytes);
+ uint32_t processed = 0;
+
+ uint8_t* dst = (uint8_t*)data;
+
+ while (processed < bytes) {
+ ring_buffer_pause();
+ if (bytes - processed < candidate_step) {
+ candidate_step = bytes - processed;
+ }
+
+ long processed_here = 0;
+ ring_buffer_wait_read(r, v, candidate_step, (uint64_t)(-1));
+
+ if (v) {
+ processed_here = ring_buffer_view_read(r, v, dst + processed, candidate_step, 1);
+ } else {
+ processed_here = ring_buffer_read(r, dst + processed, candidate_step, 1);
+ }
+
+ processed += processed_here ? candidate_step : 0;
+ }
+}
+
+void ring_buffer_sync_init(struct ring_buffer* r) {
+ __atomic_store_n(&r->state, RING_BUFFER_SYNC_PRODUCER_IDLE, __ATOMIC_SEQ_CST);
+}
+
+bool ring_buffer_producer_acquire(struct ring_buffer* r) {
+ uint32_t expected_idle = RING_BUFFER_SYNC_PRODUCER_IDLE;
+ bool success = __atomic_compare_exchange_n(
+ &r->state,
+ &expected_idle,
+ RING_BUFFER_SYNC_PRODUCER_ACTIVE,
+ false /* strong */,
+ __ATOMIC_SEQ_CST,
+ __ATOMIC_SEQ_CST);
+ return success;
+}
+
+bool ring_buffer_producer_acquire_from_hangup(struct ring_buffer* r) {
+ uint32_t expected_hangup = RING_BUFFER_SYNC_CONSUMER_HUNG_UP;
+ bool success = __atomic_compare_exchange_n(
+ &r->state,
+ &expected_hangup,
+ RING_BUFFER_SYNC_PRODUCER_ACTIVE,
+ false /* strong */,
+ __ATOMIC_SEQ_CST,
+ __ATOMIC_SEQ_CST);
+ return success;
+}
+
+void ring_buffer_producer_wait_hangup(struct ring_buffer* r) {
+ while (__atomic_load_n(&r->state, __ATOMIC_SEQ_CST) !=
+ RING_BUFFER_SYNC_CONSUMER_HUNG_UP) {
+ ring_buffer_yield();
+ }
+}
+
+void ring_buffer_producer_idle(struct ring_buffer* r) {
+ __atomic_store_n(&r->state, RING_BUFFER_SYNC_PRODUCER_IDLE, __ATOMIC_SEQ_CST);
+}
+
+bool ring_buffer_consumer_hangup(struct ring_buffer* r) {
+ uint32_t expected_idle = RING_BUFFER_SYNC_PRODUCER_IDLE;
+ bool success = __atomic_compare_exchange_n(
+ &r->state,
+ &expected_idle,
+ RING_BUFFER_SYNC_CONSUMER_HANGING_UP,
+ false /* strong */,
+ __ATOMIC_SEQ_CST,
+ __ATOMIC_SEQ_CST);
+ return success;
+}
+
+void ring_buffer_consumer_wait_producer_idle(struct ring_buffer* r) {
+ while (__atomic_load_n(&r->state, __ATOMIC_SEQ_CST) !=
+ RING_BUFFER_SYNC_PRODUCER_IDLE) {
+ ring_buffer_yield();
+ }
+}
+
+void ring_buffer_consumer_hung_up(struct ring_buffer* r) {
+ __atomic_store_n(&r->state, RING_BUFFER_SYNC_CONSUMER_HUNG_UP, __ATOMIC_SEQ_CST);
+}
diff --git a/android-emu/android/base/ring_buffer.h b/android-emu/android/base/ring_buffer.h
new file mode 100644
index 0000000..34c0666
--- /dev/null
+++ b/android-emu/android/base/ring_buffer.h
@@ -0,0 +1,185 @@
+// Copyright 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+#include "android/utils/compiler.h"
+
+ANDROID_BEGIN_HEADER
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#define RING_BUFFER_SHIFT 11
+#define RING_BUFFER_SIZE (1 << RING_BUFFER_SHIFT)
+#define NUM_CONFIG_FIELDS 32
+
+// Single producer/consumer ring buffer struct that can be shared
+// between host and guest as-is.
+struct ring_buffer {
+ uint32_t host_version;
+ uint32_t guest_version;
+ uint32_t write_pos; // Atomically updated for the consumer
+ uint32_t unused0[13]; // Separate cache line
+ uint32_t read_pos; // Atomically updated for the producer
+ uint32_t read_live_count;
+ uint32_t read_yield_count;
+ uint32_t read_sleep_us_count;
+ uint32_t unused1[12]; // Separate cache line
+ uint8_t buf[RING_BUFFER_SIZE];
+ uint32_t state; // An atomically updated variable from both
+ // producer and consumer for other forms of
+ // coordination.
+ // Configuration fields
+ uint32_t config[NUM_CONFIG_FIELDS];
+};
+
+void ring_buffer_init(struct ring_buffer* r);
+
+// Writes or reads step_size at a time. Sets errno=EAGAIN if full or empty.
+// Returns the number of step_size steps read.
+long ring_buffer_write(
+ struct ring_buffer* r, const void* data, uint32_t step_size, uint32_t steps);
+long ring_buffer_read(
+ struct ring_buffer* r, void* data, uint32_t step_size, uint32_t steps);
+
+// If we want to work with dynamically allocated buffers, a separate struct is
+// needed; the host and guest are in different address spaces and thus have
+// different views of the same memory, with the host and guest having different
+// copies of this struct.
+struct ring_buffer_view {
+ uint8_t* buf;
+ uint32_t size;
+ uint32_t mask;
+};
+
+
+// Calculates the highest power of 2 so that
+// (1 << shift) <= size.
+uint32_t ring_buffer_calc_shift(uint32_t size);
+
+// Initializes ring buffer with view using |buf|. If |size| is not a power of
+// two, then the buffer will assume a size equal to the greater power of two
+// less than |size|.
+void ring_buffer_view_init(
+ struct ring_buffer* r,
+ struct ring_buffer_view* v,
+ uint8_t* buf,
+ uint32_t size);
+
+void ring_buffer_init_view_only(
+ struct ring_buffer_view* v,
+ uint8_t* buf,
+ uint32_t size);
+
+// Read/write functions with the view.
+long ring_buffer_view_write(
+ struct ring_buffer* r,
+ struct ring_buffer_view* v,
+ const void* data, uint32_t step_size, uint32_t steps);
+long ring_buffer_view_read(
+ struct ring_buffer* r,
+ struct ring_buffer_view* v,
+ void* data, uint32_t step_size, uint32_t steps);
+
+// Usage of ring_buffer as a waitable object.
+// These functions will back off if spinning too long.
+//
+// if |v| is null, it is assumed that the statically allocated ring buffer is
+// used.
+//
+// Returns true if ring buffer became available, false if timed out.
+bool ring_buffer_wait_write(
+ const struct ring_buffer* r,
+ const struct ring_buffer_view* v,
+ uint32_t bytes,
+ uint64_t timeout_us);
+bool ring_buffer_wait_read(
+ const struct ring_buffer* r,
+ const struct ring_buffer_view* v,
+ uint32_t bytes,
+ uint64_t timeout_us);
+
+// read/write fully, blocking if there is nothing to read/write.
+void ring_buffer_write_fully(
+ struct ring_buffer* r,
+ struct ring_buffer_view* v,
+ const void* data,
+ uint32_t bytes);
+void ring_buffer_read_fully(
+ struct ring_buffer* r,
+ struct ring_buffer_view* v,
+ void* data,
+ uint32_t bytes);
+
+bool ring_buffer_can_write(
+ const struct ring_buffer* r, uint32_t bytes);
+bool ring_buffer_can_read(
+ const struct ring_buffer* r, uint32_t bytes);
+bool ring_buffer_view_can_write(
+ const struct ring_buffer* r,
+ const struct ring_buffer_view* v,
+ uint32_t bytes);
+bool ring_buffer_view_can_read(
+ const struct ring_buffer* r,
+ const struct ring_buffer_view* v,
+ uint32_t bytes);
+uint32_t ring_buffer_available_read(
+ const struct ring_buffer* r,
+ const struct ring_buffer_view* v);
+
+// Lockless synchronization where the consumer is allowed to hang up and go to
+// sleep. This can be considered a sort of asymmetric lock for two threads,
+// where the consumer can be more sleepy. It captures the pattern we usually use
+// for emulator devices; the guest asks the host for something, and some host
+// thread services the request and goes back to sleep.
+enum ring_buffer_sync_state {
+ RING_BUFFER_SYNC_PRODUCER_IDLE = 0,
+ RING_BUFFER_SYNC_PRODUCER_ACTIVE = 1,
+ RING_BUFFER_SYNC_CONSUMER_HANGING_UP = 2,
+ RING_BUFFER_SYNC_CONSUMER_HUNG_UP = 3,
+};
+
+// Sync state is RING_BUFFER_SYNC_PRODUCER_IDLE.
+void ring_buffer_sync_init(struct ring_buffer* r);
+
+// Tries to acquire the channel for sending.
+// Returns false if the consumer was in the middle of hanging up,
+// true if the producer successfully acquired the channel
+// (put it in the RING_BUFFER_SYNC_PRODUCER_ACTIVE state).
+bool ring_buffer_producer_acquire(struct ring_buffer* r);
+// Same as above, but acquires from RING_BUFFER_SYNC_CONSUMER_HUNG_UP.
+bool ring_buffer_producer_acquire_from_hangup(struct ring_buffer* r);
+// Waits until the consumer hangs up.
+void ring_buffer_producer_wait_hangup(struct ring_buffer* r);
+// Sets the state back to RING_BUFFER_SYNC_PRODUCER_IDLE.
+void ring_buffer_producer_idle(struct ring_buffer* r);
+
+// There is no symmetric consumer acquire because the consumer can consume with
+// the ring buffer being in any state (albeit with long waiting if the producer
+// does not send anything)
+
+// Tries to acquire the channel on the consumer side for
+// hanging up. Returns false if the producer is in the middle of sending,
+// true if the consumer successfully hung up the channel
+// (put it in the RING_BUFFER_SYNC_CONSUMER_HUNG_UP state).
+bool ring_buffer_consumer_hangup(struct ring_buffer* r);
+// Waits until the producer has set the state to
+// RING_BUFFER_SYNC_PRODUCER_IDLE.
+void ring_buffer_consumer_wait_producer_idle(struct ring_buffer* r);
+// Sets the state to hung up.
+void ring_buffer_consumer_hung_up(struct ring_buffer* r);
+
+// Convenient function to reschedule thread
+void ring_buffer_yield();
+ANDROID_END_HEADER
diff --git a/host/include/libOpenglRender/IOStream.h b/host/include/libOpenglRender/IOStream.h
index ad82072..2f699bc 100644
--- a/host/include/libOpenglRender/IOStream.h
+++ b/host/include/libOpenglRender/IOStream.h
@@ -25,11 +25,15 @@
public:
IOStream(size_t bufSize) {
- m_buf = NULL;
+ m_iostreamBuf = NULL;
m_bufsize = bufSize;
m_free = 0;
}
+ virtual size_t idealAllocSize(size_t len) {
+ return m_bufsize < len ? len : m_bufsize;
+ }
+
virtual void *allocBuffer(size_t minSize) = 0;
virtual int commitBuffer(size_t size) = 0;
virtual const unsigned char *readFully( void *buf, size_t len) = 0;
@@ -39,22 +43,22 @@
virtual ~IOStream() {
- // NOTE: m_buf is 'owned' by the child class thus we expect it to be released by it
+ // NOTE: m_iostreamBuf is 'owned' by the child class thus we expect it to be released by it
}
virtual unsigned char *alloc(size_t len) {
- if (m_buf && len > m_free) {
+ if (m_iostreamBuf && len > m_free) {
if (flush() < 0) {
ERR("Failed to flush in alloc\n");
return NULL; // we failed to flush so something is wrong
}
}
- if (!m_buf || len > m_bufsize) {
- int allocLen = m_bufsize < len ? len : m_bufsize;
- m_buf = (unsigned char *)allocBuffer(allocLen);
- if (!m_buf) {
+ if (!m_iostreamBuf || len > m_bufsize) {
+ int allocLen = this->idealAllocSize(len);
+ m_iostreamBuf = (unsigned char *)allocBuffer(allocLen);
+ if (!m_iostreamBuf) {
ERR("Alloc (%u bytes) failed\n", allocLen);
return NULL;
}
@@ -63,7 +67,7 @@
unsigned char *ptr;
- ptr = m_buf + (m_bufsize - m_free);
+ ptr = m_iostreamBuf + (m_bufsize - m_free);
m_free -= len;
return ptr;
@@ -71,18 +75,18 @@
virtual int flush() {
- if (!m_buf || m_free == m_bufsize) return 0;
+ if (!m_iostreamBuf || m_free == m_bufsize) return 0;
int stat = commitBuffer(m_bufsize - m_free);
- m_buf = NULL;
+ m_iostreamBuf = NULL;
m_free = 0;
return stat;
}
const unsigned char *readback(void *buf, size_t len) {
- if (m_buf && m_free != m_bufsize) {
+ if (m_iostreamBuf && m_free != m_bufsize) {
size_t size = m_bufsize - m_free;
- m_buf = NULL;
+ m_iostreamBuf = NULL;
m_free = 0;
return commitBufferAndReadFully(size, buf, len);
}
@@ -93,7 +97,7 @@
private:
- unsigned char *m_buf;
+ unsigned char *m_iostreamBuf;
size_t m_bufsize;
size_t m_free;
};
diff --git a/shared/OpenglCodecCommon/goldfish_address_space.h b/shared/OpenglCodecCommon/goldfish_address_space.h
index 6b2576d..f02fa2e 100644
--- a/shared/OpenglCodecCommon/goldfish_address_space.h
+++ b/shared/OpenglCodecCommon/goldfish_address_space.h
@@ -45,13 +45,9 @@
class GoldfishAddressSpaceBlockProvider {
public:
-#ifdef __Fuchsia__
- GoldfishAddressSpaceBlockProvider();
-#else
static const uint64_t SUBDEVICE_TYPE_NO_SUBDEVICE_ID = -1;
static const uint64_t SUBDEVICE_TYPE_HOST_MEMORY_ALLOCATOR_ID = 5;
GoldfishAddressSpaceBlockProvider(uint64_t subdevice);
-#endif // __Fuchsia__
~GoldfishAddressSpaceBlockProvider();
private:
@@ -61,6 +57,7 @@
bool is_opened() const;
void close();
address_space_handle_t release();
+ static void closeHandle(address_space_handle_t handle);
#ifdef __Fuchsia__
fuchsia::hardware::goldfish::address::space::DeviceSyncPtr m_device;
@@ -86,6 +83,8 @@
void *guestPtr() const;
void replace(GoldfishAddressSpaceBlock *other);
void release();
+ static int memoryMap(void *addr, size_t len, address_space_handle_t fd, uint64_t off, void** dst);
+ static void memoryUnmap(void *ptr, size_t size);
private:
void destroy();
@@ -114,6 +113,7 @@
bool is_opened() const;
address_space_handle_t release() { return m_provider.release(); }
+ static void closeHandle(address_space_handle_t handle) { GoldfishAddressSpaceBlockProvider::closeHandle(handle); }
private:
GoldfishAddressSpaceBlockProvider m_provider;
diff --git a/shared/OpenglCodecCommon/goldfish_address_space_android.impl b/shared/OpenglCodecCommon/goldfish_address_space_android.impl
index f0abf04..90fc097 100644
--- a/shared/OpenglCodecCommon/goldfish_address_space_android.impl
+++ b/shared/OpenglCodecCommon/goldfish_address_space_android.impl
@@ -97,7 +97,7 @@
GoldfishAddressSpaceBlockProvider::GoldfishAddressSpaceBlockProvider(uint64_t subdevice)
: m_handle(create_address_space_fd())
{
- if ((subdevice != SUBDEVICE_TYPE_HOST_MEMORY_ALLOCATOR_ID) && is_opened()) {
+ if ((subdevice != SUBDEVICE_TYPE_NO_SUBDEVICE_ID) && is_opened()) {
const long ret = set_address_space_subdevice_type(m_handle, subdevice);
if (ret) {
ALOGE("%s: set_address_space_subdevice_type failed for device_type=%lu, ret=%ld",
@@ -134,6 +134,11 @@
return handle;
}
+void GoldfishAddressSpaceBlockProvider::closeHandle(address_space_handle_t handle)
+{
+ ::close(handle);
+}
+
GoldfishAddressSpaceBlock::GoldfishAddressSpaceBlock()
: m_handle(-1)
, m_mmaped_ptr(NULL)
@@ -212,13 +217,14 @@
::abort();
}
- void *result = ::mmap64(NULL, m_size, PROT_WRITE, MAP_SHARED, m_handle, m_offset);
- if (result == MAP_FAILED) {
+ void *result;
+ const int res = memoryMap(NULL, m_size, m_handle, m_offset, &result);
+ if (res) {
ALOGE("%s: host memory map failed with size 0x%llx "
"off 0x%llx errno %d\n",
__func__,
(unsigned long long)m_size,
- (unsigned long long)m_offset, errno);
+ (unsigned long long)m_offset, res);
return NULL;
} else {
m_mmaped_ptr = result;
@@ -235,7 +241,7 @@
void GoldfishAddressSpaceBlock::destroy()
{
if (m_mmaped_ptr && m_size) {
- ::munmap(m_mmaped_ptr, m_size);
+ memoryUnmap(m_mmaped_ptr, m_size);
m_mmaped_ptr = NULL;
}
@@ -263,6 +269,25 @@
m_size = 0;
}
+int GoldfishAddressSpaceBlock::memoryMap(void *addr,
+ size_t len,
+ address_space_handle_t fd,
+ uint64_t off,
+ void** dst) {
+ void* ptr = ::mmap64(addr, len, PROT_WRITE, MAP_SHARED, fd, off);
+ if (MAP_FAILED == ptr) {
+ return errno;
+ } else {
+ *dst = ptr;
+ return 0;
+ }
+}
+
+void GoldfishAddressSpaceBlock::memoryUnmap(void *ptr, size_t size)
+{
+ ::munmap(ptr, size);
+}
+
GoldfishAddressSpaceHostMemoryAllocator::GoldfishAddressSpaceHostMemoryAllocator()
: m_provider(GoldfishAddressSpaceBlockProvider::SUBDEVICE_TYPE_HOST_MEMORY_ALLOCATOR_ID) {}
diff --git a/shared/OpenglCodecCommon/goldfish_address_space_fuchsia.impl b/shared/OpenglCodecCommon/goldfish_address_space_fuchsia.impl
index 711dfa4..d11fcd1 100644
--- a/shared/OpenglCodecCommon/goldfish_address_space_fuchsia.impl
+++ b/shared/OpenglCodecCommon/goldfish_address_space_fuchsia.impl
@@ -29,7 +29,13 @@
#include "goldfish_address_space.h"
-GoldfishAddressSpaceBlockProvider::GoldfishAddressSpaceBlockProvider() {
+GoldfishAddressSpaceBlockProvider::GoldfishAddressSpaceBlockProvider(uint64_t subdevice) {
+
+ if (subdevice != SUBDEVICE_TYPE_NO_SUBDEVICE_ID) {
+ ALOGE("%s: Tried to use a nontrivial subdevice when support has not been added\n", __func__);
+ abort();
+ }
+
zx::channel channel;
zx_status_t status =
fdio_get_service_handle(::open(GOLDFISH_ADDRESS_SPACE_DEVICE_NAME, O_RDWR),
@@ -187,6 +193,7 @@
}
GoldfishAddressSpaceHostMemoryAllocator::GoldfishAddressSpaceHostMemoryAllocator()
+ : m_provider(GoldfishAddressSpaceBlockProvider::SUBDEVICE_TYPE_HOST_MEMORY_ALLOCATOR_ID)
{
}
diff --git a/shared/OpenglCodecCommon/goldfish_address_space_host.impl b/shared/OpenglCodecCommon/goldfish_address_space_host.impl
index 99e1b0c..7d07d8b 100644
--- a/shared/OpenglCodecCommon/goldfish_address_space_host.impl
+++ b/shared/OpenglCodecCommon/goldfish_address_space_host.impl
@@ -37,7 +37,7 @@
GoldfishAddressSpaceBlockProvider::GoldfishAddressSpaceBlockProvider(uint64_t subdevice)
: m_handle(HostAddressSpaceDevice::get()->open())
{
- if ((subdevice != SUBDEVICE_TYPE_HOST_MEMORY_ALLOCATOR_ID) && is_opened()) {
+ if ((subdevice != SUBDEVICE_TYPE_NO_SUBDEVICE_ID) && is_opened()) {
AddressSpaceDevicePingInfo request;
::memset(&request, 0, sizeof(request));
request.metadata = subdevice;
@@ -73,6 +73,11 @@
return handle;
}
+void GoldfishAddressSpaceBlockProvider::closeHandle(address_space_handle_t handle)
+{
+ HostAddressSpaceDevice::get()->close(handle);
+}
+
GoldfishAddressSpaceBlock::GoldfishAddressSpaceBlock()
: m_handle(0)
, m_mmaped_ptr(NULL)
@@ -175,6 +180,17 @@
m_size = 0;
}
+int GoldfishAddressSpaceBlock::memoryMap(void *addr,
+ size_t,
+ address_space_handle_t,
+ uint64_t,
+ void** dst) {
+ *dst = addr;
+ return 0;
+}
+
+void GoldfishAddressSpaceBlock::memoryUnmap(void *ptr, size_t size) {}
+
GoldfishAddressSpaceHostMemoryAllocator::GoldfishAddressSpaceHostMemoryAllocator()
: m_provider(GoldfishAddressSpaceBlockProvider::SUBDEVICE_TYPE_HOST_MEMORY_ALLOCATOR_ID) {}
diff --git a/shared/OpenglCodecCommon/gralloc_cb.h b/shared/OpenglCodecCommon/gralloc_cb.h
index 2d80f26..3167ca0 100644
--- a/shared/OpenglCodecCommon/gralloc_cb.h
+++ b/shared/OpenglCodecCommon/gralloc_cb.h
@@ -17,7 +17,103 @@
#ifndef __GRALLOC_CB_H__
#define __GRALLOC_CB_H__
-#include "gralloc_cb_old.h"
-typedef cb_handle_old_t cb_handle_t;
+#include <cutils/native_handle.h>
+#include "qemu_pipe.h"
+
+const uint32_t CB_HANDLE_MAGIC_MASK = 0xFFFFFFF0;
+const uint32_t CB_HANDLE_MAGIC_BASE = 0xABFABFA0;
+
+#define CB_HANDLE_NUM_INTS(nfd) \
+ ((sizeof(*this)-sizeof(native_handle_t)-nfd*sizeof(int32_t))/sizeof(int32_t))
+
+struct cb_handle_t : public native_handle_t {
+ cb_handle_t(int32_t p_bufferFd,
+ QEMU_PIPE_HANDLE p_hostHandleRefCountFd,
+ uint32_t p_magic,
+ uint32_t p_hostHandle,
+ int32_t p_usage,
+ int32_t p_width,
+ int32_t p_height,
+ int32_t p_format,
+ int32_t p_glFormat,
+ int32_t p_glType,
+ uint32_t p_bufSize,
+ void* p_bufPtr)
+ : bufferFd(p_bufferFd),
+ hostHandleRefCountFd(p_hostHandleRefCountFd),
+ magic(p_magic),
+ hostHandle(p_hostHandle),
+ usage(p_usage),
+ width(p_width),
+ height(p_height),
+ format(p_format),
+ glFormat(p_glFormat),
+ glType(p_glType),
+ bufferSize(p_bufSize),
+ lockedLeft(0),
+ lockedTop(0),
+ lockedWidth(0),
+ lockedHeight(0) {
+ version = sizeof(native_handle);
+ numFds = ((bufferFd >= 0) ? 1 : 0) + (qemu_pipe_valid(hostHandleRefCountFd) ? 1 : 0);
+ numInts = 0; // has to be overwritten in children classes
+ setBufferPtr(p_bufPtr);
+ }
+
+ void* getBufferPtr() const {
+ const uint64_t addr = (uint64_t(bufferPtrHi) << 32) | bufferPtrLo;
+ return reinterpret_cast<void*>(static_cast<uintptr_t>(addr));
+ }
+
+ void setBufferPtr(void* ptr) {
+ const uint64_t addr = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(ptr));
+ bufferPtrLo = uint32_t(addr);
+ bufferPtrHi = uint32_t(addr >> 32);
+ }
+
+ uint32_t allocatedSize() const {
+ return getBufferPtr() ? bufferSize : 0;
+ }
+
+ bool isValid() const {
+ return (version == sizeof(native_handle))
+ && (magic & CB_HANDLE_MAGIC_MASK) == CB_HANDLE_MAGIC_BASE;
+ }
+
+ static cb_handle_t* from(void* p) {
+ if (!p) { return nullptr; }
+ cb_handle_t* cb = static_cast<cb_handle_t*>(p);
+ return cb->isValid() ? cb : nullptr;
+ }
+
+ static const cb_handle_t* from(const void* p) {
+ return from(const_cast<void*>(p));
+ }
+
+ static cb_handle_t* from_unconst(const void* p) {
+ return from(const_cast<void*>(p));
+ }
+
+ // fds
+ int32_t bufferFd; // underlying buffer file handle
+ QEMU_PIPE_HANDLE hostHandleRefCountFd; // guest side refcounter to hostHandle
+
+ // ints
+ uint32_t magic; // magic number in order to validate a pointer
+ uint32_t hostHandle; // the host reference to this buffer
+ int32_t usage; // usage bits the buffer was created with
+ int32_t width; // buffer width
+ int32_t height; // buffer height
+ int32_t format; // real internal pixel format format
+ int32_t glFormat; // OpenGL format enum used for host h/w color buffer
+ int32_t glType; // OpenGL type enum used when uploading to host
+ uint32_t bufferSize; // buffer size and location
+ uint32_t bufferPtrLo;
+ uint32_t bufferPtrHi;
+ int32_t lockedLeft; // region of buffer locked for s/w write
+ int32_t lockedTop;
+ int32_t lockedWidth;
+ int32_t lockedHeight;
+};
#endif //__GRALLOC_CB_H__
diff --git a/shared/OpenglCodecCommon/gralloc_cb_common.h b/shared/OpenglCodecCommon/gralloc_cb_common.h
deleted file mode 100644
index 94ada2f..0000000
--- a/shared/OpenglCodecCommon/gralloc_cb_common.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
-* Copyright 2011 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 __GRALLOC_CB_COMMON_H__
-#define __GRALLOC_CB_COMMON_H__
-
-// Tell the emulator which gralloc formats
-// need special handling.
-enum EmulatorFrameworkFormat {
- FRAMEWORK_FORMAT_GL_COMPATIBLE = 0,
- FRAMEWORK_FORMAT_YV12 = 1,
- FRAMEWORK_FORMAT_YUV_420_888 = 2, // (Y+)(U+)(V+)
-};
-
-#endif //__GRALLOC_CB_COMMON_H__
diff --git a/shared/OpenglCodecCommon/gralloc_cb_old.h b/shared/OpenglCodecCommon/gralloc_cb_old.h
deleted file mode 100644
index ab01537..0000000
--- a/shared/OpenglCodecCommon/gralloc_cb_old.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
-* Copyright 2011 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 __GRALLOC_CB_OLD_H__
-#define __GRALLOC_CB_OLD_H__
-
-#include <hardware/hardware.h>
-#include <hardware/gralloc.h>
-#include <cutils/native_handle.h>
-
-#include "gralloc_cb_common.h"
-#include "qemu_pipe.h"
-
-#define BUFFER_HANDLE_MAGIC ((int)0xabfabfab)
-#define CB_HANDLE_NUM_INTS(nfds) (int)((sizeof(cb_handle_old_t) - (nfds)*sizeof(int)) / sizeof(int))
-
-//
-// Our buffer handle structure
-//
-struct cb_handle_old_t : public native_handle {
-
- cb_handle_old_t(int p_fd, int p_ashmemSize, int p_usage,
- int p_width, int p_height,
- int p_format, int p_glFormat, int p_glType,
- EmulatorFrameworkFormat p_emuFrameworkFormat) :
- fd(p_fd),
- magic(BUFFER_HANDLE_MAGIC),
- usage(p_usage),
- width(p_width),
- height(p_height),
- format(p_format),
- glFormat(p_glFormat),
- glType(p_glType),
- ashmemSize(p_ashmemSize),
- ashmemBase(0),
- ashmemBasePid(0),
- mappedPid(0),
- lockedLeft(0),
- lockedTop(0),
- lockedWidth(0),
- lockedHeight(0),
- hostHandle(0),
- emuFrameworkFormat(p_emuFrameworkFormat)
- {
- refcount_pipe_fd = QEMU_PIPE_INVALID_HANDLE;
- version = sizeof(native_handle);
- numFds = 0;
- numInts = CB_HANDLE_NUM_INTS(numFds);
- }
-
- ~cb_handle_old_t() {
- magic = 0;
- }
-
- static cb_handle_old_t* from_native_handle(native_handle* n) {
- return static_cast<cb_handle_old_t*>(n);
- }
-
- static const cb_handle_old_t* from_native_handle(const native_handle* n) {
- return static_cast<const cb_handle_old_t*>(n);
- }
-
- static cb_handle_old_t* from_raw_pointer(void* ptr) {
- return from_native_handle(static_cast<native_handle*>(ptr));
- }
-
- static const cb_handle_old_t* from_raw_pointer(const void* ptr) {
- return from_native_handle(static_cast<const native_handle*>(ptr));
- }
-
- void setFd(int p_fd) {
- if (p_fd >= 0) {
- numFds++;
- }
- fd = p_fd;
- numInts = CB_HANDLE_NUM_INTS(numFds);
- }
-
- bool hasRefcountPipe() {
- return qemu_pipe_valid(refcount_pipe_fd);
- }
-
- void setRefcountPipeFd(QEMU_PIPE_HANDLE fd) {
- if (qemu_pipe_valid(fd)) {
- numFds++;
- }
- refcount_pipe_fd = fd;
- numInts = CB_HANDLE_NUM_INTS(numFds);
- }
-
- static bool validate(const cb_handle_old_t* hnd) {
- return (hnd &&
- hnd->version == sizeof(native_handle) &&
- hnd->magic == BUFFER_HANDLE_MAGIC &&
- hnd->numInts == CB_HANDLE_NUM_INTS(hnd->numFds));
- }
-
- bool canBePosted() {
- return (0 != (usage & GRALLOC_USAGE_HW_FB));
- }
-
- uint32_t allocationSize() const {
- return ashmemBase ? ashmemSize : 0;
- }
-
- // file-descriptors
- int fd; // ashmem fd (-1 of ashmem region did not allocated, i.e. no SW access needed)
- QEMU_PIPE_HANDLE refcount_pipe_fd; // goldfish pipe service for gralloc refcounting fd.
-
- // ints
- int magic; // magic number in order to validate a pointer to be a cb_handle_old_t
- int usage; // usage bits the buffer was created with
- int width; // buffer width
- int height; // buffer height
- int format; // real internal pixel format format
- int glFormat; // OpenGL format enum used for host h/w color buffer
- int glType; // OpenGL type enum used when uploading to host
- int ashmemSize; // ashmem region size for the buffer (0 unless is HW_FB buffer or
- // s/w access is needed)
- union {
- intptr_t ashmemBase; // CPU address of the mapped ashmem region
- uint64_t padding; // enforce same size on 32-bit/64-bit
- } __attribute__((aligned(8)));
-
- int ashmemBasePid; // process id which mapped the ashmem region
- int mappedPid; // process id which succeeded gralloc_register call
- int lockedLeft; // region of buffer locked for s/w write
- int lockedTop;
- int lockedWidth;
- int lockedHeight;
- uint32_t hostHandle;
-
- EmulatorFrameworkFormat emuFrameworkFormat;
-};
-
-
-#endif //__GRALLOC_CB_OLD_H__
diff --git a/system/GLESv2_enc/GL2Encoder.cpp b/system/GLESv2_enc/GL2Encoder.cpp
index 208173e..2f20516 100755
--- a/system/GLESv2_enc/GL2Encoder.cpp
+++ b/system/GLESv2_enc/GL2Encoder.cpp
@@ -72,6 +72,7 @@
{
m_currMajorVersion = 2;
m_currMinorVersion = 0;
+ m_hasAsyncUnmapBuffer = false;
m_initialized = false;
m_noHostError = false;
m_state = NULL;
@@ -101,6 +102,7 @@
m_ssbo_offset_align = 0;
m_ubo_offset_align = 0;
+ m_drawCallFlushInterval = 800;
m_drawCallFlushCount = 0;
m_primitiveRestartEnabled = false;
m_primitiveRestartIndex = 0;
@@ -1302,11 +1304,7 @@
}
void GL2Encoder::flushDrawCall() {
- // This used to be every other draw call, but
- // now that we are using real GPU buffers on host,
- // set this to every 200 draw calls
- // (tuned on z840 linux NVIDIA Quadro K2200)
- if (m_drawCallFlushCount % 200 == 0) {
+ if (m_drawCallFlushCount % m_drawCallFlushInterval == 0) {
m_stream->flush();
}
m_drawCallFlushCount++;
@@ -1463,6 +1461,7 @@
ctx->sendVertexAttributes(0, count, false);
ctx->m_glDrawArraysNullAEMU_enc(ctx, mode, first, count);
}
+ ctx->flushDrawCall();
}
void GL2Encoder::s_glDrawElementsNullAEMU(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices)
@@ -2955,11 +2954,16 @@
GLbitfield access, BufferData* buf) {
char* bits = (char*)buf->m_fixedBuffer.ptr() + offset;
- ctx->glMapBufferRangeAEMU(
- ctx, target,
- offset, length,
- access,
- bits);
+ if ((access & GL_MAP_READ_BIT) ||
+ ((access & GL_MAP_WRITE_BIT) &&
+ (!(access & GL_MAP_INVALIDATE_RANGE_BIT) &&
+ !(access & GL_MAP_INVALIDATE_BUFFER_BIT)))) {
+ ctx->glMapBufferRangeAEMU(
+ ctx, target,
+ offset, length,
+ access,
+ bits);
+ }
return bits;
}
@@ -3071,13 +3075,25 @@
goldfish_dma_guest_paddr(&buf->dma_buffer.get()),
&host_res);
} else {
- ctx->glUnmapBufferAEMU(
- ctx, target,
- buf->m_mappedOffset,
- buf->m_mappedLength,
- buf->m_mappedAccess,
- (void*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset),
- &host_res);
+ if (ctx->m_hasAsyncUnmapBuffer) {
+ ctx->glUnmapBufferAsyncAEMU(
+ ctx, target,
+ buf->m_mappedOffset,
+ buf->m_mappedLength,
+ buf->m_mappedAccess,
+ (void*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset),
+ &host_res);
+ } else {
+ if (buf->m_mappedAccess & GL_MAP_WRITE_BIT) {
+ ctx->glUnmapBufferAEMU(
+ ctx, target,
+ buf->m_mappedOffset,
+ buf->m_mappedLength,
+ buf->m_mappedAccess,
+ (void*)((char*)buf->m_fixedBuffer.ptr() + buf->m_mappedOffset),
+ &host_res);
+ }
+ }
}
buf->m_mapped = false;
@@ -3109,12 +3125,21 @@
buf->m_indexRangeCache.invalidateRange(totalOffset, length);
- ctx->glFlushMappedBufferRangeAEMU(
- ctx, target,
- totalOffset,
- length,
- buf->m_mappedAccess,
- (void*)((char*)buf->m_fixedBuffer.ptr() + totalOffset));
+ if (ctx->m_hasAsyncUnmapBuffer) {
+ ctx->glFlushMappedBufferRangeAEMU2(
+ ctx, target,
+ totalOffset,
+ length,
+ buf->m_mappedAccess,
+ (void*)((char*)buf->m_fixedBuffer.ptr() + totalOffset));
+ } else {
+ ctx->glFlushMappedBufferRangeAEMU(
+ ctx, target,
+ totalOffset,
+ length,
+ buf->m_mappedAccess,
+ (void*)((char*)buf->m_fixedBuffer.ptr() + totalOffset));
+ }
}
void GL2Encoder::s_glCompressedTexImage2D(void* self, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) {
diff --git a/system/GLESv2_enc/GL2Encoder.h b/system/GLESv2_enc/GL2Encoder.h
index c617a36..d016898 100644
--- a/system/GLESv2_enc/GL2Encoder.h
+++ b/system/GLESv2_enc/GL2Encoder.h
@@ -28,6 +28,12 @@
public:
GL2Encoder(IOStream *stream, ChecksumCalculator* protocol);
virtual ~GL2Encoder();
+ void setDrawCallFlushInterval(uint32_t interval) {
+ m_drawCallFlushInterval = interval;
+ }
+ void setHasAsyncUnmapBuffer(int version) {
+ m_hasAsyncUnmapBuffer = version;
+ }
void setNoHostError(bool noHostError) {
m_noHostError = noHostError;
}
@@ -98,6 +104,7 @@
std::string m_currExtensions;
std::vector<std::string> m_currExtensionsArray;
+ bool m_hasAsyncUnmapBuffer;
bool m_initialized;
bool m_noHostError;
GLClientState *m_state;
@@ -131,7 +138,8 @@
FixedBuffer m_fixedBuffer;
- int m_drawCallFlushCount;
+ uint32_t m_drawCallFlushInterval;
+ uint32_t m_drawCallFlushCount;
bool m_primitiveRestartEnabled;
GLuint m_primitiveRestartIndex;
diff --git a/system/GLESv2_enc/gl2_client_context.cpp b/system/GLESv2_enc/gl2_client_context.cpp
index c811b66..aaa0325 100644
--- a/system/GLESv2_enc/gl2_client_context.cpp
+++ b/system/GLESv2_enc/gl2_client_context.cpp
@@ -434,6 +434,8 @@
glDrawElementsNullAEMU = (glDrawElementsNullAEMU_client_proc_t) getProc("glDrawElementsNullAEMU", userData);
glDrawElementsOffsetNullAEMU = (glDrawElementsOffsetNullAEMU_client_proc_t) getProc("glDrawElementsOffsetNullAEMU", userData);
glDrawElementsDataNullAEMU = (glDrawElementsDataNullAEMU_client_proc_t) getProc("glDrawElementsDataNullAEMU", userData);
+ glUnmapBufferAsyncAEMU = (glUnmapBufferAsyncAEMU_client_proc_t) getProc("glUnmapBufferAsyncAEMU", userData);
+ glFlushMappedBufferRangeAEMU2 = (glFlushMappedBufferRangeAEMU2_client_proc_t) getProc("glFlushMappedBufferRangeAEMU2", userData);
return 0;
}
diff --git a/system/GLESv2_enc/gl2_client_context.h b/system/GLESv2_enc/gl2_client_context.h
index ce0cf47..575395a 100644
--- a/system/GLESv2_enc/gl2_client_context.h
+++ b/system/GLESv2_enc/gl2_client_context.h
@@ -434,6 +434,8 @@
glDrawElementsNullAEMU_client_proc_t glDrawElementsNullAEMU;
glDrawElementsOffsetNullAEMU_client_proc_t glDrawElementsOffsetNullAEMU;
glDrawElementsDataNullAEMU_client_proc_t glDrawElementsDataNullAEMU;
+ glUnmapBufferAsyncAEMU_client_proc_t glUnmapBufferAsyncAEMU;
+ glFlushMappedBufferRangeAEMU2_client_proc_t glFlushMappedBufferRangeAEMU2;
virtual ~gl2_client_context_t() {}
typedef gl2_client_context_t *CONTEXT_ACCESSOR_TYPE(void);
diff --git a/system/GLESv2_enc/gl2_client_proc.h b/system/GLESv2_enc/gl2_client_proc.h
index dea6d12..615b123 100644
--- a/system/GLESv2_enc/gl2_client_proc.h
+++ b/system/GLESv2_enc/gl2_client_proc.h
@@ -436,6 +436,8 @@
typedef void (gl2_APIENTRY *glDrawElementsNullAEMU_client_proc_t) (void * ctx, GLenum, GLsizei, GLenum, const GLvoid*);
typedef void (gl2_APIENTRY *glDrawElementsOffsetNullAEMU_client_proc_t) (void * ctx, GLenum, GLsizei, GLenum, GLuint);
typedef void (gl2_APIENTRY *glDrawElementsDataNullAEMU_client_proc_t) (void * ctx, GLenum, GLsizei, GLenum, void*, GLuint);
+typedef void (gl2_APIENTRY *glUnmapBufferAsyncAEMU_client_proc_t) (void * ctx, GLenum, GLintptr, GLsizeiptr, GLbitfield, void*, GLboolean*);
+typedef void (gl2_APIENTRY *glFlushMappedBufferRangeAEMU2_client_proc_t) (void * ctx, GLenum, GLintptr, GLsizeiptr, GLbitfield, void*);
#endif
diff --git a/system/GLESv2_enc/gl2_enc.cpp b/system/GLESv2_enc/gl2_enc.cpp
index 17b3cba..0df93f8 100644
--- a/system/GLESv2_enc/gl2_enc.cpp
+++ b/system/GLESv2_enc/gl2_enc.cpp
@@ -11482,6 +11482,87 @@
}
+void glUnmapBufferAsyncAEMU_enc(void *self , GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, void* guest_buffer, GLboolean* out_res)
+{
+
+ gl2_encoder_context_t *ctx = (gl2_encoder_context_t *)self;
+ IOStream *stream = ctx->m_stream;
+ ChecksumCalculator *checksumCalculator = ctx->m_checksumCalculator;
+ bool useChecksum = checksumCalculator->getVersion() > 0;
+
+ const unsigned int __size_guest_buffer = ((guest_buffer != NULL) ? length : 0);
+ const unsigned int __size_out_res = (sizeof(GLboolean));
+ unsigned char *ptr;
+ unsigned char *buf;
+ const size_t sizeWithoutChecksum = 8 + 4 + 4 + 4 + 4 + __size_guest_buffer + __size_out_res + 2*4;
+ const size_t checksumSize = checksumCalculator->checksumByteSize();
+ const size_t totalSize = sizeWithoutChecksum + checksumSize;
+ buf = stream->alloc(8 + 4 + 4 + 4 + 4);
+ ptr = buf;
+ int tmp = OP_glUnmapBufferAsyncAEMU;memcpy(ptr, &tmp, 4); ptr += 4;
+ memcpy(ptr, &totalSize, 4); ptr += 4;
+
+ memcpy(ptr, &target, 4); ptr += 4;
+ memcpy(ptr, &offset, 4); ptr += 4;
+ memcpy(ptr, &length, 4); ptr += 4;
+ memcpy(ptr, &access, 4); ptr += 4;
+
+ if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+ stream->flush();
+ stream->writeFully(&__size_guest_buffer,4);
+ if (useChecksum) checksumCalculator->addBuffer(&__size_guest_buffer,4);
+ if (guest_buffer != NULL) {
+ stream->writeFully(guest_buffer, __size_guest_buffer);
+ if (useChecksum) checksumCalculator->addBuffer(guest_buffer, __size_guest_buffer);
+ }
+ buf = stream->alloc(__size_out_res + 1*4);
+ ptr = buf;
+ *(unsigned int *)(ptr) = __size_out_res; ptr += 4;
+ memcpy(ptr, out_res, __size_out_res);ptr += __size_out_res;
+
+ if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+ buf = stream->alloc(checksumSize);
+ if (useChecksum) checksumCalculator->writeChecksum(buf, checksumSize);
+
+}
+
+void glFlushMappedBufferRangeAEMU2_enc(void *self , GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, void* guest_buffer)
+{
+
+ gl2_encoder_context_t *ctx = (gl2_encoder_context_t *)self;
+ IOStream *stream = ctx->m_stream;
+ ChecksumCalculator *checksumCalculator = ctx->m_checksumCalculator;
+ bool useChecksum = checksumCalculator->getVersion() > 0;
+
+ const unsigned int __size_guest_buffer = ((guest_buffer != NULL) ? length : 0);
+ unsigned char *ptr;
+ unsigned char *buf;
+ const size_t sizeWithoutChecksum = 8 + 4 + 4 + 4 + 4 + __size_guest_buffer + 1*4;
+ const size_t checksumSize = checksumCalculator->checksumByteSize();
+ const size_t totalSize = sizeWithoutChecksum + checksumSize;
+ buf = stream->alloc(8 + 4 + 4 + 4 + 4);
+ ptr = buf;
+ int tmp = OP_glFlushMappedBufferRangeAEMU2;memcpy(ptr, &tmp, 4); ptr += 4;
+ memcpy(ptr, &totalSize, 4); ptr += 4;
+
+ memcpy(ptr, &target, 4); ptr += 4;
+ memcpy(ptr, &offset, 4); ptr += 4;
+ memcpy(ptr, &length, 4); ptr += 4;
+ memcpy(ptr, &access, 4); ptr += 4;
+
+ if (useChecksum) checksumCalculator->addBuffer(buf, ptr-buf);
+ stream->flush();
+ stream->writeFully(&__size_guest_buffer,4);
+ if (useChecksum) checksumCalculator->addBuffer(&__size_guest_buffer,4);
+ if (guest_buffer != NULL) {
+ stream->writeFully(guest_buffer, __size_guest_buffer);
+ if (useChecksum) checksumCalculator->addBuffer(guest_buffer, __size_guest_buffer);
+ }
+ buf = stream->alloc(checksumSize);
+ if (useChecksum) checksumCalculator->writeChecksum(buf, checksumSize);
+
+}
+
} // namespace
gl2_encoder_context_t::gl2_encoder_context_t(IOStream *stream, ChecksumCalculator *checksumCalculator)
@@ -11913,5 +11994,7 @@
this->glDrawElementsNullAEMU = (glDrawElementsNullAEMU_client_proc_t) &enc_unsupported;
this->glDrawElementsOffsetNullAEMU = &glDrawElementsOffsetNullAEMU_enc;
this->glDrawElementsDataNullAEMU = &glDrawElementsDataNullAEMU_enc;
+ this->glUnmapBufferAsyncAEMU = &glUnmapBufferAsyncAEMU_enc;
+ this->glFlushMappedBufferRangeAEMU2 = &glFlushMappedBufferRangeAEMU2_enc;
}
diff --git a/system/GLESv2_enc/gl2_entry.cpp b/system/GLESv2_enc/gl2_entry.cpp
index 69ce39d..a5d6c87 100644
--- a/system/GLESv2_enc/gl2_entry.cpp
+++ b/system/GLESv2_enc/gl2_entry.cpp
@@ -429,6 +429,8 @@
void glDrawElementsNullAEMU(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
void glDrawElementsOffsetNullAEMU(GLenum mode, GLsizei count, GLenum type, GLuint offset);
void glDrawElementsDataNullAEMU(GLenum mode, GLsizei count, GLenum type, void* data, GLuint datalen);
+ void glUnmapBufferAsyncAEMU(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, void* guest_buffer, GLboolean* out_res);
+ void glFlushMappedBufferRangeAEMU2(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, void* guest_buffer);
};
#ifndef GET_CONTEXT
@@ -3018,3 +3020,15 @@
ctx->glDrawElementsDataNullAEMU(ctx, mode, count, type, data, datalen);
}
+void glUnmapBufferAsyncAEMU(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, void* guest_buffer, GLboolean* out_res)
+{
+ GET_CONTEXT;
+ ctx->glUnmapBufferAsyncAEMU(ctx, target, offset, length, access, guest_buffer, out_res);
+}
+
+void glFlushMappedBufferRangeAEMU2(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access, void* guest_buffer)
+{
+ GET_CONTEXT;
+ ctx->glFlushMappedBufferRangeAEMU2(ctx, target, offset, length, access, guest_buffer);
+}
+
diff --git a/system/GLESv2_enc/gl2_opcodes.h b/system/GLESv2_enc/gl2_opcodes.h
index 7628a2e..9c619e1 100644
--- a/system/GLESv2_enc/gl2_opcodes.h
+++ b/system/GLESv2_enc/gl2_opcodes.h
@@ -427,7 +427,9 @@
#define OP_glDrawElementsNullAEMU 2469
#define OP_glDrawElementsOffsetNullAEMU 2470
#define OP_glDrawElementsDataNullAEMU 2471
-#define OP_last 2472
+#define OP_glUnmapBufferAsyncAEMU 2472
+#define OP_glFlushMappedBufferRangeAEMU2 2473
+#define OP_last 2474
#endif
diff --git a/system/OpenglSystemCommon/EmulatorFeatureInfo.h b/system/OpenglSystemCommon/EmulatorFeatureInfo.h
index 422812c..9df134f 100644
--- a/system/OpenglSystemCommon/EmulatorFeatureInfo.h
+++ b/system/OpenglSystemCommon/EmulatorFeatureInfo.h
@@ -87,12 +87,12 @@
// Vulkan create resources with requirements
static const char kVulkanCreateResourcesWithRequirements[] = "ANDROID_EMU_vulkan_create_resources_with_requirements";
-// YUV420_888 to NV21
-static const char kYUV420888toNV21[] = "ANDROID_EMU_YUV420_888_to_NV21";
-
// YUV host cache
static const char kYUVCache[] = "ANDROID_EMU_YUV_Cache";
+// GL protocol v2
+static const char kAsyncUnmapBuffer[] = "ANDROID_EMU_async_unmap_buffer";
+
// Struct describing available emulator features
struct EmulatorFeatureInfo {
@@ -106,8 +106,8 @@
hasDeferredVulkanCommands(false),
hasVulkanNullOptionalStrings(false),
hasVulkanCreateResourcesWithRequirements(false),
- hasYUV420888toNV21(false),
- hasYUVCache (false) { }
+ hasYUVCache (false),
+ hasAsyncUnmapBuffer (false) { }
SyncImpl syncImpl;
DmaImpl dmaImpl;
@@ -118,8 +118,8 @@
bool hasDeferredVulkanCommands;
bool hasVulkanNullOptionalStrings;
bool hasVulkanCreateResourcesWithRequirements;
- bool hasYUV420888toNV21;
bool hasYUVCache;
+ bool hasAsyncUnmapBuffer;
};
#endif // __COMMON_EMULATOR_FEATURE_INFO_H
diff --git a/system/OpenglSystemCommon/FormatConversions.cpp b/system/OpenglSystemCommon/FormatConversions.cpp
index 83aff9c..ca4286c 100644
--- a/system/OpenglSystemCommon/FormatConversions.cpp
+++ b/system/OpenglSystemCommon/FormatConversions.cpp
@@ -68,9 +68,9 @@
uint32_t* totalSz_out) {
uint32_t align = 1;
uint32_t yStride = (width + (align - 1)) & ~(align-1);
- uint32_t uvStride = yStride;
+ uint32_t uvStride = (yStride / 2 + (align - 1)) & ~(align-1);
uint32_t uvHeight = height / 2;
- uint32_t sz = yStride * height + uvHeight * uvStride;
+ uint32_t sz = yStride * height + 2 * (uvHeight * uvStride);
if (yStride_out) *yStride_out = yStride;
if (cStride_out) *cStride_out = uvStride;
@@ -229,42 +229,6 @@
}
}
-//HAL_PIXEL_FORMAT_YCbCr_420_888, or yuv420p is treated as NV21 across our
-//gralloc and camera module when feature YUV420888toNV21 enabled
-void rgb888_to_nv21(char* dest, char* src, int width, int height,
- int left, int top, int right, int bottom) {
- const int rgb_stride = 3;
-
- DD("%s convert %d by %d", __func__, width, height);
- int yStride = width;
- int cStride = yStride;
-
- uint8_t *rgb_ptr0 = (uint8_t *)src;
- uint8_t *nv21_y0 = (uint8_t *)dest;
- uint8_t *nv21_v0 = nv21_y0 + yStride * height;
-
- for (int j = top; j <= bottom; ++j) {
- uint8_t *nv21_y = nv21_y0 + j * yStride;
- uint8_t *nv21_v = nv21_v0 + (j/2) * cStride;
- uint8_t *nv21_u = nv21_v + 1;
- uint8_t *rgb_ptr = rgb_ptr0 + get_rgb_offset(j, width, rgb_stride);
- bool jeven = (j & 1) == 0;
- for (int i = left; i <= right; ++i) {
- uint8_t R = rgb_ptr[i*rgb_stride];
- uint8_t G = rgb_ptr[i*rgb_stride+1];
- uint8_t B = rgb_ptr[i*rgb_stride+2];
- // convert to YV12
- // frameworks/base/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
- nv21_y[i] = clamp_rgb((77 * R + 150 * G + 29 * B) >> 8);
- bool ieven = (i & 1) == 0;
- if (jeven && ieven) {
- nv21_u[i] = clamp_rgb((( -43 * R - 85 * G + 128 * B) >> 8) + 128);
- nv21_v[i] = clamp_rgb((( 128 * R - 107 * G - 21 * B) >> 8) + 128);
- }
- }
- }
-}
-
// YV12 is aka YUV420Planar, or YUV420p; the only difference is that YV12 has
// certain stride requirements for Y and UV respectively.
void yv12_to_rgb565(char* dest, char* src, int width, int height,
@@ -350,6 +314,8 @@
}
}
+// YV12 is aka YUV420Planar, or YUV420p; the only difference is that YV12 has
+// certain stride requirements for Y and UV respectively.
void yuv420p_to_rgb888(char* dest, char* src, int width, int height,
int left, int top, int right, int bottom) {
const int rgb_stride = 3;
@@ -392,49 +358,6 @@
}
}
-//HAL_PIXEL_FORMAT_YCbCr_420_888, or yuv420p is treated as NV21 across our
-//gralloc and camera module when feature YUV420888toNV21 enabled
-void nv21_to_rgb888(char* dest, char* src, int width, int height,
- int left, int top, int right, int bottom) {
- const int rgb_stride = 3;
-
- DD("%s convert %d by %d", __func__, width, height);
- int yStride = width;
- int cStride = yStride;
-
- uint8_t *rgb_ptr0 = (uint8_t *)dest;
- uint8_t *nv21_y0 = (uint8_t *)src;
- uint8_t *nv21_v0 = nv21_y0 + yStride * height;
-
- for (int j = top; j <= bottom; ++j) {
- uint8_t *nv21_y = nv21_y0 + j * yStride;
- uint8_t *nv21_v = nv21_v0 + (j/2) * cStride;
- uint8_t *nv21_u = nv21_v + 1;
- uint8_t *rgb_ptr = rgb_ptr0 + get_rgb_offset(j - top, right - left + 1, rgb_stride);
- for (int i = left; i <= right; ++i) {
- // convert to rgb
- // frameworks/av/media/libstagefright/colorconversion/ColorConverter.cpp
- signed y1 = (signed)nv21_y[i] - 16;
- signed u = (signed)nv21_u[i / 2] - 128;
- signed v = (signed)nv21_v[i / 2] - 128;
-
- signed u_b = u * 517;
- signed u_g = -u * 100;
- signed v_g = -v * 208;
- signed v_r = v * 409;
-
- signed tmp1 = y1 * 298;
- signed b1 = clamp_rgb((tmp1 + u_b) / 256);
- signed g1 = clamp_rgb((tmp1 + v_g + u_g) / 256);
- signed r1 = clamp_rgb((tmp1 + v_r) / 256);
-
- rgb_ptr[(i-left)*rgb_stride] = r1;
- rgb_ptr[(i-left)*rgb_stride+1] = g1;
- rgb_ptr[(i-left)*rgb_stride+2] = b1;
- }
- }
-}
-
void copy_rgb_buffer_from_unlocked(
char* dst, const char* raw_data,
int unlockedWidth,
diff --git a/system/OpenglSystemCommon/FormatConversions.h b/system/OpenglSystemCommon/FormatConversions.h
index 2a8da2b..f9d7806 100644
--- a/system/OpenglSystemCommon/FormatConversions.h
+++ b/system/OpenglSystemCommon/FormatConversions.h
@@ -35,16 +35,12 @@
int left, int top, int right, int bottom);
void rgb888_to_yuv420p(char* dest, char* src, int width, int height,
int left, int top, int right, int bottom);
-void rgb888_to_nv21(char* dest, char* src, int width, int height,
- int left, int top, int right, int bottom);
void yv12_to_rgb565(char* dest, char* src, int width, int height,
int left, int top, int right, int bottom);
void yv12_to_rgb888(char* dest, char* src, int width, int height,
int left, int top, int right, int bottom);
void yuv420p_to_rgb888(char* dest, char* src, int width, int height,
int left, int top, int right, int bottom);
-void nv21_to_rgb888(char* dest, char* src, int width, int height,
- int left, int top, int right, int bottom);
void copy_rgb_buffer_from_unlocked(char* _dst, const char* raw_data,
int unlockedWidth,
int width, int height, int top, int left,
diff --git a/system/OpenglSystemCommon/HostConnection.cpp b/system/OpenglSystemCommon/HostConnection.cpp
index 9708829..2cd1d38 100644
--- a/system/OpenglSystemCommon/HostConnection.cpp
+++ b/system/OpenglSystemCommon/HostConnection.cpp
@@ -15,6 +15,8 @@
*/
#include "HostConnection.h"
+#include "cutils/properties.h"
+
#ifdef GOLDFISH_NO_GL
struct gl_client_context_t {
int placeholder;
@@ -32,6 +34,8 @@
GL2Encoder(IOStream*, ChecksumCalculator*) { }
void setContextAccessor(gl2_client_context_t *()) { }
void setNoHostError(bool) { }
+ void setDrawCallFlushInterval(uint32_t) { }
+ void setHasAsyncUnmapBuffer(int) { }
};
#else
#include "GLEncoder.h"
@@ -73,23 +77,47 @@
#define STREAM_BUFFER_SIZE (4*1024*1024)
#define STREAM_PORT_NUM 22468
-enum HostConnectionType {
- HOST_CONNECTION_TCP = 0,
- HOST_CONNECTION_QEMU_PIPE = 1,
- HOST_CONNECTION_VIRTIO_GPU = 2,
-};
+static HostConnectionType getConnectionTypeFromProperty() {
+ char transportValue[PROPERTY_VALUE_MAX] = "";
+ property_get("ro.kernel.qemu.gltransport", transportValue, "");
+
+ bool isValid = transportValue[0] != '\0';
+ if (!isValid) return HOST_CONNECTION_QEMU_PIPE;
+
+ if (!strcmp("tcp", transportValue)) return HOST_CONNECTION_TCP;
+ if (!strcmp("pipe", transportValue)) return HOST_CONNECTION_QEMU_PIPE;
+ if (!strcmp("virtio-gpu", transportValue)) return HOST_CONNECTION_VIRTIO_GPU;
+ if (!strcmp("asg", transportValue)) return HOST_CONNECTION_ADDRESS_SPACE;
+
+ return HOST_CONNECTION_QEMU_PIPE;
+}
+
+static uint32_t getDrawCallFlushIntervalFromProperty() {
+ char flushValue[PROPERTY_VALUE_MAX] = "";
+ property_get("ro.kernel.qemu.gltransport.drawFlushInterval", flushValue, "");
+
+ bool isValid = flushValue[0] != '\0';
+ if (!isValid) return 800;
+
+ long interval = strtol(flushValue, 0, 10);
+
+ if (!interval) return 800;
+
+ return (uint32_t)interval;
+}
+
class GoldfishGralloc : public Gralloc
{
public:
uint32_t getHostHandle(native_handle_t const* handle)
{
- return cb_handle_t::from_native_handle(handle)->hostHandle;
+ return cb_handle_t::from(handle)->hostHandle;
}
int getFormat(native_handle_t const* handle)
{
- return cb_handle_t::from_native_handle(handle)->format;
+ return cb_handle_t::from(handle)->format;
}
};
@@ -114,9 +142,7 @@
m_checksumHelper(),
m_glExtensions(),
m_grallocOnly(true),
- m_noHostError(false)
-{
-}
+ m_noHostError(false) { }
HostConnection::~HostConnection()
{
@@ -135,10 +161,12 @@
HostConnection* HostConnection::connect(HostConnection* con) {
if (!con) return con;
- const enum HostConnectionType connType = HOST_CONNECTION_VIRTIO_GPU;
+ const enum HostConnectionType connType = getConnectionTypeFromProperty();
switch (connType) {
default:
+ case HOST_CONNECTION_ADDRESS_SPACE: // Not implemented yet
+ ALOGE("Trying to use address space graphics device, not implemented yet\n");
case HOST_CONNECTION_QEMU_PIPE: {
QemuPipeStream *stream = new QemuPipeStream(STREAM_BUFFER_SIZE);
if (!stream) {
@@ -152,12 +180,19 @@
delete con;
return NULL;
}
+ con->m_connectionType = HOST_CONNECTION_QEMU_PIPE;
con->m_stream = stream;
con->m_grallocHelper = &m_goldfishGralloc;
con->m_processPipe = &m_goldfishProcessPipe;
break;
}
case HOST_CONNECTION_TCP: {
+#ifdef __Fuchsia__
+ ALOGE("Fuchsia doesn't support HOST_CONNECTION_TCP!!!\n");
+ delete con;
+ return NULL;
+ break;
+#else
TcpStream *stream = new TcpStream(STREAM_BUFFER_SIZE);
if (!stream) {
ALOGE("Failed to create TcpStream for host connection!!!\n");
@@ -171,10 +206,12 @@
delete con;
return NULL;
}
+ con->m_connectionType = HOST_CONNECTION_TCP;
con->m_stream = stream;
con->m_grallocHelper = &m_goldfishGralloc;
con->m_processPipe = &m_goldfishProcessPipe;
break;
+#endif
}
#ifdef VIRTIO_GPU
case HOST_CONNECTION_VIRTIO_GPU: {
@@ -190,6 +227,7 @@
delete con;
return NULL;
}
+ con->m_connectionType = HOST_CONNECTION_VIRTIO_GPU;
con->m_stream = stream;
con->m_grallocHelper = stream->getGralloc();
con->m_processPipe = stream->getProcessPipe();
@@ -271,6 +309,9 @@
m_gl2Enc, getCurrentThreadId());
m_gl2Enc->setContextAccessor(s_getGL2Context);
m_gl2Enc->setNoHostError(m_noHostError);
+ m_gl2Enc->setDrawCallFlushInterval(
+ getDrawCallFlushIntervalFromProperty());
+ m_gl2Enc->setHasAsyncUnmapBuffer(m_rcEnc->hasAsyncUnmapBuffer());
}
return m_gl2Enc;
}
@@ -298,8 +339,8 @@
queryAndSetDeferredVulkanCommandsSupport(m_rcEnc);
queryAndSetVulkanNullOptionalStringsSupport(m_rcEnc);
queryAndSetVulkanCreateResourcesWithRequirementsSupport(m_rcEnc);
- queryAndSetYUV420888toNV21(m_rcEnc);
queryAndSetYUVCache(m_rcEnc);
+ queryAndSetAsyncUnmapBuffer(m_rcEnc);
if (m_processPipe) {
m_processPipe->processPipeInit(m_rcEnc);
}
@@ -474,16 +515,17 @@
}
}
-void HostConnection::queryAndSetYUV420888toNV21(ExtendedRCEncoderContext* rcEnc) {
- std::string glExtensions = queryGLExtensions(rcEnc);
- if (glExtensions.find(kYUV420888toNV21) != std::string::npos) {
- rcEnc->featureInfo()->hasYUV420888toNV21 = true;
- }
-}
-
void HostConnection::queryAndSetYUVCache(ExtendedRCEncoderContext* rcEnc) {
std::string glExtensions = queryGLExtensions(rcEnc);
if (glExtensions.find(kYUVCache) != std::string::npos) {
rcEnc->featureInfo()->hasYUVCache = true;
}
}
+
+void HostConnection::queryAndSetAsyncUnmapBuffer(ExtendedRCEncoderContext* rcEnc) {
+ std::string glExtensions = queryGLExtensions(rcEnc);
+ if (glExtensions.find(kAsyncUnmapBuffer) != std::string::npos) {
+ rcEnc->featureInfo()->hasAsyncUnmapBuffer = true;
+ }
+}
+
diff --git a/system/OpenglSystemCommon/HostConnection.h b/system/OpenglSystemCommon/HostConnection.h
index a6424ab..c7547ca 100644
--- a/system/OpenglSystemCommon/HostConnection.h
+++ b/system/OpenglSystemCommon/HostConnection.h
@@ -58,10 +58,10 @@
return m_featureInfo.hostComposition == HOST_COMPOSITION_V1; }
bool hasHostCompositionV2() const {
return m_featureInfo.hostComposition == HOST_COMPOSITION_V2; }
- bool hasYUV420toNV21() const {
- return m_featureInfo.hasYUV420888toNV21; }
bool hasYUVCache() const {
return m_featureInfo.hasYUVCache; }
+ bool hasAsyncUnmapBuffer() const {
+ return m_featureInfo.hasAsyncUnmapBuffer; }
DmaImpl getDmaVersion() const { return m_featureInfo.dmaImpl; }
void bindDmaContext(struct goldfish_dma_context* cxt) { m_dmaCxt = cxt; }
void bindDmaDirectly(void* dmaPtr, uint64_t dmaPhysAddr) {
@@ -127,6 +127,13 @@
struct EGLThreadInfo;
+enum HostConnectionType {
+ HOST_CONNECTION_TCP = 0,
+ HOST_CONNECTION_QEMU_PIPE = 1,
+ HOST_CONNECTION_VIRTIO_GPU = 2,
+ HOST_CONNECTION_ADDRESS_SPACE = 3,
+};
+
class HostConnection
{
public:
@@ -139,6 +146,10 @@
~HostConnection();
+ HostConnectionType connectionType() const {
+ return m_connectionType;
+ }
+
GLEncoder *glEncoder();
GL2Encoder *gl2Encoder();
goldfish_vk::VkEncoder *vkEncoder();
@@ -191,10 +202,11 @@
void queryAndSetDeferredVulkanCommandsSupport(ExtendedRCEncoderContext *rcEnc);
void queryAndSetVulkanNullOptionalStringsSupport(ExtendedRCEncoderContext *rcEnc);
void queryAndSetVulkanCreateResourcesWithRequirementsSupport(ExtendedRCEncoderContext *rcEnc);
- void queryAndSetYUV420888toNV21(ExtendedRCEncoderContext *mrcEnc);
void queryAndSetYUVCache(ExtendedRCEncoderContext *mrcEnc);
+ void queryAndSetAsyncUnmapBuffer(ExtendedRCEncoderContext *rcEnc);
private:
+ HostConnectionType m_connectionType;
IOStream *m_stream;
GLEncoder *m_glEnc;
GL2Encoder *m_gl2Enc;
diff --git a/system/gralloc/gralloc_common.h b/system/gralloc/gralloc_common.h
index 574e659..6dba9cd 100644
--- a/system/gralloc/gralloc_common.h
+++ b/system/gralloc/gralloc_common.h
@@ -17,6 +17,14 @@
#ifndef __GRALLOC_COMMON_H__
#define __GRALLOC_COMMON_H__
+// Tell the emulator which gralloc formats
+// need special handling.
+enum EmulatorFrameworkFormat {
+ FRAMEWORK_FORMAT_GL_COMPATIBLE = 0,
+ FRAMEWORK_FORMAT_YV12 = 1,
+ FRAMEWORK_FORMAT_YUV_420_888 = 2, // (Y+)(U+)(V+)
+};
+
#ifndef GL_RGBA16F
#define GL_RGBA16F 0x881A
#endif // GL_RGBA16F
diff --git a/system/gralloc/gralloc_old.cpp b/system/gralloc/gralloc_old.cpp
index 773f786..6ab38a2 100644
--- a/system/gralloc/gralloc_old.cpp
+++ b/system/gralloc/gralloc_old.cpp
@@ -1,4 +1,4 @@
-/*
+ /*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
#include <string.h>
#include <pthread.h>
#include <limits.h>
@@ -21,11 +22,12 @@
#include <errno.h>
#include <dlfcn.h>
#include <sys/mman.h>
+#include <hardware/gralloc.h>
#if PLATFORM_SDK_VERSION < 28
-#include "gralloc_cb_old.h"
+#include "gralloc_cb.h"
#else
-#include "../../shared/OpenglCodecCommon/gralloc_cb_old.h"
+#include "../../shared/OpenglCodecCommon/gralloc_cb.h"
#endif
#include "gralloc_common.h"
@@ -81,8 +83,69 @@
static const bool isHidlGralloc = false;
#endif
-int32_t* getOpenCountPtr(cb_handle_old_t* cb) {
- return ((int32_t*)cb->ashmemBase) + 1;
+const uint32_t CB_HANDLE_MAGIC_OLD = CB_HANDLE_MAGIC_BASE | 0x1;
+
+struct cb_handle_old_t : public cb_handle_t {
+ cb_handle_old_t(int p_fd, int p_ashmemSize, int p_usage,
+ int p_width, int p_height,
+ int p_format, int p_glFormat, int p_glType)
+ : cb_handle_t(p_fd,
+ QEMU_PIPE_INVALID_HANDLE,
+ CB_HANDLE_MAGIC_OLD,
+ 0,
+ p_usage,
+ p_width,
+ p_height,
+ p_format,
+ p_glFormat,
+ p_glType,
+ p_ashmemSize,
+ nullptr),
+ ashmemBasePid(0),
+ mappedPid(0) {
+ numInts = CB_HANDLE_NUM_INTS(numFds);
+ }
+
+ bool hasRefcountPipe() const {
+ return qemu_pipe_valid(hostHandleRefCountFd);
+ }
+
+ void setRefcountPipeFd(QEMU_PIPE_HANDLE fd) {
+ if (qemu_pipe_valid(fd)) {
+ numFds++;
+ }
+ hostHandleRefCountFd = fd;
+ numInts = CB_HANDLE_NUM_INTS(numFds);
+ }
+
+ bool canBePosted() const {
+ return (0 != (usage & GRALLOC_USAGE_HW_FB));
+ }
+
+ bool isValid() const {
+ return (version == sizeof(native_handle)) && (magic == CB_HANDLE_MAGIC_OLD);
+ }
+
+ static cb_handle_old_t* from(void* p) {
+ if (!p) { return nullptr; }
+ cb_handle_old_t* cb = static_cast<cb_handle_old_t*>(p);
+ return cb->isValid() ? cb : nullptr;
+ }
+
+ static const cb_handle_old_t* from(const void* p) {
+ return from(const_cast<void*>(p));
+ }
+
+ static cb_handle_old_t* from_unconst(const void* p) {
+ return from(const_cast<void*>(p));
+ }
+
+ int32_t ashmemBasePid; // process id which mapped the ashmem region
+ int32_t mappedPid; // process id which succeeded gralloc_register call
+};
+
+int32_t* getOpenCountPtr(const cb_handle_old_t* cb) {
+ return ((int32_t*)cb->getBufferPtr()) + 1;
}
uint32_t getAshmemColorOffset(cb_handle_old_t* cb) {
@@ -331,7 +394,7 @@
dump_regions(rcEnc);
#endif
- get_mem_region((void*)cb->ashmemBase);
+ get_mem_region(cb->getBufferPtr());
#if DEBUG
dump_regions(rcEnc);
@@ -345,13 +408,13 @@
dump_regions(rcEnc);
#endif
- const bool should_unmap = put_mem_region(rcEnc, (void*)cb->ashmemBase);
+ const bool should_unmap = put_mem_region(rcEnc, cb->getBufferPtr());
#if DEBUG
dump_regions(rcEnc);
#endif
- put_gralloc_region(rcEnc, cb->ashmemSize);
+ put_gralloc_region(rcEnc, cb->bufferSize);
return should_unmap;
}
@@ -365,21 +428,21 @@
static int map_buffer(cb_handle_old_t *cb, void **vaddr)
{
- if (cb->fd < 0 || cb->ashmemSize <= 0) {
+ if (cb->bufferFd < 0) {
return -EINVAL;
}
- void *addr = mmap(0, cb->ashmemSize, PROT_READ | PROT_WRITE,
- MAP_SHARED, cb->fd, 0);
+ void *addr = mmap(0, cb->bufferSize, PROT_READ | PROT_WRITE,
+ MAP_SHARED, cb->bufferFd, 0);
if (addr == MAP_FAILED) {
ALOGE("%s: failed to map ashmem region!", __FUNCTION__);
return -errno;
}
- cb->ashmemBase = intptr_t(addr);
+ cb->setBufferPtr(addr);
cb->ashmemBasePid = getpid();
D("%s: %p mapped ashmem base %p size %d\n", __FUNCTION__,
- cb, cb->ashmemBase, cb->ashmemSize);
+ cb, addr, cb->bufferSize);
*vaddr = addr;
return 0;
@@ -496,17 +559,12 @@
case HAL_PIXEL_FORMAT_YCbCr_420_888:
convertedBuf.resize(rgbSz);
to_send = &convertedBuf.front();
- if (rcEnc->hasYUV420toNV21()) {
- nv21_to_rgb888(to_send, pixels,
- width, height, left, top,
- left + width - 1, top + height - 1);
- } else {
- yuv420p_to_rgb888(to_send, pixels,
- width, height, left, top,
- left + width - 1, top + height - 1);
- }
+ yuv420p_to_rgb888(to_send, pixels,
+ width, height, left, top,
+ left + width - 1, top + height - 1);
break;
}
+
rcEnc->rcUpdateColorBuffer(rcEnc, cb->hostHandle,
left, top, width, height,
cb->glFormat, cb->glType, to_send);
@@ -780,8 +838,7 @@
cb_handle_old_t *cb = new cb_handle_old_t(fd, ashmem_size, usage,
w, h, format,
- glFormat, glType,
- selectedEmuFrameworkFormat);
+ glFormat, glType);
if (ashmem_size > 0) {
//
@@ -794,7 +851,6 @@
delete cb;
return err;
}
- cb->setFd(fd);
}
const bool hasDMA = has_DMA_support(rcEnc);
@@ -813,7 +869,7 @@
hostCon->lock();
if (hasDMA) {
- cb->hostHandle = rcEnc->rcCreateColorBufferDMA(rcEnc, w, h, allocFormat, cb->emuFrameworkFormat);
+ cb->hostHandle = rcEnc->rcCreateColorBufferDMA(rcEnc, w, h, allocFormat, selectedEmuFrameworkFormat);
} else {
cb->hostHandle = rcEnc->rcCreateColorBuffer(rcEnc, w, h, allocFormat);
}
@@ -871,20 +927,20 @@
{
DEFINE_AND_VALIDATE_HOST_CONNECTION;
- cb_handle_old_t *cb = (cb_handle_old_t *)handle;
- if (!cb_handle_old_t::validate((cb_handle_old_t*)cb)) {
- ERR("gralloc_free: invalid handle");
+ const cb_handle_old_t *cb = cb_handle_old_t::from(handle);
+ if (!cb) {
+ ERR("gralloc_free: invalid handle %p", handle);
return -EINVAL;
}
D("%s: for buf %p ptr %p size %d\n",
- __FUNCTION__, handle, cb->ashmemBase, cb->ashmemSize);
+ __FUNCTION__, handle, cb->getBufferPtr(), cb->bufferSize);
if (cb->hostHandle && !cb->hasRefcountPipe()) {
int32_t openCount = 1;
int32_t* openCountPtr = &openCount;
- if (isHidlGralloc && cb->ashmemBase) {
+ if (isHidlGralloc && cb->getBufferPtr()) {
openCountPtr = getOpenCountPtr(cb);
}
@@ -902,17 +958,17 @@
//
// detach and unmap ashmem area if present
//
- if (cb->fd > 0) {
- if (cb->ashmemSize > 0 && cb->ashmemBase) {
- D("%s: unmapped %p", __FUNCTION__, cb->ashmemBase);
- munmap((void *)cb->ashmemBase, cb->ashmemSize);
- put_gralloc_region(rcEnc, cb->ashmemSize);
+ if (cb->bufferFd > 0) {
+ if (cb->bufferSize > 0 && cb->getBufferPtr()) {
+ D("%s: unmapped %p", __FUNCTION__, cb->getBufferPtr());
+ munmap(cb->getBufferPtr(), cb->bufferSize);
+ put_gralloc_region(rcEnc, cb->bufferSize);
}
- close(cb->fd);
+ close(cb->bufferFd);
}
- if(qemu_pipe_valid(cb->refcount_pipe_fd)) {
- qemu_pipe_close(cb->refcount_pipe_fd);
+ if(qemu_pipe_valid(cb->hostHandleRefCountFd)) {
+ qemu_pipe_close(cb->hostHandleRefCountFd);
}
D("%s: done", __FUNCTION__);
// remove it from the allocated list
@@ -955,9 +1011,14 @@
static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
{
fb_device_t *fbdev = (fb_device_t *)dev;
- cb_handle_old_t *cb = (cb_handle_old_t *)buffer;
-
- if (!fbdev || !cb_handle_old_t::validate(cb) || !cb->canBePosted()) {
+ if (!fbdev) {
+ return -EINVAL;
+ }
+ const cb_handle_old_t *cb = cb_handle_old_t::from(buffer);
+ if (!cb) {
+ return -EINVAL;
+ }
+ if (!cb->canBePosted()) {
return -EINVAL;
}
@@ -965,7 +1026,7 @@
DEFINE_AND_VALIDATE_HOST_CONNECTION;
// increment the post count of the buffer
- intptr_t *postCountPtr = (intptr_t *)cb->ashmemBase;
+ int32_t *postCountPtr = (int32_t *)cb->getBufferPtr();
if (!postCountPtr) {
// This should not happen
return -EINVAL;
@@ -1053,9 +1114,12 @@
}
private_module_t *gr = (private_module_t *)module;
- cb_handle_old_t *cb = (cb_handle_old_t *)handle;
+ if (!gr) {
+ return -EINVAL;
+ }
- if (!gr || !cb_handle_old_t::validate(cb)) {
+ cb_handle_old_t *cb = cb_handle_old_t::from_unconst(handle);
+ if (!cb) {
ERR("gralloc_register_buffer(%p): invalid buffer", cb);
return -EINVAL;
}
@@ -1074,7 +1138,7 @@
// if the color buffer has ashmem region and it is not mapped in this
// process map it now.
//
- if (cb->ashmemSize > 0 && cb->mappedPid != getpid()) {
+ if (cb->bufferSize > 0 && cb->mappedPid != getpid()) {
void *vaddr;
int err = map_buffer(cb, &vaddr);
if (err) {
@@ -1089,7 +1153,7 @@
}
}
- if (cb->ashmemSize > 0) {
+ if (cb->bufferSize > 0) {
get_ashmem_region(rcEnc, cb);
}
@@ -1106,9 +1170,12 @@
}
private_module_t *gr = (private_module_t *)module;
- cb_handle_old_t *cb = (cb_handle_old_t *)handle;
+ if (!gr) {
+ return -EINVAL;
+ }
- if (!gr || !cb_handle_old_t::validate(cb)) {
+ cb_handle_old_t *cb = cb_handle_old_t::from_unconst(handle);
+ if (!cb) {
ERR("gralloc_unregister_buffer(%p): invalid buffer", cb);
return -EINVAL;
}
@@ -1122,7 +1189,7 @@
if (isHidlGralloc) {
// Queue up another rcCloseColorBuffer if applicable.
// invariant: have ashmem.
- if (cb->ashmemSize > 0 && cb->mappedPid == getpid()) {
+ if (cb->bufferSize > 0 && cb->mappedPid == getpid()) {
int32_t* openCountPtr = getOpenCountPtr(cb);
if (*openCountPtr == -1) {
D("%s: revenge of the rcCloseColorBuffer!", __func__);
@@ -1138,16 +1205,16 @@
// unmap ashmem region if it was previously mapped in this process
// (through register_buffer)
//
- if (cb->ashmemSize > 0 && cb->mappedPid == getpid()) {
+ if (cb->bufferSize > 0 && cb->mappedPid == getpid()) {
const bool should_unmap = put_ashmem_region(rcEnc, cb);
if (!should_unmap) goto done;
- int err = munmap((void *)cb->ashmemBase, cb->ashmemSize);
+ int err = munmap(cb->getBufferPtr(), cb->bufferSize);
if (err) {
ERR("gralloc_unregister_buffer(%p): unmap failed", cb);
return -EINVAL;
}
- cb->ashmemBase = 0;
+ cb->bufferSize = 0;
cb->mappedPid = 0;
D("%s: Unregister buffer previous mapped to pid %d", __FUNCTION__, getpid());
}
@@ -1167,9 +1234,12 @@
}
private_module_t *gr = (private_module_t *)module;
- cb_handle_old_t *cb = (cb_handle_old_t *)handle;
+ if (!gr) {
+ return -EINVAL;
+ }
- if (!gr || !cb_handle_old_t::validate(cb)) {
+ cb_handle_old_t *cb = cb_handle_old_t::from_unconst(handle);
+ if (!cb) {
ALOGE("gralloc_lock bad handle\n");
return -EINVAL;
}
@@ -1229,11 +1299,11 @@
if (cb->canBePosted() || sw_read || sw_write ||
hw_cam_write || hw_cam_read ||
hw_vid_enc_read) {
- if (cb->ashmemBasePid != getpid() || !cb->ashmemBase) {
+ if (cb->ashmemBasePid != getpid() || !cb->getBufferPtr()) {
return -EACCES;
}
- cpu_addr = (void *)(cb->ashmemBase + getAshmemColorOffset(cb));
+ cpu_addr = (void *)((char*)cb->getBufferPtr() + getAshmemColorOffset(cb));
}
if (cb->hostHandle) {
@@ -1255,7 +1325,7 @@
}
// camera delivers bits to the buffer directly and does not require
- // an explicit read, it also writes in YUV_420 (interleaved)
+ // an explicit read.
if (sw_read & !(usage & GRALLOC_USAGE_HW_CAMERA_MASK)) {
D("gralloc_lock read back color buffer %d %d ashmem base %p sz %d\n",
cb->width, cb->height, cb->ashmemBase, cb->ashmemSize);
@@ -1285,13 +1355,8 @@
D("convert rgb888 to yv12 here");
rgb888_to_yv12((char*)cpu_addr, tmpBuf, cb->width, cb->height, l, t, l+w-1, t+h-1);
} else if (cb->format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
- if (rcEnc->hasYUV420toNV21()) {
- D("convert rgb888 to nv21 here");
- rgb888_to_nv21((char*)cpu_addr, tmpBuf, cb->width, cb->height, l, t, l+w-1, t+h-1);
- } else {
- D("convert rgb888 to yuv420p here");
- rgb888_to_yuv420p((char*)cpu_addr, tmpBuf, cb->width, cb->height, l, t, l+w-1, t+h-1);
- }
+ D("convert rgb888 to yuv420p here");
+ rgb888_to_yuv420p((char*)cpu_addr, tmpBuf, cb->width, cb->height, l, t, l+w-1, t+h-1);
}
delete [] tmpBuf;
}
@@ -1302,7 +1367,7 @@
}
if (has_DMA_support(rcEnc)) {
- gralloc_dmaregion_register_ashmem(rcEnc, cb->ashmemSize);
+ gralloc_dmaregion_register_ashmem(rcEnc, cb->bufferSize);
}
hostCon->unlock();
}
@@ -1338,10 +1403,13 @@
}
private_module_t *gr = (private_module_t *)module;
- cb_handle_old_t *cb = (cb_handle_old_t *)handle;
+ if (!gr) {
+ return -EINVAL;
+ }
- if (!gr || !cb_handle_old_t::validate(cb)) {
- ALOGD("%s: invalid gr or cb handle. -EINVAL", __FUNCTION__);
+ cb_handle_old_t *cb = cb_handle_old_t::from_unconst(handle);
+ if (!cb) {
+ ALOGD("%s: invalid cb handle. -EINVAL", __FUNCTION__);
return -EINVAL;
}
@@ -1355,14 +1423,13 @@
DEFINE_AND_VALIDATE_HOST_CONNECTION;
hostCon->lock();
- void *cpu_addr = (void *)(cb->ashmemBase + getAshmemColorOffset(cb));
+ char *cpu_addr = (char*)cb->getBufferPtr() + getAshmemColorOffset(cb);
- char* rgb_addr = (char *)cpu_addr;
if (cb->lockedWidth < cb->width || cb->lockedHeight < cb->height) {
- updateHostColorBuffer(cb, true, rgb_addr);
+ updateHostColorBuffer(cb, true, cpu_addr);
}
else {
- updateHostColorBuffer(cb, false, rgb_addr);
+ updateHostColorBuffer(cb, false, cpu_addr);
}
hostCon->unlock();
@@ -1391,8 +1458,12 @@
}
private_module_t *gr = (private_module_t *)module;
- cb_handle_old_t *cb = (cb_handle_old_t *)handle;
- if (!gr || !cb_handle_old_t::validate(cb)) {
+ if (!gr) {
+ return -EINVAL;
+ }
+
+ cb_handle_old_t *cb = cb_handle_old_t::from_unconst(handle);
+ if (!cb) {
ALOGE("%s: bad colorbuffer handle. -EINVAL", __FUNCTION__);
return -EINVAL;
}
@@ -1445,34 +1516,14 @@
uOffset = vOffset + cSize;
cStep = 1;
break;
- case HAL_PIXEL_FORMAT_YCbCr_420_888: {
- DEFINE_AND_VALIDATE_HOST_CONNECTION
- if (rcEnc->hasYUV420toNV21()) {
- yStride = cb->width;
- cStride = cb->width;
- yOffset = 0;
- vOffset = yStride * cb->height;
- uOffset = vOffset + 1;
- cStep = 2;
- } else {
- if (usage & GRALLOC_USAGE_HW_CAMERA_MASK) {
- yStride = cb->width;
- cStride = cb->width;
- yOffset = 0;
- vOffset = yStride * cb->height;
- uOffset = vOffset + 1;
- cStep = 2;
- } else {
- yStride = cb->width;
- cStride = yStride / 2;
- yOffset = 0;
- uOffset = cb->height * yStride;
- vOffset = uOffset + cStride * cb->height / 2;
- cStep = 1;
- }
- }
+ case HAL_PIXEL_FORMAT_YCbCr_420_888:
+ yStride = cb->width;
+ cStride = yStride / 2;
+ yOffset = 0;
+ uOffset = cb->height * yStride;
+ vOffset = uOffset + cStride * cb->height / 2;
+ cStep = 1;
break;
- }
default:
ALOGE("gralloc_lock_ycbcr unexpected internal format %x",
cb->format);
diff --git a/system/hwc2/EmuHWC2.cpp b/system/hwc2/EmuHWC2.cpp
index 921d848..edf6397 100644
--- a/system/hwc2/EmuHWC2.cpp
+++ b/system/hwc2/EmuHWC2.cpp
@@ -31,6 +31,7 @@
#include "../egl/goldfish_sync.h"
#include "ThreadInfo.h"
+#include "gralloc_cb.h"
#if defined(LOG_NNDEBUG) && LOG_NNDEBUG == 0
#define ALOGVV ALOGV
@@ -219,6 +220,23 @@
displayHook<decltype(&Display::getClientTargetSupport),
&Display::getClientTargetSupport, uint32_t, uint32_t,
int32_t, int32_t>);
+ // 2.3 required functions
+ case FunctionDescriptor::GetDisplayIdentificationData:
+ return asFP<HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA>(
+ displayHook<decltype(&Display::getDisplayIdentificationData),
+ &Display::getDisplayIdentificationData, uint8_t*, uint32_t*, uint8_t*>);
+ case FunctionDescriptor::GetDisplayCapabilities:
+ return asFP<HWC2_PFN_GET_DISPLAY_CAPABILITIES>(
+ displayHook<decltype(&Display::getDisplayCapabilities),
+ &Display::getDisplayCapabilities, uint32_t*, uint32_t*>);
+ case FunctionDescriptor::GetDisplayBrightnessSupport:
+ return asFP<HWC2_PFN_GET_DISPLAY_BRIGHTNESS_SUPPORT>(
+ displayHook<decltype(&Display::getDisplayBrightnessSupport),
+ &Display::getDisplayBrightnessSupport, bool*>);
+ case FunctionDescriptor::SetDisplayBrightness:
+ return asFP<HWC2_PFN_SET_DISPLAY_BRIGHTNESS>(
+ displayHook<decltype(&Display::setDisplayBrightness),
+ &Display::setDisplayBrightness, float>);
// Layer functions
case FunctionDescriptor::SetCursorPosition:
return asFP<HWC2_PFN_SET_CURSOR_POSITION>(
@@ -374,8 +392,7 @@
if (mHandle != nullptr) {
mGralloc->unregisterBuffer(mGralloc, mHandle);
mAllocDev->free(mAllocDev, mHandle);
- ALOGI("free targetCb %u",
- cb_handle_t::from_raw_pointer(mHandle)->hostHandle);
+ ALOGI("free targetCb %u", cb_handle_t::from(mHandle)->hostHandle);
}
}
@@ -390,9 +407,9 @@
&mHandle, &stride);
assert(ret == 0 && "Fail to allocate target ColorBuffer");
mGralloc->registerBuffer(mGralloc, mHandle);
- ALOGI("targetCb %u", cb_handle_t::from_raw_pointer(mHandle)->hostHandle);
+ ALOGI("targetCb %u", cb_handle_t::from(mHandle)->hostHandle);
}
- return cb_handle_t::from_raw_pointer(mHandle)->hostHandle;
+ return cb_handle_t::from(mHandle)->hostHandle;
}
// Display functions
@@ -796,7 +813,7 @@
__FUNCTION__, (uint32_t)layer->getId());
}
const cb_handle_t *cb =
- cb_handle_t::from_raw_pointer(layer->getLayerBuffer().getBuffer());
+ cb_handle_t::from(layer->getLayerBuffer().getBuffer());
if (cb != nullptr) {
l->cbHandle = cb->hostHandle;
}
@@ -906,7 +923,7 @@
int32_t acquireFence, int32_t /*dataspace*/, hwc_region_t /*damage*/) {
ALOGVV("%s", __FUNCTION__);
- const cb_handle_t *cb = cb_handle_t::from_raw_pointer(target);
+ const cb_handle_t *cb = cb_handle_t::from(target);
ALOGV("%s: display(%u) buffer handle %p cb %d, acquireFence %d", __FUNCTION__,
(uint32_t)mId, target, cb->hostHandle, acquireFence);
std::unique_lock<std::mutex> lock(mStateMutex);
@@ -1130,6 +1147,136 @@
return Error::None;
}
+// thess EDIDs are carefully generated according to the EDID spec version 1.3, more info
+// can be found from the following file:
+// frameworks/native/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
+// approved pnp ids can be found here: https://uefi.org/pnp_id_list
+// pnp id: GGL, name: EMU_display_0, last byte is checksum
+// display id is local:8141603649153536
+static const std::vector<uint8_t> sEDID0 {
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1c, 0xec, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x1b, 0x10, 0x01, 0x03, 0x80, 0x50, 0x2d, 0x78, 0x0a, 0x0d, 0xc9, 0xa0, 0x57, 0x47, 0x98, 0x27,
+ 0x12, 0x48, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
+ 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+ 0x00, 0x45, 0x4d, 0x55, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x30, 0x00, 0x4b
+};
+
+// pnp id: GGL, name: EMU_display_1
+// display id is local:8140900251843329
+static const std::vector<uint8_t> sEDID1 {
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1c, 0xec, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x1b, 0x10, 0x01, 0x03, 0x80, 0x50, 0x2d, 0x78, 0x0a, 0x0d, 0xc9, 0xa0, 0x57, 0x47, 0x98, 0x27,
+ 0x12, 0x48, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
+ 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+ 0x00, 0x45, 0x4d, 0x55, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x31, 0x00, 0x3b
+};
+
+// pnp id: GGL, name: EMU_display_2
+// display id is local:8140940453066754
+static const std::vector<uint8_t> sEDID2 {
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1c, 0xec, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x1b, 0x10, 0x01, 0x03, 0x80, 0x50, 0x2d, 0x78, 0x0a, 0x0d, 0xc9, 0xa0, 0x57, 0x47, 0x98, 0x27,
+ 0x12, 0x48, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
+ 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+ 0x00, 0x45, 0x4d, 0x55, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x32, 0x00, 0x49
+};
+
+Error EmuHWC2::Display::getDisplayIdentificationData(uint8_t* outPort,
+ uint32_t* outDataSize, uint8_t* outData) {
+ ALOGVV("%s DisplayId %u", __FUNCTION__, (uint32_t)mId);
+ if (outPort == nullptr || outDataSize == nullptr)
+ return Error::BadParameter;
+
+ uint32_t len = std::min(*outDataSize, (uint32_t)(sEDID0.size()));
+ if (outData != nullptr && len < (uint32_t)(sEDID0.size())) {
+ ALOGW("%s DisplayId %u, small buffer size: %u is specified",
+ __FUNCTION__, (uint32_t)mId, len);
+ }
+ *outDataSize = (int32_t)(sEDID0.size());
+ switch (mId) {
+ case 0:
+ *outPort = 0;
+ if (outData)
+ memcpy(outData, sEDID0.data(), len);
+ break;
+
+ case 1:
+ *outPort = 1;
+ if (outData)
+ memcpy(outData, sEDID1.data(), len);
+ break;
+
+ case 2:
+ *outPort = 2;
+ if (outData)
+ memcpy(outData, sEDID2.data(), len);
+ break;
+
+ default:
+ *outPort = (uint8_t)mId;
+ if (outData) {
+ memcpy(outData, sEDID2.data(), len);
+ uint32_t size = sEDID0.size();
+ // change the name to EMU_display_<mID>
+ // note the 3rd char from back is the number, _0, _1, _2, etc.
+ if (len >= size - 2)
+ outData[size-3] = '0' + (uint8_t)mId;
+ if (len >= size) {
+ // update the last byte, which is checksum byte
+ uint8_t checksum = -(uint8_t)std::accumulate(
+ outData, outData + size - 1, static_cast<uint8_t>(0));
+ outData[size - 1] = checksum;
+ }
+ }
+ break;
+ }
+
+ return Error::None;
+}
+
+Error EmuHWC2::Display::getDisplayCapabilities(uint32_t* outNumCapabilities,
+ uint32_t* outCapabilities) {
+ if (outNumCapabilities == nullptr) {
+ return Error::None;
+ }
+
+ bool brightness_support = true;
+ bool doze_support = true;
+
+ uint32_t count = 1 + static_cast<uint32_t>(doze_support) + (brightness_support ? 1 : 0);
+ int index = 0;
+ if (outCapabilities != nullptr && (*outNumCapabilities >= count)) {
+ outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
+ if (doze_support) {
+ outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_DOZE;
+ }
+ if (brightness_support) {
+ outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_BRIGHTNESS;
+ }
+ }
+
+ *outNumCapabilities = count;
+ return Error::None;
+}
+
+Error EmuHWC2::Display::getDisplayBrightnessSupport(bool *out_support) {
+ *out_support = false;
+ return Error::None;
+}
+
+Error EmuHWC2::Display::setDisplayBrightness(float brightness) {
+ ALOGW("TODO: setDisplayBrightness() is not implemented yet: brightness=%f", brightness);
+ return Error::None;
+}
int EmuHWC2::Display::populatePrimaryConfigs() {
ALOGVV("%s DisplayId %u", __FUNCTION__, (uint32_t)mId);
@@ -1524,6 +1671,7 @@
EmuHWC2::Display* EmuHWC2::getDisplay(hwc2_display_t id) {
auto display = mDisplays.find(id);
if (display == mDisplays.end()) {
+ ALOGE("Failed to get display for id=%d", (uint32_t)id);
return nullptr;
}
return display->second.get();
diff --git a/system/hwc2/EmuHWC2.h b/system/hwc2/EmuHWC2.h
index d4615a7..ff056ca 100644
--- a/system/hwc2/EmuHWC2.h
+++ b/system/hwc2/EmuHWC2.h
@@ -27,13 +27,14 @@
#include <atomic>
#include <map>
#include <mutex>
+#include <numeric>
#include <sstream>
#include <vector>
#include <unordered_set>
#include <unordered_map>
#include <set>
+#include <cutils/native_handle.h>
-#include "gralloc_cb.h"
#include "MiniFence.h"
#include "HostConnection.h"
@@ -257,6 +258,13 @@
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);
+ // 2.3 required functions
+ HWC2::Error getDisplayIdentificationData(uint8_t* outPort,
+ uint32_t* outDataSize, uint8_t* outData);
+ HWC2::Error getDisplayCapabilities(uint32_t* outNumCapabilities,
+ uint32_t* outCapabilities);
+ HWC2::Error getDisplayBrightnessSupport(bool *out_support);
+ HWC2::Error setDisplayBrightness(float brightness);
// Read configs from PRIMARY Display
int populatePrimaryConfigs();
diff --git a/system/vulkan_enc/AndroidHardwareBuffer.cpp b/system/vulkan_enc/AndroidHardwareBuffer.cpp
index e2f2ad1..0a71d6d 100644
--- a/system/vulkan_enc/AndroidHardwareBuffer.cpp
+++ b/system/vulkan_enc/AndroidHardwareBuffer.cpp
@@ -111,9 +111,12 @@
const native_handle_t *handle =
AHardwareBuffer_getNativeHandle(buffer);
- const cb_handle_t* cb_handle = cb_handle_t::from_native_handle(handle);
- uint32_t colorBufferHandle = cb_handle->hostHandle;
+ const cb_handle_t* cb_handle = cb_handle_t::from(handle);
+ if (!cb_handle) {
+ return VK_ERROR_INVALID_EXTERNAL_HANDLE;
+ }
+ uint32_t colorBufferHandle = cb_handle->hostHandle;
if (!colorBufferHandle) {
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
}
@@ -128,7 +131,7 @@
}
pProperties->memoryTypeBits = memoryTypeBits;
- pProperties->allocationSize = cb_handle->allocationSize();
+ pProperties->allocationSize = cb_handle->allocatedSize();
return VK_SUCCESS;
}
@@ -164,9 +167,12 @@
const native_handle_t *handle =
AHardwareBuffer_getNativeHandle(info->buffer);
- const cb_handle_t* cb_handle = cb_handle_t::from_native_handle(handle);
- uint32_t colorBufferHandle = cb_handle->hostHandle;
+ const cb_handle_t* cb_handle = cb_handle_t::from(handle);
+ if (!cb_handle) {
+ return VK_ERROR_INVALID_EXTERNAL_HANDLE;
+ }
+ uint32_t colorBufferHandle = cb_handle->hostHandle;
if (!colorBufferHandle) {
return VK_ERROR_INVALID_EXTERNAL_HANDLE;
}
diff --git a/system/vulkan_enc/ResourceTracker.cpp b/system/vulkan_enc/ResourceTracker.cpp
index 98bf049..363d3b9 100644
--- a/system/vulkan_enc/ResourceTracker.cpp
+++ b/system/vulkan_enc/ResourceTracker.cpp
@@ -1836,7 +1836,7 @@
ALOGD("%s: Import AHardwareBulffer", __func__);
const native_handle_t *handle =
AHardwareBuffer_getNativeHandle(ahw);
- const cb_handle_t* cb_handle = cb_handle_t::from_native_handle(handle);
+ const cb_handle_t* cb_handle = cb_handle_t::from(handle);
importCbInfo.colorBuffer = cb_handle->hostHandle;
vk_append_struct(&structChainIter, &importCbInfo);
}
@@ -3463,9 +3463,7 @@
return;
}
- const cb_handle_t* cb_handle =
- cb_handle_t::from_raw_pointer(nativeInfo->handle);
-
+ const cb_handle_t* cb_handle = cb_handle_t::from(nativeInfo->handle);
if (!cb_handle) return;
VkNativeBufferANDROID* nativeInfoOut =
diff --git a/system/vulkan_enc/vk_format_info.h b/system/vulkan_enc/vk_format_info.h
index 8c0b7dc..c517cb1 100644
--- a/system/vulkan_enc/vk_format_info.h
+++ b/system/vulkan_enc/vk_format_info.h
@@ -27,6 +27,7 @@
#define VK_FORMAT_INFO_H
#include <stdbool.h>
+#include <system/graphics.h>
#include <vulkan/vulkan.h>
#include <vndk/hardware_buffer.h>
diff --git a/system/vulkan_enc/vulkan_enc_unittests.cpp b/system/vulkan_enc/vulkan_enc_unittests.cpp
index 920550a..744ea31 100644
--- a/system/vulkan_enc/vulkan_enc_unittests.cpp
+++ b/system/vulkan_enc/vulkan_enc_unittests.cpp
@@ -95,6 +95,9 @@
p.waitAny(handle, -1);
EXPECT_GE(x, 1);
+
+ // Prevent use after scope after test finish
+ p.waitAll(handle);
}
// Tests waitAll primitive; each worker increments the atomic int once,