blob: 5eb6e3daa9b7c71132ca091514073e5afb399be8 [file] [log] [blame]
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08001#define LOG_TAG "libgvr_shim"
2
3#include <EGL/egl.h>
4#include <EGL/eglext.h>
5#include <GLES2/gl2.h>
6#include <GLES2/gl2ext.h>
7#include <GLES3/gl31.h>
8#include <GLES3/gl3ext.h>
9#include <algorithm>
10#include <cmath>
11
12#ifdef __ARM_NEON
13#include <arm_neon.h>
14#else
15#ifndef __FLOAT32X4T_86
16#define __FLOAT32X4T_86
17typedef float float32x4_t __attribute__ ((__vector_size__ (16)));
18typedef struct float32x4x4_t { float32x4_t val[4]; };
19#endif
20#endif
21
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080022#include <dvr/graphics.h>
23#include <dvr/performance_client_api.h>
24#include <dvr/pose_client.h>
Alex Vakulenko4fe60582017-02-02 11:35:59 -080025#include <log/log.h>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080026#include <private/dvr/buffer_hub_queue_core.h>
27#include <private/dvr/buffer_hub_queue_producer.h>
28#include <private/dvr/clock_ns.h>
29#include <private/dvr/display_client.h>
30#include <private/dvr/graphics_private.h>
31#include <private/dvr/internal_types.h>
32#include <private/dvr/numeric.h>
33#include <private/dvr/types.h>
34#include <private/dvr/video_mesh_surface_client.h>
35#include <sys/system_properties.h>
36#include <vr/gvr/capi/include/gvr.h>
37#include <vr/gvr/capi/include/gvr_ext.h>
38#include <vr/gvr/capi/include/gvr_util.h>
39#include <vr/gvr/capi/src/gvr_experimental.h>
40#include <vr/gvr/capi/src/gvr_private.h>
41
42#include <android_runtime/android_view_Surface.h>
43#include <gui/Surface.h>
44
45using android::dvr::DisplayClient;
46using android::dvr::EigenToGvrMatrix;
47using android::dvr::FieldOfView;
48using android::dvr::FovRadiansToDegrees;
49using android::dvr::GetSystemClockNs;
50using android::dvr::GvrIdentityMatrix;
51using android::dvr::GvrMatrixToPosef;
52using android::dvr::GvrToDvrFov;
53using android::dvr::GvrToEigenMatrix;
54using android::dvr::GvrToEigenRotation;
55using android::dvr::GvrTranslationMatrix;
56using android::dvr::IsEqual;
57using android::dvr::PosefToGvrMatrix;
58using android::dvr::mat3;
59using android::dvr::mat4;
60using android::dvr::Posef;
61using android::dvr::quat;
62using android::dvr::vec3;
63
64namespace {
65
66constexpr static int32_t GVR_SDK_MAJOR_VERSION = 2;
67constexpr static int32_t GVR_SDK_MINOR_VERSION = 0;
68constexpr static int32_t GVR_SDK_PATCH_VERSION = 0;
69
70// The "DaydreamOS" part has been appended to make easier to see when VrCore
71// dynamic GVR API loading is effectively working.
72static const char* kVersionString = "2.0.0 DaydreamOS";
73static const char* kViewerVendor = "Google";
74static const char* kViewerModel = "Lucid";
75
76// Experimental system property used to provide 6DoF information on 3DoF APIs.
77static const char* kForce6DofProp = "experimental.force_6dof";
78
79static constexpr int kControllerCount = 2;
80
81gvr_frame* GetFrameFromSwapChain(gvr_swap_chain* swap_chain) {
82 return reinterpret_cast<gvr_frame*>(swap_chain);
83}
84
85gvr_swap_chain* GetSwapChainForFrame(gvr_frame* frame) {
86 return reinterpret_cast<gvr_swap_chain*>(frame);
87}
88
89const gvr_swap_chain* GetSwapChainForFrame(const gvr_frame* frame) {
90 return reinterpret_cast<const gvr_swap_chain*>(frame);
91}
92
93// Returns the world to head transform as a Posef.
94Posef ToPosef(const DvrPoseAsync& pose) {
95 return Posef(
96 quat(pose.orientation[3], pose.orientation[0], pose.orientation[1],
97 pose.orientation[2]),
98 vec3(pose.translation[0], pose.translation[1], pose.translation[2]));
99}
100
101// Returns the world to head transform, with 0 position, as a gvr matrix
102gvr_mat4f Gvr6dofTo3dof(const gvr_mat4f& pose) {
103 gvr_mat4f ret = pose;
104 ret.m[0][3] = 0;
105 ret.m[1][3] = 0;
106 ret.m[2][3] = 0;
107 return ret;
108}
109
110void GvrToDvrPose(gvr_mat4f world_to_head_transform,
111 /*out*/ float32x4_t* orientation,
112 /*out */ float32x4_t* translation) {
113 Posef pose = GvrMatrixToPosef(world_to_head_transform);
114 (*orientation)[0] = pose.GetRotation().x();
115 (*orientation)[1] = pose.GetRotation().y();
116 (*orientation)[2] = pose.GetRotation().z();
117 (*orientation)[3] = pose.GetRotation().w();
118 (*translation)[0] = pose.GetPosition().x();
119 (*translation)[1] = pose.GetPosition().y();
120 (*translation)[2] = pose.GetPosition().z();
121 (*translation)[3] = 0;
122}
123
124bool MatricesAlmostEqual(const gvr_mat4f& m1, const gvr_mat4f& m2,
125 float tolerance) {
126 for (int row = 0; row < 4; ++row) {
127 for (int col = 0; col < 4; ++col) {
128 if (!IsEqual(m1.m[row][col], m2.m[row][col], tolerance))
129 return false;
130 }
131 }
132 return true;
133}
134
135gvr_mat4f FovToViewportTransform(const gvr_rectf& fov) {
136 // Depth range (1 1000) is chosen to match gvr impl in google3, which is
137 // chosen to match Unity integration.
138 return EigenToGvrMatrix(
139 GvrToDvrFov(fov).GetProjectionMatrix(1.f, 1000.f).inverse());
140}
141
142gvr_rectf ViewportTransformToFov(const gvr_mat4f& transform) {
143 return DvrToGvrFov(
144 FieldOfView::FromProjectionMatrix(GvrToEigenMatrix(transform).inverse()));
145}
146
147bool GetGlColorFormat(int32_t gvr_color_format,
148 /*out*/ GLenum* gl_color_format) {
149 switch (gvr_color_format) {
150 case GVR_COLOR_FORMAT_RGBA_8888:
151 *gl_color_format = GL_RGBA8;
152 break;
153 case GVR_COLOR_FORMAT_RGB_565:
154 *gl_color_format = GL_RGB565;
155 break;
156 default:
157 return false;
158 }
159 return true;
160}
161
162bool GetGlDepthFormat(int32_t gvr_depth_format,
163 /*out*/ GLenum* gl_depth_format) {
164 switch (gvr_depth_format) {
165 case GVR_DEPTH_STENCIL_FORMAT_DEPTH_16:
166 *gl_depth_format = GL_DEPTH_COMPONENT16;
167 break;
168 case GVR_DEPTH_STENCIL_FORMAT_DEPTH_24:
169 *gl_depth_format = GL_DEPTH_COMPONENT24;
170 break;
171 case GVR_DEPTH_STENCIL_FORMAT_DEPTH_24_STENCIL_8:
172 *gl_depth_format = GL_DEPTH24_STENCIL8;
173 break;
174 case GVR_DEPTH_STENCIL_FORMAT_DEPTH_32_F:
175 *gl_depth_format = GL_DEPTH_COMPONENT32F;
176 break;
177 case GVR_DEPTH_STENCIL_FORMAT_DEPTH_32_F_STENCIL_8:
178 *gl_depth_format = GL_DEPTH32F_STENCIL8;
179 break;
180 default:
181 return false;
182 }
183 return true;
184}
185
186// Returns true on success, false on failure. If the swap_chain already has a
187// DvrGraphicsContext and gvr buffer, they'll be freed first. If creation fails,
188// the DvrGraphicsContext in the swap_chain will be set to null and the
189// corresponding gvr buffer will be freed.
190bool CreateDvrGraphicsContextAndGvrBuffer(gvr_swap_chain* swap_chain) {
191 if (swap_chain->buffers_.empty()) {
192 ALOGE("Can't create a graphics context for an empty swap chain");
193 return false;
194 }
195
196 // We currently only render the first gvr buffer. Create a DvrGraphicsContext
197 // for the first buffer only.
198 gvr_buffer& buf = swap_chain->buffers_[0];
199 buf.FreeGl();
200
201 bool visible;
202 int z_order;
203 if (swap_chain->graphics_context_ != nullptr) {
204 visible = dvrGraphicsSurfaceGetVisible(swap_chain->graphics_context_);
205 z_order = dvrGraphicsSurfaceGetZOrder(swap_chain->graphics_context_);
206 dvrGraphicsContextDestroy(swap_chain->graphics_context_);
207 swap_chain->graphics_context_ = nullptr;
208 } else {
209 visible = buf.spec.initially_visible;
210 z_order = buf.spec.z_order;
211 }
212
213 int width = 0, height = 0;
214 GLuint texture_id = 0;
215 GLenum texture_target = 0;
216 DvrSurfaceParameter surface_params[] = {
217 DVR_SURFACE_PARAMETER_IN(DISABLE_DISTORTION, false),
218 DVR_SURFACE_PARAMETER_IN(CREATE_GL_CONTEXT, 0),
219 DVR_SURFACE_PARAMETER_IN(WIDTH, buf.spec.size.width),
220 DVR_SURFACE_PARAMETER_IN(HEIGHT, buf.spec.size.height),
221 DVR_SURFACE_PARAMETER_IN(BLUR_BEHIND, buf.spec.blur_behind),
222 DVR_SURFACE_PARAMETER_IN(VISIBLE, visible),
223 DVR_SURFACE_PARAMETER_IN(Z_ORDER, z_order),
224 DVR_SURFACE_PARAMETER_OUT(SURFACE_WIDTH, &width),
225 DVR_SURFACE_PARAMETER_OUT(SURFACE_HEIGHT, &height),
226 DVR_SURFACE_PARAMETER_OUT(SURFACE_TEXTURE_TARGET_TYPE, &texture_target),
227 DVR_SURFACE_PARAMETER_OUT(SURFACE_TEXTURE_TARGET_ID, &texture_id),
228 DVR_SURFACE_PARAMETER_LIST_END,
229 };
230
231 DvrGraphicsContext* graphics_context;
232 int ret = dvrGraphicsContextCreate(surface_params, &graphics_context);
233 if (ret < 0) {
234 ALOGE("dvrGraphicsContextCreate failed: %d (%s)", ret, strerror(-ret));
235 gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL);
236 return false;
237 }
238
239 // Sanity check that the size of the buffer we allocated from the system is
240 // what we expect
241 if (buf.spec.size != gvr_sizei{width, height}) {
242 ALOGE(
243 "The created surface is the wrong size."
244 " Should be %dx%d, instead got %dx%d.",
245 buf.spec.size.width, buf.spec.size.height, width, height);
246 gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL);
247 dvrGraphicsContextDestroy(graphics_context);
248 return false;
249 }
250
251 buf = gvr_buffer(swap_chain->context, buf.spec, texture_id, texture_target);
252 if (buf.frame_buffer == 0) {
253 dvrGraphicsContextDestroy(graphics_context);
254 return false;
255 }
256
257 swap_chain->graphics_context_ = graphics_context;
258 return true;
259}
260
261bool SwapChainResizeBuffer(gvr_swap_chain* swap_chain, int buffer_index) {
262 gvr_buffer& buf = swap_chain->buffers_[buffer_index];
263 buf.FreeGl();
264 gvr_sizei orig_size = buf.spec.size;
265 buf.spec.size = buf.requested_size;
266 bool resize_successful = false;
267 if (buffer_index == 0) {
268 resize_successful = CreateDvrGraphicsContextAndGvrBuffer(swap_chain);
269 } else {
270 buf = gvr_buffer(swap_chain->context, buf.spec, 0, GL_TEXTURE_2D);
271 resize_successful = buf.frame_buffer != 0;
272 }
273
274 if (resize_successful) {
275 // The resize was successful, so clear the resize request
276 buf.requested_size = {-1, -1};
277 } else {
278 ALOGE("Failed to resize buffer. orig_size=%dx%d requested_size=%dx%d.",
279 orig_size.width, orig_size.height, buf.requested_size.width,
280 buf.requested_size.height);
281 gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL);
282 buf.spec.size = orig_size;
283 }
284
285 return resize_successful;
286}
287
288void WaitNextFrame(gvr_swap_chain* swap_chain, int64_t start_delay_nanos,
289 gvr_frame_schedule* out_next_frame_schedule,
290 bool called_by_app) {
291 if (called_by_app)
292 swap_chain->wait_next_frame_called_by_app_ = true;
293
294 DvrFrameSchedule dvr_schedule;
295 int ret = dvrGraphicsWaitNextFrame(swap_chain->graphics_context_,
296 start_delay_nanos, &dvr_schedule);
297 if (ret < 0) {
298 gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL);
299 return;
300 }
301 if (out_next_frame_schedule) {
302 out_next_frame_schedule->vsync_count = dvr_schedule.vsync_count;
303 out_next_frame_schedule->scheduled_finish.monotonic_system_time_nanos =
304 dvr_schedule.scheduled_frame_finish_ns;
305 }
306
307 DvrPoseAsync pose;
308 ret = dvrPoseGet(swap_chain->context->pose_client_, dvr_schedule.vsync_count,
309 &pose);
310 if (ret < 0) {
311 ALOGW("dvrPoseGet failed: %d", ret);
312 gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL);
313 return;
314 }
315
316 swap_chain->context->next_frame_6dof_pose_ = PosefToGvrMatrix(ToPosef(pose));
317
318 for (int i = 0; i < kControllerCount; ++i) {
319 ret = dvrPoseGetController(swap_chain->context->pose_client_, i,
320 dvr_schedule.vsync_count, &pose);
321 if (ret == 0) {
322 // Silently fail when there are no controllers.
323 swap_chain->context->next_frame_controller_pose_[i] =
324 PosefToGvrMatrix(ToPosef(pose).Inverse());
325 }
326 }
327}
328
329bool VerifyBufferIndex(const std::string& function_name,
330 const gvr_swap_chain* swap_chain, int index) {
331 if (index > static_cast<int32_t>(swap_chain->buffers_.size())) {
332 ALOGE("%s out of range buffer index. index=%d num_buffers=%zu.",
333 function_name.c_str(), index, swap_chain->buffers_.size());
334 gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL);
335 return false;
336 }
337 return true;
338}
339
340} // anonymous namespace
341
342gvr_context* gvr_create(JNIEnv* env, jobject /* app_context */,
343 jobject /* class_loader */) {
344 std::unique_ptr<gvr_context> context(new gvr_context);
345
346 // Set cpu set to avoid default scheduling randomness.
347 dvrSetCpuPartition(0, "/application/performance");
348
349 context->jni_env_ = env;
350 context->pose_client_ = dvrPoseCreate();
351 if (!context->pose_client_) {
352 ALOGE("Failed to create pose client");
353 return nullptr;
354 }
355
356 context->display_client_ = DisplayClient::Create();
357 if (!context->display_client_) {
358 ALOGE("Failed to create display client");
359 return nullptr;
360 }
361
362 int ret =
363 context->display_client_->GetDisplayMetrics(&context->display_metrics_);
364 if (ret < 0) {
365 ALOGE("Failed to get display metrics: %d (%s)", ret, strerror(-ret));
366 return nullptr;
367 }
368
369 const float* left_fov = context->display_metrics_.left_fov_lrbt.data();
370 context->left_eye_viewport_transform_ =
371 FovToViewportTransform(FovRadiansToDegrees(
372 gvr_rectf{left_fov[0], left_fov[1], left_fov[2], left_fov[3]}));
373
374 const float* right_fov = context->display_metrics_.right_fov_lrbt.data();
375 context->right_eye_viewport_transform_ =
376 FovToViewportTransform(FovRadiansToDegrees(
377 gvr_rectf{right_fov[0], right_fov[1], right_fov[2], right_fov[3]}));
378
379 context->next_frame_6dof_pose_ = GvrIdentityMatrix();
380
381 for (int i = 0; i < kControllerCount; ++i) {
382 context->next_frame_controller_pose_[i] = GvrIdentityMatrix();
383 }
384
385 // Check the system property to force 6DoF when requested 3DoF.
386 char prop_buffer[PROP_VALUE_MAX];
387 if (__system_property_get(kForce6DofProp, prop_buffer) &&
388 (!strncasecmp("1", prop_buffer, PROP_VALUE_MAX) ||
389 !strncasecmp("true", prop_buffer, PROP_VALUE_MAX))) {
390 context->force_6dof_ = true;
391 }
392
393 return context.release();
394}
395
396gvr_version gvr_get_version() {
397 gvr_version version = {};
398 version.major = GVR_SDK_MAJOR_VERSION;
399 version.minor = GVR_SDK_MINOR_VERSION;
400 version.patch = GVR_SDK_PATCH_VERSION;
401 return version;
402}
403
404const char* gvr_get_version_string() { return kVersionString; }
405
406int32_t gvr_get_error(gvr_context* gvr) { return gvr->last_error_; }
407
408int32_t gvr_clear_error(gvr_context* gvr) {
409 int32_t last_error = gvr->last_error_;
410 gvr->last_error_ = GVR_ERROR_NONE;
411 return last_error;
412}
413
414const char* gvr_get_error_string(int32_t error_code) {
415 switch (error_code) {
416 case GVR_ERROR_NONE:
417 return "No error";
418 case GVR_ERROR_CONTROLLER_CREATE_FAILED:
419 return "Creation of GVR controller context failed";
420 case GVR_ERROR_NO_FRAME_AVAILABLE:
421 return "No frame available in swap chain";
422 case GVR_ERROR_INTERNAL:
423 return "Internal error";
424 default:
425 return "(Internal error: unknown error code)";
426 }
427}
428
429const gvr_user_prefs* gvr_get_user_prefs(gvr_context* gvr) {
430 return &gvr->user_prefs_;
431}
432
433int32_t gvr_user_prefs_get_controller_handedness(
434 const gvr_user_prefs* /* user_prefs */) {
435 return GVR_CONTROLLER_RIGHT_HANDED;
436}
437
438gvr_context_::~gvr_context_() {
439 for (gvr_swap_chain* swap_chain : swap_chains_)
440 swap_chain->context = nullptr;
441 if (pose_client_)
442 dvrPoseDestroy(pose_client_);
443}
444
445void gvr_destroy(gvr_context** gvr) {
446 if (!gvr || !(*gvr)) {
447 ALOGW("gvr_destroy: Invalid gvr_context pointer.");
448 return;
449 }
450 delete *gvr;
451 *gvr = nullptr;
452}
453
454void gvr_initialize_gl(gvr_context* /* gvr */) {}
455
456bool gvr_get_async_reprojection_enabled(const gvr_context* /* gvr */) {
457 return true;
458}
459
460void gvr_get_recommended_buffer_viewports(
461 const gvr_context* gvr, gvr_buffer_viewport_list* viewport_list) {
462 gvr_buffer_viewport left(
463 /*buffer_index*/ 0,
464 /*uv*/ {0, .5f, 0, 1}, gvr->left_eye_viewport_transform_, GVR_LEFT_EYE,
465 GVR_EXTERNAL_SURFACE_ID_NONE, GVR_REPROJECTION_FULL);
466
467 gvr_buffer_viewport right(
468 /*buffer_index*/ 0,
469 /*uv*/ {.5f, 1, 0, 1}, gvr->right_eye_viewport_transform_, GVR_RIGHT_EYE,
470 GVR_EXTERNAL_SURFACE_ID_NONE, GVR_REPROJECTION_FULL);
471
472 viewport_list->viewports.resize(2);
473 viewport_list->viewports[0] = left;
474 viewport_list->viewports[1] = right;
475}
476
477void gvr_get_screen_buffer_viewports(const gvr_context* gvr,
478 gvr_buffer_viewport_list* viewport_list) {
479 gvr_get_recommended_buffer_viewports(gvr, viewport_list);
480}
481
482gvr_sizei gvr_get_maximum_effective_render_target_size(const gvr_context* gvr) {
483 return gvr_sizei{
484 static_cast<int32_t>(gvr->display_metrics_.distorted_width),
485 static_cast<int32_t>(gvr->display_metrics_.distorted_height)};
486}
487
488gvr_sizei gvr_get_screen_target_size(const gvr_context* gvr) {
489 // DisplayMetrics returns native_width and native_height for the display in
490 // portrait orientation, which our device is never in. Swap the width and
491 // height to account for this.
492 return gvr_sizei{
493 static_cast<int32_t>(gvr->display_metrics_.display_native_height),
494 static_cast<int32_t>(gvr->display_metrics_.display_native_width)};
495}
496
497void gvr_set_surface_size(gvr_context* gvr,
498 gvr_sizei /* surface_size_pixels */) {
499 // TODO(leandrogracia): this needs to be properly implemented.
500 ALOGE("gvr_set_surface_size not implemented.");
501 gvr_set_error(gvr, GVR_ERROR_INTERNAL);
502}
503
504void gvr_distort_to_screen(
505 gvr_context* gvr, int32_t /* texture_id */,
506 const gvr_buffer_viewport_list* /* viewport_list */,
507 gvr_mat4f /* head_space_from_start_space */,
508 gvr_clock_time_point /* target_presentation_time */) {
509 // TODO(leandrogracia): this needs to be properly implemented.
510 ALOGE("gvr_distort_to_screen not implemented.");
511 gvr_set_error(gvr, GVR_ERROR_INTERNAL);
512}
513
Steven Thomas52690192017-01-30 19:10:26 -0800514bool gvr_is_feature_supported(const gvr_context* /*gvr*/, int32_t feature) {
Steven Thomas07a42a22017-02-01 18:02:10 -0800515 return feature == GVR_FEATURE_ASYNC_REPROJECTION ||
516 feature == GVR_FEATURE_HEAD_POSE_6DOF;
Steven Thomas52690192017-01-30 19:10:26 -0800517}
518
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800519/////////////////////////////////////////////////////////////////////////////
520// Viewports and viewport lists
521/////////////////////////////////////////////////////////////////////////////
522
523bool gvr_buffer_viewport::operator==(const gvr_buffer_viewport_& other) const {
524 return buffer_index == other.buffer_index && uv == other.uv &&
525 eye == other.eye && external_surface_id == other.external_surface_id &&
526 reprojection == other.reprojection &&
527 MatricesAlmostEqual(transform, other.transform, 1e-5f);
528}
529
530gvr_buffer_viewport* gvr_buffer_viewport_create(gvr_context* /* gvr */) {
531 return new gvr_buffer_viewport;
532}
533
534void gvr_buffer_viewport_destroy(gvr_buffer_viewport** viewport) {
535 if (viewport) {
536 delete *viewport;
537 *viewport = nullptr;
538 }
539}
540
541gvr_rectf gvr_buffer_viewport_get_source_uv(
542 const gvr_buffer_viewport* viewport) {
543 return viewport->uv;
544}
545
546void gvr_buffer_viewport_set_source_uv(gvr_buffer_viewport* viewport,
547 gvr_rectf uv) {
548 viewport->uv = uv;
549}
550
551gvr_rectf gvr_buffer_viewport_get_source_fov(
552 const gvr_buffer_viewport* viewport) {
553 return ViewportTransformToFov(viewport->transform);
554}
555
556void gvr_buffer_viewport_set_source_fov(gvr_buffer_viewport* viewport,
557 gvr_rectf fov) {
558 viewport->transform = FovToViewportTransform(fov);
559}
560
561gvr_mat4f gvr_buffer_viewport_get_transform(
562 const gvr_buffer_viewport* viewport) {
563 return viewport->transform;
564}
565
566void gvr_buffer_viewport_set_transform(gvr_buffer_viewport* viewport,
567 gvr_mat4f transform) {
568 viewport->transform = transform;
569}
570
571int32_t gvr_buffer_viewport_get_target_eye(
572 const gvr_buffer_viewport* viewport) {
573 return viewport->eye;
574}
575
576void gvr_buffer_viewport_set_target_eye(gvr_buffer_viewport* viewport,
577 int32_t index) {
578 viewport->eye = index;
579}
580
581int32_t gvr_buffer_viewport_get_source_buffer_index(
582 const gvr_buffer_viewport* viewport) {
583 return viewport->buffer_index;
584}
585
586void gvr_buffer_viewport_set_source_buffer_index(gvr_buffer_viewport* viewport,
587 int32_t buffer_index) {
588 viewport->buffer_index = buffer_index;
589}
590
591int32_t gvr_buffer_viewport_get_external_surface_id(
592 const gvr_buffer_viewport* viewport) {
593 return viewport->external_surface_id;
594}
595
596void gvr_buffer_viewport_set_external_surface_id(gvr_buffer_viewport* viewport,
597 int32_t external_surface_id) {
598 viewport->external_surface_id = external_surface_id;
599}
600
601int32_t gvr_buffer_viewport_get_reprojection(
602 const gvr_buffer_viewport* viewport) {
603 return viewport->reprojection;
604}
605
606void gvr_buffer_viewport_set_reprojection(gvr_buffer_viewport* viewport,
607 int32_t reprojection) {
608 viewport->reprojection = static_cast<gvr_reprojection>(reprojection);
609}
610
611bool gvr_buffer_viewport_equal(const gvr_buffer_viewport* a,
612 const gvr_buffer_viewport* b) {
613 return *a == *b;
614}
615
616gvr_buffer_viewport_list* gvr_buffer_viewport_list_create(
617 const gvr_context* /* gvr */) {
618 return new gvr_buffer_viewport_list;
619}
620
621void gvr_buffer_viewport_list_destroy(
622 gvr_buffer_viewport_list** viewport_list) {
623 if (!viewport_list || !(*viewport_list)) {
624 ALOGW("gvr_buffer_viewport_list_destroy: Invalid list pointer.");
625 return;
626 }
627 delete *viewport_list;
628 *viewport_list = nullptr;
629}
630
631size_t gvr_buffer_viewport_list_get_size(
632 const gvr_buffer_viewport_list* viewport_list) {
633 return viewport_list->viewports.size();
634}
635
636void gvr_buffer_viewport_list_get_item(
637 const gvr_buffer_viewport_list* viewport_list, size_t index,
638 gvr_buffer_viewport* viewport) {
639 *viewport = viewport_list->viewports[index];
640}
641
642void gvr_buffer_viewport_list_set_item(gvr_buffer_viewport_list* viewport_list,
643 size_t index,
644 const gvr_buffer_viewport* viewport) {
645 if (index < viewport_list->viewports.size())
646 viewport_list->viewports[index] = *viewport;
647 else
648 viewport_list->viewports.push_back(*viewport);
649}
650
651/////////////////////////////////////////////////////////////////////////////
652// Swapchains and frames
653/////////////////////////////////////////////////////////////////////////////
654
655gvr_buffer_spec* gvr_buffer_spec_create(gvr_context* /* gvr */) {
656 return new gvr_buffer_spec;
657}
658
659void gvr_buffer_spec_destroy(gvr_buffer_spec** spec) {
660 if (spec) {
661 delete *spec;
662 *spec = nullptr;
663 }
664}
665
666gvr_sizei gvr_buffer_spec_get_size(const gvr_buffer_spec* spec) {
667 return spec->size;
668}
669
670void gvr_buffer_spec_set_size(gvr_buffer_spec* spec, gvr_sizei size) {
671 spec->size = size;
672}
673
674int32_t gvr_buffer_spec_get_samples(const gvr_buffer_spec* spec) {
675 return spec->msaa_samples;
676}
677
678void gvr_buffer_spec_set_samples(gvr_buffer_spec* spec, int32_t num_samples) {
679 spec->msaa_samples = num_samples;
680}
681
682void gvr_buffer_spec_set_color_format(gvr_buffer_spec* spec,
683 int32_t color_format) {
684 spec->color_format = color_format;
685}
686
687void gvr_buffer_spec_set_depth_stencil_format(gvr_buffer_spec* spec,
688 int32_t depth_stencil_format) {
689 spec->depth_stencil_format = depth_stencil_format;
690}
691
692void gvr_buffer_spec_set_z_order(gvr_buffer_spec* spec, int z_order) {
693 spec->z_order = z_order;
694}
695
696void gvr_buffer_spec_set_visibility(gvr_buffer_spec* spec,
697 int32_t visibility) {
698 spec->initially_visible = (visibility != GVR_INVISIBLE);
699}
700
701void gvr_buffer_spec_set_blur_behind(gvr_buffer_spec* spec,
702 int32_t blur_behind) {
703 spec->blur_behind = (blur_behind != GVR_BLUR_BEHIND_FALSE);
704}
705
706void gvr_buffer::SetDefaults() {
707 spec = gvr_buffer_spec();
708 frame_buffer = 0;
709 color_render_buffer = 0;
710 depth_stencil_render_buffer = 0;
711 requested_size = {-1, -1};
712}
713
714gvr_buffer::gvr_buffer() { SetDefaults(); }
715
716gvr_buffer::gvr_buffer(gvr_context* gvr, const gvr_buffer_spec& spec_in,
717 GLuint texture_id, GLenum texture_target) {
718 SetDefaults();
719 spec = spec_in;
720
721 glGetError(); // Clear error state
722 glGenFramebuffers(1, &frame_buffer);
723 glBindFramebuffer(GL_FRAMEBUFFER, frame_buffer);
724
725 if (texture_id == 0) {
726 GLenum gl_color_format;
727 if (!GetGlColorFormat(spec.color_format, &gl_color_format)) {
728 ALOGE("Unknown color format: %d", spec.color_format);
729 gvr_set_error(gvr, GVR_ERROR_INTERNAL);
730 FreeGl();
731 return;
732 }
733
734 glGenRenderbuffers(1, &color_render_buffer);
735 glBindRenderbuffer(GL_RENDERBUFFER, color_render_buffer);
736 if (spec.msaa_samples < 2) {
737 glRenderbufferStorage(GL_RENDERBUFFER, gl_color_format, spec.size.width,
738 spec.size.height);
739 } else {
740 glRenderbufferStorageMultisample(GL_RENDERBUFFER, spec.msaa_samples,
741 gl_color_format, spec.size.width,
742 spec.size.height);
743 }
744 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
745 GL_RENDERBUFFER, color_render_buffer);
746 } else {
747 if (spec.msaa_samples < 2) {
748 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
749 texture_target, texture_id, 0);
750 } else {
751 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
752 texture_target, texture_id, 0,
753 spec.msaa_samples);
754 }
755 }
756
757 if (spec.depth_stencil_format != GVR_DEPTH_STENCIL_FORMAT_NONE) {
758 GLenum gl_depth_format;
759 if (!GetGlDepthFormat(spec.depth_stencil_format, &gl_depth_format)) {
760 ALOGE("Unknown depth/stencil format: %d", spec.depth_stencil_format);
761 gvr_set_error(gvr, GVR_ERROR_INTERNAL);
762 FreeGl();
763 return;
764 }
765
766 glGenRenderbuffers(1, &depth_stencil_render_buffer);
767 glBindRenderbuffer(GL_RENDERBUFFER, depth_stencil_render_buffer);
768 if (spec.msaa_samples < 2) {
769 glRenderbufferStorage(GL_RENDERBUFFER, gl_depth_format, spec.size.width,
770 spec.size.height);
771 } else {
772 glRenderbufferStorageMultisample(GL_RENDERBUFFER, spec.msaa_samples,
773 gl_depth_format, spec.size.width,
774 spec.size.height);
775 }
776 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
777 GL_RENDERBUFFER, depth_stencil_render_buffer);
778 }
779
780 GLenum gl_error = glGetError();
781 if (gl_error != GL_NO_ERROR) {
782 ALOGE("GL error after creating framebuffer: %d", gl_error);
783 gvr_set_error(gvr, GVR_ERROR_INTERNAL);
784 FreeGl();
785 return;
786 }
787
788 GLenum framebuffer_complete_result = glCheckFramebufferStatus(GL_FRAMEBUFFER);
789 if (framebuffer_complete_result != GL_FRAMEBUFFER_COMPLETE) {
790 ALOGE("Framebuffer setup failed. glCheckFramebufferStatus returned %d",
791 framebuffer_complete_result);
792 gvr_set_error(gvr, GVR_ERROR_INTERNAL);
793 FreeGl();
794 return;
795 }
796}
797
798void gvr_buffer::FreeGl() {
799 if (frame_buffer != 0) {
800 glDeleteFramebuffers(1, &frame_buffer);
801 frame_buffer = 0;
802 }
803 if (color_render_buffer != 0) {
804 glDeleteRenderbuffers(1, &color_render_buffer);
805 color_render_buffer = 0;
806 }
807 if (depth_stencil_render_buffer != 0) {
808 glDeleteRenderbuffers(1, &depth_stencil_render_buffer);
809 depth_stencil_render_buffer = 0;
810 }
811}
812
813gvr_buffer::~gvr_buffer() { FreeGl(); }
814
815gvr_buffer::gvr_buffer(gvr_buffer&& other) {
816 spec = other.spec;
817 frame_buffer = other.frame_buffer;
818 color_render_buffer = other.color_render_buffer;
819 depth_stencil_render_buffer = other.depth_stencil_render_buffer;
820 requested_size = other.requested_size;
821 other.SetDefaults();
822}
823
824gvr_buffer& gvr_buffer::operator=(gvr_buffer&& other) {
825 if (this == &other)
826 return *this;
827 spec = other.spec;
828 frame_buffer = other.frame_buffer;
829 color_render_buffer = other.color_render_buffer;
830 depth_stencil_render_buffer = other.depth_stencil_render_buffer;
831 requested_size = other.requested_size;
832 other.SetDefaults();
833 return *this;
834}
835
836gvr_swap_chain* gvr_swap_chain_create(gvr_context* gvr,
837 const gvr_buffer_spec** buffers,
838 int32_t count) {
839 if (count == 0) {
840 ALOGE("At least one buffer must be requested");
841 gvr_set_error(gvr, GVR_ERROR_INTERNAL);
842 return nullptr;
843 }
844
845 // We only support one buffer, but it's common for gvr apps to use more than
846 // one. Print an error to the log if the app requests more than one buffer,
847 // but continue on. We'll only render the first buffer in that case.
848 if (count > 1) {
849 ALOGE(
850 "Only one buffer is supported but the app requested %d."
851 " Only the first buffer will be rendered.",
852 count);
853 }
854
855 std::unique_ptr<gvr_swap_chain> swap_chain(new gvr_swap_chain(gvr));
856
857 // The first buffer gets a DvrGraphicsContext, which contains the surface we
858 // pass to displayd for rendering.
859 swap_chain->buffers_.push_back(gvr_buffer());
860 swap_chain->buffers_.back().spec = *buffers[0];
861 if (!CreateDvrGraphicsContextAndGvrBuffer(swap_chain.get()))
862 return nullptr;
863
864 // The rest of the buffers, which we don't render for now, get color render
865 // buffers.
866 for (int i = 1; i < count; ++i) {
867 swap_chain->buffers_.push_back(
868 gvr_buffer(gvr, *buffers[i], 0, GL_TEXTURE_2D));
869 if (swap_chain->buffers_.back().frame_buffer == 0)
870 return nullptr;
871 }
872
873 gvr->swap_chains_.push_back(swap_chain.get());
874 return swap_chain.release();
875}
876
877gvr_swap_chain_::~gvr_swap_chain_() {
878 if (context) {
879 auto iter = std::find(std::begin(context->swap_chains_),
880 std::end(context->swap_chains_), this);
881 if (iter != context->swap_chains_.end())
882 context->swap_chains_.erase(iter);
883 }
884 buffers_.clear();
885 if (graphics_context_ != nullptr)
886 dvrGraphicsContextDestroy(graphics_context_);
887}
888
889void gvr_swap_chain_destroy(gvr_swap_chain** swap_chain) {
890 if (!swap_chain || !(*swap_chain)) {
891 ALOGW("gvr_swap_chain_destroy: Invalid swap chain pointer.");
892 return;
893 }
894 delete *swap_chain;
895 *swap_chain = nullptr;
896}
897
898int32_t gvr_swap_chain_get_buffer_count(const gvr_swap_chain* swap_chain) {
899 return swap_chain ? static_cast<int32_t>(swap_chain->buffers_.size()) : 0;
900}
901
902gvr_sizei gvr_swap_chain_get_buffer_size(gvr_swap_chain* swap_chain,
903 int32_t index) {
904 if (!VerifyBufferIndex("gvr_swap_chain_get_buffer_size", swap_chain, index))
905 return gvr_sizei{0, 0};
906
907 gvr_buffer& buf = swap_chain->buffers_[index];
908 if (buf.requested_size != gvr_sizei{-1, -1})
909 return buf.requested_size;
910 else
911 return buf.spec.size;
912}
913
914void gvr_swap_chain_resize_buffer(gvr_swap_chain* swap_chain, int32_t index,
915 gvr_sizei size) {
916 if (!VerifyBufferIndex("gvr_swap_chain_resize_buffer", swap_chain, index))
917 return;
918
919 gvr_buffer& buf = swap_chain->buffers_[index];
920 if (size != buf.spec.size)
921 buf.requested_size = size;
922 else
923 buf.requested_size = {-1, -1};
924}
925
926gvr_frame* gvr_swap_chain_acquire_frame(gvr_swap_chain* swap_chain) {
927 if (!swap_chain)
928 return nullptr;
929
930 if (swap_chain->frame_acquired_) {
931 gvr_set_error(swap_chain->context, GVR_ERROR_NO_FRAME_AVAILABLE);
932 return nullptr;
933 }
934
935 // Resize buffers if necessary
936 for (int i = 0; i < static_cast<int>(swap_chain->buffers_.size()); ++i) {
937 gvr_buffer& buf = swap_chain->buffers_[i];
938 if (buf.requested_size != gvr_sizei{-1, -1}) {
939 if (!SwapChainResizeBuffer(swap_chain, i))
940 return nullptr;
941 }
942 }
943
944 // Only call gvr_wait_next_frame() if the app didn't call it already.
945 if (!swap_chain->wait_next_frame_called_by_app_)
946 WaitNextFrame(swap_chain, 0, nullptr, /*called_by_app*/ false);
947
948 int ret = dvrBeginRenderFrame(swap_chain->graphics_context_);
949 if (ret < 0) {
950 gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL);
951 return nullptr;
952 }
953
954 swap_chain->frame_acquired_ = true;
955 return GetFrameFromSwapChain(swap_chain);
956}
957
958void gvr_frame_bind_buffer(gvr_frame* frame, int32_t index) {
959 gvr_swap_chain* swap_chain = GetSwapChainForFrame(frame);
960 if (!VerifyBufferIndex("gvr_frame_bind_buffer", swap_chain, index))
961 return;
962 glBindFramebuffer(GL_FRAMEBUFFER, swap_chain->buffers_[index].frame_buffer);
963}
964
965void gvr_frame_unbind(gvr_frame* /* frame */) {
966 glBindFramebuffer(GL_FRAMEBUFFER, 0);
967}
968
969gvr_sizei gvr_frame_get_buffer_size(const gvr_frame* frame, int32_t index) {
970 const gvr_swap_chain* swap_chain = GetSwapChainForFrame(frame);
971 if (!VerifyBufferIndex("gvr_frame_get_buffer_size", swap_chain, index))
972 return gvr_sizei{0, 0};
973 return swap_chain->buffers_[index].spec.size;
974}
975
976int32_t gvr_frame_get_framebuffer_object(const gvr_frame* frame,
977 int32_t index) {
978 const gvr_swap_chain* swap_chain = GetSwapChainForFrame(frame);
979 if (!VerifyBufferIndex("gvr_frame_get_framebuffer_object", swap_chain, index))
980 return 0;
981 return swap_chain->buffers_[index].frame_buffer;
982}
983
984void gvr_frame_submit(gvr_frame** frame, const gvr_buffer_viewport_list* list,
985 gvr_mat4f head_space_from_start_space) {
986 if (!frame)
987 return;
988
989 gvr_swap_chain* swap_chain = GetSwapChainForFrame(*frame);
990
991 if (!swap_chain->frame_acquired_) {
992 ALOGE("Frame was never acquired before being submitted");
993 gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL);
994 return;
995 }
996
997 *frame = nullptr;
998 swap_chain->frame_acquired_ = false;
999
1000 // Currently, support for arbitrary buffer viewport configs is very limited.
1001 // We assume that the first two viewports have to be the recommended color
1002 // buffer viewports, followed by pairs of external external buffer viewports
1003 // for video rendering.
1004 gvr_buffer_viewport_list supported_viewports;
1005 gvr_get_recommended_buffer_viewports(swap_chain->context,
1006 &supported_viewports);
1007 for (size_t i = 0; i < supported_viewports.viewports.size(); ++i) {
1008 if (i >= list->viewports.size() ||
1009 supported_viewports.viewports[i] != list->viewports[i]) {
1010 ALOGE("Custom viewport configurations are not fully supported.");
1011 gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL);
1012 return;
1013 }
1014 }
1015
1016 for (size_t i = supported_viewports.viewports.size();
1017 i < list->viewports.size(); ++i) {
1018 int32_t external_surface_id = list->viewports[i].external_surface_id;
1019 // Ignore additional custom buffer viewport for now, only those buffer
1020 // viewports backed by external surfaces are supported.
1021 // TODO(b/31442094, b/31771861, 28954457) Add full GVR buffer viewport
1022 // support.
1023 if (external_surface_id == GVR_EXTERNAL_SURFACE_ID_NONE)
1024 continue;
1025
1026 auto surface_it = swap_chain->external_surfaces_.find(external_surface_id);
1027 if (surface_it == swap_chain->external_surfaces_.end()) {
1028 ALOGE("Cannot find external_surface by id: %d.", external_surface_id);
1029 gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL);
1030 return;
1031 }
1032
1033 // Pass the transfrom matrix of video mesh to displayd.
1034 dvrGraphicsVideoMeshSurfacePresent(
1035 swap_chain->graphics_context_, surface_it->second->video_surface,
1036 list->viewports[i].eye,
1037 GvrToEigenMatrix(list->viewports[i].transform).data());
1038 }
1039
1040 float32x4_t pose_orientation, pose_translation;
1041 GvrToDvrPose(head_space_from_start_space, &pose_orientation,
1042 &pose_translation);
1043 int ret = dvrSetEdsPose(swap_chain->graphics_context_, pose_orientation,
1044 pose_translation);
1045 if (ret < 0)
1046 gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL);
1047
1048 ret = dvrPresent(swap_chain->graphics_context_);
1049 if (ret < 0) {
1050 gvr_set_error(swap_chain->context, GVR_ERROR_INTERNAL);
1051 return;
1052 }
1053}
1054
1055void gvr_bind_default_framebuffer(gvr_context* /* gvr */) {
1056 glBindFramebuffer(GL_FRAMEBUFFER, 0);
1057}
1058
1059/////////////////////////////////////////////////////////////////////////////
1060// Head tracking
1061/////////////////////////////////////////////////////////////////////////////
1062
1063gvr_clock_time_point gvr_get_time_point_now() {
1064 return gvr_clock_time_point{GetSystemClockNs()};
1065}
1066
1067gvr_mat4f gvr_get_head_space_from_start_space_rotation(
1068 const gvr_context* gvr, const gvr_clock_time_point /* time */) {
1069 // TODO(steventhomas): Implement prediction according to the supplied time
1070 // value.
1071 return gvr->force_6dof_ ? gvr->next_frame_6dof_pose_
1072 : Gvr6dofTo3dof(gvr->next_frame_6dof_pose_);
1073}
1074
1075gvr_mat4f gvr_apply_neck_model(const gvr_context* /* gvr */,
1076 gvr_mat4f head_space_from_start_space_rotation,
1077 float /* factor */) {
1078 // TODO(leandrogracia): this needs to be properly implemented.
1079 ALOGE("gvr_apply_neck_model not implemented.");
1080 return head_space_from_start_space_rotation;
1081}
1082
1083// This is used to turn off sensors to save power. Not relevant for our all in
1084// one device.
1085void gvr_pause_tracking(gvr_context* /* gvr */) {}
1086
1087// This is used to turn on sensors. Not relevant for our all in one device.
1088void gvr_resume_tracking(gvr_context* /* gvr */) {}
1089
1090void gvr_reset_tracking(gvr_context* gvr) {
1091 // TODO(leandrogracia): this needs to be properly implemented.
1092 ALOGE("gvr_reset_tracking not implemented.");
1093 gvr_set_error(gvr, GVR_ERROR_INTERNAL);
1094}
1095
1096void gvr_recenter_tracking(gvr_context* gvr) {
1097 // TODO(leandrogracia): this needs to be properly implemented.
1098 ALOGE("gvr_recenter_tracking not implemented.");
1099 gvr_set_error(gvr, GVR_ERROR_INTERNAL);
1100}
1101
1102/////////////////////////////////////////////////////////////////////////////
1103// Head mounted display
1104/////////////////////////////////////////////////////////////////////////////
1105
1106bool gvr_set_default_viewer_profile(gvr_context* gvr,
1107 const char* /* viewer_profile_uri */) {
1108 // TODO(leandrogracia): this needs to be properly implemented.
1109 ALOGE("gvr_set_default_viewer_profile not implemented.");
1110 gvr_set_error(gvr, GVR_ERROR_INTERNAL);
1111 return false;
1112}
1113
1114void gvr_refresh_viewer_profile(gvr_context* /* gvr */) {}
1115
1116const char* gvr_get_viewer_vendor(const gvr_context* /* gvr */) {
1117 return kViewerVendor;
1118}
1119
1120const char* gvr_get_viewer_model(const gvr_context* /* gvr */) {
1121 return kViewerModel;
1122}
1123
1124int32_t gvr_get_viewer_type(const gvr_context* /* gvr */) {
1125 // TODO(leandrogracia): this needs to be properly implemented.
1126 // In this case, we will probably need to define a new viewer type that
1127 // has 6DoF support.
1128 return GVR_VIEWER_TYPE_DAYDREAM;
1129}
1130
1131gvr_mat4f gvr_get_eye_from_head_matrix(const gvr_context* gvr,
1132 const int32_t eye) {
1133 float eye_mult = eye == GVR_LEFT_EYE ? 1 : -1;
1134 return GvrTranslationMatrix(
1135 .5f * eye_mult * gvr->display_metrics_.inter_lens_distance_m, 0, 0);
1136}
1137
1138gvr_recti gvr_get_window_bounds(const gvr_context* gvr) {
1139 // Our app windows are always full screen
1140 gvr_sizei screen_size = gvr_get_screen_target_size(gvr);
1141 return gvr_recti{0, screen_size.width, 0, screen_size.height};
1142}
1143
1144void gvr_compute_distorted_point(const gvr_context* /* gvr */,
1145 const int32_t /* eye */,
1146 const gvr_vec2f /* uv_in */,
1147 gvr_vec2f /* uv_out */[3]) {
1148 // TODO(leandrogracia): this needs to be properly implemented.
1149 ALOGE("gvr_compute_distorted_point not implemented.");
1150}
1151
1152/////////////////////////////////////////////////////////////////////////////
1153// GVR API extension (from gvr_ext.h)
1154/////////////////////////////////////////////////////////////////////////////
1155
1156gvr_frame_schedule* gvr_frame_schedule_create() {
1157 return new gvr_frame_schedule;
1158}
1159
1160void gvr_frame_schedule_destroy(gvr_frame_schedule** schedule) {
1161 if (!schedule || !(*schedule)) {
1162 ALOGW("gvr_frame_schedule_destroy: Invalid frame schedule pointer.");
1163 return;
1164 }
1165 delete *schedule;
1166 *schedule = nullptr;
1167}
1168
1169uint32_t gvr_frame_schedule_get_vsync_count(gvr_frame_schedule* schedule) {
1170 return schedule->vsync_count;
1171}
1172
1173gvr_clock_time_point gvr_frame_schedule_get_scheduled_finish(
1174 gvr_frame_schedule* schedule) {
1175 return schedule->scheduled_finish;
1176}
1177
1178void gvr_wait_next_frame(gvr_swap_chain* swap_chain, int64_t start_delay_nanos,
1179 gvr_frame_schedule* out_next_frame_schedule) {
1180 WaitNextFrame(swap_chain, start_delay_nanos, out_next_frame_schedule,
1181 /*called_by_app*/ true);
1182}
1183
1184gvr_mat4f gvr_get_6dof_head_pose_in_start_space(gvr_context* gvr,
1185 uint32_t vsync_count) {
1186 DvrPoseAsync pose;
1187 int ret = dvrPoseGet(gvr->pose_client_, vsync_count, &pose);
1188 if (ret < 0) {
1189 ALOGW("dvrPoseGet failed: %d", ret);
1190 gvr_set_error(gvr, GVR_ERROR_INTERNAL);
1191 return GvrIdentityMatrix();
1192 }
1193
1194 return PosefToGvrMatrix(ToPosef(pose));
1195}
1196
1197gvr_mat4f gvr_get_head_space_from_start_space_pose(
1198 gvr_context* gvr, const gvr_clock_time_point /* time */) {
1199 // TODO(leandrogracia): implement prediction based on the provided time.
1200 // We need to do the same for the 3dof version too.
1201 return gvr->next_frame_6dof_pose_;
1202}
1203
1204void gvr_swap_chain_set_z_order(const gvr_swap_chain* swap_chain, int z_order) {
1205 dvrGraphicsSurfaceSetZOrder(swap_chain->graphics_context_, z_order);
1206}
1207
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08001208bool gvr_experimental_register_perf_event_callback(
1209 gvr_context* gvr, int* /* out_handle */, void* /* user_data */,
1210 void (* /* event_callback */)(void*, int, float)) {
1211 ALOGE("gvr_experimental_register_perf_event_callback not implemented.");
1212 gvr_set_error(gvr, GVR_ERROR_INTERNAL);
1213 return false;
1214}
1215
1216bool gvr_experimental_unregister_perf_event_callback(gvr_context* gvr,
1217 int /* handle */) {
1218 ALOGE("gvr_experimental_unregister_perf_event_callback not implemented.");
1219 gvr_set_error(gvr, GVR_ERROR_INTERNAL);
1220 return false;
1221}
1222
1223const gvr_analytics* gvr_get_analytics(gvr_context* gvr) {
1224 ALOGE("gvr_get_analytics not implemented.");
1225 gvr_set_error(gvr, GVR_ERROR_INTERNAL);
1226 return nullptr;
1227}
1228
1229const gvr_analytics_sample* gvr_analytics_create_sample(
1230 const gvr_analytics* analytics) {
1231 ALOGE("gvr_analytics_create_sample not implemented.");
1232 return nullptr;
1233}
1234
1235const char* gvr_analytics_sample_get_buffer(const gvr_analytics_sample* sample) {
1236 ALOGE("gvr_analytics_sample_get_buffer not implemented.");
1237 return nullptr;
1238}
1239
1240size_t gvr_analytics_sample_get_buffer_length(
1241 const gvr_analytics_sample* sample) {
1242 ALOGE("gvr_analytics_sample_get_buffer_length not implemented.");
1243 return 0;
1244}
1245
1246void gvr_analytics_destroy_sample(const gvr_analytics_sample** sample) {
1247 ALOGE("gvr_analytics_destroy_sample not implemented.");
1248}
1249
1250bool gvr_user_prefs_get_performance_monitoring_enabled(
1251 const gvr_user_prefs* /* user_prefs */) {
1252 ALOGW("gvr_user_prefs_get_performance_monitoring_enabled not implemented.");
1253 return false;
1254}
1255
1256void gvr_enable_context_sharing(gvr_context* gvr,
1257 gvr_egl_context_listener /* handler */,
1258 void* /* user_data */) {
1259 ALOGW("gvr_enable_context_sharing not implemented.");
1260 gvr_set_error(gvr, GVR_ERROR_INTERNAL);
1261}
1262
1263gvr_mat4f gvr_get_start_space_from_controller_space_pose(
1264 gvr_context* gvr, int controller_id,
1265 const gvr_clock_time_point /* time */) {
1266 if (controller_id < 0 || controller_id >= kControllerCount) {
1267 return GvrIdentityMatrix();
1268 }
1269
1270 // TODO(leandrogracia): implement prediction based on the provided time.
1271 // We need to do the same for the 3dof version too.
1272 return gvr->next_frame_controller_pose_[controller_id];
1273}
1274
1275gvr_external_surface* gvr_external_surface_create(gvr_context* context) {
1276 // A |gvr_external_surface| is bound to a DVR Graphics context at the
1277 // moment, which means we need an |gvr_swap_chain| created prior to the call
1278 // of |gvr_external_surface_create|. Check whether the current GVR context
1279 // has |gvr_swap_chain| created. Fail if there is no swap chain created
1280 // already.
1281 if (context->swap_chains_.empty()) {
1282 ALOGE("gvr_external_surface_create: No swapchain has been created yet.");
1283 return nullptr;
1284 }
1285
1286 // In case there are multiple swap chains in the context, the first is
1287 // implicitly chosen. Actually, this should not happen as current scanline
1288 // racing based GVR implementation only supports single swap chain per GVR
1289 // context.
1290 if (context->swap_chains_.size() > 1) {
1291 ALOGW("gvr_external_surface_create: Multiple swap chains detected. "
1292 "Choosing the first one but this may yield unexpected results.");
1293 }
1294 gvr_swap_chain* swap_chain = context->swap_chains_[0];
1295 DvrVideoMeshSurface* video_surface = dvrGraphicsVideoMeshSurfaceCreate(
1296 swap_chain->graphics_context_);
1297
1298 if (video_surface == nullptr) {
1299 ALOGE("gvr_external_surface_create: Failed to create video mesh surface.");
1300 return nullptr;
1301 }
1302
1303 gvr_external_surface* surface = new gvr_external_surface;
1304 surface->id = swap_chain->next_external_surface_id_++;
1305 surface->swap_chain = swap_chain;
1306 surface->video_surface = video_surface;
1307
1308 // Insert the surface into a lookup table in swap_chain. This will be
1309 // needed to by the external_surface_id in |gvr_buffer_viewport|.
1310 swap_chain->external_surfaces_.insert({surface->id, surface});
1311 return surface;
1312}
1313
1314void gvr_external_surface_destroy(gvr_external_surface** surface) {
1315 if (!surface || !(*surface)) {
1316 ALOGW("gvr_external_surface_destroy: Invalid external surface pointer.");
1317 return;
1318 }
1319
1320 (*surface)->swap_chain->external_surfaces_.erase((*surface)->id);
1321 if ((*surface)->video_surface != nullptr) {
1322 dvrGraphicsVideoMeshSurfaceDestroy((*surface)->video_surface);
1323 }
1324
1325 delete *surface;
1326 *surface = nullptr;
1327}
1328
1329void* gvr_external_surface_get_surface(const gvr_external_surface* surface) {
Alex Vakulenko4fe60582017-02-02 11:35:59 -08001330 LOG_ALWAYS_FATAL_IF(surface->swap_chain == nullptr ||
1331 surface->swap_chain->context == nullptr ||
1332 surface->swap_chain->context->jni_env_ == nullptr,
1333 "gvr_external_surface_get_surface: Surface must be "
1334 "constructed within a JNIEnv. Check |gvr_create| call.");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08001335
Alex Vakulenko4fe60582017-02-02 11:35:59 -08001336 LOG_ALWAYS_FATAL_IF(surface->video_surface == nullptr,
1337 "gvr_external_surface_get_surface: Invalid surface.");
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08001338
1339 std::shared_ptr<android::dvr::ProducerQueue> producer_queue =
1340 surface->video_surface->client->GetProducerQueue();
1341 std::shared_ptr<android::dvr::BufferHubQueueCore> core =
1342 android::dvr::BufferHubQueueCore::Create(producer_queue);
1343
1344 return android_view_Surface_createFromIGraphicBufferProducer(
1345 surface->swap_chain->context->jni_env_,
1346 new android::dvr::BufferHubQueueProducer(core));
1347}
1348
1349int32_t gvr_external_surface_get_surface_id(
1350 const gvr_external_surface* surface) {
1351 return surface->id;
1352}