blob: ea05b0153c264f04bb371aa54fd51fc0d8cf56b4 [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();
408
409 glEnable(BINNING_CONTROL_HINT_QCOM);
410 glHint(BINNING_CONTROL_HINT_QCOM, RENDER_DIRECT_TO_FRAMEBUFFER_QCOM);
411 is_render_direct_ = true;
412 CHECK_GL();
413
414 // Initialize the placeholder 1x1 framebuffer that we bind during compute
415 // shader instances to avoid accesses to other framebuffers.
416 glGenFramebuffers(1, &compute_fbo_);
417 glGenTextures(1, &compute_fbo_texture_);
418 glBindFramebuffer(GL_FRAMEBUFFER, compute_fbo_);
419 glBindTexture(GL_TEXTURE_2D, compute_fbo_texture_);
420 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
421 nullptr);
422 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
423 compute_fbo_texture_, 0);
424 CHECK_GL();
425 CHECK_GL_FBO();
426 glBindTexture(GL_TEXTURE_2D, 0);
427 glBindFramebuffer(GL_FRAMEBUFFER, 0);
428
429 return true;
430}
431
432void Compositor::Shutdown() {
John Bates093516f2017-04-17 14:58:58 -0700433 glFinish();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800434 render_target_[0].Destroy();
435 render_target_[1].Destroy();
436 layers_.clear();
437 glDeleteFramebuffers(1, &compute_fbo_);
438 glDeleteTextures(1, &compute_fbo_texture_);
439
440 debug_hud_.reset();
441 eds_renderer_.reset();
442
443 if (context_) {
444 eglDestroyContext(display_, context_);
445 context_ = 0;
446 }
447
448 if (surface_ != EGL_NO_SURFACE) {
449 eglDestroySurface(display_, surface_);
450 surface_ = EGL_NO_SURFACE;
451 }
452}
453
454void Compositor::RemoveAllBuffers() { layers_.clear(); }
455
456void Compositor::UpdateSurfaces(
457 const std::vector<std::shared_ptr<DisplaySurface>>& surfaces) {
458 // Delete the removed surfaces.
459 layers_.erase(
460 std::remove_if(layers_.begin(), layers_.end(),
461 [&surfaces](const AppFrame& layer) {
462 for (const auto& surface : surfaces)
463 if (surface->surface_id() == layer.surface_id())
464 return false;
465 return true;
466 }),
467 layers_.end());
468 // New surfaces are added on-demand as buffers are posted.
469}
470
471Compositor::AppFrame::AppFrame()
472 : surface_id_(-1),
473 blur_(0.0f),
474 z_order_(0),
475 vertical_flip_(false),
476 enable_cac_(true),
477 render_buffer_index_(0) {}
478
479Compositor::AppFrame::~AppFrame() {}
480
481const Compositor::Texture* Compositor::AppFrame::GetGlTextureId(
482 EGLDisplay display, int index) {
483 auto buffer_consumer = buffer_.buffer();
484 if (!buffer_consumer) {
485 return nullptr;
486 }
487 auto texture_it = std::find_if(
488 textures_.begin(), textures_.end(),
489 [buffer_consumer, index](const std::shared_ptr<Texture>& t) {
490 return t->consumer() == buffer_consumer && t->index() == index;
491 });
492
493 if (texture_it != textures_.end()) {
494 return (*texture_it).get();
495 }
496
497 textures_.push_back(
498 std::make_shared<Texture>(buffer_consumer, display, index));
499 if (!textures_.back()->Initialize()) {
500 textures_.pop_back();
501 return nullptr;
502 }
503 return textures_.back().get();
504}
505
506bool Compositor::AppFrame::UpdateSurface(
507 const std::shared_ptr<DisplaySurface>& surface) {
508 int surface_id = surface->surface_id();
509 float blur = surface->manager_blur();
510 bool need_sort = false;
511 if (z_order_ != surface->layer_order()) {
512 need_sort = true;
513 z_order_ = surface->layer_order();
514 }
515
516 surface_id_ = surface_id;
517 if (!render_pose_buffer_object_) {
518 render_pose_buffer_object_.reset(
519 new RenderPoseBufferObject(surface->GetMetadataBufferFd()));
520 }
521
522 blur_ = blur;
523 vertical_flip_ =
524 !!(surface->flags() & DVR_DISPLAY_SURFACE_FLAGS_VERTICAL_FLIP);
525 enable_cac_ =
526 !(surface->flags() & DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_CAC);
527
528 AcquiredBuffer skipped_buffer;
529 AcquiredBuffer buffer =
530 surface->AcquireNewestAvailableBuffer(&skipped_buffer);
531 if (!skipped_buffer.IsEmpty()) {
532 DebugHudData::data.SkipLayerFrame(z_order_);
533 ATRACE_NAME("DropToCatchUp");
534 ATRACE_ASYNC_END("BufferPost", skipped_buffer.buffer()->id());
535 }
536 if (!buffer.IsEmpty()) {
537 DebugHudData::data.AddLayerFrame(z_order_);
538 // Buffer was already ready, so we don't need to wait on the fence.
539 buffer.ClaimAcquireFence().Close();
540 ATRACE_ASYNC_END("BufferPost", buffer.buffer()->id());
541
542 render_buffer_index_ = surface->GetRenderBufferIndex(buffer.buffer()->id());
543
544#ifdef TRACE
545 const volatile DisplaySurfaceMetadata* data =
546 surface->GetMetadataBufferPtr();
547#endif
548 ALOGE_IF(TRACE, "read pose index %d %f %f", render_buffer_index_,
549 data->orientation[render_buffer_index_][0],
550 data->orientation[render_buffer_index_][1]);
551
552 // Move the new buffer over the old. AcquiredBuffer releases the old one.
553 buffer_ = std::move(buffer);
554 }
555 return need_sort;
556}
557
558void Compositor::AppFrame::UpdateVideoMeshSurface(
559 const std::shared_ptr<DisplaySurface>& surface) {
560 // Update |video_compositors_| with |video_surface|. Note that
561 // |UpdateVideoMeshSurface| should only be called on the PostThread before
562 // |DrawFrame| is called. Thus, no synchronization is required for
563 // |video_compositors_|.
564 if (!surface->video_mesh_surfaces_updated())
565 return;
566
567 // TODO(jwcai) The following loop handles adding new surfaces; video mesh
568 // removal logic shall be handled by listening to |OnChannelClose| event from
569 // DisplayService.
570 for (const auto& video_surface : surface->GetVideoMeshSurfaces()) {
571 // Here we assume number of |video_surface|s is relatively small, thus, the
572 // merge should be efficient enough.
573 auto video_compositor_it = std::find_if(
574 video_compositors_.begin(), video_compositors_.end(),
575 [video_surface](const std::shared_ptr<VideoCompositor>& c) {
576 return c->surface_id() == video_surface->surface_id();
577 });
578
579 if (video_compositor_it == video_compositors_.end()) {
580 // This video surface is new, create a new VideoCompositor.
581 video_compositors_.push_back(std::make_shared<VideoCompositor>(
582 video_surface, surface->GetMetadataBufferPtr()));
583 } else {
584 // There is a compositor in |video_compositors_| is already set up for
585 // this |video_surface|.
586 ALOGW("Duplicated video_mesh_surface: surface_id=%d",
587 video_surface->surface_id());
588 }
589 }
590}
591
592void Compositor::AppFrame::ResetBlurrers() { blurrers_.clear(); }
593
594void Compositor::AppFrame::AddBlurrer(Blur* blurrer) {
595 blurrers_.emplace_back(blurrer);
596}
597
598void Compositor::PostBuffer(const std::shared_ptr<DisplaySurface>& surface) {
599 int surface_id = surface->surface_id();
600
601 ALOGD_IF(TRACE, "Post surface %d", surface_id);
602
603 auto layer_it = std::find_if(layers_.begin(), layers_.end(),
604 [surface_id](const AppFrame& frame) {
605 return frame.surface_id() == surface_id;
606 });
607
608 bool need_sort = false;
609 if (layer_it == layers_.end()) {
610 layers_.push_back(AppFrame());
611 layer_it = layers_.end() - 1;
612 need_sort = true;
613 }
614
615 need_sort |= layer_it->UpdateSurface(surface);
616 layer_it->UpdateVideoMeshSurface(surface);
617
618 if (need_sort) {
619 std::stable_sort(layers_.begin(), layers_.end());
620 }
621}
622
623std::vector<uint8_t> Compositor::ReadLayerPixels(size_t index, int* width,
624 int* height) {
625 if (index >= layers_.size()) {
626 return {};
627 }
628
629 const Texture* texture = layers_[index].GetGlTextureId(display_, 0);
630 if (!texture) {
631 return {};
632 }
633
634 *width = texture->size()[0];
635 *height = texture->size()[1];
636 return ReadTextureRGBA(texture->texture_id(), *width, *height);
637}
638
639std::vector<uint8_t> Compositor::ReadBufferPixels(const IonBuffer* buffer) {
640 android::sp<TemporaryNativeBuffer> native_buffer =
641 new TemporaryNativeBuffer(buffer);
642
643 // Finish to make sure the GL driver has completed drawing of prior FBOs.
644 // Since we are creating an EGL image here, the driver will not know that
645 // there is a dependency on earlier GL draws.
646 glFinish();
647
648 EGLImageKHR image = eglCreateImageKHR(
649 display_, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
650 static_cast<ANativeWindowBuffer*>(native_buffer.get()), nullptr);
651 if (!image) {
652 ALOGE("Failed to create EGLImage\n");
653 return {};
654 }
655
656 GLuint texture_id;
657 glGenTextures(1, &texture_id);
658 glActiveTexture(GL_TEXTURE0);
659 glBindTexture(GL_TEXTURE_2D, texture_id);
660 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
661
662 int width = buffer->width();
663 int height = buffer->height();
664 std::vector<uint8_t> data = ReadTextureRGBA(texture_id, width, height);
665
666 glBindTexture(GL_TEXTURE_2D, 0);
667 glDeleteTextures(1, &texture_id);
668 eglDestroyImageKHR(display_, image);
669 return data;
670}
671
672bool Compositor::DrawFrame(uint32_t target_vsync_count,
673 LocalHandle* buffer_fence_fd) {
674 CheckAndUpdateHeadMountMetrics(false);
675
676 ATRACE_NAME("Compositor::DrawFrame");
677 GpuProfiler::Get()->PollGlTimerQueries();
678
679 if (buffer_fence_fd)
680 buffer_fence_fd->Close();
681
682 int num_layers = 0;
683 const int kMaxLayers = 4;
684 GLuint texture_id[2][kMaxLayers] = {{0}};
685 GLuint render_pose_buffer_id[kMaxLayers] = {0};
686 uint32_t render_buffer_index[kMaxLayers] = {0};
687 bool vertical_flip[kMaxLayers] = {false};
688 bool separate_eye_textures[kMaxLayers] = {false};
689 bool enable_cac[kMaxLayers] = {};
690 CHECK_GL();
691 for (auto& layer : layers_) {
692 if (!layer.buffer().buffer()) {
693 ATRACE_NAME("no_buffer");
694 continue;
695 }
696
697 // Extract surface parameters.
698 render_buffer_index[num_layers] = layer.render_buffer_index();
699 render_pose_buffer_id[num_layers] =
700 layer.render_pose_buffer_object()->object_id();
701 vertical_flip[num_layers] = layer.vertical_flip();
702 enable_cac[num_layers] =
703 head_mount_metrics_.supports_chromatic_aberration_correction() &&
704 layer.enable_cac();
705
706 // Extract per-eye textures. These may be separate or joined (atlased).
707 vec2i size(0, 0);
708 int view_count = layer.buffer().buffer()->slice_count();
709 ALOGE_IF(view_count > 2, "Error: more than 2 views not supported");
710 view_count = std::min(2, view_count);
711 separate_eye_textures[num_layers] = (view_count > 1);
712 bool is_missing_texture = false;
713 for (int eye = 0; eye < 2; ++eye) {
714 // If view_count is 1, each eye texture is the 0th.
715 int view_index = (view_count == 2) ? eye : 0;
716 const Texture* texture = layer.GetGlTextureId(display_, view_index);
717 // Texture will be null if the EGL image creation fails (hopefully never).
718 if (!texture) {
719 is_missing_texture = true;
720 break;
721 }
722 // All views are currently expected to have the same size.
723 size = texture->size();
724 texture_id[eye][num_layers] = texture->texture_id();
725 }
726 if (is_missing_texture) {
727 continue;
728 }
729
730 // Perform blur if requested.
731 if (fabs(layer.blur()) > 0.001f) {
732 // No need for CAC on blurred layers.
733 enable_cac[num_layers] = false;
734 if (layer.blurrer_count() < 1 || layer.blurrer(0)->width() != size[0] ||
735 layer.blurrer(0)->height() != size[1]) {
736 // Blur is created with the left eye texture, but the same instance
737 // can be used for the right eye as well.
738 layer.ResetBlurrers();
739 layer.AddBlurrer(new Blur(size[0], size[1], texture_id[0][num_layers],
740 GL_TEXTURE_2D, GL_TEXTURE_2D, true, display_,
741 view_count));
742 }
743 // Reset blur instances to prepare for drawing.
744 layer.blurrer(0)->StartFrame();
745 layer.blurrer(0)->set_scale(layer.blur());
746 // Perform blur and replace source texture with blurred output texture.
747 if (view_count == 1) {
748 // Single wide buffer for both eyes, blur both eyes in one operation.
749 texture_id[0][num_layers] = texture_id[1][num_layers] =
750 layer.blurrer(0)->DrawBlur(texture_id[0][num_layers]);
751 } else {
752 // Split eye buffers in a single frame, blur each framebuffer.
753 texture_id[0][num_layers] =
754 layer.blurrer(0)->DrawBlur(texture_id[0][num_layers]);
755 texture_id[1][num_layers] =
756 layer.blurrer(0)->DrawBlur(texture_id[1][num_layers]);
757 }
758 }
759
760 ++num_layers;
761 if (num_layers >= kMaxLayers)
762 break;
763 }
764
765 CHECK_GL();
766 // Set appropriate binning mode for the number of layers.
767 if (num_layers > 1 && is_render_direct_) {
768 is_render_direct_ = false;
769 glDisable(BINNING_CONTROL_HINT_QCOM);
770 } else if (num_layers <= 1 && !is_render_direct_) {
771 is_render_direct_ = true;
772 glEnable(BINNING_CONTROL_HINT_QCOM);
773 glHint(BINNING_CONTROL_HINT_QCOM, RENDER_DIRECT_TO_FRAMEBUFFER_QCOM);
774 }
775
776 // Workaround for GL driver bug that causes the currently bound FBO to be
777 // accessed during a compute shader pass (DoLateLatch below). Based on an
778 // analysis with systrace, the best pattern here was to run the compute shader
779 // with a *different* FBO than what will be drawn to afterward. So we bind
780 // a dummy 1x1 FBO here and discard it. If instead, the current render target
781 // is bound during the compute shader, the following draw calls will be forced
782 // into direct mode rendering.
783 glBindFramebuffer(GL_FRAMEBUFFER, compute_fbo_);
784 GLenum attachment = GL_COLOR_ATTACHMENT0;
785 glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, &attachment);
786
787 // Double buffer the render target. Get the render target we're drawing into,
788 // and update the active buffer to the next buffer.
789 RenderTarget& render_target = GetRenderTarget();
790 SetNextRenderTarget();
791
792 if (num_layers > 0) {
793 // This trace prints the EDS+Warp GPU overhead and prints every 5 seconds:
794 TRACE_GPU_PRINT("GPU EDS+Warp", 5 * 60);
795 CHECK_GL();
796 eds_renderer_->DoLateLatch(target_vsync_count, render_buffer_index,
797 render_pose_buffer_id, vertical_flip,
798 separate_eye_textures, num_layers);
799
800 render_target.BindFramebuffer();
801
802 // Discard to avoid unresolving the framebuffer during tiled rendering.
803 render_target.DiscardColorAttachment();
804
805 // For tiled mode rendering, we clear every frame to avoid garbage showing
806 // up in the parts of tiles that are not rendered.
807 if (!is_render_direct_) {
808 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
809 glClear(GL_COLOR_BUFFER_BIT);
810 }
811
812 for (int eye = kLeftEye; eye <= kRightEye; ++eye) {
813 eds_renderer_->PrepGlState(static_cast<EyeType>(eye));
814 for (int layer_i = 0; layer_i < num_layers; ++layer_i) {
815 bool blend_with_previous = layer_i > 0;
816 uint32_t current_buffer_index = render_buffer_index[layer_i];
817
818 // Render video mesh in the background of each graphics layer.
819 layers_[layer_i].ForEachVideoCompositor([this, eye, layer_i,
820 current_buffer_index,
821 &blend_with_previous](
822 const std::shared_ptr<VideoCompositor>& video_compositor) mutable {
823 eds_renderer_->DrawVideoQuad(
824 static_cast<EyeType>(eye), layer_i,
825 video_compositor->GetActiveTextureId(display_),
826 video_compositor->GetTransform(eye, current_buffer_index));
827 blend_with_previous = true;
828 });
829
830 // Apply distortion to frame submitted from the app's GL context.
831 eds_renderer_->SetChromaticAberrationCorrectionEnabled(
832 enable_cac[layer_i]);
833 eds_renderer_->ApplyDistortionCorrectionToTexture(
834 static_cast<EyeType>(eye), &texture_id[eye][layer_i],
835 &vertical_flip[layer_i], &separate_eye_textures[layer_i], &layer_i,
836 1, blend_with_previous, false);
837 }
838 }
839 eds_renderer_->ResetGlState(1);
840 CHECK_GL();
841 } else {
842 ALOGI("No buffers for compositing, clearing to black.");
843 render_target.BindFramebuffer();
844 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
845 glClear(GL_COLOR_BUFFER_BIT);
846 }
847
848 debug_hud_->Update();
849 debug_hud_->Draw();
850
851 LocalHandle fence_fd = CreateGLSyncAndFlush(display_);
852
853 if (buffer_fence_fd)
854 *buffer_fence_fd = std::move(fence_fd);
855
856 if (eds_pose_capture_enabled_) {
857 std::lock_guard<std::mutex> _lock(mutex_);
858 eds_renderer_->GetLastEdsPose(&eds_pose_capture_);
859 }
860
861 return true;
862}
863
864bool Compositor::GetLastEdsPose(LateLatchOutput* out_data) {
865 if (eds_pose_capture_enabled_) {
866 std::lock_guard<std::mutex> _lock(mutex_);
867 *out_data = eds_pose_capture_;
868 return true;
869 } else {
870 ALOGE("Eds pose capture is not enabled.");
871 return false;
872 }
873}
874
875} // namespace dvr
876} // namespace android