2 * Copyright (C) 2015 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
18 #define LOG_TAG "GLCompositor"
22 #include <cutils/log.h>
24 #include <ui/GraphicBuffer.h>
25 #include <utils/Trace.h>
27 #include <sync/sync.h>
30 #include "drm_hwcomposer.h"
32 #include "gl_compositor.h"
37 static const char *get_gl_error(void);
38 static const char *get_egl_error(void);
39 static bool has_extension(const char *extension, const char *extensions);
42 int AllocResource(std::vector<T> &array) {
43 for (typename std::vector<T>::iterator it = array.begin(); it != array.end();
46 return std::distance(array.begin(), it);
51 return array.size() - 1;
55 void FreeResource(std::vector<T> &array, int index) {
56 if (index == (int)array.size() - 1) {
58 } else if (index >= 0 && (unsigned)index < array.size()) {
66 unsigned composition_count;
68 GLTarget() : forgotten(true), composition_count(0) {
74 composition_count = 0;
77 bool is_some() const {
82 struct GLCompositor::priv_data {
84 std::vector<GLTarget> targets;
85 std::vector<GLComposition *> compositions;
89 priv_data() : current_target(-1) {
93 class GLComposition : public Composition {
100 GLComposition(GLCompositor *owner, Importer *imp)
101 : compositor(owner), importer(imp), target_handle(-1), timeline_fd(-1) {
102 int ret = sw_sync_timeline_create();
104 ALOGE("Failed to create sw sync timeline %d", ret);
109 virtual ~GLComposition() {
110 if (timeline_fd >= 0)
113 if (compositor == NULL) {
117 // Removes this composition from the owning compositor automatically.
118 std::vector<GLComposition *> &compositions =
119 compositor->priv_->compositions;
120 std::vector<GLComposition *>::iterator it =
121 std::find(compositions.begin(), compositions.end(), this);
122 if (it != compositions.end()) {
123 compositions.erase(it);
126 GLTarget *target = &compositor->priv_->targets[target_handle];
127 target->composition_count--;
128 compositor->CheckAndDestroyTarget(target_handle);
131 virtual int AddLayer(int display, hwc_layer_1 *layer, hwc_drm_bo *bo) {
133 if (layer->compositionType != HWC_OVERLAY) {
134 ALOGE("Must add layers with compositionType == HWC_OVERLAY");
138 if (layer->handle == 0) {
139 ALOGE("Must add layers with valid buffer handle");
143 layer->releaseFenceFd = sw_sync_fence_create(
144 timeline_fd, "GLComposition release fence", layers.size() + 1);
146 layers.push_back(*layer);
148 return importer->ReleaseBuffer(bo);
151 virtual unsigned GetRemainingLayers(int display, unsigned num_needed) const {
156 GLCompositor *compositor;
160 std::vector<hwc_layer_1> layers;
163 GLCompositor::GLCompositor() {
164 priv_ = new priv_data;
167 GLCompositor::~GLCompositor() {
168 for (std::vector<GLComposition *>::iterator it = priv_->compositions.end();
169 it != priv_->compositions.begin(); it = priv_->compositions.end()) {
172 // Prevents compositor from trying to erase itself
173 (*it)->compositor = NULL;
175 priv_->compositions.erase(it);
181 int GLCompositor::Init() {
182 return priv_->worker.Init();
185 Targeting *GLCompositor::targeting() {
186 return (Targeting *)this;
189 int GLCompositor::CreateTarget(sp<GraphicBuffer> &buffer) {
192 int target_handle = AllocResource(priv_->targets);
193 GLTarget *target = &priv_->targets[target_handle];
196 target->forgotten = false;
198 return target_handle;
201 void GLCompositor::SetTarget(int target_handle) {
202 if (target_handle >= 0 && (unsigned)target_handle < priv_->targets.size()) {
203 GLTarget *target = &priv_->targets[target_handle];
204 if (target->is_some()) {
205 priv_->current_target = target_handle;
210 priv_->current_target = -1;
213 void GLCompositor::ForgetTarget(int target_handle) {
214 if (target_handle >= 0 && (unsigned)target_handle < priv_->targets.size()) {
215 if (target_handle == priv_->current_target) {
216 priv_->current_target = -1;
219 GLTarget *target = &priv_->targets[target_handle];
220 if (target->is_some()) {
221 target->forgotten = true;
222 CheckAndDestroyTarget(target_handle);
227 ALOGE("Failed to forget target because of invalid handle");
230 void GLCompositor::CheckAndDestroyTarget(int target_handle) {
231 GLTarget *target = &priv_->targets[target_handle];
232 if (target->composition_count == 0 && target->forgotten) {
233 FreeResource(priv_->targets, target_handle);
237 Composition *GLCompositor::CreateComposition(Importer *importer) {
238 if (priv_->current_target >= 0 &&
239 (unsigned)priv_->current_target < priv_->targets.size()) {
240 GLTarget *target = &priv_->targets[priv_->current_target];
241 if (target->is_some()) {
242 GLComposition *composition = new GLComposition(this, importer);
243 composition->target_handle = priv_->current_target;
244 target->composition_count++;
245 priv_->compositions.push_back(composition);
250 ALOGE("Failed to create composition because of invalid target handle %d",
251 priv_->current_target);
256 int GLCompositor::QueueComposition(Composition *composition) {
258 GLComposition *gl_composition = (GLComposition *)composition;
259 int ret = DoComposition(gl_composition);
260 gl_composition->timeline_fd = -1;
265 ALOGE("Failed to queue composition because of invalid composition handle");
270 int GLCompositor::Composite() {
274 int GLCompositor::DoComposition(GLComposition *composition) {
278 GLTarget *target = &priv_->targets[composition->target_handle];
280 work.layers = composition->layers.data();
281 work.num_layers = composition->layers.size();
282 work.timeline_fd = composition->timeline_fd;
283 work.framebuffer = target->fb;
285 ret = priv_->worker.DoWork(&work);
287 if (work.timeline_fd >= 0) {
288 sw_sync_timeline_inc(work.timeline_fd, work.num_layers + 1);
289 close(work.timeline_fd);
295 } // namespace android