blob: 239ef758253e0d95b182f2a0dd381d9783a8e570 [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:
John Bates093516f2017-04-17 14:58:58 -0700249 RenderPoseBufferObject(LocalHandle&& render_pose_buffer_fd) :
250 fd_(std::move(render_pose_buffer_fd)) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800251 // Create new pose tracking buffer for this surface.
252 glGenBuffers(1, &render_pose_buffer_object_);
253 glBindBuffer(GL_UNIFORM_BUFFER, render_pose_buffer_object_);
John Bates093516f2017-04-17 14:58:58 -0700254 if (fd_) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800255 LOG_ALWAYS_FATAL_IF(!glBindSharedBufferQCOM);
256 if (glBindSharedBufferQCOM)
257 glBindSharedBufferQCOM(GL_UNIFORM_BUFFER,
258 sizeof(DisplaySurfaceMetadata),
John Bates093516f2017-04-17 14:58:58 -0700259 fd_.Get());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800260 else
261 ALOGE("Error: Missing gralloc buffer extension");
262 CHECK_GL();
263 }
264 glBindBuffer(GL_UNIFORM_BUFFER, 0);
265 }
266
267 ~RenderPoseBufferObject() { glDeleteBuffers(1, &render_pose_buffer_object_); }
268
269 GLuint object_id() const { return render_pose_buffer_object_; }
270
271 private:
272 // Render pose buffer object. This contains an array of poses that corresponds
273 // with the surface buffers.
274 GLuint render_pose_buffer_object_;
John Bates093516f2017-04-17 14:58:58 -0700275 LocalHandle fd_;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800276
277 RenderPoseBufferObject(const RenderPoseBufferObject&) = delete;
278 void operator=(const RenderPoseBufferObject&) = delete;
279};
280
281HeadMountMetrics CreateDefaultHeadMountMetrics() {
282 const bool enable_distortion =
283 property_get_bool(kDisableLensDistortionProp, 0) == 0;
284 return enable_distortion ? CreateHeadMountMetrics()
285 : CreateUndistortedHeadMountMetrics();
286}
287
288Compositor::Compositor()
289 : head_mount_metrics_(CreateDefaultHeadMountMetrics()),
290 display_(0),
291 config_(0),
292 surface_(0),
293 context_(0),
294 active_render_target_(0),
295 is_render_direct_(false),
296 compute_fbo_(0),
297 compute_fbo_texture_(0),
298 hmd_metrics_requires_update_(false),
299 eds_pose_capture_enabled_(false) {}
300
301Compositor::~Compositor() {}
302
303bool Compositor::Initialize(const DisplayMetrics& display_metrics) {
304 ATRACE_NAME("Compositor::Initialize");
305 if (!InitializeEGL())
306 return false;
307
308 display_metrics_ = display_metrics;
309 const int width = display_metrics_.GetSizePixels().x();
310 const int height = display_metrics_.GetSizePixels().y();
311
312 render_target_[0].Initialize(width, height);
313 render_target_[1].Initialize(width, height);
314
315 // EDS:
316 GpuProfiler::Get()->SetEnableGpuTracing(true);
317
318 eds_pose_capture_enabled_ = property_get_bool(kEnableEdsPoseSaveProp, 0) == 1;
319
320 CheckAndUpdateHeadMountMetrics(true);
321
322 debug_hud_.reset(new DebugHudView(*composite_hmd_.get()));
323 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
324
325 return true;
326}
327
328void Compositor::UpdateHeadMountMetrics(
329 const HeadMountMetrics& head_mount_metrics) {
330 // Recalculating the mesh must be done in the draw loop, defer until then.
331 std::lock_guard<std::mutex> _lock(mutex_);
332 head_mount_metrics_ = head_mount_metrics;
333 hmd_metrics_requires_update_ = true;
334}
335
336void Compositor::CheckAndUpdateHeadMountMetrics(bool force_update) {
337 std::lock_guard<std::mutex> _lock(mutex_);
338 if (hmd_metrics_requires_update_ || force_update) {
339 hmd_metrics_requires_update_ = false;
340 composite_hmd_.reset(
341 new CompositeHmd(head_mount_metrics_, display_metrics_));
342 CHECK_GL();
343 eds_renderer_.reset(new DistortionRenderer(
344 *composite_hmd_.get(), display_metrics_.GetSizePixels(),
345 kDistortionMeshResolution, true, false, false, true, true));
346 }
347}
348
349bool Compositor::InitializeEGL() {
350 ATRACE_NAME("Compositor::InitializeEGL");
351 display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
352 if (!display_) {
353 ALOGE("Failed to get egl display\n");
354 return false;
355 }
356
357 eglInitialize(display_, nullptr, nullptr);
358
359 EGLint attribs[] = {
360 EGL_BUFFER_SIZE,
361 32,
362 EGL_ALPHA_SIZE,
363 0,
364 EGL_BLUE_SIZE,
365 8,
366 EGL_RED_SIZE,
367 8,
368 EGL_GREEN_SIZE,
369 8,
370 EGL_DEPTH_SIZE,
371 0,
372 EGL_SURFACE_TYPE,
373 EGL_WINDOW_BIT,
374 EGL_RENDERABLE_TYPE,
375 EGL_OPENGL_ES2_BIT,
376 EGL_NONE,
377 };
378
379 EGLint num_configs;
380 if (!eglChooseConfig(display_, attribs, &config_, 1, &num_configs)) {
381 ALOGE("Couldn't find config");
382 return false;
383 }
384
385 std::unique_ptr<DummyNativeWindow> window(new DummyNativeWindow());
386
387 surface_ = eglCreateWindowSurface(display_, config_, window.get(), nullptr);
388 if (surface_ == EGL_NO_SURFACE) {
389 ALOGE("Failed to create egl surface");
390 return false;
391 }
392 window.release();
393
394 EGLint context_attribs[] = {EGL_CONTEXT_MAJOR_VERSION,
395 3,
396 EGL_CONTEXT_MINOR_VERSION,
397 1,
398 EGL_CONTEXT_PRIORITY_LEVEL_IMG,
399 EGL_CONTEXT_PRIORITY_HIGH_IMG,
400 EGL_NONE};
401 context_ = eglCreateContext(display_, config_, nullptr, context_attribs);
402 if (!eglMakeCurrent(display_, surface_, surface_, context_)) {
403 ALOGE("Unable to create GLESv2 context");
404 return false;
405 }
406
407 load_gl_extensions();
Steven Thomas28f85d62017-04-17 11:55:34 -0700408 GpuProfiler::Get()->OnGlContextCreated();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800409
410 glEnable(BINNING_CONTROL_HINT_QCOM);
411 glHint(BINNING_CONTROL_HINT_QCOM, RENDER_DIRECT_TO_FRAMEBUFFER_QCOM);
412 is_render_direct_ = true;
413 CHECK_GL();
414
415 // Initialize the placeholder 1x1 framebuffer that we bind during compute
416 // shader instances to avoid accesses to other framebuffers.
417 glGenFramebuffers(1, &compute_fbo_);
418 glGenTextures(1, &compute_fbo_texture_);
419 glBindFramebuffer(GL_FRAMEBUFFER, compute_fbo_);
420 glBindTexture(GL_TEXTURE_2D, compute_fbo_texture_);
421 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
422 nullptr);
423 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
424 compute_fbo_texture_, 0);
425 CHECK_GL();
426 CHECK_GL_FBO();
427 glBindTexture(GL_TEXTURE_2D, 0);
428 glBindFramebuffer(GL_FRAMEBUFFER, 0);
429
430 return true;
431}
432
433void Compositor::Shutdown() {
John Bates093516f2017-04-17 14:58:58 -0700434 glFinish();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800435 render_target_[0].Destroy();
436 render_target_[1].Destroy();
437 layers_.clear();
438 glDeleteFramebuffers(1, &compute_fbo_);
439 glDeleteTextures(1, &compute_fbo_texture_);
440
441 debug_hud_.reset();
442 eds_renderer_.reset();
443
444 if (context_) {
Steven Thomas28f85d62017-04-17 11:55:34 -0700445 GpuProfiler::Get()->OnGlContextDestroyed();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800446 eglDestroyContext(display_, context_);
447 context_ = 0;
448 }
449
450 if (surface_ != EGL_NO_SURFACE) {
451 eglDestroySurface(display_, surface_);
452 surface_ = EGL_NO_SURFACE;
453 }
454}
455
456void Compositor::RemoveAllBuffers() { layers_.clear(); }
457
458void Compositor::UpdateSurfaces(
459 const std::vector<std::shared_ptr<DisplaySurface>>& surfaces) {
460 // Delete the removed surfaces.
461 layers_.erase(
462 std::remove_if(layers_.begin(), layers_.end(),
463 [&surfaces](const AppFrame& layer) {
464 for (const auto& surface : surfaces)
465 if (surface->surface_id() == layer.surface_id())
466 return false;
467 return true;
468 }),
469 layers_.end());
470 // New surfaces are added on-demand as buffers are posted.
471}
472
473Compositor::AppFrame::AppFrame()
474 : surface_id_(-1),
475 blur_(0.0f),
476 z_order_(0),
477 vertical_flip_(false),
478 enable_cac_(true),
479 render_buffer_index_(0) {}
480
481Compositor::AppFrame::~AppFrame() {}
482
483const Compositor::Texture* Compositor::AppFrame::GetGlTextureId(
484 EGLDisplay display, int index) {
485 auto buffer_consumer = buffer_.buffer();
486 if (!buffer_consumer) {
487 return nullptr;
488 }
489 auto texture_it = std::find_if(
490 textures_.begin(), textures_.end(),
491 [buffer_consumer, index](const std::shared_ptr<Texture>& t) {
492 return t->consumer() == buffer_consumer && t->index() == index;
493 });
494
495 if (texture_it != textures_.end()) {
496 return (*texture_it).get();
497 }
498
499 textures_.push_back(
500 std::make_shared<Texture>(buffer_consumer, display, index));
501 if (!textures_.back()->Initialize()) {
502 textures_.pop_back();
503 return nullptr;
504 }
505 return textures_.back().get();
506}
507
508bool Compositor::AppFrame::UpdateSurface(
509 const std::shared_ptr<DisplaySurface>& surface) {
510 int surface_id = surface->surface_id();
511 float blur = surface->manager_blur();
512 bool need_sort = false;
513 if (z_order_ != surface->layer_order()) {
514 need_sort = true;
515 z_order_ = surface->layer_order();
516 }
517
518 surface_id_ = surface_id;
519 if (!render_pose_buffer_object_) {
520 render_pose_buffer_object_.reset(
521 new RenderPoseBufferObject(surface->GetMetadataBufferFd()));
522 }
523
524 blur_ = blur;
525 vertical_flip_ =
526 !!(surface->flags() & DVR_DISPLAY_SURFACE_FLAGS_VERTICAL_FLIP);
527 enable_cac_ =
528 !(surface->flags() & DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_CAC);
529
530 AcquiredBuffer skipped_buffer;
531 AcquiredBuffer buffer =
532 surface->AcquireNewestAvailableBuffer(&skipped_buffer);
533 if (!skipped_buffer.IsEmpty()) {
534 DebugHudData::data.SkipLayerFrame(z_order_);
535 ATRACE_NAME("DropToCatchUp");
536 ATRACE_ASYNC_END("BufferPost", skipped_buffer.buffer()->id());
537 }
538 if (!buffer.IsEmpty()) {
539 DebugHudData::data.AddLayerFrame(z_order_);
540 // Buffer was already ready, so we don't need to wait on the fence.
541 buffer.ClaimAcquireFence().Close();
542 ATRACE_ASYNC_END("BufferPost", buffer.buffer()->id());
543
544 render_buffer_index_ = surface->GetRenderBufferIndex(buffer.buffer()->id());
545
546#ifdef TRACE
547 const volatile DisplaySurfaceMetadata* data =
548 surface->GetMetadataBufferPtr();
549#endif
550 ALOGE_IF(TRACE, "read pose index %d %f %f", render_buffer_index_,
551 data->orientation[render_buffer_index_][0],
552 data->orientation[render_buffer_index_][1]);
553
554 // Move the new buffer over the old. AcquiredBuffer releases the old one.
555 buffer_ = std::move(buffer);
556 }
557 return need_sort;
558}
559
560void Compositor::AppFrame::UpdateVideoMeshSurface(
561 const std::shared_ptr<DisplaySurface>& surface) {
562 // Update |video_compositors_| with |video_surface|. Note that
563 // |UpdateVideoMeshSurface| should only be called on the PostThread before
564 // |DrawFrame| is called. Thus, no synchronization is required for
565 // |video_compositors_|.
566 if (!surface->video_mesh_surfaces_updated())
567 return;
568
569 // TODO(jwcai) The following loop handles adding new surfaces; video mesh
570 // removal logic shall be handled by listening to |OnChannelClose| event from
571 // DisplayService.
572 for (const auto& video_surface : surface->GetVideoMeshSurfaces()) {
573 // Here we assume number of |video_surface|s is relatively small, thus, the
574 // merge should be efficient enough.
575 auto video_compositor_it = std::find_if(
576 video_compositors_.begin(), video_compositors_.end(),
577 [video_surface](const std::shared_ptr<VideoCompositor>& c) {
578 return c->surface_id() == video_surface->surface_id();
579 });
580
581 if (video_compositor_it == video_compositors_.end()) {
582 // This video surface is new, create a new VideoCompositor.
583 video_compositors_.push_back(std::make_shared<VideoCompositor>(
584 video_surface, surface->GetMetadataBufferPtr()));
585 } else {
586 // There is a compositor in |video_compositors_| is already set up for
587 // this |video_surface|.
588 ALOGW("Duplicated video_mesh_surface: surface_id=%d",
589 video_surface->surface_id());
590 }
591 }
592}
593
594void Compositor::AppFrame::ResetBlurrers() { blurrers_.clear(); }
595
596void Compositor::AppFrame::AddBlurrer(Blur* blurrer) {
597 blurrers_.emplace_back(blurrer);
598}
599
600void Compositor::PostBuffer(const std::shared_ptr<DisplaySurface>& surface) {
601 int surface_id = surface->surface_id();
602
603 ALOGD_IF(TRACE, "Post surface %d", surface_id);
604
605 auto layer_it = std::find_if(layers_.begin(), layers_.end(),
606 [surface_id](const AppFrame& frame) {
607 return frame.surface_id() == surface_id;
608 });
609
610 bool need_sort = false;
611 if (layer_it == layers_.end()) {
612 layers_.push_back(AppFrame());
613 layer_it = layers_.end() - 1;
614 need_sort = true;
615 }
616
617 need_sort |= layer_it->UpdateSurface(surface);
618 layer_it->UpdateVideoMeshSurface(surface);
619
620 if (need_sort) {
621 std::stable_sort(layers_.begin(), layers_.end());
622 }
623}
624
625std::vector<uint8_t> Compositor::ReadLayerPixels(size_t index, int* width,
626 int* height) {
627 if (index >= layers_.size()) {
628 return {};
629 }
630
631 const Texture* texture = layers_[index].GetGlTextureId(display_, 0);
632 if (!texture) {
633 return {};
634 }
635
636 *width = texture->size()[0];
637 *height = texture->size()[1];
638 return ReadTextureRGBA(texture->texture_id(), *width, *height);
639}
640
641std::vector<uint8_t> Compositor::ReadBufferPixels(const IonBuffer* buffer) {
642 android::sp<TemporaryNativeBuffer> native_buffer =
643 new TemporaryNativeBuffer(buffer);
644
645 // Finish to make sure the GL driver has completed drawing of prior FBOs.
646 // Since we are creating an EGL image here, the driver will not know that
647 // there is a dependency on earlier GL draws.
648 glFinish();
649
650 EGLImageKHR image = eglCreateImageKHR(
651 display_, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
652 static_cast<ANativeWindowBuffer*>(native_buffer.get()), nullptr);
653 if (!image) {
654 ALOGE("Failed to create EGLImage\n");
655 return {};
656 }
657
658 GLuint texture_id;
659 glGenTextures(1, &texture_id);
660 glActiveTexture(GL_TEXTURE0);
661 glBindTexture(GL_TEXTURE_2D, texture_id);
662 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
663
664 int width = buffer->width();
665 int height = buffer->height();
666 std::vector<uint8_t> data = ReadTextureRGBA(texture_id, width, height);
667
668 glBindTexture(GL_TEXTURE_2D, 0);
669 glDeleteTextures(1, &texture_id);
670 eglDestroyImageKHR(display_, image);
671 return data;
672}
673
674bool Compositor::DrawFrame(uint32_t target_vsync_count,
675 LocalHandle* buffer_fence_fd) {
676 CheckAndUpdateHeadMountMetrics(false);
677
678 ATRACE_NAME("Compositor::DrawFrame");
679 GpuProfiler::Get()->PollGlTimerQueries();
680
681 if (buffer_fence_fd)
682 buffer_fence_fd->Close();
683
684 int num_layers = 0;
685 const int kMaxLayers = 4;
686 GLuint texture_id[2][kMaxLayers] = {{0}};
687 GLuint render_pose_buffer_id[kMaxLayers] = {0};
688 uint32_t render_buffer_index[kMaxLayers] = {0};
689 bool vertical_flip[kMaxLayers] = {false};
690 bool separate_eye_textures[kMaxLayers] = {false};
691 bool enable_cac[kMaxLayers] = {};
692 CHECK_GL();
693 for (auto& layer : layers_) {
694 if (!layer.buffer().buffer()) {
695 ATRACE_NAME("no_buffer");
696 continue;
697 }
698
699 // Extract surface parameters.
700 render_buffer_index[num_layers] = layer.render_buffer_index();
701 render_pose_buffer_id[num_layers] =
702 layer.render_pose_buffer_object()->object_id();
703 vertical_flip[num_layers] = layer.vertical_flip();
704 enable_cac[num_layers] =
705 head_mount_metrics_.supports_chromatic_aberration_correction() &&
706 layer.enable_cac();
707
708 // Extract per-eye textures. These may be separate or joined (atlased).
709 vec2i size(0, 0);
710 int view_count = layer.buffer().buffer()->slice_count();
711 ALOGE_IF(view_count > 2, "Error: more than 2 views not supported");
712 view_count = std::min(2, view_count);
713 separate_eye_textures[num_layers] = (view_count > 1);
714 bool is_missing_texture = false;
715 for (int eye = 0; eye < 2; ++eye) {
716 // If view_count is 1, each eye texture is the 0th.
717 int view_index = (view_count == 2) ? eye : 0;
718 const Texture* texture = layer.GetGlTextureId(display_, view_index);
719 // Texture will be null if the EGL image creation fails (hopefully never).
720 if (!texture) {
721 is_missing_texture = true;
722 break;
723 }
724 // All views are currently expected to have the same size.
725 size = texture->size();
726 texture_id[eye][num_layers] = texture->texture_id();
727 }
728 if (is_missing_texture) {
729 continue;
730 }
731
732 // Perform blur if requested.
733 if (fabs(layer.blur()) > 0.001f) {
734 // No need for CAC on blurred layers.
735 enable_cac[num_layers] = false;
736 if (layer.blurrer_count() < 1 || layer.blurrer(0)->width() != size[0] ||
737 layer.blurrer(0)->height() != size[1]) {
738 // Blur is created with the left eye texture, but the same instance
739 // can be used for the right eye as well.
740 layer.ResetBlurrers();
741 layer.AddBlurrer(new Blur(size[0], size[1], texture_id[0][num_layers],
742 GL_TEXTURE_2D, GL_TEXTURE_2D, true, display_,
743 view_count));
744 }
745 // Reset blur instances to prepare for drawing.
746 layer.blurrer(0)->StartFrame();
747 layer.blurrer(0)->set_scale(layer.blur());
748 // Perform blur and replace source texture with blurred output texture.
749 if (view_count == 1) {
750 // Single wide buffer for both eyes, blur both eyes in one operation.
751 texture_id[0][num_layers] = texture_id[1][num_layers] =
752 layer.blurrer(0)->DrawBlur(texture_id[0][num_layers]);
753 } else {
754 // Split eye buffers in a single frame, blur each framebuffer.
755 texture_id[0][num_layers] =
756 layer.blurrer(0)->DrawBlur(texture_id[0][num_layers]);
757 texture_id[1][num_layers] =
758 layer.blurrer(0)->DrawBlur(texture_id[1][num_layers]);
759 }
760 }
761
762 ++num_layers;
763 if (num_layers >= kMaxLayers)
764 break;
765 }
766
767 CHECK_GL();
768 // Set appropriate binning mode for the number of layers.
769 if (num_layers > 1 && is_render_direct_) {
770 is_render_direct_ = false;
771 glDisable(BINNING_CONTROL_HINT_QCOM);
772 } else if (num_layers <= 1 && !is_render_direct_) {
773 is_render_direct_ = true;
774 glEnable(BINNING_CONTROL_HINT_QCOM);
775 glHint(BINNING_CONTROL_HINT_QCOM, RENDER_DIRECT_TO_FRAMEBUFFER_QCOM);
776 }
777
778 // Workaround for GL driver bug that causes the currently bound FBO to be
779 // accessed during a compute shader pass (DoLateLatch below). Based on an
780 // analysis with systrace, the best pattern here was to run the compute shader
781 // with a *different* FBO than what will be drawn to afterward. So we bind
782 // a dummy 1x1 FBO here and discard it. If instead, the current render target
783 // is bound during the compute shader, the following draw calls will be forced
784 // into direct mode rendering.
785 glBindFramebuffer(GL_FRAMEBUFFER, compute_fbo_);
786 GLenum attachment = GL_COLOR_ATTACHMENT0;
787 glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, &attachment);
788
789 // Double buffer the render target. Get the render target we're drawing into,
790 // and update the active buffer to the next buffer.
791 RenderTarget& render_target = GetRenderTarget();
792 SetNextRenderTarget();
793
794 if (num_layers > 0) {
795 // This trace prints the EDS+Warp GPU overhead and prints every 5 seconds:
796 TRACE_GPU_PRINT("GPU EDS+Warp", 5 * 60);
797 CHECK_GL();
798 eds_renderer_->DoLateLatch(target_vsync_count, render_buffer_index,
799 render_pose_buffer_id, vertical_flip,
800 separate_eye_textures, num_layers);
801
802 render_target.BindFramebuffer();
803
804 // Discard to avoid unresolving the framebuffer during tiled rendering.
805 render_target.DiscardColorAttachment();
806
807 // For tiled mode rendering, we clear every frame to avoid garbage showing
808 // up in the parts of tiles that are not rendered.
809 if (!is_render_direct_) {
810 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
811 glClear(GL_COLOR_BUFFER_BIT);
812 }
813
814 for (int eye = kLeftEye; eye <= kRightEye; ++eye) {
815 eds_renderer_->PrepGlState(static_cast<EyeType>(eye));
816 for (int layer_i = 0; layer_i < num_layers; ++layer_i) {
817 bool blend_with_previous = layer_i > 0;
818 uint32_t current_buffer_index = render_buffer_index[layer_i];
819
820 // Render video mesh in the background of each graphics layer.
821 layers_[layer_i].ForEachVideoCompositor([this, eye, layer_i,
822 current_buffer_index,
823 &blend_with_previous](
824 const std::shared_ptr<VideoCompositor>& video_compositor) mutable {
825 eds_renderer_->DrawVideoQuad(
826 static_cast<EyeType>(eye), layer_i,
827 video_compositor->GetActiveTextureId(display_),
828 video_compositor->GetTransform(eye, current_buffer_index));
829 blend_with_previous = true;
830 });
831
832 // Apply distortion to frame submitted from the app's GL context.
833 eds_renderer_->SetChromaticAberrationCorrectionEnabled(
834 enable_cac[layer_i]);
835 eds_renderer_->ApplyDistortionCorrectionToTexture(
836 static_cast<EyeType>(eye), &texture_id[eye][layer_i],
837 &vertical_flip[layer_i], &separate_eye_textures[layer_i], &layer_i,
838 1, blend_with_previous, false);
839 }
840 }
841 eds_renderer_->ResetGlState(1);
842 CHECK_GL();
843 } else {
844 ALOGI("No buffers for compositing, clearing to black.");
845 render_target.BindFramebuffer();
846 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
847 glClear(GL_COLOR_BUFFER_BIT);
848 }
849
850 debug_hud_->Update();
851 debug_hud_->Draw();
852
853 LocalHandle fence_fd = CreateGLSyncAndFlush(display_);
854
855 if (buffer_fence_fd)
856 *buffer_fence_fd = std::move(fence_fd);
857
858 if (eds_pose_capture_enabled_) {
859 std::lock_guard<std::mutex> _lock(mutex_);
860 eds_renderer_->GetLastEdsPose(&eds_pose_capture_);
861 }
862
863 return true;
864}
865
866bool Compositor::GetLastEdsPose(LateLatchOutput* out_data) {
867 if (eds_pose_capture_enabled_) {
868 std::lock_guard<std::mutex> _lock(mutex_);
869 *out_data = eds_pose_capture_;
870 return true;
871 } else {
872 ALOGE("Eds pose capture is not enabled.");
873 return false;
874 }
875}
876
877} // namespace dvr
878} // namespace android