1 // Copyright 2022 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either expresso or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "CompositorGl.h"
16 
17 #include "BorrowedImageGl.h"
18 #include "DebugGl.h"
19 #include "DisplaySurfaceGl.h"
20 #include "OpenGLESDispatch/DispatchTables.h"
21 #include "TextureDraw.h"
22 #include "host-common/GfxstreamFatalError.h"
23 #include "host-common/misc.h"
24 
25 namespace gfxstream {
26 namespace gl {
27 namespace {
28 
getInfoOrAbort(const std::unique_ptr<BorrowedImageInfo> & info)29 const BorrowedImageInfoGl* getInfoOrAbort(const std::unique_ptr<BorrowedImageInfo>& info) {
30     auto imageGl = static_cast<const BorrowedImageInfoGl*>(info.get());
31     if (imageGl != nullptr) {
32         return imageGl;
33     }
34 
35     GFXSTREAM_ABORT(emugl::FatalError(emugl::ABORT_REASON_OTHER))
36         << "CompositorGl did not find BorrowedImageInfoGl";
37     return nullptr;
38 }
39 
getCompletedFuture()40 std::shared_future<void> getCompletedFuture() {
41     std::shared_future<void> completedFuture = std::async(std::launch::deferred, [] {}).share();
42     completedFuture.wait();
43     return completedFuture;
44 }
45 
46 }  // namespace
47 
CompositorGl(TextureDraw * textureDraw)48 CompositorGl::CompositorGl(TextureDraw* textureDraw) : m_textureDraw(textureDraw) {}
49 
~CompositorGl()50 CompositorGl::~CompositorGl() {}
51 
compose(const CompositionRequest & composeRequest)52 Compositor::CompositionFinishedWaitable CompositorGl::compose(
53         const CompositionRequest& composeRequest) {
54     const auto* targetImage = getInfoOrAbort(composeRequest.target);
55     const uint32_t targetWidth = targetImage->width;
56     const uint32_t targetHeight = targetImage->height;
57     const GLuint targetTexture = targetImage->texture;
58     GL_SCOPED_DEBUG_GROUP("CompositorGl::compose() into texture:%d", targetTexture);
59 
60     GLint restoredViewport[4] = {0, 0, 0, 0};
61     s_gles2.glGetIntegerv(GL_VIEWPORT, restoredViewport);
62 
63     s_gles2.glViewport(0, 0, targetWidth, targetHeight);
64     if (!m_composeFbo) {
65         s_gles2.glGenFramebuffers(1, &m_composeFbo);
66     }
67     s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, m_composeFbo);
68     s_gles2.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D,
69                                    targetTexture,
70                                    /*level=*/0);
71 
72     m_textureDraw->prepareForDrawLayer();
73 
74     for (const CompositionRequestLayer& layer : composeRequest.layers) {
75         if (layer.props.composeMode == HWC2_COMPOSITION_DEVICE) {
76             const BorrowedImageInfoGl* layerImage = getInfoOrAbort(layer.source);
77             const GLuint layerTexture = layerImage->texture;
78             GL_SCOPED_DEBUG_GROUP("CompositorGl::compose() from layer texture:%d", layerTexture);
79             m_textureDraw->drawLayer(layer.props, targetWidth, targetHeight, layerImage->width,
80                                      layerImage->height, layerTexture);
81         } else {
82             m_textureDraw->drawLayer(layer.props, targetWidth, targetHeight, 1, 1, 0);
83         }
84     }
85 
86     s_gles2.glBindFramebuffer(GL_FRAMEBUFFER, 0);
87     s_gles2.glViewport(restoredViewport[0], restoredViewport[1], restoredViewport[2],
88                        restoredViewport[3]);
89 
90     m_textureDraw->cleanupForDrawLayer();
91 
92     targetImage->onCommandsIssued();
93 
94     // Note: This should be returning a future when all work, both CPU and GPU, is
95     // complete but is currently only returning a future when all CPU work is completed.
96     // In the future, CompositionFinishedWaitable should be replaced with something that
97     // passes along a GL fence or VK fence.
98     return getCompletedFuture();
99 }
100 
101 }  // namespace gl
102 }  // namespace gfxstream