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