blob: 07e4a8b67594a6e8503832ebc66a8cf275421232 [file] [log] [blame]
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001#include "compositor.h"
2
3#include <EGL/eglext.h>
4#include <GLES/gl.h>
5#include <GLES/glext.h>
6#include <GLES2/gl2.h>
7
8#include <memory>
9
10#include <cutils/properties.h>
11
12#include <dvr/graphics.h>
13#include <private/dvr/buffer_hub_client.h>
14#include <private/dvr/clock_ns.h>
15#include <private/dvr/debug.h>
Hendrik Wagenaar302b74f2017-04-04 14:38:36 -070016#include <private/dvr/device_metrics.h>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080017#include <private/dvr/display_types.h>
18#include <private/dvr/dummy_native_window.h>
19#include <private/dvr/gl_fenced_flush.h>
20#include <private/dvr/graphics/blur.h>
21#include <private/dvr/graphics/gpu_profiler.h>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080022#include <private/dvr/native_buffer.h>
23#include <private/dvr/platform_defines.h>
24#include <utils/Log.h>
25#include <utils/Trace.h>
26
27#include "debug_hud_data.h"
28#include "debug_hud_view.h"
29#include "display_surface.h"
30
31#define BINNING_CONTROL_HINT_QCOM 0x8FB0
32
33// Accepted by the <hint> parameter of glHint:
34#define BINNING_QCOM 0x8FB1
35#define VISIBILITY_OPTIMIZED_BINNING_QCOM 0x8FB2
36#define RENDER_DIRECT_TO_FRAMEBUFFER_QCOM 0x8FB3
37
38#ifndef EGL_CONTEXT_MAJOR_VERSION
39#define EGL_CONTEXT_MAJOR_VERSION 0x3098
40#define EGL_CONTEXT_MINOR_VERSION 0x30FB
41#endif
42
43using android::pdx::LocalHandle;
44
45static const int kDistortionMeshResolution = 40;
46
47static std::shared_ptr<int64_t> eds_gpu_duration_ns =
48 std::make_shared<int64_t>(0);
49
50static constexpr char kDisableLensDistortionProp[] =
51 "persist.dreamos.disable_distort";
52
53static constexpr char kEnableEdsPoseSaveProp[] =
54 "persist.dreamos.save_eds_pose";
55
56namespace android {
57namespace dvr {
58
59namespace {
60
61// An implementation of ANativeWindowBuffer backed by a temporary IonBuffer.
62// Do not hold on to this kind of object, because the IonBuffer may become
63// invalid in other scopes.
64class TemporaryNativeBuffer
65 : public ANativeObjectBase<ANativeWindowBuffer, TemporaryNativeBuffer,
66 LightRefBase<TemporaryNativeBuffer>> {
67 public:
68 explicit TemporaryNativeBuffer(const IonBuffer* buffer) : BASE() {
69 ANativeWindowBuffer::width = buffer->width();
70 ANativeWindowBuffer::height = buffer->height();
71 ANativeWindowBuffer::stride = buffer->stride();
72 ANativeWindowBuffer::format = buffer->format();
73 ANativeWindowBuffer::usage = buffer->usage();
74 // TODO(eieio): Update NYC to support layer_count.
75 // ANativeWindowBuffer::layer_count = 1;
76 handle = buffer->handle();
77 }
78
79 private:
80 friend class android::LightRefBase<TemporaryNativeBuffer>;
81
82 TemporaryNativeBuffer(const TemporaryNativeBuffer&) = delete;
83 void operator=(TemporaryNativeBuffer&) = delete;
84};
85
86std::vector<uint8_t> ReadTextureRGBA(GLuint texture_id, int width, int height) {
87 std::vector<uint8_t> data(width * height * 4);
88 GLuint fbo;
89 glGenFramebuffers(1, &fbo);
90 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
91 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
92 texture_id, 0);
93 // Using default GL_PACK_ALIGNMENT of 4 for the 4 byte source data.
94 glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data.data());
95 glBindFramebuffer(GL_FRAMEBUFFER, 0);
96 glDeleteFramebuffers(1, &fbo);
97 CHECK_GL();
98 return data;
99}
100
101} // namespace
102
103class Compositor::Texture {
104 public:
105 Texture(std::shared_ptr<BufferConsumer> consumer, EGLDisplay display,
106 int index);
107 ~Texture();
108
109 std::shared_ptr<BufferConsumer> consumer() const { return consumer_; }
110 GLuint texture_id() const { return texture_id_; }
111 vec2i size() const {
112 return vec2i(native_buffer_.get()->width, native_buffer_.get()->height);
113 }
114 int index() const { return index_; }
115
116 bool Initialize();
117
118 private:
119 Texture(const Texture&) = delete;
120 void operator=(const Texture&) = delete;
121
122 std::shared_ptr<BufferConsumer> consumer_;
123
124 android::sp<NativeBufferConsumer> native_buffer_;
125
126 EGLDisplay display_;
127 EGLImageKHR image_;
128 GLuint texture_id_;
129 int index_;
130};
131
132Compositor::Texture::Texture(std::shared_ptr<BufferConsumer> consumer,
133 EGLDisplay display, int index)
134 : consumer_(consumer),
135 display_(display),
136 image_(nullptr),
137 texture_id_(0),
138 index_(index) {}
139
140Compositor::Texture::~Texture() {
141 glDeleteTextures(1, &texture_id_);
142 eglDestroyImageKHR(display_, image_);
143}
144
145bool Compositor::Texture::Initialize() {
146 native_buffer_ = new NativeBufferConsumer(consumer_, index_);
147
148 CHECK_GL();
149 image_ = eglCreateImageKHR(
150 display_, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
151 static_cast<ANativeWindowBuffer*>(native_buffer_.get()), nullptr);
152 if (!image_) {
153 ALOGE("Failed to create EGLImage\n");
154 return false;
155 }
156
157 glGenTextures(1, &texture_id_);
158 glActiveTexture(GL_TEXTURE0);
159 glBindTexture(GL_TEXTURE_2D, texture_id_);
160 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image_);
161 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
162 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
163 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
164 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
165 CHECK_GL();
166 return true;
167}
168
169Compositor::RenderTarget::RenderTarget()
170 : buffer_texture_id_(0),
171 buffer_framebuffer_id_(0),
172 buffer_image_(nullptr) {}
173
174Compositor::RenderTarget::~RenderTarget() { Destroy(); }
175
176void Compositor::RenderTarget::Destroy() {
177 glDeleteFramebuffers(1, &buffer_framebuffer_id_);
178 glDeleteTextures(1, &buffer_texture_id_);
179 eglDestroyImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), buffer_image_);
180 buffer_texture_id_ = 0;
181 buffer_framebuffer_id_ = 0;
182 buffer_image_ = nullptr;
183}
184
185void Compositor::RenderTarget::Initialize(int width, int height) {
186 LOG_ALWAYS_FATAL_IF(buffer_texture_id_ || buffer_framebuffer_id_ ||
187 buffer_image_);
188 constexpr int usage = GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_COMPOSER |
189 GRALLOC_USAGE_HW_RENDER |
190 GRALLOC_USAGE_QCOM_FRAMEBUFFER_COMPRESSION;
191 buffer_ = std::make_shared<IonBuffer>(width, height,
192 HAL_PIXEL_FORMAT_RGBA_8888, usage);
193
194 native_buffer_ = new NativeBuffer(buffer_);
195
196 buffer_image_ = eglCreateImageKHR(
197 eglGetDisplay(EGL_DEFAULT_DISPLAY), EGL_NO_CONTEXT,
198 EGL_NATIVE_BUFFER_ANDROID,
199 static_cast<ANativeWindowBuffer*>(native_buffer_.get()), nullptr);
200
201 glGenTextures(1, &buffer_texture_id_);
202 glBindTexture(GL_TEXTURE_2D, buffer_texture_id_);
203 CHECK_GL();
204
205 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, buffer_image_);
206 CHECK_GL();
207
208 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
209 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
210 glBindTexture(GL_TEXTURE_2D, 0);
211
212 // Generate a framebuffer.
213 glGenFramebuffers(1, &buffer_framebuffer_id_);
214 glBindFramebuffer(GL_FRAMEBUFFER, buffer_framebuffer_id_);
215 CHECK_GL();
216
217 // Attach the color buffer
218 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
219 buffer_texture_id_, 0);
220 CHECK_GL();
221 GLenum result = glCheckFramebufferStatus(GL_FRAMEBUFFER);
222 CHECK_GL();
223 if (result != GL_FRAMEBUFFER_COMPLETE) {
224 ALOGE("Framebuffer incomplete: %d", result);
225 }
226
227 // Clear the render target to black once. In direct render mode we never draw
228 // the corner pixels.
229 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
230 glClear(GL_COLOR_BUFFER_BIT);
231 glFlush();
232
233 glBindFramebuffer(GL_FRAMEBUFFER, 0);
234 CHECK_GL();
235}
236
237void Compositor::RenderTarget::BindFramebuffer() {
238 glBindFramebuffer(GL_FRAMEBUFFER, buffer_framebuffer_id_);
239}
240
241void Compositor::RenderTarget::DiscardColorAttachment() {
242 GLenum attachment = GL_COLOR_ATTACHMENT0;
243 glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, &attachment);
244 CHECK_GL();
245}
246
247class Compositor::RenderPoseBufferObject {
248 public:
249 RenderPoseBufferObject(LocalHandle&& render_pose_buffer_fd) {
250 // Create new pose tracking buffer for this surface.
251 glGenBuffers(1, &render_pose_buffer_object_);
252 glBindBuffer(GL_UNIFORM_BUFFER, render_pose_buffer_object_);
253 if (render_pose_buffer_fd) {
254 LOG_ALWAYS_FATAL_IF(!glBindSharedBufferQCOM);
255 if (glBindSharedBufferQCOM)
256 glBindSharedBufferQCOM(GL_UNIFORM_BUFFER,
257 sizeof(DisplaySurfaceMetadata),
258 render_pose_buffer_fd.Get());
259 else
260 ALOGE("Error: Missing gralloc buffer extension");
261 CHECK_GL();
262 }
263 glBindBuffer(GL_UNIFORM_BUFFER, 0);
264 }
265
266 ~RenderPoseBufferObject() { glDeleteBuffers(1, &render_pose_buffer_object_); }
267
268 GLuint object_id() const { return render_pose_buffer_object_; }
269
270 private:
271 // Render pose buffer object. This contains an array of poses that corresponds
272 // with the surface buffers.
273 GLuint render_pose_buffer_object_;
274
275 RenderPoseBufferObject(const RenderPoseBufferObject&) = delete;
276 void operator=(const RenderPoseBufferObject&) = delete;
277};
278
279HeadMountMetrics CreateDefaultHeadMountMetrics() {
280 const bool enable_distortion =
281 property_get_bool(kDisableLensDistortionProp, 0) == 0;
282 return enable_distortion ? CreateHeadMountMetrics()
283 : CreateUndistortedHeadMountMetrics();
284}
285
286Compositor::Compositor()
287 : head_mount_metrics_(CreateDefaultHeadMountMetrics()),
288 display_(0),
289 config_(0),
290 surface_(0),
291 context_(0),
292 active_render_target_(0),
293 is_render_direct_(false),
294 compute_fbo_(0),
295 compute_fbo_texture_(0),
296 hmd_metrics_requires_update_(false),
297 eds_pose_capture_enabled_(false) {}
298
299Compositor::~Compositor() {}
300
301bool Compositor::Initialize(const DisplayMetrics& display_metrics) {
302 ATRACE_NAME("Compositor::Initialize");
303 if (!InitializeEGL())
304 return false;
305
306 display_metrics_ = display_metrics;
307 const int width = display_metrics_.GetSizePixels().x();
308 const int height = display_metrics_.GetSizePixels().y();
309
310 render_target_[0].Initialize(width, height);
311 render_target_[1].Initialize(width, height);
312
313 // EDS:
314 GpuProfiler::Get()->SetEnableGpuTracing(true);
315
316 eds_pose_capture_enabled_ = property_get_bool(kEnableEdsPoseSaveProp, 0) == 1;
317
318 CheckAndUpdateHeadMountMetrics(true);
319
320 debug_hud_.reset(new DebugHudView(*composite_hmd_.get()));
321 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
322
323 return true;
324}
325
326void Compositor::UpdateHeadMountMetrics(
327 const HeadMountMetrics& head_mount_metrics) {
328 // Recalculating the mesh must be done in the draw loop, defer until then.
329 std::lock_guard<std::mutex> _lock(mutex_);
330 head_mount_metrics_ = head_mount_metrics;
331 hmd_metrics_requires_update_ = true;
332}
333
334void Compositor::CheckAndUpdateHeadMountMetrics(bool force_update) {
335 std::lock_guard<std::mutex> _lock(mutex_);
336 if (hmd_metrics_requires_update_ || force_update) {
337 hmd_metrics_requires_update_ = false;
338 composite_hmd_.reset(
339 new CompositeHmd(head_mount_metrics_, display_metrics_));
340 CHECK_GL();
341 eds_renderer_.reset(new DistortionRenderer(
342 *composite_hmd_.get(), display_metrics_.GetSizePixels(),
343 kDistortionMeshResolution, true, false, false, true, true));
344 }
345}
346
347bool Compositor::InitializeEGL() {
348 ATRACE_NAME("Compositor::InitializeEGL");
349 display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
350 if (!display_) {
351 ALOGE("Failed to get egl display\n");
352 return false;
353 }
354
355 eglInitialize(display_, nullptr, nullptr);
356
357 EGLint attribs[] = {
358 EGL_BUFFER_SIZE,
359 32,
360 EGL_ALPHA_SIZE,
361 0,
362 EGL_BLUE_SIZE,
363 8,
364 EGL_RED_SIZE,
365 8,
366 EGL_GREEN_SIZE,
367 8,
368 EGL_DEPTH_SIZE,
369 0,
370 EGL_SURFACE_TYPE,
371 EGL_WINDOW_BIT,
372 EGL_RENDERABLE_TYPE,
373 EGL_OPENGL_ES2_BIT,
374 EGL_NONE,
375 };
376
377 EGLint num_configs;
378 if (!eglChooseConfig(display_, attribs, &config_, 1, &num_configs)) {
379 ALOGE("Couldn't find config");
380 return false;
381 }
382
383 std::unique_ptr<DummyNativeWindow> window(new DummyNativeWindow());
384
385 surface_ = eglCreateWindowSurface(display_, config_, window.get(), nullptr);
386 if (surface_ == EGL_NO_SURFACE) {
387 ALOGE("Failed to create egl surface");
388 return false;
389 }
390 window.release();
391
392 EGLint context_attribs[] = {EGL_CONTEXT_MAJOR_VERSION,
393 3,
394 EGL_CONTEXT_MINOR_VERSION,
395 1,
396 EGL_CONTEXT_PRIORITY_LEVEL_IMG,
397 EGL_CONTEXT_PRIORITY_HIGH_IMG,
398 EGL_NONE};
399 context_ = eglCreateContext(display_, config_, nullptr, context_attribs);
400 if (!eglMakeCurrent(display_, surface_, surface_, context_)) {
401 ALOGE("Unable to create GLESv2 context");
402 return false;
403 }
404
405 load_gl_extensions();
Steven Thomas28f85d62017-04-17 11:55:34 -0700406 GpuProfiler::Get()->OnGlContextCreated();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800407
408 glEnable(BINNING_CONTROL_HINT_QCOM);
409 glHint(BINNING_CONTROL_HINT_QCOM, RENDER_DIRECT_TO_FRAMEBUFFER_QCOM);
410 is_render_direct_ = true;
411 CHECK_GL();
412
413 // Initialize the placeholder 1x1 framebuffer that we bind during compute
414 // shader instances to avoid accesses to other framebuffers.
415 glGenFramebuffers(1, &compute_fbo_);
416 glGenTextures(1, &compute_fbo_texture_);
417 glBindFramebuffer(GL_FRAMEBUFFER, compute_fbo_);
418 glBindTexture(GL_TEXTURE_2D, compute_fbo_texture_);
419 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
420 nullptr);
421 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
422 compute_fbo_texture_, 0);
423 CHECK_GL();
424 CHECK_GL_FBO();
425 glBindTexture(GL_TEXTURE_2D, 0);
426 glBindFramebuffer(GL_FRAMEBUFFER, 0);
427
428 return true;
429}
430
431void Compositor::Shutdown() {
432 render_target_[0].Destroy();
433 render_target_[1].Destroy();
434 layers_.clear();
435 glDeleteFramebuffers(1, &compute_fbo_);
436 glDeleteTextures(1, &compute_fbo_texture_);
437
438 debug_hud_.reset();
439 eds_renderer_.reset();
440
441 if (context_) {
Steven Thomas28f85d62017-04-17 11:55:34 -0700442 GpuProfiler::Get()->OnGlContextDestroyed();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800443 eglDestroyContext(display_, context_);
444 context_ = 0;
445 }
446
447 if (surface_ != EGL_NO_SURFACE) {
448 eglDestroySurface(display_, surface_);
449 surface_ = EGL_NO_SURFACE;
450 }
451}
452
453void Compositor::RemoveAllBuffers() { layers_.clear(); }
454
455void Compositor::UpdateSurfaces(
456 const std::vector<std::shared_ptr<DisplaySurface>>& surfaces) {
457 // Delete the removed surfaces.
458 layers_.erase(
459 std::remove_if(layers_.begin(), layers_.end(),
460 [&surfaces](const AppFrame& layer) {
461 for (const auto& surface : surfaces)
462 if (surface->surface_id() == layer.surface_id())
463 return false;
464 return true;
465 }),
466 layers_.end());
467 // New surfaces are added on-demand as buffers are posted.
468}
469
470Compositor::AppFrame::AppFrame()
471 : surface_id_(-1),
472 blur_(0.0f),
473 z_order_(0),
474 vertical_flip_(false),
475 enable_cac_(true),
476 render_buffer_index_(0) {}
477
478Compositor::AppFrame::~AppFrame() {}
479
480const Compositor::Texture* Compositor::AppFrame::GetGlTextureId(
481 EGLDisplay display, int index) {
482 auto buffer_consumer = buffer_.buffer();
483 if (!buffer_consumer) {
484 return nullptr;
485 }
486 auto texture_it = std::find_if(
487 textures_.begin(), textures_.end(),
488 [buffer_consumer, index](const std::shared_ptr<Texture>& t) {
489 return t->consumer() == buffer_consumer && t->index() == index;
490 });
491
492 if (texture_it != textures_.end()) {
493 return (*texture_it).get();
494 }
495
496 textures_.push_back(
497 std::make_shared<Texture>(buffer_consumer, display, index));
498 if (!textures_.back()->Initialize()) {
499 textures_.pop_back();
500 return nullptr;
501 }
502 return textures_.back().get();
503}
504
505bool Compositor::AppFrame::UpdateSurface(
506 const std::shared_ptr<DisplaySurface>& surface) {
507 int surface_id = surface->surface_id();
508 float blur = surface->manager_blur();
509 bool need_sort = false;
510 if (z_order_ != surface->layer_order()) {
511 need_sort = true;
512 z_order_ = surface->layer_order();
513 }
514
515 surface_id_ = surface_id;
516 if (!render_pose_buffer_object_) {
517 render_pose_buffer_object_.reset(
518 new RenderPoseBufferObject(surface->GetMetadataBufferFd()));
519 }
520
521 blur_ = blur;
522 vertical_flip_ =
523 !!(surface->flags() & DVR_DISPLAY_SURFACE_FLAGS_VERTICAL_FLIP);
524 enable_cac_ =
525 !(surface->flags() & DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_CAC);
526
527 AcquiredBuffer skipped_buffer;
528 AcquiredBuffer buffer =
529 surface->AcquireNewestAvailableBuffer(&skipped_buffer);
530 if (!skipped_buffer.IsEmpty()) {
531 DebugHudData::data.SkipLayerFrame(z_order_);
532 ATRACE_NAME("DropToCatchUp");
533 ATRACE_ASYNC_END("BufferPost", skipped_buffer.buffer()->id());
534 }
535 if (!buffer.IsEmpty()) {
536 DebugHudData::data.AddLayerFrame(z_order_);
537 // Buffer was already ready, so we don't need to wait on the fence.
538 buffer.ClaimAcquireFence().Close();
539 ATRACE_ASYNC_END("BufferPost", buffer.buffer()->id());
540
541 render_buffer_index_ = surface->GetRenderBufferIndex(buffer.buffer()->id());
542
543#ifdef TRACE
544 const volatile DisplaySurfaceMetadata* data =
545 surface->GetMetadataBufferPtr();
546#endif
547 ALOGE_IF(TRACE, "read pose index %d %f %f", render_buffer_index_,
548 data->orientation[render_buffer_index_][0],
549 data->orientation[render_buffer_index_][1]);
550
551 // Move the new buffer over the old. AcquiredBuffer releases the old one.
552 buffer_ = std::move(buffer);
553 }
554 return need_sort;
555}
556
557void Compositor::AppFrame::UpdateVideoMeshSurface(
558 const std::shared_ptr<DisplaySurface>& surface) {
559 // Update |video_compositors_| with |video_surface|. Note that
560 // |UpdateVideoMeshSurface| should only be called on the PostThread before
561 // |DrawFrame| is called. Thus, no synchronization is required for
562 // |video_compositors_|.
563 if (!surface->video_mesh_surfaces_updated())
564 return;
565
566 // TODO(jwcai) The following loop handles adding new surfaces; video mesh
567 // removal logic shall be handled by listening to |OnChannelClose| event from
568 // DisplayService.
569 for (const auto& video_surface : surface->GetVideoMeshSurfaces()) {
570 // Here we assume number of |video_surface|s is relatively small, thus, the
571 // merge should be efficient enough.
572 auto video_compositor_it = std::find_if(
573 video_compositors_.begin(), video_compositors_.end(),
574 [video_surface](const std::shared_ptr<VideoCompositor>& c) {
575 return c->surface_id() == video_surface->surface_id();
576 });
577
578 if (video_compositor_it == video_compositors_.end()) {
579 // This video surface is new, create a new VideoCompositor.
580 video_compositors_.push_back(std::make_shared<VideoCompositor>(
581 video_surface, surface->GetMetadataBufferPtr()));
582 } else {
583 // There is a compositor in |video_compositors_| is already set up for
584 // this |video_surface|.
585 ALOGW("Duplicated video_mesh_surface: surface_id=%d",
586 video_surface->surface_id());
587 }
588 }
589}
590
591void Compositor::AppFrame::ResetBlurrers() { blurrers_.clear(); }
592
593void Compositor::AppFrame::AddBlurrer(Blur* blurrer) {
594 blurrers_.emplace_back(blurrer);
595}
596
597void Compositor::PostBuffer(const std::shared_ptr<DisplaySurface>& surface) {
598 int surface_id = surface->surface_id();
599
600 ALOGD_IF(TRACE, "Post surface %d", surface_id);
601
602 auto layer_it = std::find_if(layers_.begin(), layers_.end(),
603 [surface_id](const AppFrame& frame) {
604 return frame.surface_id() == surface_id;
605 });
606
607 bool need_sort = false;
608 if (layer_it == layers_.end()) {
609 layers_.push_back(AppFrame());
610 layer_it = layers_.end() - 1;
611 need_sort = true;
612 }
613
614 need_sort |= layer_it->UpdateSurface(surface);
615 layer_it->UpdateVideoMeshSurface(surface);
616
617 if (need_sort) {
618 std::stable_sort(layers_.begin(), layers_.end());
619 }
620}
621
622std::vector<uint8_t> Compositor::ReadLayerPixels(size_t index, int* width,
623 int* height) {
624 if (index >= layers_.size()) {
625 return {};
626 }
627
628 const Texture* texture = layers_[index].GetGlTextureId(display_, 0);
629 if (!texture) {
630 return {};
631 }
632
633 *width = texture->size()[0];
634 *height = texture->size()[1];
635 return ReadTextureRGBA(texture->texture_id(), *width, *height);
636}
637
638std::vector<uint8_t> Compositor::ReadBufferPixels(const IonBuffer* buffer) {
639 android::sp<TemporaryNativeBuffer> native_buffer =
640 new TemporaryNativeBuffer(buffer);
641
642 // Finish to make sure the GL driver has completed drawing of prior FBOs.
643 // Since we are creating an EGL image here, the driver will not know that
644 // there is a dependency on earlier GL draws.
645 glFinish();
646
647 EGLImageKHR image = eglCreateImageKHR(
648 display_, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
649 static_cast<ANativeWindowBuffer*>(native_buffer.get()), nullptr);
650 if (!image) {
651 ALOGE("Failed to create EGLImage\n");
652 return {};
653 }
654
655 GLuint texture_id;
656 glGenTextures(1, &texture_id);
657 glActiveTexture(GL_TEXTURE0);
658 glBindTexture(GL_TEXTURE_2D, texture_id);
659 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
660
661 int width = buffer->width();
662 int height = buffer->height();
663 std::vector<uint8_t> data = ReadTextureRGBA(texture_id, width, height);
664
665 glBindTexture(GL_TEXTURE_2D, 0);
666 glDeleteTextures(1, &texture_id);
667 eglDestroyImageKHR(display_, image);
668 return data;
669}
670
671bool Compositor::DrawFrame(uint32_t target_vsync_count,
672 LocalHandle* buffer_fence_fd) {
673 CheckAndUpdateHeadMountMetrics(false);
674
675 ATRACE_NAME("Compositor::DrawFrame");
676 GpuProfiler::Get()->PollGlTimerQueries();
677
678 if (buffer_fence_fd)
679 buffer_fence_fd->Close();
680
681 int num_layers = 0;
682 const int kMaxLayers = 4;
683 GLuint texture_id[2][kMaxLayers] = {{0}};
684 GLuint render_pose_buffer_id[kMaxLayers] = {0};
685 uint32_t render_buffer_index[kMaxLayers] = {0};
686 bool vertical_flip[kMaxLayers] = {false};
687 bool separate_eye_textures[kMaxLayers] = {false};
688 bool enable_cac[kMaxLayers] = {};
689 CHECK_GL();
690 for (auto& layer : layers_) {
691 if (!layer.buffer().buffer()) {
692 ATRACE_NAME("no_buffer");
693 continue;
694 }
695
696 // Extract surface parameters.
697 render_buffer_index[num_layers] = layer.render_buffer_index();
698 render_pose_buffer_id[num_layers] =
699 layer.render_pose_buffer_object()->object_id();
700 vertical_flip[num_layers] = layer.vertical_flip();
701 enable_cac[num_layers] =
702 head_mount_metrics_.supports_chromatic_aberration_correction() &&
703 layer.enable_cac();
704
705 // Extract per-eye textures. These may be separate or joined (atlased).
706 vec2i size(0, 0);
707 int view_count = layer.buffer().buffer()->slice_count();
708 ALOGE_IF(view_count > 2, "Error: more than 2 views not supported");
709 view_count = std::min(2, view_count);
710 separate_eye_textures[num_layers] = (view_count > 1);
711 bool is_missing_texture = false;
712 for (int eye = 0; eye < 2; ++eye) {
713 // If view_count is 1, each eye texture is the 0th.
714 int view_index = (view_count == 2) ? eye : 0;
715 const Texture* texture = layer.GetGlTextureId(display_, view_index);
716 // Texture will be null if the EGL image creation fails (hopefully never).
717 if (!texture) {
718 is_missing_texture = true;
719 break;
720 }
721 // All views are currently expected to have the same size.
722 size = texture->size();
723 texture_id[eye][num_layers] = texture->texture_id();
724 }
725 if (is_missing_texture) {
726 continue;
727 }
728
729 // Perform blur if requested.
730 if (fabs(layer.blur()) > 0.001f) {
731 // No need for CAC on blurred layers.
732 enable_cac[num_layers] = false;
733 if (layer.blurrer_count() < 1 || layer.blurrer(0)->width() != size[0] ||
734 layer.blurrer(0)->height() != size[1]) {
735 // Blur is created with the left eye texture, but the same instance
736 // can be used for the right eye as well.
737 layer.ResetBlurrers();
738 layer.AddBlurrer(new Blur(size[0], size[1], texture_id[0][num_layers],
739 GL_TEXTURE_2D, GL_TEXTURE_2D, true, display_,
740 view_count));
741 }
742 // Reset blur instances to prepare for drawing.
743 layer.blurrer(0)->StartFrame();
744 layer.blurrer(0)->set_scale(layer.blur());
745 // Perform blur and replace source texture with blurred output texture.
746 if (view_count == 1) {
747 // Single wide buffer for both eyes, blur both eyes in one operation.
748 texture_id[0][num_layers] = texture_id[1][num_layers] =
749 layer.blurrer(0)->DrawBlur(texture_id[0][num_layers]);
750 } else {
751 // Split eye buffers in a single frame, blur each framebuffer.
752 texture_id[0][num_layers] =
753 layer.blurrer(0)->DrawBlur(texture_id[0][num_layers]);
754 texture_id[1][num_layers] =
755 layer.blurrer(0)->DrawBlur(texture_id[1][num_layers]);
756 }
757 }
758
759 ++num_layers;
760 if (num_layers >= kMaxLayers)
761 break;
762 }
763
764 CHECK_GL();
765 // Set appropriate binning mode for the number of layers.
766 if (num_layers > 1 && is_render_direct_) {
767 is_render_direct_ = false;
768 glDisable(BINNING_CONTROL_HINT_QCOM);
769 } else if (num_layers <= 1 && !is_render_direct_) {
770 is_render_direct_ = true;
771 glEnable(BINNING_CONTROL_HINT_QCOM);
772 glHint(BINNING_CONTROL_HINT_QCOM, RENDER_DIRECT_TO_FRAMEBUFFER_QCOM);
773 }
774
775 // Workaround for GL driver bug that causes the currently bound FBO to be
776 // accessed during a compute shader pass (DoLateLatch below). Based on an
777 // analysis with systrace, the best pattern here was to run the compute shader
778 // with a *different* FBO than what will be drawn to afterward. So we bind
779 // a dummy 1x1 FBO here and discard it. If instead, the current render target
780 // is bound during the compute shader, the following draw calls will be forced
781 // into direct mode rendering.
782 glBindFramebuffer(GL_FRAMEBUFFER, compute_fbo_);
783 GLenum attachment = GL_COLOR_ATTACHMENT0;
784 glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, &attachment);
785
786 // Double buffer the render target. Get the render target we're drawing into,
787 // and update the active buffer to the next buffer.
788 RenderTarget& render_target = GetRenderTarget();
789 SetNextRenderTarget();
790
791 if (num_layers > 0) {
792 // This trace prints the EDS+Warp GPU overhead and prints every 5 seconds:
793 TRACE_GPU_PRINT("GPU EDS+Warp", 5 * 60);
794 CHECK_GL();
795 eds_renderer_->DoLateLatch(target_vsync_count, render_buffer_index,
796 render_pose_buffer_id, vertical_flip,
797 separate_eye_textures, num_layers);
798
799 render_target.BindFramebuffer();
800
801 // Discard to avoid unresolving the framebuffer during tiled rendering.
802 render_target.DiscardColorAttachment();
803
804 // For tiled mode rendering, we clear every frame to avoid garbage showing
805 // up in the parts of tiles that are not rendered.
806 if (!is_render_direct_) {
807 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
808 glClear(GL_COLOR_BUFFER_BIT);
809 }
810
811 for (int eye = kLeftEye; eye <= kRightEye; ++eye) {
812 eds_renderer_->PrepGlState(static_cast<EyeType>(eye));
813 for (int layer_i = 0; layer_i < num_layers; ++layer_i) {
814 bool blend_with_previous = layer_i > 0;
815 uint32_t current_buffer_index = render_buffer_index[layer_i];
816
817 // Render video mesh in the background of each graphics layer.
818 layers_[layer_i].ForEachVideoCompositor([this, eye, layer_i,
819 current_buffer_index,
820 &blend_with_previous](
821 const std::shared_ptr<VideoCompositor>& video_compositor) mutable {
822 eds_renderer_->DrawVideoQuad(
823 static_cast<EyeType>(eye), layer_i,
824 video_compositor->GetActiveTextureId(display_),
825 video_compositor->GetTransform(eye, current_buffer_index));
826 blend_with_previous = true;
827 });
828
829 // Apply distortion to frame submitted from the app's GL context.
830 eds_renderer_->SetChromaticAberrationCorrectionEnabled(
831 enable_cac[layer_i]);
832 eds_renderer_->ApplyDistortionCorrectionToTexture(
833 static_cast<EyeType>(eye), &texture_id[eye][layer_i],
834 &vertical_flip[layer_i], &separate_eye_textures[layer_i], &layer_i,
835 1, blend_with_previous, false);
836 }
837 }
838 eds_renderer_->ResetGlState(1);
839 CHECK_GL();
840 } else {
841 ALOGI("No buffers for compositing, clearing to black.");
842 render_target.BindFramebuffer();
843 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
844 glClear(GL_COLOR_BUFFER_BIT);
845 }
846
847 debug_hud_->Update();
848 debug_hud_->Draw();
849
850 LocalHandle fence_fd = CreateGLSyncAndFlush(display_);
851
852 if (buffer_fence_fd)
853 *buffer_fence_fd = std::move(fence_fd);
854
855 if (eds_pose_capture_enabled_) {
856 std::lock_guard<std::mutex> _lock(mutex_);
857 eds_renderer_->GetLastEdsPose(&eds_pose_capture_);
858 }
859
860 return true;
861}
862
863bool Compositor::GetLastEdsPose(LateLatchOutput* out_data) {
864 if (eds_pose_capture_enabled_) {
865 std::lock_guard<std::mutex> _lock(mutex_);
866 *out_data = eds_pose_capture_;
867 return true;
868 } else {
869 ALOGE("Eds pose capture is not enabled.");
870 return false;
871 }
872}
873
874} // namespace dvr
875} // namespace android