Revert "Remove NativeWindow and unused DVR functions"
This reverts commit a001af5ae07e156f9c31dcdb24fb7ddead4d9f1e.
Change-Id: Ieb60bc8e8e7caefee30b0fbd13cda15298c32075
diff --git a/libs/vr/libdisplay/Android.mk b/libs/vr/libdisplay/Android.mk
index 05e1bab..6a9458c 100644
--- a/libs/vr/libdisplay/Android.mk
+++ b/libs/vr/libdisplay/Android.mk
@@ -15,6 +15,7 @@
LOCAL_PATH := $(call my-dir)
sourceFiles := \
+ native_window.cpp \
native_buffer_queue.cpp \
display_client.cpp \
display_manager_client.cpp \
diff --git a/libs/vr/libdisplay/graphics.cpp b/libs/vr/libdisplay/graphics.cpp
index 61f6fea..d0557a9 100644
--- a/libs/vr/libdisplay/graphics.cpp
+++ b/libs/vr/libdisplay/graphics.cpp
@@ -483,6 +483,25 @@
return 0;
}
+extern "C" int dvrGetDisplaySurfaceInfo(EGLNativeWindowType win, int* width,
+ int* height, int* format) {
+ ANativeWindow* nwin = reinterpret_cast<ANativeWindow*>(win);
+ int w, h, f;
+
+ nwin->query(nwin, NATIVE_WINDOW_DEFAULT_WIDTH, &w);
+ nwin->query(nwin, NATIVE_WINDOW_DEFAULT_HEIGHT, &h);
+ nwin->query(nwin, NATIVE_WINDOW_FORMAT, &f);
+
+ if (width)
+ *width = w;
+ if (height)
+ *height = h;
+ if (format)
+ *format = f;
+
+ return 0;
+}
+
struct DvrGraphicsContext : public android::ANativeObjectBase<
ANativeWindow, DvrGraphicsContext,
android::LightRefBase<DvrGraphicsContext>> {
diff --git a/libs/vr/libdisplay/include/dvr/graphics.h b/libs/vr/libdisplay/include/dvr/graphics.h
index 19deec3..50d2754 100644
--- a/libs/vr/libdisplay/include/dvr/graphics.h
+++ b/libs/vr/libdisplay/include/dvr/graphics.h
@@ -21,6 +21,11 @@
__BEGIN_DECLS
+// Create a stereo surface that will be lens-warped by the system.
+EGLNativeWindowType dvrCreateWarpedDisplaySurface(int* display_width,
+ int* display_height);
+EGLNativeWindowType dvrCreateDisplaySurface(void);
+
// Display surface parameters used to specify display surface options.
enum {
DVR_SURFACE_PARAMETER_NONE = 0,
@@ -158,16 +163,9 @@
float right_fov[4];
};
-int dvrGetNativeDisplayDimensions(int* native_width, int* native_height);
-
-// Opaque struct that represents a graphics context, the texture swap chain,
-// and surfaces.
-typedef struct DvrGraphicsContext DvrGraphicsContext;
-
-// Create the graphics context. with the given parameters. The list of
-// parameters is terminated with an entry where key ==
-// DVR_SURFACE_PARAMETER_NONE. For example, the parameters array could be built
-// as follows:
+// Creates a display surface with the given parameters. The list of parameters
+// is terminated with an entry where key == DVR_SURFACE_PARAMETER_NONE.
+// For example, the parameters array could be built as follows:
// int display_width = 0, display_height = 0;
// int surface_width = 0, surface_height = 0;
// float inter_lens_meters = 0.0f;
@@ -185,6 +183,38 @@
// DVR_SURFACE_PARAMETER_OUT(RIGHT_FOV_LRBT, right_fov),
// DVR_SURFACE_PARAMETER_LIST_END,
// };
+EGLNativeWindowType dvrCreateDisplaySurfaceExtended(
+ struct DvrSurfaceParameter* parameters);
+
+int dvrGetNativeDisplayDimensions(int* native_width, int* native_height);
+
+int dvrGetDisplaySurfaceInfo(EGLNativeWindowType win, int* width, int* height,
+ int* format);
+
+// NOTE: Only call the functions below on windows created with the API above.
+
+// Sets the display surface visible based on the boolean evaluation of
+// |visible|.
+void dvrDisplaySurfaceSetVisible(EGLNativeWindowType window, int visible);
+
+// Sets the application z-order of the display surface. Higher values display on
+// top of lower values.
+void dvrDisplaySurfaceSetZOrder(EGLNativeWindowType window, int z_order);
+
+// Post the next buffer early. This allows the application to race with either
+// the async EDS process or the scanline for applications that are not using
+// system distortion. When this is called, the next buffer in the queue is
+// posted for display. It is up to the application to kick its GPU rendering
+// work in time. If the rendering is incomplete there will be significant,
+// undesirable tearing artifacts.
+// It is not recommended to use this feature with system distortion.
+void dvrDisplayPostEarly(EGLNativeWindowType window);
+
+// Opaque struct that represents a graphics context, the texture swap chain,
+// and surfaces.
+typedef struct DvrGraphicsContext DvrGraphicsContext;
+
+// Create the graphics context.
int dvrGraphicsContextCreate(struct DvrSurfaceParameter* parameters,
DvrGraphicsContext** return_graphics_context);
diff --git a/libs/vr/libdisplay/native_window.cpp b/libs/vr/libdisplay/native_window.cpp
new file mode 100644
index 0000000..24ecd8a
--- /dev/null
+++ b/libs/vr/libdisplay/native_window.cpp
@@ -0,0 +1,458 @@
+#include <EGL/egl.h>
+
+#include <android/native_window.h>
+#include <cutils/native_handle.h>
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/timerfd.h>
+#include <system/window.h>
+#include <time.h>
+#include <ui/ANativeObjectBase.h>
+#include <utils/Errors.h>
+
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#include <utils/Trace.h>
+
+#include <log/log.h>
+
+#include <memory>
+#include <mutex>
+
+#include <dvr/graphics.h>
+#include <private/dvr/clock_ns.h>
+#include <private/dvr/display_client.h>
+#include <private/dvr/native_buffer.h>
+#include <private/dvr/native_buffer_queue.h>
+
+namespace {
+
+constexpr int kDefaultDisplaySurfaceUsage =
+ GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
+constexpr int kDefaultDisplaySurfaceFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+constexpr int kWarpedDisplaySurfaceFlags = 0;
+constexpr int kUnwarpedDisplaySurfaceFlags =
+ DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_EDS |
+ DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION |
+ DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_CAC;
+constexpr int kDefaultBufferCount = 4;
+
+} // anonymous namespace
+
+namespace android {
+namespace dvr {
+
+// NativeWindow is an implementation of ANativeWindow. This class interacts with
+// displayd through the DisplaySurfaceClient and NativeBufferQueue.
+class NativeWindow : public ANativeObjectBase<ANativeWindow, NativeWindow,
+ LightRefBase<NativeWindow> > {
+ public:
+ explicit NativeWindow(const std::shared_ptr<DisplaySurfaceClient>& surface);
+
+ void SetVisible(bool visible);
+ void SetZOrder(int z_order);
+ void PostEarly();
+
+ private:
+ friend class LightRefBase<NativeWindow>;
+
+ void Post(sp<NativeBufferProducer> buffer, int fence_fd);
+
+ static int SetSwapInterval(ANativeWindow* window, int interval);
+ static int DequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer,
+ int* fence_fd);
+ static int QueueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer,
+ int fence_fd);
+ static int CancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer,
+ int fence_fd);
+ static int Query(const ANativeWindow* window, int what, int* value);
+ static int Perform(ANativeWindow* window, int operation, ...);
+
+ static int DequeueBuffer_DEPRECATED(ANativeWindow* window,
+ ANativeWindowBuffer** buffer);
+ static int CancelBuffer_DEPRECATED(ANativeWindow* window,
+ ANativeWindowBuffer* buffer);
+ static int QueueBuffer_DEPRECATED(ANativeWindow* window,
+ ANativeWindowBuffer* buffer);
+ static int LockBuffer_DEPRECATED(ANativeWindow* window,
+ ANativeWindowBuffer* buffer);
+
+ std::shared_ptr<DisplaySurfaceClient> surface_;
+
+ std::mutex lock_;
+ NativeBufferQueue buffer_queue_;
+ sp<NativeBufferProducer> next_post_buffer_;
+ bool next_buffer_already_posted_;
+
+ NativeWindow(const NativeWindow&) = delete;
+ void operator=(NativeWindow&) = delete;
+};
+
+NativeWindow::NativeWindow(const std::shared_ptr<DisplaySurfaceClient>& surface)
+ : surface_(surface),
+ buffer_queue_(surface, kDefaultBufferCount),
+ next_post_buffer_(nullptr),
+ next_buffer_already_posted_(false) {
+ ANativeWindow::setSwapInterval = SetSwapInterval;
+ ANativeWindow::dequeueBuffer = DequeueBuffer;
+ ANativeWindow::cancelBuffer = CancelBuffer;
+ ANativeWindow::queueBuffer = QueueBuffer;
+ ANativeWindow::query = Query;
+ ANativeWindow::perform = Perform;
+
+ ANativeWindow::dequeueBuffer_DEPRECATED = DequeueBuffer_DEPRECATED;
+ ANativeWindow::cancelBuffer_DEPRECATED = CancelBuffer_DEPRECATED;
+ ANativeWindow::lockBuffer_DEPRECATED = LockBuffer_DEPRECATED;
+ ANativeWindow::queueBuffer_DEPRECATED = QueueBuffer_DEPRECATED;
+}
+
+void NativeWindow::SetVisible(bool visible) { surface_->SetVisible(visible); }
+
+void NativeWindow::SetZOrder(int z_order) { surface_->SetZOrder(z_order); }
+
+void NativeWindow::PostEarly() {
+ ATRACE_NAME("NativeWindow::PostEarly");
+ ALOGI_IF(TRACE, "NativeWindow::PostEarly");
+
+ std::lock_guard<std::mutex> autolock(lock_);
+
+ if (!next_buffer_already_posted_) {
+ next_buffer_already_posted_ = true;
+
+ if (!next_post_buffer_.get()) {
+ next_post_buffer_ = buffer_queue_.Dequeue();
+ }
+ ATRACE_ASYNC_BEGIN("BufferPost", next_post_buffer_->buffer()->id());
+ Post(next_post_buffer_, -1);
+ }
+}
+
+void NativeWindow::Post(sp<NativeBufferProducer> buffer, int fence_fd) {
+ ATRACE_NAME(__PRETTY_FUNCTION__);
+ ALOGI_IF(TRACE, "NativeWindow::Post: buffer_id=%d, fence_fd=%d",
+ buffer->buffer()->id(), fence_fd);
+ ALOGW_IF(!surface_->visible(),
+ "NativeWindow::Post: Posting buffer on invisible surface!!!");
+ buffer->Post(fence_fd, 0);
+}
+
+int NativeWindow::SetSwapInterval(ANativeWindow* window, int interval) {
+ ALOGI_IF(TRACE, "SetSwapInterval: window=%p interval=%d", window, interval);
+ return 0;
+}
+
+int NativeWindow::DequeueBuffer(ANativeWindow* window,
+ ANativeWindowBuffer** buffer, int* fence_fd) {
+ ATRACE_NAME(__PRETTY_FUNCTION__);
+
+ NativeWindow* self = getSelf(window);
+ std::lock_guard<std::mutex> autolock(self->lock_);
+
+ if (!self->next_post_buffer_.get()) {
+ self->next_post_buffer_ = self->buffer_queue_.Dequeue();
+ }
+ ATRACE_ASYNC_BEGIN("BufferDraw", self->next_post_buffer_->buffer()->id());
+ *fence_fd = self->next_post_buffer_->ClaimReleaseFence().Release();
+ *buffer = self->next_post_buffer_.get();
+
+ ALOGI_IF(TRACE, "NativeWindow::DequeueBuffer: fence_fd=%d", *fence_fd);
+ return 0;
+}
+
+int NativeWindow::QueueBuffer(ANativeWindow* window,
+ ANativeWindowBuffer* buffer, int fence_fd) {
+ ATRACE_NAME("NativeWindow::QueueBuffer");
+ ALOGI_IF(TRACE, "NativeWindow::QueueBuffer: fence_fd=%d", fence_fd);
+
+ NativeWindow* self = getSelf(window);
+ std::lock_guard<std::mutex> autolock(self->lock_);
+
+ NativeBufferProducer* native_buffer =
+ static_cast<NativeBufferProducer*>(buffer);
+ ATRACE_ASYNC_END("BufferDraw", native_buffer->buffer()->id());
+ bool do_post = true;
+ if (self->next_buffer_already_posted_) {
+ // Check that the buffer is the one we expect, but handle it if this happens
+ // in production by allowing this buffer to post on top of the previous one.
+ LOG_FATAL_IF(native_buffer != self->next_post_buffer_.get());
+ if (native_buffer == self->next_post_buffer_.get()) {
+ do_post = false;
+ if (fence_fd >= 0)
+ close(fence_fd);
+ }
+ }
+ if (do_post) {
+ ATRACE_ASYNC_BEGIN("BufferPost", native_buffer->buffer()->id());
+ self->Post(native_buffer, fence_fd);
+ }
+ self->next_buffer_already_posted_ = false;
+ self->next_post_buffer_ = nullptr;
+
+ return NO_ERROR;
+}
+
+int NativeWindow::CancelBuffer(ANativeWindow* window,
+ ANativeWindowBuffer* buffer, int fence_fd) {
+ ATRACE_NAME("NativeWindow::CancelBuffer");
+ ALOGI_IF(TRACE, "NativeWindow::CancelBuffer: fence_fd: %d", fence_fd);
+
+ NativeWindow* self = getSelf(window);
+ std::lock_guard<std::mutex> autolock(self->lock_);
+
+ NativeBufferProducer* native_buffer =
+ static_cast<NativeBufferProducer*>(buffer);
+ ATRACE_ASYNC_END("BufferDraw", native_buffer->buffer()->id());
+ ATRACE_INT("CancelBuffer", native_buffer->buffer()->id());
+ bool do_enqueue = true;
+ if (self->next_buffer_already_posted_) {
+ // Check that the buffer is the one we expect, but handle it if this happens
+ // in production by returning this buffer to the buffer queue.
+ LOG_FATAL_IF(native_buffer != self->next_post_buffer_.get());
+ if (native_buffer == self->next_post_buffer_.get()) {
+ do_enqueue = false;
+ }
+ }
+ if (do_enqueue) {
+ self->buffer_queue_.Enqueue(native_buffer);
+ }
+ if (fence_fd >= 0)
+ close(fence_fd);
+ self->next_buffer_already_posted_ = false;
+ self->next_post_buffer_ = nullptr;
+
+ return NO_ERROR;
+}
+
+int NativeWindow::Query(const ANativeWindow* window, int what, int* value) {
+ NativeWindow* self = getSelf(const_cast<ANativeWindow*>(window));
+ std::lock_guard<std::mutex> autolock(self->lock_);
+
+ switch (what) {
+ case NATIVE_WINDOW_WIDTH:
+ *value = self->surface_->width();
+ return NO_ERROR;
+ case NATIVE_WINDOW_HEIGHT:
+ *value = self->surface_->height();
+ return NO_ERROR;
+ case NATIVE_WINDOW_FORMAT:
+ *value = self->surface_->format();
+ return NO_ERROR;
+ case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
+ *value = 1;
+ return NO_ERROR;
+ case NATIVE_WINDOW_CONCRETE_TYPE:
+ *value = NATIVE_WINDOW_SURFACE;
+ return NO_ERROR;
+ case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
+ *value = 1;
+ return NO_ERROR;
+ case NATIVE_WINDOW_DEFAULT_WIDTH:
+ *value = self->surface_->width();
+ return NO_ERROR;
+ case NATIVE_WINDOW_DEFAULT_HEIGHT:
+ *value = self->surface_->height();
+ return NO_ERROR;
+ case NATIVE_WINDOW_TRANSFORM_HINT:
+ *value = 0;
+ return NO_ERROR;
+ }
+
+ *value = 0;
+ return BAD_VALUE;
+}
+
+int NativeWindow::Perform(ANativeWindow* window, int operation, ...) {
+ NativeWindow* self = getSelf(window);
+ std::lock_guard<std::mutex> autolock(self->lock_);
+
+ va_list args;
+ va_start(args, operation);
+
+ // TODO(eieio): The following operations are not used at this time. They are
+ // included here to help document which operations may be useful and what
+ // parameters they take.
+ switch (operation) {
+ case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS: {
+ int w = va_arg(args, int);
+ int h = va_arg(args, int);
+ ALOGD_IF(TRACE, "NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS: w=%d h=%d", w, h);
+ return NO_ERROR;
+ }
+
+ case NATIVE_WINDOW_SET_BUFFERS_FORMAT: {
+ int format = va_arg(args, int);
+ ALOGD_IF(TRACE, "NATIVE_WINDOW_SET_BUFFERS_FORMAT: format=%d", format);
+ return NO_ERROR;
+ }
+
+ case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM: {
+ int transform = va_arg(args, int);
+ ALOGD_IF(TRACE, "NATIVE_WINDOW_SET_BUFFERS_TRANSFORM: transform=%d",
+ transform);
+ return NO_ERROR;
+ }
+
+ case NATIVE_WINDOW_SET_USAGE: {
+ int usage = va_arg(args, int);
+ ALOGD_IF(TRACE, "NATIVE_WINDOW_SET_USAGE: usage=%d", usage);
+ return NO_ERROR;
+ }
+
+ case NATIVE_WINDOW_CONNECT:
+ case NATIVE_WINDOW_DISCONNECT:
+ case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
+ case NATIVE_WINDOW_API_CONNECT:
+ case NATIVE_WINDOW_API_DISCONNECT:
+ // TODO(eieio): we should implement these
+ return NO_ERROR;
+
+ case NATIVE_WINDOW_SET_BUFFER_COUNT: {
+ int buffer_count = va_arg(args, int);
+ ALOGD_IF(TRACE, "NATIVE_WINDOW_SET_BUFFER_COUNT: bufferCount=%d",
+ buffer_count);
+ return NO_ERROR;
+ }
+ case NATIVE_WINDOW_SET_BUFFERS_DATASPACE: {
+ android_dataspace_t data_space =
+ static_cast<android_dataspace_t>(va_arg(args, int));
+ ALOGD_IF(TRACE, "NATIVE_WINDOW_SET_BUFFERS_DATASPACE: dataSpace=%d",
+ data_space);
+ return NO_ERROR;
+ }
+ case NATIVE_WINDOW_SET_SCALING_MODE: {
+ int mode = va_arg(args, int);
+ ALOGD_IF(TRACE, "NATIVE_WINDOW_SET_SCALING_MODE: mode=%d", mode);
+ return NO_ERROR;
+ }
+
+ case NATIVE_WINDOW_LOCK:
+ case NATIVE_WINDOW_UNLOCK_AND_POST:
+ case NATIVE_WINDOW_SET_CROP:
+ case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
+ return INVALID_OPERATION;
+ }
+
+ return NAME_NOT_FOUND;
+}
+
+int NativeWindow::DequeueBuffer_DEPRECATED(ANativeWindow* window,
+ ANativeWindowBuffer** buffer) {
+ int fence_fd = -1;
+ int ret = DequeueBuffer(window, buffer, &fence_fd);
+
+ // wait for fence
+ if (ret == NO_ERROR && fence_fd != -1)
+ close(fence_fd);
+
+ return ret;
+}
+
+int NativeWindow::CancelBuffer_DEPRECATED(ANativeWindow* window,
+ ANativeWindowBuffer* buffer) {
+ return CancelBuffer(window, buffer, -1);
+}
+
+int NativeWindow::QueueBuffer_DEPRECATED(ANativeWindow* window,
+ ANativeWindowBuffer* buffer) {
+ return QueueBuffer(window, buffer, -1);
+}
+
+int NativeWindow::LockBuffer_DEPRECATED(ANativeWindow* /*window*/,
+ ANativeWindowBuffer* /*buffer*/) {
+ return NO_ERROR;
+}
+
+} // namespace dvr
+} // namespace android
+
+static EGLNativeWindowType CreateDisplaySurface(int* display_width,
+ int* display_height, int format,
+ int usage, int flags) {
+ auto client = android::dvr::DisplayClient::Create();
+ if (!client) {
+ ALOGE("Failed to create display client!");
+ return nullptr;
+ }
+
+ // TODO(eieio,jbates): Consider passing flags and other parameters to get
+ // metrics based on specific surface requirements.
+ android::dvr::SystemDisplayMetrics metrics;
+ const int ret = client->GetDisplayMetrics(&metrics);
+ if (ret < 0) {
+ ALOGE("Failed to get display metrics: %s", strerror(-ret));
+ return nullptr;
+ }
+
+ int width, height;
+
+ if (flags & DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION) {
+ width = metrics.display_native_width;
+ height = metrics.display_native_height;
+ } else {
+ width = metrics.distorted_width;
+ height = metrics.distorted_height;
+ }
+
+ std::shared_ptr<android::dvr::DisplaySurfaceClient> surface =
+ client->CreateDisplaySurface(width, height, format, usage, flags);
+
+ if (display_width)
+ *display_width = metrics.display_native_width;
+ if (display_height)
+ *display_height = metrics.display_native_height;
+
+ // Set the surface visible by default.
+ // TODO(eieio,jbates): Remove this from here and set visible somewhere closer
+ // to the application to account for situations where the application wants to
+ // create surfaces that will be used later or shouldn't be visible yet.
+ surface->SetVisible(true);
+
+ return new android::dvr::NativeWindow(surface);
+}
+
+std::shared_ptr<android::dvr::DisplaySurfaceClient> CreateDisplaySurfaceClient(
+ struct DvrSurfaceParameter* parameters,
+ /*out*/ android::dvr::SystemDisplayMetrics* metrics);
+
+extern "C" EGLNativeWindowType dvrCreateDisplaySurfaceExtended(
+ struct DvrSurfaceParameter* parameters) {
+ android::dvr::SystemDisplayMetrics metrics;
+ auto surface = CreateDisplaySurfaceClient(parameters, &metrics);
+ if (!surface) {
+ ALOGE("Failed to create display surface client");
+ return nullptr;
+ }
+ return new android::dvr::NativeWindow(surface);
+}
+
+extern "C" EGLNativeWindowType dvrCreateDisplaySurface() {
+ return CreateDisplaySurface(NULL, NULL, kDefaultDisplaySurfaceFormat,
+ kDefaultDisplaySurfaceUsage,
+ kUnwarpedDisplaySurfaceFlags);
+}
+
+extern "C" EGLNativeWindowType dvrCreateWarpedDisplaySurface(
+ int* display_width, int* display_height) {
+ return CreateDisplaySurface(
+ display_width, display_height, kDefaultDisplaySurfaceFormat,
+ kDefaultDisplaySurfaceUsage, kWarpedDisplaySurfaceFlags);
+}
+
+extern "C" void dvrDisplaySurfaceSetVisible(EGLNativeWindowType window,
+ int visible) {
+ auto native_window = reinterpret_cast<android::dvr::NativeWindow*>(window);
+ native_window->SetVisible(visible);
+}
+
+extern "C" void dvrDisplaySurfaceSetZOrder(EGLNativeWindowType window,
+ int z_order) {
+ auto native_window = reinterpret_cast<android::dvr::NativeWindow*>(window);
+ native_window->SetZOrder(z_order);
+}
+
+extern "C" void dvrDisplayPostEarly(EGLNativeWindowType window) {
+ auto native_window = reinterpret_cast<android::dvr::NativeWindow*>(window);
+ native_window->PostEarly();
+}
diff --git a/libs/vr/libdisplay/native_window_test.cpp b/libs/vr/libdisplay/native_window_test.cpp
new file mode 100644
index 0000000..2f3bc33
--- /dev/null
+++ b/libs/vr/libdisplay/native_window_test.cpp
@@ -0,0 +1,43 @@
+#include <iostream>
+#include <memory>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <dvr/graphics.h>
+#include <private/dvr/display_client.h>
+
+#include <cpp_free_mock/cpp_free_mock.h>
+
+// Checks querying the VSync of the device on display surface creation.
+TEST(CreateDisplaySurface, QueryVSyncPeriod) {
+ using ::testing::_;
+
+ const uint64_t kExpectedVSync = 123456;
+
+ // We only care about the expected VSync value
+ android::dvr::DisplayMetrics metrics;
+ metrics.vsync_period_ns = kExpectedVSync;
+
+ uint64_t outPeriod;
+
+ DvrSurfaceParameter display_params[] = {
+ DVR_SURFACE_PARAMETER_IN(WIDTH, 256),
+ DVR_SURFACE_PARAMETER_IN(HEIGHT, 256),
+ DVR_SURFACE_PARAMETER_OUT(VSYNC_PERIOD, &outPeriod),
+ DVR_SURFACE_PARAMETER_LIST_END,
+ };
+
+ // inject the mocking code to the target method
+ auto mocked_function =
+ MOCKER(&android::dvr::DisplayClient::GetDisplayMetrics);
+
+ // instrument the mock function to return our custom metrics
+ EXPECT_CALL(*mocked_function, MOCK_FUNCTION(_, _))
+ .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(metrics),
+ ::testing::Return(0)));
+
+ ASSERT_NE(nullptr, dvrCreateDisplaySurfaceExtended(display_params));
+
+ EXPECT_EQ(kExpectedVSync, outPeriod);
+}
diff --git a/libs/vr/libdisplay/tests/graphics_app_tests.cpp b/libs/vr/libdisplay/tests/graphics_app_tests.cpp
index f51dd8a..7ea3952 100644
--- a/libs/vr/libdisplay/tests/graphics_app_tests.cpp
+++ b/libs/vr/libdisplay/tests/graphics_app_tests.cpp
@@ -1,6 +1,55 @@
#include <dvr/graphics.h>
#include <gtest/gtest.h>
+TEST(GraphicsAppTests, CreateWarpedDisplaySurfaceParams) {
+ int width = 0, height = 0;
+ EGLNativeWindowType window = dvrCreateWarpedDisplaySurface(&width, &height);
+ EXPECT_GT(width, 0);
+ EXPECT_GT(height, 0);
+ EXPECT_NE(window, nullptr);
+}
+
+TEST(GraphicsAppTests, CreateDisplaySurface) {
+ EGLNativeWindowType window = dvrCreateDisplaySurface();
+ EXPECT_NE(window, nullptr);
+}
+
+TEST(GraphicsAppTests, CreateDisplaySurfaceExtended) {
+ int display_width = 0, display_height = 0;
+ int surface_width = 0, surface_height = 0;
+ float inter_lens_meters = 0.0f;
+ float left_fov[4] = {0.0f};
+ float right_fov[4] = {0.0f};
+ int disable_warp = 0;
+ DvrSurfaceParameter surface_params[] = {
+ DVR_SURFACE_PARAMETER_IN(DISABLE_DISTORTION, disable_warp),
+ DVR_SURFACE_PARAMETER_OUT(DISPLAY_WIDTH, &display_width),
+ DVR_SURFACE_PARAMETER_OUT(DISPLAY_HEIGHT, &display_height),
+ DVR_SURFACE_PARAMETER_OUT(SURFACE_WIDTH, &surface_width),
+ DVR_SURFACE_PARAMETER_OUT(SURFACE_HEIGHT, &surface_height),
+ DVR_SURFACE_PARAMETER_OUT(INTER_LENS_METERS, &inter_lens_meters),
+ DVR_SURFACE_PARAMETER_OUT(LEFT_FOV_LRBT, left_fov),
+ DVR_SURFACE_PARAMETER_OUT(RIGHT_FOV_LRBT, right_fov),
+ DVR_SURFACE_PARAMETER_LIST_END,
+ };
+
+ EGLNativeWindowType window = dvrCreateDisplaySurfaceExtended(surface_params);
+ EXPECT_NE(window, nullptr);
+ EXPECT_GT(display_width, 0);
+ EXPECT_GT(display_height, 0);
+ EXPECT_GT(surface_width, 0);
+ EXPECT_GT(surface_height, 0);
+ EXPECT_GT(inter_lens_meters, 0);
+ EXPECT_GT(left_fov[0], 0);
+ EXPECT_GT(left_fov[1], 0);
+ EXPECT_GT(left_fov[2], 0);
+ EXPECT_GT(left_fov[3], 0);
+ EXPECT_GT(right_fov[0], 0);
+ EXPECT_GT(right_fov[1], 0);
+ EXPECT_GT(right_fov[2], 0);
+ EXPECT_GT(right_fov[3], 0);
+}
+
TEST(GraphicsAppTests, GetNativeDisplayDimensions) {
int width, height;
dvrGetNativeDisplayDimensions(&width, &height);
@@ -8,6 +57,17 @@
EXPECT_GT(height, 0);
}
+TEST(GraphicsAppTests, GetDisplaySurfaceInfo) {
+ int ret, width, height, format;
+ EGLNativeWindowType window = dvrCreateDisplaySurface();
+ ASSERT_NE(window, nullptr);
+ ret = dvrGetDisplaySurfaceInfo(window, &width, &height, &format);
+ ASSERT_EQ(0, ret);
+ ASSERT_GT(width, 0);
+ ASSERT_GT(height, 0);
+ ASSERT_NE(0, format);
+}
+
// TODO(jpoichet) How to check it worked?
TEST(GraphicsAppTests, GraphicsSurfaceSetVisible) {
DvrSurfaceParameter surface_params[] = {DVR_SURFACE_PARAMETER_LIST_END};