blob: 0605c04f9b0db75fe952f36ab47d168e94a17e55 [file] [log] [blame]
Zach Reizner01935f32015-04-29 11:15:09 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
Stéphane Marchesinbe98c8c2015-06-23 16:18:10 -070017#define ATRACE_TAG ATRACE_TAG_GRAPHICS
Zach Reizner01935f32015-04-29 11:15:09 -070018#define LOG_TAG "GLCompositor"
19
Zach Reizner01935f32015-04-29 11:15:09 -070020#include <vector>
21
22#include <cutils/log.h>
23
Zach Reizner01935f32015-04-29 11:15:09 -070024#include <ui/GraphicBuffer.h>
Stéphane Marchesinbe98c8c2015-06-23 16:18:10 -070025#include <utils/Trace.h>
Zach Reizner01935f32015-04-29 11:15:09 -070026
Zach Reizner01935f32015-04-29 11:15:09 -070027#include <sync/sync.h>
28#include <sw_sync.h>
29
30#include "drm_hwcomposer.h"
31
32#include "gl_compositor.h"
Zach Reizner6cbe8832015-06-26 18:25:38 -070033#include "glworker.h"
Zach Reizner01935f32015-04-29 11:15:09 -070034
35namespace android {
36
Zach Reizner01935f32015-04-29 11:15:09 -070037static const char *get_gl_error(void);
38static const char *get_egl_error(void);
39static bool has_extension(const char *extension, const char *extensions);
40
41template <typename T>
42int AllocResource(std::vector<T> &array) {
43 for (typename std::vector<T>::iterator it = array.begin(); it != array.end();
44 ++it) {
45 if (!it->is_some()) {
46 return std::distance(array.begin(), it);
47 }
48 }
49
50 array.push_back(T());
51 return array.size() - 1;
52}
53
54template <typename T>
55void FreeResource(std::vector<T> &array, int index) {
56 if (index == (int)array.size() - 1) {
57 array.pop_back();
58 } else if (index >= 0 && (unsigned)index < array.size()) {
59 array[index].Reset();
60 }
61}
62
63struct GLTarget {
64 sp<GraphicBuffer> fb;
Zach Reizner01935f32015-04-29 11:15:09 -070065 bool forgotten;
66 unsigned composition_count;
67
Zach Reizner6cbe8832015-06-26 18:25:38 -070068 GLTarget() : forgotten(true), composition_count(0) {
Zach Reizner01935f32015-04-29 11:15:09 -070069 }
70
71 void Reset() {
72 fb.clear();
Zach Reizner01935f32015-04-29 11:15:09 -070073 forgotten = true;
74 composition_count = 0;
75 }
76
77 bool is_some() const {
Zach Reizner6cbe8832015-06-26 18:25:38 -070078 return fb != NULL;
Zach Reizner01935f32015-04-29 11:15:09 -070079 }
80};
81
82struct GLCompositor::priv_data {
Zach Reizner01935f32015-04-29 11:15:09 -070083 int current_target;
84 std::vector<GLTarget> targets;
85 std::vector<GLComposition *> compositions;
86
Zach Reizner6cbe8832015-06-26 18:25:38 -070087 GLWorker worker;
Zach Reizner01935f32015-04-29 11:15:09 -070088
Zach Reizner6cbe8832015-06-26 18:25:38 -070089 priv_data() : current_target(-1) {
Zach Reizner01935f32015-04-29 11:15:09 -070090 }
91};
92
93class GLComposition : public Composition {
94 public:
95 struct LayerData {
96 hwc_layer_1 layer;
97 hwc_drm_bo bo;
98 };
99
Zach Reiznerf5fa77c2015-06-11 11:28:48 -0700100 GLComposition(GLCompositor *owner, Importer *imp)
Zach Reizner6cbe8832015-06-26 18:25:38 -0700101 : compositor(owner), importer(imp), target_handle(-1), timeline_fd(-1) {
102 int ret = sw_sync_timeline_create();
103 if (ret < 0) {
104 ALOGE("Failed to create sw sync timeline %d", ret);
105 }
106 timeline_fd = ret;
Zach Reizner01935f32015-04-29 11:15:09 -0700107 }
108
109 virtual ~GLComposition() {
Zach Reizner6cbe8832015-06-26 18:25:38 -0700110 if (timeline_fd >= 0)
111 close(timeline_fd);
112
Zach Reizner01935f32015-04-29 11:15:09 -0700113 if (compositor == NULL) {
114 return;
115 }
116
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);
124 }
125
126 GLTarget *target = &compositor->priv_->targets[target_handle];
127 target->composition_count--;
128 compositor->CheckAndDestroyTarget(target_handle);
129 }
130
131 virtual int AddLayer(int display, hwc_layer_1 *layer, hwc_drm_bo *bo) {
132 (void)display;
133 if (layer->compositionType != HWC_OVERLAY) {
134 ALOGE("Must add layers with compositionType == HWC_OVERLAY");
135 return 1;
136 }
137
138 if (layer->handle == 0) {
139 ALOGE("Must add layers with valid buffer handle");
140 return 1;
141 }
142
Zach Reizner6cbe8832015-06-26 18:25:38 -0700143 layer->releaseFenceFd = sw_sync_fence_create(
144 timeline_fd, "GLComposition release fence", layers.size() + 1);
145
146 layers.push_back(*layer);
Zach Reizner01935f32015-04-29 11:15:09 -0700147
Zach Reiznerf5fa77c2015-06-11 11:28:48 -0700148 return importer->ReleaseBuffer(bo);
Zach Reizner01935f32015-04-29 11:15:09 -0700149 }
150
151 virtual unsigned GetRemainingLayers(int display, unsigned num_needed) const {
152 (void)display;
153 return num_needed;
154 }
155
156 GLCompositor *compositor;
Zach Reiznerf5fa77c2015-06-11 11:28:48 -0700157 Importer *importer;
Zach Reizner01935f32015-04-29 11:15:09 -0700158 int target_handle;
Zach Reizner6cbe8832015-06-26 18:25:38 -0700159 int timeline_fd;
160 std::vector<hwc_layer_1> layers;
Zach Reizner01935f32015-04-29 11:15:09 -0700161};
162
Zach Reizner01935f32015-04-29 11:15:09 -0700163GLCompositor::GLCompositor() {
164 priv_ = new priv_data;
165}
166
167GLCompositor::~GLCompositor() {
Zach Reizner01935f32015-04-29 11:15:09 -0700168 for (std::vector<GLComposition *>::iterator it = priv_->compositions.end();
169 it != priv_->compositions.begin(); it = priv_->compositions.end()) {
170 --it;
171
172 // Prevents compositor from trying to erase itself
173 (*it)->compositor = NULL;
174 delete *it;
175 priv_->compositions.erase(it);
176 }
177
Zach Reizner01935f32015-04-29 11:15:09 -0700178 delete priv_;
179}
180
181int GLCompositor::Init() {
Zach Reizner6cbe8832015-06-26 18:25:38 -0700182 return priv_->worker.Init();
Zach Reizner01935f32015-04-29 11:15:09 -0700183}
184
185Targeting *GLCompositor::targeting() {
186 return (Targeting *)this;
187}
188
189int GLCompositor::CreateTarget(sp<GraphicBuffer> &buffer) {
190 int ret;
191
Zach Reizner01935f32015-04-29 11:15:09 -0700192 int target_handle = AllocResource(priv_->targets);
193 GLTarget *target = &priv_->targets[target_handle];
194
195 target->fb = buffer;
Zach Reizner01935f32015-04-29 11:15:09 -0700196 target->forgotten = false;
197
Zach Reizner6cbe8832015-06-26 18:25:38 -0700198 return target_handle;
Zach Reizner01935f32015-04-29 11:15:09 -0700199}
200
201void 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;
206 return;
207 }
208 }
209
210 priv_->current_target = -1;
211}
212
213void 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;
217 }
218
219 GLTarget *target = &priv_->targets[target_handle];
220 if (target->is_some()) {
221 target->forgotten = true;
222 CheckAndDestroyTarget(target_handle);
223 return;
224 }
225 }
226
227 ALOGE("Failed to forget target because of invalid handle");
228}
229
230void GLCompositor::CheckAndDestroyTarget(int target_handle) {
231 GLTarget *target = &priv_->targets[target_handle];
232 if (target->composition_count == 0 && target->forgotten) {
Zach Reizner01935f32015-04-29 11:15:09 -0700233 FreeResource(priv_->targets, target_handle);
234 }
235}
236
Zach Reiznerf5fa77c2015-06-11 11:28:48 -0700237Composition *GLCompositor::CreateComposition(Importer *importer) {
Zach Reizner01935f32015-04-29 11:15:09 -0700238 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()) {
Zach Reiznerf5fa77c2015-06-11 11:28:48 -0700242 GLComposition *composition = new GLComposition(this, importer);
Zach Reizner01935f32015-04-29 11:15:09 -0700243 composition->target_handle = priv_->current_target;
244 target->composition_count++;
245 priv_->compositions.push_back(composition);
246 return composition;
247 }
248 }
249
250 ALOGE("Failed to create composition because of invalid target handle %d",
251 priv_->current_target);
252
253 return NULL;
254}
255
256int GLCompositor::QueueComposition(Composition *composition) {
257 if (composition) {
Zach Reizner6cbe8832015-06-26 18:25:38 -0700258 GLComposition *gl_composition = (GLComposition *)composition;
259 int ret = DoComposition(gl_composition);
260 gl_composition->timeline_fd = -1;
Zach Reizner01935f32015-04-29 11:15:09 -0700261 delete composition;
262 return ret;
263 }
264
265 ALOGE("Failed to queue composition because of invalid composition handle");
266
267 return -EINVAL;
268}
269
270int GLCompositor::Composite() {
271 return 0;
272}
273
Zach Reizner6cbe8832015-06-26 18:25:38 -0700274int GLCompositor::DoComposition(GLComposition *composition) {
Stéphane Marchesinbe98c8c2015-06-23 16:18:10 -0700275 ATRACE_CALL();
Zach Reizner01935f32015-04-29 11:15:09 -0700276 int ret = 0;
Zach Reizner01935f32015-04-29 11:15:09 -0700277
Zach Reizner6cbe8832015-06-26 18:25:38 -0700278 GLTarget *target = &priv_->targets[composition->target_handle];
279 GLWorker::Work work;
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;
284
285 ret = priv_->worker.DoWork(&work);
286
287 if (work.timeline_fd >= 0) {
288 sw_sync_timeline_inc(work.timeline_fd, work.num_layers + 1);
289 close(work.timeline_fd);
Zach Reizner01935f32015-04-29 11:15:09 -0700290 }
291
Zach Reizner01935f32015-04-29 11:15:09 -0700292 return ret;
293}
294
Zach Reizner01935f32015-04-29 11:15:09 -0700295} // namespace android